[dali_1.1.31] Merge branch 'devel/master' 73/66973/1
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 22 Apr 2016 09:08:35 +0000 (10:08 +0100)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Fri, 22 Apr 2016 09:08:35 +0000 (10:08 +0100)
Change-Id: I644ed1b09b5a5f8b3ffeafde16d6fa537d0dfbd0

175 files changed:
automated-tests/src/dali-toolkit-internal/CMakeLists.txt
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-model.cpp [moved from automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp with 99% similarity]
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-model.h [moved from automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.h with 100% similarity]
automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Layout.cpp
automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
automated-tests/src/dali-toolkit/CMakeLists.txt
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/mesh-builder.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/mesh-builder.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-application.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-intrusive-ptr.h [new file with mode: 0644]
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-native-image.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-native-image.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.h
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-test-application.h
automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp
automated-tests/src/dali-toolkit/utc-Dali-ControlRenderer.cpp
automated-tests/src/dali-toolkit/utc-Dali-DefaultControls.cpp [deleted file]
automated-tests/src/dali-toolkit/utc-Dali-FlexContainer.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit/utc-Dali-ItemLayout.cpp
automated-tests/src/dali-toolkit/utc-Dali-ItemView.cpp
automated-tests/src/dali-toolkit/utc-Dali-KeyInputFocusManager.cpp
automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextLabel.cpp
build/tizen/configure.ac
build/tizen/dali-toolkit/Makefile.am
dali-toolkit/devel-api/controls/flex-container/flex-container.cpp [new file with mode: 0644]
dali-toolkit/devel-api/controls/flex-container/flex-container.h [new file with mode: 0644]
dali-toolkit/devel-api/controls/renderer-factory/control-renderer.h
dali-toolkit/devel-api/file.list
dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp
dali-toolkit/internal/controls/bubble-effect/bubble-actor.cpp
dali-toolkit/internal/controls/bubble-effect/bubble-actor.h
dali-toolkit/internal/controls/bubble-effect/bubble-effect.h
dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.cpp
dali-toolkit/internal/controls/bubble-effect/bubble-emitter-impl.h
dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp [new file with mode: 0644]
dali-toolkit/internal/controls/flex-container/flex-container-impl.h [new file with mode: 0644]
dali-toolkit/internal/controls/flex-container/layout.c [new file with mode: 0644]
dali-toolkit/internal/controls/flex-container/layout.h [new file with mode: 0644]
dali-toolkit/internal/controls/model3d-view/model3d-view-impl.cpp
dali-toolkit/internal/controls/model3d-view/model3d-view-impl.h
dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.cpp
dali-toolkit/internal/controls/page-turn-view/page-turn-view-impl.h
dali-toolkit/internal/controls/renderers/border/border-renderer.cpp
dali-toolkit/internal/controls/renderers/color/color-renderer.cpp
dali-toolkit/internal/controls/renderers/debug/debug-renderer.cpp
dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.cpp
dali-toolkit/internal/controls/renderers/image-atlas-manager.cpp
dali-toolkit/internal/controls/renderers/image-atlas-manager.h
dali-toolkit/internal/controls/renderers/image/image-renderer.cpp
dali-toolkit/internal/controls/renderers/image/image-renderer.h
dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp
dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h
dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp
dali-toolkit/internal/controls/renderers/svg/svg-rasterize-thread.cpp
dali-toolkit/internal/controls/renderers/svg/svg-rasterize-thread.h
dali-toolkit/internal/controls/renderers/svg/svg-renderer.cpp
dali-toolkit/internal/controls/renderers/svg/svg-renderer.h
dali-toolkit/internal/controls/scrollable/bouncing-effect-actor.cpp
dali-toolkit/internal/controls/scrollable/scrollable-impl.cpp
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-label-impl.cpp
dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/filters/blur-two-pass-filter.cpp
dali-toolkit/internal/text/decorator/text-decorator.cpp
dali-toolkit/internal/text/glyph-metrics-helper.cpp [new file with mode: 0644]
dali-toolkit/internal/text/glyph-metrics-helper.h [new file with mode: 0644]
dali-toolkit/internal/text/layouts/layout-engine.cpp
dali-toolkit/internal/text/layouts/layout-parameters.h
dali-toolkit/internal/text/metrics.h
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.h
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h
dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-manager-impl.h
dali-toolkit/internal/text/rendering/atlas/atlas-manager.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-manager.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/rendering/text-backend-impl.cpp
dali-toolkit/internal/text/rendering/vector-based/file.list [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.cpp [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.cpp [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.cpp [new file with mode: 0644]
dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h [new file with mode: 0644]
dali-toolkit/internal/text/text-controller-impl.cpp
dali-toolkit/internal/text/text-controller-impl.h
dali-toolkit/internal/text/text-controller.cpp
dali-toolkit/internal/text/text-controller.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/transition-effects/cube-transition-effect-impl.cpp
dali-toolkit/po/ar.po [new file with mode: 0755]
dali-toolkit/po/az.po [new file with mode: 0755]
dali-toolkit/po/bg.po [new file with mode: 0755]
dali-toolkit/po/ca.po [new file with mode: 0755]
dali-toolkit/po/cs.po [new file with mode: 0755]
dali-toolkit/po/da.po [new file with mode: 0755]
dali-toolkit/po/de.po [new file with mode: 0755]
dali-toolkit/po/el_GR.po [new file with mode: 0755]
dali-toolkit/po/en.po [new file with mode: 0755]
dali-toolkit/po/en_PH.po [new file with mode: 0755]
dali-toolkit/po/en_US.po [new file with mode: 0755]
dali-toolkit/po/es_ES.po [new file with mode: 0755]
dali-toolkit/po/es_US.po [new file with mode: 0755]
dali-toolkit/po/et.po [new file with mode: 0755]
dali-toolkit/po/eu.po [new file with mode: 0755]
dali-toolkit/po/fi.po [new file with mode: 0755]
dali-toolkit/po/fr.po [new file with mode: 0755]
dali-toolkit/po/fr_CA.po [new file with mode: 0755]
dali-toolkit/po/ga.po [new file with mode: 0755]
dali-toolkit/po/gl.po [new file with mode: 0755]
dali-toolkit/po/hi.po [new file with mode: 0755]
dali-toolkit/po/hr.po [new file with mode: 0755]
dali-toolkit/po/hu.po [new file with mode: 0755]
dali-toolkit/po/hy.po [new file with mode: 0755]
dali-toolkit/po/is.po [new file with mode: 0755]
dali-toolkit/po/it_IT.po [new file with mode: 0755]
dali-toolkit/po/ja_JP.po [new file with mode: 0755]
dali-toolkit/po/ka.po [new file with mode: 0755]
dali-toolkit/po/kk.po [new file with mode: 0755]
dali-toolkit/po/ko_KR.po [new file with mode: 0755]
dali-toolkit/po/lt.po [new file with mode: 0755]
dali-toolkit/po/lv.po [new file with mode: 0755]
dali-toolkit/po/mk.po [new file with mode: 0755]
dali-toolkit/po/nb.po [new file with mode: 0755]
dali-toolkit/po/nl.po [new file with mode: 0755]
dali-toolkit/po/pl.po [new file with mode: 0755]
dali-toolkit/po/pt_BR.po [new file with mode: 0755]
dali-toolkit/po/pt_PT.po [new file with mode: 0755]
dali-toolkit/po/ro.po [new file with mode: 0755]
dali-toolkit/po/ru_RU.po [new file with mode: 0755]
dali-toolkit/po/sk.po [new file with mode: 0755]
dali-toolkit/po/sl.po [new file with mode: 0755]
dali-toolkit/po/sr.po [new file with mode: 0755]
dali-toolkit/po/sv.po [new file with mode: 0755]
dali-toolkit/po/tr_TR.po [new file with mode: 0755]
dali-toolkit/po/uk.po [new file with mode: 0755]
dali-toolkit/po/uz.po [new file with mode: 0755]
dali-toolkit/po/zh_CN.po [new file with mode: 0755]
dali-toolkit/po/zh_HK.po [new file with mode: 0755]
dali-toolkit/po/zh_TW.po [new file with mode: 0755]
dali-toolkit/public-api/controls/scrollable/scrollable.h
dali-toolkit/public-api/dali-toolkit-version.cpp
dali-toolkit/public-api/text/rendering-backend.h
node-addon/build/tizen/CMakeLists.txt
packaging/dali-toolkit.spec
plugins/dali-script-v8/file.list
plugins/dali-script-v8/src/actors/actor-api.cpp
plugins/dali-script-v8/src/dali-wrapper.cpp
plugins/dali-script-v8/src/object/property-value-wrapper.cpp
plugins/dali-script-v8/src/rendering/material-api.cpp [deleted file]
plugins/dali-script-v8/src/rendering/material-api.h [deleted file]
plugins/dali-script-v8/src/rendering/material-wrapper.h [deleted file]
plugins/dali-script-v8/src/rendering/renderer-api.cpp
plugins/dali-script-v8/src/rendering/renderer-api.h
plugins/dali-script-v8/src/rendering/renderer-wrapper.cpp
plugins/dali-script-v8/src/rendering/texture-set-api.cpp [new file with mode: 0644]
plugins/dali-script-v8/src/rendering/texture-set-api.h [new file with mode: 0644]
plugins/dali-script-v8/src/rendering/texture-set-wrapper.cpp [moved from plugins/dali-script-v8/src/rendering/material-wrapper.cpp with 51% similarity]
plugins/dali-script-v8/src/rendering/texture-set-wrapper.h [new file with mode: 0644]
plugins/dali-script-v8/src/shared/base-wrapped-object.h

index 7696421..b2a4e29 100644 (file)
@@ -20,27 +20,35 @@ SET(TC_SOURCES
 
 # Append list of test harness files (Won't get parsed for test cases)
 LIST(APPEND TC_SOURCES
-   ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-accessibility-adaptor.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-application.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/toolkit-event-thread-callback.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/toolkit-environment-variable.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-imf-manager.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-orientation.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-physical-keyboard.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-style-monitor.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-singleton-service.cpp
    ../dali-toolkit/dali-toolkit-test-utils/toolkit-timer.cpp
-   ../dali-toolkit/dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
-   ../dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
-   ../dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/toolkit-tts-player.cpp
    ../dali-toolkit/dali-toolkit-test-utils/dali-test-suite-utils.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/mesh-builder.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-animation-data.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-application.cpp
-   ../dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-button.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-harness.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-gesture-manager.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-platform-abstraction.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-render-controller.cpp
    ../dali-toolkit/dali-toolkit-test-utils/test-trace-call-stack.cpp
+   ../dali-toolkit/dali-toolkit-test-utils/test-native-image.cpp
+   dali-toolkit-test-utils/toolkit-text-model.cpp
 )
 
 
@@ -60,11 +68,13 @@ INCLUDE_DIRECTORIES(
     ../../../
     ${${CAPI_LIB}_INCLUDE_DIRS}
     ../dali-toolkit/dali-toolkit-test-utils
+    dali-toolkit-test-utils
 )
 
 ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES})
 TARGET_LINK_LIBRARIES(${EXEC_NAME}
     ${${CAPI_LIB}_LIBRARIES}
+    -lpthread
 )
 
 INSTALL(PROGRAMS ${EXEC_NAME}
@@ -295,6 +295,8 @@ void CreateTextModel( const std::string& text,
   // The initial glyph and the number of glyphs to layout.
   layoutParameters.startGlyphIndex = 0u;
   layoutParameters.numberOfGlyphs = numberOfGlyphs;
+  layoutParameters.startLineIndex = 0u;
+  layoutParameters.estimatedNumberOfLines = logicalModel->mParagraphInfo.Count();
 
   layoutEngine.LayoutText( layoutParameters,
                            glyphPositions,
index d849430..521cbf9 100644 (file)
@@ -177,6 +177,7 @@ bool LayoutTextTest( const LayoutTextData& data )
   layoutParameters.startGlyphIndex = data.startIndex;
   layoutParameters.numberOfGlyphs = data.numberOfGlyphs;
   layoutParameters.startLineIndex = startRemoveIndex;
+  layoutParameters.estimatedNumberOfLines = logicalModel->mParagraphInfo.Count();
 
   layoutSize = Vector2::ZERO;
 
@@ -746,7 +747,7 @@ int UtcDaliTextLayoutSmallTextArea02(void)
   fontDescriptionRuns.PushBack( fontDescriptionRun );
   Size textArea(1.f, 1.f);
   Size layoutSize(80.f, 20.f);
-  float positions[] = { 1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f };
+  float positions[] = { 1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f };
   struct LineRun line =
   {
     { 0u, 11u },
@@ -831,11 +832,11 @@ int UtcDaliTextLayoutMultilineText01(void)
   Size layoutSize(95.f, 97.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
-    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 32.f, 42.f, 23.f,
-    1.f, 43.f, 9.f, 46.f, 17.f, 46.f, 27.f, 46.f, 36.f, 46.f, 45.f, 44.f, 51.f, 55.f,
-    1.f, 62.f, 11.f, 62.f, 15.f, 62.f, 26.f, 65.f, 35.f, 65.f, 41.f, 65.f, 50.f, 65.f, 59.f, 63.f, 65.f, 74.f,
-    1.f, 81.f, 5.f, 81.f, 9.f, 84.f, 19.f, 84.f, 28.f, 84.f, 35.f, 93.f, 41.f, 84.f, 50.f, 81.f, 54.f, 93.f, 59.f, 82.f, 66.f, 84.f, 75.f, 84.f, 83.f, 82.f, 91.f, 91.f
+    1.f, -12.f, 12.f,  -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f,  -0.f, 40.f, -9.f, 51.f,  -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f,  -9.f, 18.f,  -9.f, 30.f,  -9.f, 39.f, -3.f, 42.f, -12.f,
+    1.f, -12.f,  9.f,  -9.f, 17.f,  -9.f, 27.f,  -9.f, 36.f, -9.f, 45.f, -11.f, 51.f, -0.f,
+    1.f, -12.f, 11.f, -12.f, 15.f, -12.f, 26.f,  -9.f, 35.f, -9.f, 41.f,  -9.f, 50.f, -9.f, 59.f, -11.f, 65.f, -0.f,
+    1.f, -12.f,  5.f, -12.f,  9.f,  -9.f, 19.f,  -9.f, 28.f, -9.f, 35.f,  -0.f, 41.f, -9.f, 50.f, -12.f, 54.f, -0.f, 59.f, -11.f, 66.f,  -9.f, 75.f, -9.f, 83.f, -11.f, 91.f, -2.f
   };
   struct LineRun line0 =
   {
@@ -1009,12 +1010,12 @@ int UtcDaliTextLayoutMultilineText02(void)
   Size layoutSize(81.f, 120.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
-    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
-    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
-    1.f, 65.f, 12.f, 62.f, 19.f, 65.f, 24.f, 65.f, 32.f, 75.f, 37.f, 65.f, 45.f, 65.f, 50.f, 62.f, 58.f, 65.f, 66.f, 75.f,
-    1.f, 82.f, 10.f, 86.f, 18.f, 82.f, 22.f, 82.f, 25.f, 86.f, 34.f, 95.f, 38.f, 86.f, 49.f, 86.f, 59.f, 86.f, 65.f, 82.f, 68.f, 82.f, 77.f, 95.f,
-    0.f, 102.f, 10.f, 106.f, 18.f, 106.f, 30.f, 106.f, 39.f, 112.f
+    1.f, -12.f, 12.f,  -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f,  -0.f, 40.f,  -9.f, 51.f,  -9.f, 61.f,  -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f,  -9.f, 18.f,  -9.f, 30.f,  -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f,  -0.f,
+    1.f, -10.f,  9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f,  -0.f,
+    1.f, -13.f, 10.f,  -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f,  -0.f, 38.f,  -9.f, 49.f,  -9.f, 59.f,  -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -13.f, 10.f,  -9.f, 18.f,  -9.f, 30.f,  -9.f, 39.f, -3.f,
   };
   struct LineRun line0 =
   {
@@ -1153,9 +1154,9 @@ int UtcDaliTextLayoutMultilineText03(void)
   Size layoutSize(96.f, 60.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 6.f, 47.f, 6.f, 57.f, 6.f, 63.f, 2.f, 66.f, 2.f, 75.f, 2.f, 85.f, 6.f,
-    1.f, 26.f, 13.f, 26.f, 23.f, 22.f, 32.f, 26.f, 40.f, 22.f, 44.f, 22.f, 47.f, 26.f, 56.f, 26.f, 67.f, 26.f, 77.f, 26.f, 83.f, 22.f, 86.f, 22.f,
-    0.f, 42.f, 10.f, 46.f, 18.f, 46.f, 30.f, 46.f, 39.f, 52.f
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f,  -9.f, 36.f,  -9.f, 47.f, -9.f, 57.f, -9.f, 63.f, -13.f, 66.f, -13.f, 75.f, -13.f, 85.f,  -9.f,
+    1.f,  -9.f, 13.f, -9.f, 23.f, -13.f, 32.f,  -9.f, 40.f, -13.f, 44.f, -13.f, 47.f, -9.f, 56.f, -9.f, 67.f,  -9.f, 77.f,  -9.f, 83.f, -13.f, 86.f, -13.f,
+    0.f, -13.f, 10.f, -9.f, 18.f,  -9.f, 30.f,  -9.f, 39.f,  -3.f,
   };
   struct LineRun line0 =
   {
@@ -1254,7 +1255,7 @@ int UtcDaliTextLayoutMultilineText04(void)
   Size layoutSize(83.f, 40.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 12.f, 82.f, 3.f
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -3.f, 82.f, -12.f
   };
   struct LineRun line0 =
   {
@@ -1367,8 +1368,8 @@ int UtcDaliTextLayoutMultilineText05(void)
   Size layoutSize(88.f, 53.f);
   float positions[] =
   {
-    1.f, 13.f, 12.f, 16.f, 20.f, 12.f, 24.f, 12.f, 27.f, 16.f, 36.f, 25.f, 40.f, 11.f, 59.f, 16.f, 69.f, 16.f, 75.f, 12.f, 78.f, 12.f, 87.f, 25.f,
-    0.f, 35.f, 10.f, 39.f, 18.f, 39.f, 30.f, 39.f, 39.f, 45.f
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -14.f, 59.f, -9.f, 69.f, -9.f, 75.f, -13.f, 78.f, -13.f, 87.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f,  -9.f, 30.f,  -9.f, 39.f, -3.f
   };
   struct LineRun line0 =
   {
@@ -1652,24 +1653,24 @@ int UtcDaliTextUpdateLayout01(void)
   Size layoutSize(92.f, 380.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
-    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
-    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
-    0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f,
-    0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f,
-    1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f,
-    1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f,
-    1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f,
-    0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f,
-    1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f,
-    0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f,
-    1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f,
-    1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f,
-    0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f,
-    1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f,
-    1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f,
-    1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f,
-    0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f,
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -13.f, 68.f, -9.f, 76.f, -13.f, 80.f, -13.f, 83.f, -9.f, 92.f, -0.f,
+    0.f, -9.f, 11.f, -9.f, 21.f, -9.f, 27.f, -13.f, 30.f, -13.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -3.f, 42.f, -12.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f,
   };
   struct LineRun line01 =
   {
@@ -2179,24 +2180,24 @@ int UtcDaliTextUpdateLayout02(void)
   Size layoutSize(92.f, 380.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
-    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
-    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
-    0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f,
-    0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f,
-    1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f,
-    1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f,
-    1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f,
-    0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f,
-    1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f,
-    0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f,
-    1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f,
-    1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f,
-    0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f,
-    1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f,
-    1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f,
-    1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f,
-    0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f,
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -13.f, 68.f, -9.f, 76.f, -13.f, 80.f, -13.f, 83.f, -9.f, 92.f, -0.f,
+    0.f, -9.f, 11.f, -9.f, 21.f, -9.f, 27.f, -13.f, 30.f, -13.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -3.f, 42.f, -12.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f,
   };
   struct LineRun line01 =
   {
@@ -2706,24 +2707,24 @@ int UtcDaliTextUpdateLayout03(void)
   Size layoutSize(92.f, 380.f);
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f,
-    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 25.f, 55.f, 22.f, 62.f, 25.f, 67.f, 25.f, 75.f, 35.f,
-    1.f, 45.f, 9.f, 45.f, 14.f, 42.f, 22.f, 45.f, 32.f, 53.f, 35.f, 44.f,
-    0.f, 67.f, 7.f, 69.f, 12.f, 68.f, 18.f, 68.f, 23.f, 64.f, 25.f, 75.f, 27.f, 68.f, 32.f, 64.f, 33.f, 64.f, 37.f, 67.f, 44.f, 64.f, 45.f, 64.f, 49.f, 67.f, 55.f, 75.f, 59.f, 62.f, 68.f, 66.f, 76.f, 62.f, 80.f, 62.f, 83.f, 66.f, 92.f, 75.f,
-    0.f, 86.f, 11.f, 86.f, 21.f, 86.f, 27.f, 82.f, 30.f, 82.f, 39.f, 95.f, 44.f, 85.f, 55.f, 82.f, 62.f, 85.f, 67.f, 85.f, 75.f, 95.f,
-    1.f, 105.f, 9.f, 105.f, 14.f, 102.f, 22.f, 105.f, 30.f, 115.f,
-    1.f, 125.f, 12.f, 122.f, 19.f, 125.f, 24.f, 125.f, 32.f, 135.f, 37.f, 125.f, 45.f, 125.f, 50.f, 122.f, 58.f, 125.f, 66.f, 135.f,
-    1.f, 142.f, 10.f, 146.f, 18.f, 142.f, 22.f, 142.f, 25.f, 146.f, 34.f, 155.f, 38.f, 146.f, 49.f, 146.f, 59.f, 146.f, 65.f, 142.f, 68.f, 142.f, 77.f, 155.f,
-    0.f, 162.f, 10.f, 166.f, 18.f, 166.f, 30.f, 166.f, 39.f, 172.f, 42.f, 163.f,
-    1.f, 182.f, 10.f, 186.f, 18.f, 182.f, 22.f, 182.f, 25.f, 186.f, 34.f, 195.f, 38.f, 186.f, 49.f, 186.f, 59.f, 186.f, 65.f, 182.f, 68.f, 182.f, 77.f, 195.f,
-    0.f, 207.f, 7.f, 209.f, 12.f, 208.f, 18.f, 208.f, 23.f, 204.f, 25.f, 215.f, 27.f, 208.f, 32.f, 204.f, 33.f, 204.f, 37.f, 207.f, 44.f, 204.f, 45.f, 204.f, 49.f, 207.f, 55.f, 215.f, 59.f, 205.f, 70.f, 202.f, 77.f, 205.f, 82.f, 205.f, 90.f, 215.f,
-    1.f, 225.f, 9.f, 225.f, 14.f, 222.f, 22.f, 225.f, 30.f, 235.f,
-    1.f, 243.f, 12.f, 246.f, 20.f, 242.f, 24.f, 242.f, 27.f, 246.f, 36.f, 255.f, 40.f, 246.f, 51.f, 246.f, 61.f, 246.f, 67.f, 242.f, 70.f, 242.f, 79.f, 255.f,
-    0.f, 262.f, 10.f, 266.f, 18.f, 266.f, 30.f, 266.f, 39.f, 275.f, 44.f, 265.f, 55.f, 262.f, 62.f, 265.f, 67.f, 265.f, 75.f, 275.f,
-    1.f, 285.f, 9.f, 285.f, 14.f, 282.f, 22.f, 285.f, 32.f, 293.f, 35.f, 284.f,
-    1.f, 305.f, 12.f, 302.f, 19.f, 305.f, 24.f, 305.f, 32.f, 315.f, 37.f, 305.f, 45.f, 305.f, 50.f, 302.f, 58.f, 305.f, 66.f, 315.f,
-    1.f, 322.f, 10.f, 326.f, 18.f, 322.f, 22.f, 322.f, 25.f, 326.f, 34.f, 335.f, 38.f, 326.f, 49.f, 326.f, 59.f, 326.f, 65.f, 322.f, 68.f, 322.f, 77.f, 335.f,
-    0.f, 347.f, 7.f, 349.f, 12.f, 348.f, 18.f, 348.f, 23.f, 344.f, 25.f, 355.f, 27.f, 348.f, 32.f, 344.f, 33.f, 344.f, 37.f, 347.f, 44.f, 344.f, 45.f, 344.f, 49.f, 347.f, 55.f, 355.f,
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -13.f, 68.f, -9.f, 76.f, -13.f, 80.f, -13.f, 83.f, -9.f, 92.f, -0.f,
+    0.f, -9.f, 11.f, -9.f, 21.f, -9.f, 27.f, -13.f, 30.f, -13.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -3.f, 42.f, -12.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -10.f, 55.f, -13.f, 62.f, -10.f, 67.f, -10.f, 75.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 32.f, -2.f, 35.f, -11.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f,
+    1.f, -13.f, 10.f, -9.f, 18.f, -13.f, 22.f, -13.f, 25.f, -9.f, 34.f, -0.f, 38.f, -9.f, 49.f, -9.f, 59.f, -9.f, 65.f, -13.f, 68.f, -13.f, 77.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f,
   };
   struct LineRun line01 =
   {
@@ -3049,7 +3050,7 @@ int UtcDaliTextLayoutEllipsis01(void)
 
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f, 79.f, 15.f, 83.f, 2.f
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f, 83.f, -13.f,
   };
 
   Size textArea( 100.f, 50.f );
@@ -3138,8 +3139,8 @@ int UtcDaliTextLayoutEllipsis02(void)
 
   float positions[] =
   {
-    1.f,  3.f, 12.f,  6.f, 20.f,  2.f, 24.f,  2.f, 27.f,  6.f, 36.f, 15.f, 40.f,  6.f, 51.f,  6.f, 61.f,  6.f, 67.f,  2.f, 70.f,  2.f, 79.f, 15.f,
-    0.f, 22.f, 10.f, 26.f, 18.f, 26.f, 30.f, 26.f, 39.f, 35.f, 44.f, 22.f, 53.f, 26.f, 61.f, 22.f, 65.f, 22.f, 68.f, 26.f, 77.f, 35.f, 81.f, 26.f
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f, 79.f, -0.f,
+    0.f, -13.f, 10.f, -9.f, 18.f, -9.f, 30.f, -9.f, 39.f, -0.f, 44.f, -13.f, 53.f, -9.f, 61.f, -13.f, 65.f, -13.f, 68.f, -9.f, 77.f, -0.f, 81.f, -9.f,
   };
 
   Size textArea( 100.f, 50.f );
@@ -3281,7 +3282,7 @@ int UtcDaliTextLayoutEllipsis03(void)
 
   float positions[] =
   {
-    1.f, 5.f, 12.f, 2.f, 19.f, 5.f, 24.f, 5.f, 32.f, 15.f, 37.f, 5.f, 45.f, 5.f, 50.f, 2.f, 58.f, 5.f, 66.f, 15.f, 69.f, 7.f, 76.f, 9.f, 81.f, 8.f, 87.f, 8.f, 92.f, 4.f, 94.f, 15.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -7.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
   };
 
   Size textArea( 100.f, 50.f );
@@ -3436,8 +3437,8 @@ int UtcDaliTextLayoutEllipsis04(void)
 
   float positions[] =
   {
-    1.f,  5.f, 12.f,  2.f, 19.f,  5.f, 24.f,  5.f, 32.f, 15.f, 37.f,  5.f, 45.f,  5.f, 50.f,  2.f, 58.f,  5.f, 66.f, 15.f, 69.f,  7.f, 76.f,  9.f, 81.f,  8.f, 87.f,  8.f, 92.f,  4.f, 94.f, 15.f,
-    0.f, 28.f,  5.f, 24.f,  6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f, 32.f, 25.f, 43.f, 22.f, 50.f, 25.f, 55.f, 25.f, 63.f, 35.f, 68.f, 25.f, 76.f, 25.f, 81.f, 22.f, 89.f, 25.f, 97.f, 35.f
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -7.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+    0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 10.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 28.f, -0.f, 32.f, -10.f, 43.f, -13.f, 50.f, -10.f, 55.f, -10.f, 63.f, -0.f, 68.f, -10.f, 76.f, -10.f, 81.f, -13.f, 89.f, -10.f, 97.f, -0.f,
   };
 
   Size textArea( 100.f, 50.f );
@@ -3498,7 +3499,7 @@ int UtcDaliTextReorderLayout01(void)
 
   float positions[] =
   {
-    1.f, 3.f, 12.f, 6.f, 20.f, 2.f, 24.f, 2.f, 27.f, 6.f, 36.f, 15.f, 40.f, 6.f, 51.f, 6.f, 61.f, 6.f, 67.f, 2.f, 70.f, 2.f
+    1.f, -12.f, 12.f, -9.f, 20.f, -13.f, 24.f, -13.f, 27.f, -9.f, 36.f, -0.f, 40.f, -9.f, 51.f, -9.f, 61.f, -9.f, 67.f, -13.f, 70.f, -13.f,
   };
 
   Size textArea( 100.f, 300.f );
@@ -3618,12 +3619,12 @@ int UtcDaliTextReorderLayout02(void)
 
   float positions[] =
   {
-    87.f,  5.f, 79.f,  2.f, 74.f,  5.f, 66.f,  5.f, 61.f, 15.f, 53.f,  5.f, 48.f,  5.f, 41.f,  2.f, 32.f,  5.f, 27.f, 15.f, 20.f,  7.f, 15.f,  9.f,  8.f,  8.f,  5.f,  8.f,  4.f,  4.f,  0.f, 15.f,
-    23.f, 28.f, 22.f, 24.f, 17.f, 24.f, 12.f, 27.f, 10.f, 24.f,  5.f, 24.f,  0.f, 27.f,  0.f, 35.f,
-    0.f, 47.f, 7.f, 49.f, 12.f, 48.f, 18.f, 48.f, 23.f, 44.f, 25.f, 55.f, 27.f, 48.f, 32.f, 44.f, 33.f, 44.f, 37.f, 47.f, 44.f, 44.f, 45.f, 44.f, 49.f, 47.f, 55.f, 55.f, 59.f, 45.f, 70.f, 42.f, 77.f, 45.f, 82.f, 45.f, 90.f, 55.f,
-    1.f, 65.f, 9.f, 65.f, 14.f, 62.f, 22.f, 65.f, 30.f, 75.f,
-    1.f, 85.f, 12.f, 82.f, 19.f, 85.f, 24.f, 85.f, 32.f, 95.f, 37.f, 85.f, 45.f, 85.f, 50.f, 82.f, 58.f, 85.f, 66.f, 95.f, 69.f, 87.f, 76.f, 89.f, 81.f, 88.f, 87.f, 88.f, 92.f, 84.f, 94.f, 95.f,
-    0.f, 108.f, 5.f, 104.f, 6.f, 104.f, 10.f, 107.f, 17.f, 104.f, 18.f, 104.f, 22.f, 107.f, 30.f, 113.f
+    87.f, -10.f, 79.f, -13.f, 74.f, -10.f, 66.f, -10.f, 61.f, -0.f, 53.f, -10.f, 48.f, -10.f, 41.f, -13.f, 32.f, -10.f, 27.f, -0.f, 20.f, -8.f, 15.f, -6.f, 8.f, -7.f, 5.f, -7.f, 4.f, -11.f, 0.f, -0.f,
+    23.f, -7.f, 22.f, -11.f, 17.f, -11.f, 12.f, -8.f, 10.f, -11.f, 5.f, -11.f, 0.f, -8.f, 0.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -7.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+    0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 10.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 30.f, -2.f,
   };
 
   Size textArea( 100.f, 300.f );
@@ -3745,12 +3746,12 @@ int UtcDaliTextReorderLayout03(void)
 
   float positions[] =
   {
-    1.f,  5.f, 12.f,  2.f, 19.f,  5.f, 24.f,  5.f, 32.f, 15.f, 37.f,  5.f, 45.f,  5.f, 50.f,  2.f, 58.f,  5.f, 66.f, 15.f, 69.f,  7.f, 76.f,  9.f, 81.f,  8.f, 87.f,  8.f, 92.f, 4.f, 94.f, 15.f,
-    0.f, 28.f,  5.f, 24.f,  6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f,
-    86.f, 47.f, 81.f, 49.f, 74.f, 48.f, 71.f, 48.f, 70.f, 44.f, 66.f, 55.f, 62.f, 48.f, 61.f, 44.f, 56.f, 44.f, 51.f, 47.f, 49.f, 44.f, 44.f, 44.f, 39.f, 47.f, 36.f, 55.f, 26.f, 45.f, 18.f, 42.f, 13.f, 45.f,  5.f, 45.f,  0.f, 55.f,
-    22.f, 65.f, 17.f, 65.f, 10.f, 62.f,  1.f, 65.f,  0.f, 75.f,
-    1.f, 85.f, 12.f, 82.f, 19.f, 85.f, 24.f, 85.f, 32.f, 95.f, 37.f, 85.f, 45.f, 85.f, 50.f, 82.f, 58.f, 85.f, 66.f, 95.f, 69.f, 87.f, 76.f, 89.f, 81.f, 88.f, 87.f, 88.f, 92.f, 84.f, 94.f, 95.f,
-    0.f, 108.f,  5.f, 104.f,  6.f, 104.f, 10.f, 107.f, 17.f, 104.f, 18.f, 104.f, 22.f, 107.f, 30.f, 113.f
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -7.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+    0.f, -7.f,  5.f, -11.f, 6.f, -11.f, 10.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 28.f, -0.f,
+    86.f, -8.f, 81.f, -6.f, 74.f, -7.f, 71.f, -7.f, 70.f, -11.f, 66.f, -0.f, 62.f, -7.f, 61.f, -11.f, 56.f, -11.f, 51.f, -8.f, 49.f, -11.f, 44.f, -11.f, 39.f, -8.f, 36.f, -0.f, 26.f, -10.f, 18.f, -13.f, 13.f, -10.f, 5.f, -10.f, 0.f, -0.f,
+    22.f, -10.f, 17.f, -10.f, 10.f, -13.f, 1.f, -10.f, 0.f, -0.f,
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -7.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+    0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 10.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 30.f, -2.f,
   };
 
   Size textArea( 100.f, 300.f );
@@ -3872,12 +3873,12 @@ int UtcDaliTextReorderLayout04(void)
 
   float positions[] =
   {
-    1.f,  5.f, 12.f,  2.f, 19.f,  5.f, 24.f,  5.f, 32.f, 15.f, 37.f,  5.f, 45.f,  5.f, 50.f,  2.f, 58.f,  5.f, 66.f, 15.f, 69.f,  7.f, 76.f,  9.f, 81.f,  8.f, 87.f,  8.f, 92.f, 4.f, 94.f, 15.f,
-    0.f, 28.f,  5.f, 24.f,  6.f, 24.f, 10.f, 27.f, 17.f, 24.f, 18.f, 24.f, 22.f, 27.f, 28.f, 35.f,
-    0.f, 47.f,  7.f, 49.f, 12.f, 48.f, 18.f, 48.f, 23.f, 44.f, 25.f, 55.f, 27.f, 48.f, 32.f, 44.f, 33.f, 44.f, 37.f, 47.f, 44.f, 44.f, 45.f, 44.f, 49.f, 47.f, 55.f, 55.f, 59.f, 45.f, 70.f, 42.f, 77.f, 45.f, 82.f, 45.f, 90.f, 55.f,
-    1.f, 65.f,  9.f, 65.f, 14.f, 62.f, 22.f, 65.f, 30.f, 75.f,
-    87.f, 85.f, 79.f, 82.f, 74.f, 85.f, 66.f, 85.f, 61.f, 95.f, 53.f, 85.f, 48.f, 85.f, 41.f, 82.f, 32.f, 85.f, 27.f, 95.f, 20.f, 87.f, 15.f, 89.f,  8.f, 88.f,  5.f, 88.f,  4.f, 84.f,  0.f, 95.f,
-    28.f, 108.f, 27.f, 104.f, 22.f, 104.f, 17.f, 107.f, 15.f, 104.f, 10.f, 104.f,  5.f, 107.f,  2.f, 113.f
+    1.f, -10.f, 12.f, -13.f, 19.f, -10.f, 24.f, -10.f, 32.f, -0.f, 37.f, -10.f, 45.f, -10.f, 50.f, -13.f, 58.f, -10.f, 66.f, -0.f, 69.f, -8.f, 76.f, -6.f, 81.f, -7.f, 87.f, -7.f, 92.f, -11.f, 94.f, -0.f,
+    0.f, -7.f, 5.f, -11.f, 6.f, -11.f, 10.f, -8.f, 17.f, -11.f, 18.f, -11.f, 22.f, -8.f, 28.f, -0.f,
+    0.f, -8.f, 7.f, -6.f, 12.f, -7.f, 18.f, -7.f, 23.f, -11.f, 25.f, -0.f, 27.f, -7.f, 32.f, -11.f, 33.f, -11.f, 37.f, -8.f, 44.f, -11.f, 45.f, -11.f, 49.f, -8.f, 55.f, -0.f, 59.f, -10.f, 70.f, -13.f, 77.f, -10.f, 82.f, -10.f, 90.f, -0.f,
+    1.f, -10.f, 9.f, -10.f, 14.f, -13.f, 22.f, -10.f, 30.f, -0.f,
+    87.f, -10.f, 79.f, -13.f, 74.f, -10.f, 66.f, -10.f, 61.f, -0.f, 53.f, -10.f, 48.f, -10.f, 41.f, -13.f, 32.f, -10.f, 27.f, -0.f, 20.f, -8.f, 15.f, -6.f, 8.f, -7.f, 5.f, -7.f, 4.f, -11.f, 0.f, -0.f,
+    28.f, -7.f, 27.f, -11.f, 22.f, -11.f, 17.f, -8.f, 15.f, -11.f, 10.f, -11.f, 5.f, -8.f, 2.f, -2.f,
   };
 
   Size textArea( 100.f, 300.f );
index fe6d4cb..115a0d1 100644 (file)
@@ -80,10 +80,11 @@ bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
                    logicalModel,
                    visualModel );
 
-  // 2) Clear the model.
   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
 
+  // 2) Clear the model.
+
   GlyphIndex startGlyphIndex = 0u;
   if( 0u != charactersToGlyph.Count() )
   {
@@ -159,10 +160,11 @@ bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
                    logicalModel,
                    visualModel );
 
-  // 2) Clear the model.
   Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
   Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
 
+  // 2) Clear the model.
+
   GlyphIndex startGlyphIndex = 0u;
   if( 0u != charactersToGlyph.Count() )
   {
index bf5f24b..15ffd4c 100644 (file)
@@ -15,6 +15,7 @@ SET(TC_SOURCES
    utc-Dali-ConfirmationPopup.cpp
    utc-Dali-CubeTransitionEffect.cpp
    utc-Dali-EffectsView.cpp
+   utc-Dali-FlexContainer.cpp
    utc-Dali-GaussianBlurView.cpp
    utc-Dali-ImageView.cpp
    utc-Dali-JsonParser.cpp
@@ -35,7 +36,6 @@ SET(TC_SOURCES
    utc-Dali-Button.cpp
    utc-Dali-Control.cpp
    utc-Dali-ControlImpl.cpp
-   utc-Dali-DefaultControls.cpp
    utc-Dali-AccessibilityManager.cpp
    utc-Dali-ItemLayout.cpp
    utc-Dali-ItemView.cpp
@@ -57,28 +57,31 @@ SET(TC_SOURCES
 
 # Append list of test harness files (Won't get parsed for test cases)
 LIST(APPEND TC_SOURCES
-   dali-toolkit-test-utils/test-harness.cpp
    dali-toolkit-test-utils/toolkit-accessibility-adaptor.cpp
    dali-toolkit-test-utils/toolkit-application.cpp
    dali-toolkit-test-utils/toolkit-clipboard.cpp
+   dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
    dali-toolkit-test-utils/toolkit-event-thread-callback.cpp
    dali-toolkit-test-utils/toolkit-environment-variable.cpp
    dali-toolkit-test-utils/toolkit-imf-manager.cpp
+   dali-toolkit-test-utils/toolkit-orientation.cpp
    dali-toolkit-test-utils/toolkit-physical-keyboard.cpp
    dali-toolkit-test-utils/toolkit-style-monitor.cpp
    dali-toolkit-test-utils/toolkit-singleton-service.cpp
    dali-toolkit-test-utils/toolkit-timer.cpp
-   dali-toolkit-test-utils/toolkit-clipboard-event-notifier.cpp
    dali-toolkit-test-utils/toolkit-tts-player.cpp
-   dali-toolkit-test-utils/dummy-control.cpp
    dali-toolkit-test-utils/dali-test-suite-utils.cpp
+   dali-toolkit-test-utils/dummy-control.cpp
+   dali-toolkit-test-utils/mesh-builder.cpp
+   dali-toolkit-test-utils/test-actor-utils.cpp
    dali-toolkit-test-utils/test-animation-data.cpp
-   dali-toolkit-test-utils/test-button.cpp
    dali-toolkit-test-utils/test-application.cpp
-   dali-toolkit-test-utils/test-platform-abstraction.cpp
+   dali-toolkit-test-utils/test-button.cpp
+   dali-toolkit-test-utils/test-harness.cpp
    dali-toolkit-test-utils/test-gesture-manager.cpp
    dali-toolkit-test-utils/test-gl-abstraction.cpp
    dali-toolkit-test-utils/test-gl-sync-abstraction.cpp
+   dali-toolkit-test-utils/test-platform-abstraction.cpp
    dali-toolkit-test-utils/test-render-controller.cpp
    dali-toolkit-test-utils/test-trace-call-stack.cpp
    dali-toolkit-test-utils/test-native-image.cpp
index c521fbf..baeaa6a 100644 (file)
@@ -29,6 +29,7 @@ void tet_infoline(const char*str);
 void tet_printf(const char *format, ...);
 
 #include "test-application.h"
+#include "test-actor-utils.h"
 
 using namespace Dali;
 
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/mesh-builder.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/mesh-builder.cpp
new file mode 100644 (file)
index 0000000..304e567
--- /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.
+ *
+ */
+#include "mesh-builder.h"
+
+namespace Dali
+{
+
+Shader CreateShader()
+{
+  return Shader::New( "vertexSrc", "fragmentSrc" );
+}
+
+TextureSet CreateTextureSet()
+{
+  return TextureSet::New();
+}
+TextureSet CreateTextureSet( Image image )
+{
+  TextureSet textureSet = TextureSet::New();
+  textureSet.SetImage( 0u, image );
+  return textureSet;
+}
+
+PropertyBuffer CreatePropertyBuffer()
+{
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer vertexData = PropertyBuffer::New( texturedQuadVertexFormat );
+  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, 4);
+
+  unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
+  Property::Map indexFormat;
+  indexFormat["indices"] = Property::INTEGER;
+  PropertyBuffer indices = PropertyBuffer::New( indexFormat );
+  indices.SetData( indexData, sizeof(indexData)/sizeof(indexData[0]) );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexData );
+  geometry.SetIndexBuffer( indices );
+
+  return geometry;
+}
+
+
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/mesh-builder.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/mesh-builder.h
new file mode 100644 (file)
index 0000000..bf5f6a6
--- /dev/null
@@ -0,0 +1,39 @@
+#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/texture-set.h>
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/devel-api/rendering/renderer.h>
+
+namespace Dali
+{
+
+Shader CreateShader();
+TextureSet CreateTextureSet();
+TextureSet CreateTextureSet( Image image );
+Geometry CreateQuadGeometry();
+Geometry CreateQuadGeometryFromBuffer( PropertyBuffer vertexData );
+PropertyBuffer CreatePropertyBuffer();
+
+}
+
+#endif // MESH_BUILDER_H
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.cpp
new file mode 100644 (file)
index 0000000..2f833c6
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "test-actor-utils.h"
+#include "mesh-builder.h"
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/rendering/renderer.h>
+
+namespace Dali
+{
+
+namespace
+{
+const char * const TEXTURE_UNIFORM_NAME( "sTexture" );
+
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+  attribute mediump vec2 aPosition;\n
+  uniform mediump mat4 uMvpMatrix;\n
+  uniform mediump vec3 uSize;\n
+  \n
+  void main()\n
+  {\n
+    mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
+    vertexPosition.xyz *= uSize;\n
+    gl_Position = uMvpMatrix * vertexPosition;\n
+  }\n
+);
+
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+  uniform lowp vec4 uColor;\n
+  \n
+  void main()\n
+  {\n
+    gl_FragColor = uColor;\n
+  }\n
+);
+
+} // unnamed namespace
+
+Actor CreateRenderableActor()
+{
+  return CreateRenderableActor( Image(), VERTEX_SHADER, FRAGMENT_SHADER );
+}
+
+Actor CreateRenderableActor( Image texture )
+{
+  return CreateRenderableActor( texture, VERTEX_SHADER, FRAGMENT_SHADER );
+}
+
+Actor CreateRenderableActor( Image texture, const std::string& vertexShader, const std::string& fragmentShader )
+{
+  // Create the geometry
+  Geometry geometry = CreateQuadGeometry();
+
+  // Create Shader
+  Shader shader = Shader::New( vertexShader, fragmentShader );
+
+  // Create renderer from geometry and material
+  Renderer renderer = Renderer::New( geometry, shader );
+
+  // Create actor and set renderer
+  Actor actor = Actor::New();
+  actor.AddRenderer( renderer );
+
+  // If we a texture, then create a texture-set and add to renderer
+  if( texture )
+  {
+    TextureSet textureSet = TextureSet::New();
+    textureSet.SetImage( 0u, texture );
+    renderer.SetTextures( textureSet );
+
+    // Set actor to the size of the texture if set
+    actor.SetSize( texture.GetWidth(), texture.GetHeight() );
+  }
+
+  return actor;
+}
+
+Image GetTexture( Actor actor )
+{
+  Image image;
+  if( actor && actor.GetRendererCount() )
+  {
+    Renderer renderer = actor.GetRendererAt( 0u );
+    if( renderer )
+    {
+      TextureSet textureSet = renderer.GetTextures();
+      if( textureSet && textureSet.GetTextureCount() )
+      {
+        image = textureSet.GetImage( 0u );
+      }
+    }
+  }
+
+  return image;
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h
new file mode 100644 (file)
index 0000000..c5c5d0a
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __DALI_TEST_ACTOR_UTILS_H__
+#define __DALI_TEST_ACTOR_UTILS_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
+{
+
+class Actor;
+class Image;
+
+/**
+ * @brief Creates a simple renderable-actor with solid colored quad.
+ * @return An actor with a renderer.
+ */
+Actor CreateRenderableActor();
+
+/**
+ * @brief Creates a renderable-actor with a texture.
+ * @param[in] texture Texture to set.
+ * @return An actor with a renderer.
+ */
+Actor CreateRenderableActor( Image texture );
+
+/**
+ * @brief Creates a renderable-actor with a texture and custom shaders.
+ * @param[in] texture Texture to set.
+ * @param[in] vertexShader The vertex-shader.
+ * @param[in] fragmentShader The fragment-shader.
+ * @return An actor with a renderer.
+ */
+Actor CreateRenderableActor( Image texture, const std::string& vertexShader, const std::string& fragmentShader );
+
+/**
+ * @brief Retrieves the texture used in a renderable actor (if available).
+ * @return The texture used by the actor.
+ * @note Assumes the actor only has one renderer, and that renderer only has one texture.
+ */
+Image GetTexture( Actor actor );
+
+} // namespace Dali
+
+#endif // __DALI_TEST_ACTOR_UTILS_H__
index 5fb6e11..3f7318a 100644 (file)
@@ -154,13 +154,13 @@ void TestApplication::SetSurfaceWidth( unsigned int width, unsigned height )
   mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
 }
 
-void TestApplication::DoUpdate( unsigned int intervalMilliseconds )
+void TestApplication::DoUpdate( unsigned int intervalMilliseconds, const char* location )
 {
   if( GetUpdateStatus() == 0 &&
       mRenderStatus.NeedsUpdate() == false &&
       ! GetRenderController().WasCalled(TestRenderController::RequestUpdateFunc) )
   {
-    fprintf(stderr, "WARNING - Update not required\n");
+    fprintf(stderr, "WARNING - Update not required :%s\n", location==NULL?"NULL":location);
   }
 
   unsigned int nextVSyncTime = mLastVSyncTime + intervalMilliseconds;
@@ -173,9 +173,9 @@ void TestApplication::DoUpdate( unsigned int intervalMilliseconds )
   mLastVSyncTime = nextVSyncTime;
 }
 
-bool TestApplication::Render( unsigned int intervalMilliseconds  )
+bool TestApplication::Render( unsigned int intervalMilliseconds, const char* location )
 {
-  DoUpdate( intervalMilliseconds );
+  DoUpdate( intervalMilliseconds, location );
   mCore->Render( mRenderStatus );
 
   mFrame++;
@@ -216,6 +216,7 @@ bool TestApplication::RenderOnly( )
 void TestApplication::ResetContext()
 {
   mCore->ContextDestroyed();
+  mGlAbstraction.Initialize();
   mCore->ContextCreated();
 }
 
index cb5a92c..1f1161a 100644 (file)
@@ -73,7 +73,7 @@ public:
   void ProcessEvent(const Integration::Event& event);
   void SendNotification();
   void SetSurfaceWidth( unsigned int width, unsigned height );
-  bool Render( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
+  bool Render( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL, const char* location=NULL );
   unsigned int GetUpdateStatus();
   bool UpdateOnly( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
   bool RenderOnly( );
@@ -82,7 +82,7 @@ public:
   bool GetRenderHasRendered();
 
 private:
-  void DoUpdate( unsigned int intervalMilliseconds );
+  void DoUpdate( unsigned int intervalMilliseconds, const char* location=NULL );
 
 protected:
   TestPlatformAbstraction   mPlatformAbstraction;
index 4a12bdb..d42a548 100644 (file)
@@ -32,7 +32,7 @@ void TestGlAbstraction::Initialize()
   mCurrentProgram = 0;
   mCompileStatus = GL_TRUE;
   mLinkStatus = GL_TRUE;
-
+  mNumberOfActiveUniforms = 0;
   mGetAttribLocationResult = 0;
   mGetErrorResult = 0;
   mGetStringResult = NULL;
@@ -78,6 +78,13 @@ void TestGlAbstraction::Initialize()
   mProgramUniforms3f.clear();
   mProgramUniforms4f.clear();
 
+  mCullFaceTrace.Reset();
+  mEnableDisableTrace.Reset();
+  mShaderTrace.Reset();
+  mTextureTrace.Reset();
+  mTexParamaterTrace.Reset();
+  mDrawTrace.Reset();
+
   for( unsigned int i=0; i<MAX_ATTRIBUTE_CACHE_SIZE; ++i )
   {
     mVertexAttribArrayState[i] = false;
index 3d35394..1fe97c1 100644 (file)
@@ -556,6 +556,21 @@ public:
 
   inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
   {
+    switch(index)
+    {
+      case 0:
+        *length = snprintf(name, bufsize, "sTexture");
+        *type = GL_SAMPLER_2D;
+        *size = 1;
+        break;
+      case 1:
+        *length = snprintf(name, bufsize, "sEffect");
+        *type = GL_SAMPLER_2D;
+        *size = 1;
+        break;
+      default:
+        break;
+    }
   }
 
   inline void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
@@ -620,13 +635,20 @@ public:
 
   inline void GetProgramiv(GLuint program, GLenum pname, GLint* params)
   {
-    switch( pname ) {
+    switch( pname )
+    {
       case GL_LINK_STATUS:
         *params = mLinkStatus;
         break;
       case GL_PROGRAM_BINARY_LENGTH_OES:
         *params = mProgramBinaryLength;
         break;
+      case GL_ACTIVE_UNIFORMS:
+        *params = mNumberOfActiveUniforms;
+        break;
+      case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+        *params = 100;
+        break;
     }
   }
 
@@ -634,7 +656,6 @@ public:
   {
   }
 
-
   inline void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
   {
   }
@@ -759,6 +780,10 @@ public:
     std::stringstream out;
     out << program;
     mShaderTrace.PushCall("LinkProgram", out.str());
+
+    mNumberOfActiveUniforms=2;
+    GetUniformLocation(program, "sTexture");
+    GetUniformLocation(program, "sEffect");
   }
 
   inline void PixelStorei(GLenum pname, GLint param)
@@ -1769,6 +1794,7 @@ private:
   BufferDataCalls mBufferDataCalls;
   BufferSubDataCalls mBufferSubDataCalls;
   GLuint     mLinkStatus;
+  GLint      mNumberOfActiveUniforms;
   GLint      mGetAttribLocationResult;
   GLenum     mGetErrorResult;
   GLubyte*   mGetStringResult;
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-intrusive-ptr.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-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
+
+
index d8ad2ba..135476e 100644 (file)
@@ -29,7 +29,7 @@ TestNativeImagePointer TestNativeImage::New(int width, int height)
 }
 
 TestNativeImage::TestNativeImage(int width, int height)
-: mWidth(width), mHeight(height), mExtensionCreateCalls(0), mExtensionDestroyCalls(0), mTargetTextureCalls(0)
+: mWidth(width), mHeight(height), mExtensionCreateCalls(0), mExtensionDestroyCalls(0), mTargetTextureCalls(0),createResult(true)
 {
   mExtension = new TestNativeImageExtension();
 }
index 8dc6431..f361280 100644 (file)
@@ -40,7 +40,8 @@ class DALI_IMPORT_API TestNativeImage : public Dali::NativeImageInterface
 public:
   static TestNativeImagePointer New(int width, int height);
 
-  inline virtual bool GlExtensionCreate() { ++mExtensionCreateCalls; return true;};
+  inline void SetGlExtensionCreateResult(bool result){ createResult = result;}
+  inline virtual bool GlExtensionCreate() { ++mExtensionCreateCalls; return createResult;};
   inline virtual void GlExtensionDestroy() { ++mExtensionDestroyCalls; };
   inline virtual GLenum TargetTexture() { ++mTargetTextureCalls; return 1;};
   inline virtual void PrepareTexture() {};
@@ -59,6 +60,8 @@ public:
   int mExtensionCreateCalls;
   int mExtensionDestroyCalls;
   int mTargetTextureCalls;
+
+  bool createResult;
   TestNativeImageExtension* mExtension;
 };
 
index 973f24a..2f62474 100644 (file)
@@ -188,7 +188,8 @@ bool TestPlatformAbstraction::WasCalled(TestFuncEnum func)
   {
     case SuspendFunc:                         return mTrace.FindMethod("Suspend");
     case ResumeFunc:                          return mTrace.FindMethod("Resume");
-    case LoadResourceFunc:                    return mTrace.FindMethod("LoadResource") || mTrace.FindMethod("LoadResourceSynchronously");
+    case LoadResourceFunc:                    return mTrace.FindMethod("LoadResource");
+    case LoadResourceSynchronouslyFunc:       return mTrace.FindMethod("LoadResourceSynchronously");
     case LoadFileFunc:                        return mTrace.FindMethod("LoadFile");
     case LoadShaderBinaryFileFunc:            return mTrace.FindMethod("LoadShaderBinaryFile");
     case SaveShaderBinaryFileFunc:            return mTrace.FindMethod("SaveShaderBinaryFile");
index a728ac2..d7e0563 100644 (file)
@@ -171,6 +171,7 @@ public: // TEST FUNCTIONS
     SuspendFunc,
     ResumeFunc,
     LoadResourceFunc,
+    LoadResourceSynchronouslyFunc,
     SaveFileFunc,
     LoadFileFunc,
     LoadShaderBinaryFileFunc,
index 3c83f7e..40280a0 100644 (file)
@@ -68,13 +68,4 @@ private:
 
 } // namespace Dali
 
-inline ImageActor CreateSolidColorImageActor(ToolkitTestApplication& application, const Vector4& color, int width, int height)
-{
-  ImageActor actor = ImageActor::New(CreateBufferImage(width, height, color));
-  application.SendNotification();
-  application.Render();
-  return actor;
-}
-
-
 #endif // __DALI_TOOLKIT_TEST_APPLICATION_H__
index 8b06fd1..2fb0f0c 100644 (file)
@@ -426,13 +426,13 @@ int UtcDaliBuilderConstantsP(void)
       "},"
       "\"stage\":"
       "[{"
-      "  \"type\": \"ImageActor\","
+      "  \"type\": \"ImageView\","
       "  \"name\": \"{NAME}\","
       "  \"size\": [100,100,1],"
       "  \"parentOrigin\": \"TOP_LEFT\","
       "  \"anchorPoint\": \"{ANCHOR}\","
       "  \"padding\": \"{PADDING}\","
-      "  \"image\": { \"filename\": \"dir/{IMAGE_PATH}\" },"
+      "  \"image\": { \"imageUrl\": \"dir/{IMAGE_PATH}\" },"
       "  \"sizeWidth\": \"{WIDTH}\","
       "  \"signals\": [{"
       "    \"name\": \"touched\","
@@ -496,7 +496,7 @@ int UtcDaliBuilderTemplatesAndStylesP(void)
       "\"templates\":\n"
       "{\n"
       "  \"imageTree\": { \n"
-      "    \"type\": \"ImageActor\",\n"
+      "    \"type\": \"ImageView\",\n"
       "    \"styles\": [\"imageStyle\"],\n"
       "    \"name\": \"image\",\n"
       "    \"size\": \"{SIZE}\",\n"
@@ -506,7 +506,7 @@ int UtcDaliBuilderTemplatesAndStylesP(void)
       "    }],\n"
       "    \"actors\": [\n"
       "      {\n"
-      "        \"type\":\"ImageActor\",\n"
+      "        \"type\":\"ImageView\",\n"
       "        \"name\":\"childImage\" \n"
       "      }\n"
       "    ]\n"
@@ -533,7 +533,7 @@ int UtcDaliBuilderTemplatesAndStylesP(void)
 
   std::string templatejson(
     "{ \n"
-    "  \"type\": \"ImageActor\",\n"
+    "  \"type\": \"ImageView\",\n"
     "  \"styles\": [\"imageStyle\"],\n"
     "  \"name\": \"image\",\n"
     "  \"size\": \"{SIZE}\",\n"
@@ -543,7 +543,7 @@ int UtcDaliBuilderTemplatesAndStylesP(void)
     "  }],\n"
     "  \"actors\": [\n"
     "    {\n"
-    "      \"type\":\"ImageActor\",\n"
+    "      \"type\":\"ImageView\",\n"
     "      \"name\":\"childImage\" \n"
     "    }\n"
     "  ]\n"
@@ -553,16 +553,16 @@ int UtcDaliBuilderTemplatesAndStylesP(void)
   Builder builder = Builder::New();
   builder.LoadFromString( json );
 
-  ImageActor actor = ImageActor::DownCast( builder.Create( "imageTree" ) );
+  ImageView actor = ImageView::DownCast( builder.Create( "imageTree" ) );
   DALI_TEST_CHECK( actor );
 
   Dali::Property::Map map;
   map["SIZE"] = Vector3(100,100,1);
-  actor = ImageActor::DownCast( builder.Create( "imageTree",  map ) );
+  actor = ImageView::DownCast( builder.Create( "imageTree",  map ) );
   DALI_TEST_CHECK( actor );
 
   // create from json snippet
-  actor = ImageActor::DownCast( builder.CreateFromJson( templatejson ) );
+  actor = ImageView::DownCast( builder.CreateFromJson( templatejson ) );
   DALI_TEST_CHECK( actor );
 
 
@@ -596,7 +596,7 @@ int UtcDaliBuilderRenderTasksP(void)
       "    \"name\": \"image\"\n"
       "  }, \n"
       "  { \n"
-      "    \"type\": \"ImageActor\",\n"
+      "    \"type\": \"ImageView\",\n"
       "    \"name\": \"image\",\n"
       "    \"size\": [100,100,1],\n"
       "    \"signals\": [{\n"
@@ -605,7 +605,7 @@ int UtcDaliBuilderRenderTasksP(void)
       "    }],\n"
       "    \"actors\": [\n"
       "      {\n"
-      "        \"type\":\"ImageActor\",\n"
+      "        \"type\":\"ImageView\",\n"
       "        \"name\":\"childImage\" \n"
       "      }\n"
       "    ]\n"
@@ -856,7 +856,7 @@ int UtcDaliBuilderCustomPropertyP(void)
       "\"templates\":\n"
       "{\n"
       "  \"imageTree\": { \n"
-      "    \"type\": \"ImageActor\",\n"
+      "    \"type\": \"ImageView\",\n"
       "    \"name\": \"image\",\n"
       "    \"size\": [100,100,1],\n"
       "    \"signals\": [{\n"
@@ -868,7 +868,7 @@ int UtcDaliBuilderCustomPropertyP(void)
       "    },\n"
       "    \"actors\": [\n"
       "      {\n"
-      "        \"type\":\"ImageActor\",\n"
+      "        \"type\":\"ImageView\",\n"
       "        \"name\":\"childImage\" \n"
       "      }\n"
       "    ]\n"
@@ -880,7 +880,7 @@ int UtcDaliBuilderCustomPropertyP(void)
   Builder builder = Builder::New();
   builder.LoadFromString( json );
 
-  ImageActor actor = ImageActor::DownCast( builder.Create( "imageTree" ) );
+  ImageView actor = ImageView::DownCast( builder.Create( "imageTree" ) );
   DALI_TEST_CHECK( actor );
 
   // NB: already applied in create
@@ -901,7 +901,7 @@ int UtcDaliBuilderShaderEffectP(void)
     "{\n"
     "  \"stage\": [\n"
     "    {\n"
-    "      \"type\": \"ImageActor\",\n"
+    "      \"type\": \"ImageView\",\n"
     "      \"name\": \"Image1\",\n"
     "      \"position\": [\n"
     "        0.40461349487305,\n"
@@ -1028,7 +1028,7 @@ int UtcDaliBuilderShaderEffect2P(void)
     "\"templates\":\n"
     "{\n"
     "  \"imageTree\": { \n"
-    "    \"type\": \"ImageActor\",\n"
+    "    \"type\": \"ImageView\",\n"
     "    \"size\": [100,100,1],\n"
     "    \"parentOrigin\": [0.5, 0.5, 0.5],\n"
     "    \"position\": [\n"
@@ -1042,7 +1042,7 @@ int UtcDaliBuilderShaderEffect2P(void)
     "    }],\n"
     "    \"actors\": [\n"
     "      {\n"
-    "        \"type\":\"ImageActor\",\n"
+    "        \"type\":\"ImageView\",\n"
     "        \"name\":\"childImage\" \n"
     "      }\n"
     "    ]\n"
@@ -1154,7 +1154,7 @@ int UtcDaliBuilderFrameBufferP(void)
     "  },\n"
     "  \"stage\": [\n"
     "    {\n"
-    "      \"type\": \"ImageActor\",\n"
+    "      \"type\": \"ImageView\",\n"
     "      \"name\": \"fbOnStage\",\n"
     "      \"position\": [\n"
     "        0.40461349487305,\n"
@@ -1167,17 +1167,13 @@ int UtcDaliBuilderFrameBufferP(void)
     "      \"clearColor\": [1,0,0,1]\n"
     "    },\n"
     "    {\n"
-    "      \"type\": \"ImageActor\",\n"
+    "      \"type\": \"ImageView\",\n"
     "      \"name\": \"Image1\",\n"
     "      \"size\": [200, 200, 0],\n"
     "      \"parentOrigin\": [0.5, 0.5, 0.5],\n"
     "      \"effect\": \"Ripple2D\",\n"
     "      \"image\": {\n"
-    "        \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
-    "        \"width\": 200,\n"
-    "        \"height\": 80,\n"
-    "        \"loadPolicy\": \"IMMEDIATE\",\n"
-    "        \"releasePolicy\": \"NEVER\"\n"
+    "        \"imageUrl\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\"\n"
     "      },\n"
     "      \"signals\": [\n"
     "        {\n"
@@ -1294,17 +1290,13 @@ int UtcDaliBuilderPathConstraintsP(void)
     "  },\n"
     "  \"stage\": [\n"
     "    {\n"
-    "      \"type\": \"ImageActor\",\n"
+    "      \"type\": \"ImageView\",\n"
     "      \"name\": \"Image1\",\n"
     "      \"size\": [200, 200, 0],\n"
     "      \"parentOrigin\": [0.5, 0.5, 0.5],\n"
     "      \"effect\": \"Ripple2D\",\n"
     "      \"image\": {\n"
-    "        \"filename\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\",\n"
-    "        \"width\": 200,\n"
-    "        \"height\": 80,\n"
-    "        \"loadPolicy\": \"IMMEDIATE\",\n"
-    "        \"releasePolicy\": \"NEVER\"\n"
+    "        \"imageUrl\": \"{DALI_IMAGE_DIR}gallery-medium-25.jpg\"\n"
     "      },\n"
     "      \"signals\": [\n"
     "        {\n"
index 28bb29a..9a89c9c 100644 (file)
@@ -18,7 +18,7 @@
 #include <stdlib.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali/devel-api/rendering/renderer.h>
-#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/texture-set.h>
 #include <dali/devel-api/rendering/shader.h>
 #include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
 
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-DefaultControls.cpp b/automated-tests/src/dali-toolkit/utc-Dali-DefaultControls.cpp
deleted file mode 100644 (file)
index b65fc34..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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>
-
-// Need to override adaptor classes for toolkit test harness, so include
-// test harness headers before dali headers.
-#include <dali-toolkit-test-suite-utils.h>
-
-#include <dali.h>
-#include <dali-toolkit/dali-toolkit.h>
-
-using namespace Dali;
-using namespace Toolkit;
-
-void utc_dali_toolkit_default_controls_startup(void)
-{
-  test_return_value = TET_UNDEF;
-}
-
-void utc_dali_toolkit_default_controls_cleanup(void)
-{
-  test_return_value = TET_PASS;
-}
-
-int UtcDaliDefaultControlsCreateSolidColorActor(void)
-{
-  ToolkitTestApplication application;
-
-  tet_infoline(" UtcDaliDefaultControlsCreateSolidColorActor");
-
-  ImageActor image1 = CreateSolidColorActor( Color::RED );
-  ImageActor image2 = CreateSolidColorActor( Color::RED, true, Color::BLUE, 2 );
-  ImageActor image3 = CreateSolidColorActor( Color::RED, true, Color::BLUE, 12 );
-
-  DALI_TEST_CHECK(image1);
-  DALI_TEST_CHECK(image2);
-  DALI_TEST_CHECK(!image3);
-  END_TEST;
-}
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-FlexContainer.cpp b/automated-tests/src/dali-toolkit/utc-Dali-FlexContainer.cpp
new file mode 100644 (file)
index 0000000..a2009d0
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <dali-toolkit/devel-api/controls/flex-container/flex-container.h>
+
+using namespace Dali;
+using namespace Toolkit;
+
+void dali_flexflexContainer_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void dali_flexflexContainer_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+const char* const PROPERTY_NAME_CONTENT_DIRECTION = "contentDirection";
+const char* const PROPERTY_NAME_FLEX_DIRECTION = "flexDirection";
+const char* const PROPERTY_NAME_FLEX_WRAP = "flexWrap";
+const char* const PROPERTY_NAME_JUSTIFY_CONTENT = "justifyContent";
+const char* const PROPERTY_NAME_ALIGN_ITEMS = "alignItems";
+const char* const PROPERTY_NAME_ALIGN_CONTENT =  "alignContent";
+
+} // namespace
+
+int UtcDaliToolkitFlexContainerConstructorP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerConstructorP");
+  FlexContainer flexContainer;
+  DALI_TEST_CHECK( !flexContainer );
+  END_TEST;
+}
+
+int UtcDaliToolkitFlexContainerNewP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerNewP");
+  FlexContainer flexContainer = FlexContainer::New();
+  DALI_TEST_CHECK( flexContainer );
+  END_TEST;
+}
+
+int UtcDaliToolkitFlexContainerDownCastP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerDownCastP");
+  FlexContainer flexContainer1 = FlexContainer::New();
+  BaseHandle object( flexContainer1 );
+
+  FlexContainer flexContainer2 = FlexContainer::DownCast( object );
+  DALI_TEST_CHECK( flexContainer2 );
+
+  FlexContainer flexContainer3 = DownCast< FlexContainer >( object );
+  DALI_TEST_CHECK( flexContainer3 );
+  END_TEST;
+}
+
+int UtcDaliToolkitFlexContainerDownCastN(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerDownCastN");
+  BaseHandle uninitializedObject;
+  FlexContainer flexContainer1 = FlexContainer::DownCast( uninitializedObject );
+  DALI_TEST_CHECK( !flexContainer1 );
+
+  FlexContainer flexContainer2 = DownCast< FlexContainer >( uninitializedObject );
+  DALI_TEST_CHECK( !flexContainer2 );
+  END_TEST;
+}
+
+int UtcDaliToolkitFlexContainerCopyConstructorP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerCopyConstructorP");
+  FlexContainer flexContainer = FlexContainer::New();
+  flexContainer.SetProperty( FlexContainer::Property::FLEX_DIRECTION, FlexContainer::ROW_REVERSE );
+
+  FlexContainer copy( flexContainer );
+  DALI_TEST_CHECK( copy );
+  DALI_TEST_CHECK( copy.GetProperty<int>( FlexContainer::Property::FLEX_DIRECTION ) == flexContainer.GetProperty<int>( FlexContainer::Property::FLEX_DIRECTION ) );
+
+  END_TEST;
+}
+
+int UtcDaliToolkitFlexContainerAssignmentOperatorP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerAssingmentOperatorP");
+  FlexContainer flexContainer = FlexContainer::New();
+  flexContainer.SetProperty( FlexContainer::Property::FLEX_DIRECTION, FlexContainer::ROW_REVERSE );
+
+  FlexContainer copy = flexContainer;
+  DALI_TEST_CHECK( copy );
+  DALI_TEST_CHECK( copy.GetProperty<int>( FlexContainer::Property::FLEX_DIRECTION ) == flexContainer.GetProperty<int>( FlexContainer::Property::FLEX_DIRECTION ) );
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliToolkitFlexContainerGetPropertyP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerGetPropertyP");
+  FlexContainer flexContainer = FlexContainer::New();
+  DALI_TEST_CHECK( flexContainer );
+
+  // Check Property Indices are correct
+  DALI_TEST_CHECK( flexContainer.GetPropertyIndex( PROPERTY_NAME_CONTENT_DIRECTION ) == FlexContainer::Property::CONTENT_DIRECTION );
+  DALI_TEST_CHECK( flexContainer.GetPropertyIndex( PROPERTY_NAME_FLEX_DIRECTION ) == FlexContainer::Property::FLEX_DIRECTION );
+  DALI_TEST_CHECK( flexContainer.GetPropertyIndex( PROPERTY_NAME_FLEX_WRAP ) == FlexContainer::Property::FLEX_WRAP );
+  DALI_TEST_CHECK( flexContainer.GetPropertyIndex( PROPERTY_NAME_JUSTIFY_CONTENT ) == FlexContainer::Property::JUSTIFY_CONTENT );
+  DALI_TEST_CHECK( flexContainer.GetPropertyIndex( PROPERTY_NAME_ALIGN_ITEMS ) == FlexContainer::Property::ALIGN_ITEMS );
+  DALI_TEST_CHECK( flexContainer.GetPropertyIndex( PROPERTY_NAME_ALIGN_CONTENT ) == FlexContainer::Property::ALIGN_CONTENT );
+
+  END_TEST;
+}
+
+int UtcDaliToolkitFlexContainerSetPropertyP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitFlexContainerSetPropertyP");
+  FlexContainer flexContainer = FlexContainer::New();
+  DALI_TEST_CHECK( flexContainer );
+
+  // Check content direction property.
+  flexContainer.SetProperty( FlexContainer::Property::CONTENT_DIRECTION, FlexContainer::RTL );
+  DALI_TEST_EQUALS( (FlexContainer::ContentDirection)flexContainer.GetProperty<int>( FlexContainer::Property::CONTENT_DIRECTION ), FlexContainer::RTL, TEST_LOCATION );
+
+  // Check flex direction property.
+  flexContainer.SetProperty( FlexContainer::Property::FLEX_DIRECTION, FlexContainer::COLUMN_REVERSE );
+  DALI_TEST_EQUALS( (FlexContainer::FlexDirection)flexContainer.GetProperty<int>( FlexContainer::Property::FLEX_DIRECTION ), FlexContainer::COLUMN_REVERSE, TEST_LOCATION );
+
+  // Check flex wrap property.
+  flexContainer.SetProperty( FlexContainer::Property::FLEX_WRAP, FlexContainer::WRAP );
+  DALI_TEST_EQUALS( (FlexContainer::WrapType)flexContainer.GetProperty<int>( FlexContainer::Property::FLEX_WRAP ), FlexContainer::WRAP, TEST_LOCATION );
+
+  // Check justify content property.
+  flexContainer.SetProperty( FlexContainer::Property::JUSTIFY_CONTENT, FlexContainer::JUSTIFY_SPACE_BETWEEN );
+  DALI_TEST_EQUALS( (FlexContainer::Justification)flexContainer.GetProperty<int>( FlexContainer::Property::JUSTIFY_CONTENT ), FlexContainer::JUSTIFY_SPACE_BETWEEN, TEST_LOCATION );
+
+  // Check align items property.
+  flexContainer.SetProperty( FlexContainer::Property::ALIGN_ITEMS, FlexContainer::ALIGN_FLEX_START );
+  DALI_TEST_EQUALS( (FlexContainer::Alignment)flexContainer.GetProperty<int>( FlexContainer::Property::ALIGN_ITEMS ), FlexContainer::ALIGN_FLEX_START, TEST_LOCATION );
+
+  // Check align content property.
+  flexContainer.SetProperty( FlexContainer::Property::ALIGN_CONTENT, FlexContainer::ALIGN_STRETCH );
+  DALI_TEST_EQUALS( (FlexContainer::Alignment)flexContainer.GetProperty<int>( FlexContainer::Property::ALIGN_CONTENT ), FlexContainer::ALIGN_STRETCH, TEST_LOCATION );
+
+  END_TEST;
+}
+
index c85bffd..4ee76fb 100644 (file)
@@ -74,7 +74,7 @@ public: // From ItemFactory
   {
     // Create an image actor for this item
     Image image = ResourceImage::New( TEST_IMAGE_FILE_NAME );
-    Actor actor = ImageActor::New(image);
+    Actor actor = CreateRenderableActor(image);
 
     return actor;
   }
index 2cbd51b..1f96f1b 100644 (file)
@@ -115,7 +115,7 @@ public: // From ItemFactory
   {
     // Create an image actor for this item
     Image image = ResourceImage::New( TEST_IMAGE_FILE_NAME );
-    Actor actor = ImageActor::New(image);
+    Actor actor = CreateRenderableActor(image);
 
     return actor;
   }
index eb86be2..395b409 100644 (file)
@@ -545,14 +545,14 @@ int UtcDaliKeyInputFocusManagerDestroyObject02(void)
 
   {
     BufferImage image = CreateBufferImage();
-    ImageActor imageActor = ImageActor::New( image );
-    stage.Add( imageActor );
-    imageActor.SetSize(100, 100);
+    Actor actor = CreateRenderableActor( image );
+    stage.Add( actor );
+    actor.SetSize(100, 100);
 
     application.SendNotification();
     application.Render();
 
-    stage.Remove( imageActor );
+    stage.Remove( actor );
   }
 
   DALI_TEST_CHECK( dummy2 == manager.GetCurrentFocusControl());
index 6707da6..6e22042 100644 (file)
@@ -19,7 +19,7 @@
 #include <dali-toolkit-test-suite-utils.h>
 #include <toolkit-event-thread-callback.h>
 #include <dali/devel-api/rendering/renderer.h>
-#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/texture-set.h>
 #include <dali/devel-api/rendering/shader.h>
 #include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
 
@@ -187,7 +187,6 @@ void TestControlRendererRender( ToolkitTestApplication& application,
   controlRenderer.SetOnStage( actor );
 
   DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
-  DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfTextures() == expectedSamplers );
 
   application.SendNotification();
   application.Render();
@@ -206,7 +205,8 @@ void TestControlRendererRender( ToolkitTestApplication& application,
 
   if( resourcePtr )
   {
-    DALI_TEST_CHECK(application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc));
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) ||
+                     application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceSynchronouslyFunc ));
   }
 
   DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
@@ -915,8 +915,6 @@ int UtcDaliRendererFactoryGetSvgRenderer(void)
   application.Render();
 
   DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
-  // texture is not added until the rasterization completed.
-  DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfTextures() == 0 );
 
   EventThreadCallback* eventTrigger = EventThreadCallback::Get();
   CallbackBase* callback = eventTrigger->GetCallback();
@@ -925,8 +923,6 @@ int UtcDaliRendererFactoryGetSvgRenderer(void)
   CallbackBase::Execute( *callback );
 
   DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
-  DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfTextures() == 1 );
-
 
   // waiting for the resource uploading
   application.SendNotification();
@@ -1040,7 +1036,6 @@ int UtcDaliRendererFactoryResetRenderer3(void)
   application.Render();
 
   DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
-  DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfTextures() == 1 );
 
   // reset the renderer to renderer a svg image
   factory.ResetRenderer( controlRenderer, actor, TEST_SVG_FILE_NAME, ImageDimensions( 100, 100 ) );
@@ -1048,8 +1043,6 @@ int UtcDaliRendererFactoryResetRenderer3(void)
   application.Render();
 
   DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
-  // texture is not added until the rasterization completed.
-  DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfTextures() == 0 );
 
   EventThreadCallback* eventTrigger = EventThreadCallback::Get();
   CallbackBase* callback = eventTrigger->GetCallback();
@@ -1057,7 +1050,5 @@ int UtcDaliRendererFactoryResetRenderer3(void)
   eventTrigger->WaitingForTrigger( 1 );// waiting until the svg image is rasterized.
   CallbackBase::Execute( *callback );
 
-  DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfTextures() == 1 );
-
   END_TEST;
 }
index 5e77ebb..9378648 100644 (file)
@@ -280,3 +280,44 @@ int UtcDaliToolkitTextLabelLanguagesP(void)
 
   END_TEST;
 }
+
+int UtcDaliToolkitTextLabelVectorBasedP(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline(" UtcDaliToolkitTextLabelVectorBasedP");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableTextureCallTrace( true );
+
+  TextLabel label = TextLabel::New();
+  label.SetParentOrigin( ParentOrigin::CENTER );
+  label.SetSize( Stage::GetCurrent().GetSize() );
+  label.SetProperty( TextLabel::Property::TEXT, "Hello World" );
+  label.SetProperty( TextLabel::Property::POINT_SIZE, 10.0f );
+  label.SetProperty( TextLabel::Property::RENDERING_BACKEND, Toolkit::Text::RENDERING_VECTOR_BASED );
+  Stage::GetCurrent().Add( label );
+
+  application.SendNotification();
+  application.Render();
+
+  // Test that the vector data is uploaded to atlas
+  DALI_TEST_CHECK( glAbstraction.GetTextureTrace().FindMethod("TexSubImage2D") );
+  glAbstraction.GetTextureTrace().Reset();
+
+  // Add another label with the same text in a different point-size
+  TextLabel label2 = TextLabel::New();
+  label2.SetProperty( TextLabel::Property::TEXT, "Hello World" );
+  label2.SetProperty( TextLabel::Property::POINT_SIZE, 13.0f );
+  label2.SetProperty( TextLabel::Property::RENDERING_BACKEND, Toolkit::Text::RENDERING_VECTOR_BASED );
+  Stage::GetCurrent().Add( label2 );
+
+  application.SendNotification();
+  application.Render();
+
+  // Test that no additional vector data was uploaded to atlas
+  // i.e. the same vector data can be used to render any point-size
+  DALI_TEST_CHECK( ! glAbstraction.GetTextureTrace().FindMethod("TexSubImage2D") );
+
+  END_TEST;
+}
+
index 1fa0845..a861a17 100644 (file)
@@ -142,6 +142,9 @@ fi
 #set a variable for the makefile to force compile the JAvaSplugin
 AM_CONDITIONAL([ENABLE_JAVASCRIPT_PLUGIN], [test x$build_javascript_plugin = xyes])
 
+# Platforms with highp shader support can use vector based text
+AM_CONDITIONAL([ENABLE_VECTOR_BASED_TEXT_RENDERING], [test x$dali_profile = xUBUNTU])
+
 AC_SUBST(dataReadWriteDir)
 AC_SUBST(dataReadOnlyDir)
 AC_SUBST(DALI_TOOLKIT_CFLAGS)
index 3d63299..f803a93 100644 (file)
@@ -32,6 +32,14 @@ include ../../../dali-toolkit/internal/file.list
 include ../../../dali-toolkit/public-api/file.list
 include ../../../dali-toolkit/devel-api/file.list
 
+vector_based_text_src_dir = ../../../dali-toolkit/internal/text/rendering/vector-based
+include ../../../dali-toolkit/internal/text/rendering/vector-based/file.list
+
+if ENABLE_VECTOR_BASED_TEXT_RENDERING
+toolkit_src_files += $(vector_based_text_src_files)
+DALI_TOOLKIT_CFLAGS += -DENABLE_VECTOR_BASED_TEXT_RENDERING
+endif
+
 resources_dir = ../../../resources
 daliimagedir = ${dataReadOnlyDir}/toolkit/images/
 daliimage_DATA = ${dali_toolkit_image_files}
@@ -90,6 +98,7 @@ develapicontrolsdir =           $(develapidir)/controls
 develapibloomviewdir =          $(develapicontrolsdir)/bloom-view
 develapibubbleemitterdir =      $(develapicontrolsdir)/bubble-effect
 develapieffectsviewdir =        $(develapicontrolsdir)/effects-view
+develapiflexcontainerdir =      $(develapicontrolsdir)/flex-container
 develapimagnifierdir =          $(develapicontrolsdir)/magnifier
 develapirendererfactorydir =    $(develapicontrolsdir)/renderer-factory
 develapipopupdir =              $(develapicontrolsdir)/popup
@@ -111,6 +120,7 @@ develapibloomview_HEADERS =         $(devel_api_bloom_view_header_files)
 develapibubbleemitter_HEADERS =     $(devel_api_bubble_emitter_header_files)
 develapibuilder_HEADERS =           $(devel_api_builder_header_files)
 develapieffectsview_HEADERS =       $(devel_api_effects_view_header_files)
+develapiflexcontainer_HEADERS =     $(devel_api_flex_container_header_files)
 develapifocusmanager_HEADERS =      $(devel_api_focus_manager_header_files)
 develapiimageatlas_HEADERS =        $(devel_api_image_atlas_header_files)
 develapimagnifier_HEADERS =         $(devel_api_magnifier_header_files)
diff --git a/dali-toolkit/devel-api/controls/flex-container/flex-container.cpp b/dali-toolkit/devel-api/controls/flex-container/flex-container.cpp
new file mode 100644 (file)
index 0000000..ab51c4f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit/devel-api/controls/flex-container/flex-container.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/flex-container/flex-container-impl.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+FlexContainer FlexContainer::New()
+{
+  return Internal::FlexContainer::New();
+}
+
+FlexContainer::FlexContainer()
+{
+}
+
+FlexContainer::FlexContainer( const FlexContainer& handle )
+: Control( handle )
+{
+}
+
+FlexContainer& FlexContainer::operator=( const FlexContainer& handle )
+{
+  if( &handle != this )
+  {
+    Control::operator=( handle );
+  }
+  return *this;
+}
+
+FlexContainer::~FlexContainer()
+{
+}
+
+FlexContainer FlexContainer::DownCast( BaseHandle handle )
+{
+  return Control::DownCast<FlexContainer, Internal::FlexContainer>(handle);
+}
+
+FlexContainer::FlexContainer( Internal::FlexContainer& implementation )
+: Control(implementation)
+{
+}
+
+FlexContainer::FlexContainer( Dali::Internal::CustomActor* internal )
+: Control( internal )
+{
+  VerifyCustomActorPointer<Internal::FlexContainer>( internal );
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/devel-api/controls/flex-container/flex-container.h b/dali-toolkit/devel-api/controls/flex-container/flex-container.h
new file mode 100644 (file)
index 0000000..b8540e9
--- /dev/null
@@ -0,0 +1,258 @@
+#ifndef __DALI_TOOLKIT_FLEX_CONTAINER_H__
+#define __DALI_TOOLKIT_FLEX_CONTAINER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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-toolkit/public-api/controls/control.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal DALI_INTERNAL
+{
+class FlexContainer;
+}
+
+/**
+ * @addtogroup dali_toolkit_controls_flex_container
+ * @{
+ */
+
+/**
+ * @brief FlexContainer implements a subset of the flexbox spec (defined by W3C):
+ *
+ * https://www.w3.org/TR/css3-flexbox/
+ *
+ * It aims at providing a more efficient way to lay out, align and distribute space among
+ * items in the container, even when their size is unknown or dynamic.
+ *
+ * FlexContainer has the ability to alter the width and height of its children (i.e. flex
+ * items) to fill the available space in the best possible way on different screen sizes.
+ * FlexContainer can expand items to fill available free space, or shrink them to prevent
+ * overflow.
+ *
+ * Below is an illustration of the various directions and terms as applied to a flex
+ * container with the "flex direction" defined as "row".
+ *
+ *     flex container
+ *    --------------------------------------------------------------- cross start
+ *    | ------------------ --------|--------------------------- |
+ *    | |                | |       |                          | |
+ *    | |                | |       |                          | |
+ *    | |  flex item 1   | |       |    flex item 2           | |  main axis
+ *    |-|----------------|-|-------|--------------------------|-|------------>
+ *    | |                | |       |                          | |
+ *    | |                | |       |                          | |
+ *    | |                | |       |                          | |
+ *    | ------------------ --------|--------------------------- |
+ *    -----------------------------|--------------------------------- cross end
+ *    |                            |                            |
+ *    | main start                 | cross axis                 | main end
+ *    |                            |                            |
+ *                                 v
+ *
+ * @nosubgrouping
+ * <h3>Per-child Custom properties for script supporting:</h3>
+ *
+ * The following custom properties of the actor are checked to decide how to lay out the
+ * actor inside the flex container.
+ *
+ * These properties are registered dynamically to the child and are non-animatable.
+ *
+ * | %Property Name          | Type        |
+ * |-------------------------|-------------|
+ * | flex                    | float       |
+ * | alignSelf               | integer     |
+ * | flexPadding             | Vector4     |
+ * | flexBorder              | Vector4     |
+ * | flexMargin              | Vector4     |
+ *
+ * The available values for alignSelf are: ALIGN_AUTO, ALIGN_FLEX_START, ALIGN_CENTER, ALIGN_FLEX_END, ALIGN_STRETCH
+ *
+ * @code
+ * "name":"icon",
+ * "type":"ImageView",
+ * "image":"image.png",
+ *   "customProperties": {
+ *     "flex":1,                        // property to make the item to receive the specified proportion of the free space in the container. If all items in the container use this pattern, their sizes will be proportional to the specified flex factor.
+ *     "alignSelf":"flexStart",         // property to specify how the item will align along the cross axis, if set, this overides the default alignment for all items in the container
+ *     "flexPadding":[10, 10, 10, 10],  // property to specify the space around the content (inside the flex border) of the item, if not set, default value is [0, 0, 0, 0]
+ *     "flexBorder":[5, 5, 5, 5],       // property to specify the border that goes around the flex padding and the content of the item, if not set, default value is [0, 0, 0, 0]
+ *     "flexMargin":[10, 10, 10, 10]    // property to specify the space outside the flex border, if not set, default value is [0, 0, 0, 0]
+ *   }
+ * @endcode
+ */
+
+class DALI_IMPORT_API FlexContainer : public Control
+{
+public:
+
+  /**
+   * @brief The direction of the main axis in the flex container. This determines
+   * the direction that flex items are laid out in the flex container.
+   */
+  enum FlexDirection
+  {
+    COLUMN,                  ///< The flexible items are displayed vertically as a column
+    COLUMN_REVERSE,          ///< The flexible items are displayed vertically as a column, but in reverse order
+    ROW,                     ///< The flexible items are displayed horizontally as a row
+    ROW_REVERSE              ///< The flexible items are displayed horizontally as a row, but in reverse order
+  };
+
+  /**
+   * @brief The primary direction in which content is ordered in the flex container
+   * and on which sides the “start” and “end” are.
+   */
+  enum ContentDirection
+  {
+    INHERIT,                 ///< Inherits the same direction from the parent
+    LTR,                     ///< From left to right
+    RTL                      ///< From right to left
+  };
+
+  /**
+   * @brief Alignment of the flex items when the items do not use all available
+   * space on the main-axis.
+   */
+  enum Justification
+  {
+    JUSTIFY_FLEX_START,      ///< Items are positioned at the beginning of the container
+    JUSTIFY_CENTER,          ///< Items are positioned at the center of the container
+    JUSTIFY_FLEX_END,        ///< Items are positioned at the end of the container
+    JUSTIFY_SPACE_BETWEEN,   ///< Items are positioned with equal space between the lines
+    JUSTIFY_SPACE_AROUND     ///< Items are positioned with equal space before, between, and after the lines
+  };
+
+  /**
+   * @brief Alignment of the flex items or lines when the items or lines do not
+   * use all available space on the cross-axis.
+   */
+  enum Alignment
+  {
+    ALIGN_AUTO,              ///< Inherits the same alignment from the parent (only valid for "alignSelf" property)
+    ALIGN_FLEX_START,        ///< At the beginning of the container
+    ALIGN_CENTER,            ///< At the center of the container
+    ALIGN_FLEX_END,          ///< At the end of the container
+    ALIGN_STRETCH            ///< Stretch to fit the container
+  };
+
+  /**
+   * @brief The wrap type of the flex container when there is no enough room for
+   * all the items on one flex line.
+   */
+  enum WrapType
+  {
+    NO_WRAP,                 ///< Flex items laid out in single line (shrunk to fit the flex container along the main axis)
+    WRAP                     ///< Flex items laid out in multiple lines if needed
+  };
+
+public:
+
+  /**
+   * @brief The start and end property ranges for this control.
+   */
+  enum PropertyRange
+  {
+    PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1,
+    PROPERTY_END_INDEX =   PROPERTY_START_INDEX + 1000              ///< Reserve property indices
+  };
+
+  /**
+   * @brief An enumeration of properties belonging to the FlexContainer class.
+   */
+  struct Property
+  {
+    enum
+    {
+      CONTENT_DIRECTION = PROPERTY_START_INDEX, ///< name "contentDirection",   The primary direction in which content is ordered,                                                 @see FlexContainer::ContentDirection,  type INTEGER
+      FLEX_DIRECTION,                           ///< name "flexDirection",      The direction of the main-axis which determines the direction that flex items are laid out,        @see FlexContainer::FlexDirection,     type INTEGER
+      FLEX_WRAP,                                ///< name "flexWrap",           Whether the flex items should wrap or not if there is no enough room for them on one flex line,    @see FlexContainer::WrapType,          type INTEGER
+      JUSTIFY_CONTENT,                          ///< name "justifyContent",     The alignment of flex items when the items do not use all available space on the main-axis,        @see FlexContainer::Justification,     type INTEGER
+      ALIGN_ITEMS,                              ///< name "alignItems",         The alignment of flex items when the items do not use all available space on the cross-axis,       @see FlexContainer::Alignment,         type INTEGER
+      ALIGN_CONTENT                             ///< name "alignContent",       Similar to "alignItems", but it aligns flex lines, so only works when there are multiple lines,    @see FlexContainer::Alignment,         type INTEGER
+    };
+  };
+
+  /**
+   * Create a FlexContainer handle; this can be initialised with FlexContainer::New()
+   * Calling member functions with an uninitialised handle is not allowed.
+   */
+  FlexContainer();
+
+  /**
+   * Copy constructor. Creates another handle that points to the same real object
+   * @param handle to copy from
+   */
+  FlexContainer( const FlexContainer& handle );
+
+  /**
+   * Assignment operator. Changes this handle to point to another real object
+   */
+  FlexContainer& operator=( const FlexContainer& handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~FlexContainer();
+
+  /**
+   * Create the FlexContainer control.
+   * @return A handle to the FlexContainer control.
+   */
+  static FlexContainer New();
+
+  /**
+   * Downcast an Object handle to FlexContainer. If handle points to a FlexContainer the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @param[in] handle Handle to an object
+   * @return handle to a FlexContainer or an uninitialized handle
+   */
+  static FlexContainer DownCast( BaseHandle handle );
+
+
+public: // Not intended for application developers
+
+  /**
+   * @brief Creates a handle using the Toolkit::Internal implementation.
+   *
+   * @param[in] implementation The Control implementation.
+   */
+  DALI_INTERNAL FlexContainer( Internal::FlexContainer& implementation );
+
+  /**
+   * @brief Allows the creation of this Control from an Internal::CustomActor pointer.
+   *
+   * @param[in] internal A pointer to the internal CustomActor.
+   */
+  explicit DALI_INTERNAL FlexContainer( Dali::Internal::CustomActor* internal );
+};
+
+/**
+ * @}
+ */
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_FLEX_CONTAINER_H__
index e95d906..be5db96 100644 (file)
@@ -35,7 +35,7 @@ class ControlRenderer;
 /**
  * @brief ControlRenderer provides renderer for rendering the controls. A control may have multiple ControlRenders.
  *
- * ControlRenderers reuses geometry, shader etc. across controls and manages the renderer and material to exist only when control is on-stage.
+ * ControlRenderers reuses geometry, shader etc. across controls and manages the renderer and texture sets to exist only when control is on-stage.
  * It also responds to actor size and color change, and provides the clipping at the renderer level.
  * Note: The control renderer responds to the the Actor::COLOR by blending it with the 'Multiply' operator.
  */
index a2220cd..8987002 100755 (executable)
@@ -7,6 +7,7 @@ devel_api_src_files = \
   $(devel_api_src_dir)/controls/bloom-view/bloom-view.cpp \
   $(devel_api_src_dir)/controls/bubble-effect/bubble-emitter.cpp \
   $(devel_api_src_dir)/controls/effects-view/effects-view.cpp \
+  $(devel_api_src_dir)/controls/flex-container/flex-container.cpp \
   $(devel_api_src_dir)/controls/magnifier/magnifier.cpp \
   $(devel_api_src_dir)/controls/popup/confirmation-popup.cpp \
   $(devel_api_src_dir)/controls/popup/popup.cpp \
@@ -47,6 +48,9 @@ devel_api_builder_header_files = \
 devel_api_effects_view_header_files = \
   $(devel_api_src_dir)/controls/effects-view/effects-view.h
 
+devel_api_flex_container_header_files = \
+  $(devel_api_src_dir)/controls/flex-container/flex-container.h
+
 devel_api_magnifier_header_files = \
   $(devel_api_src_dir)/controls/magnifier/magnifier.h
 
index 474a16e..ab3a9c9 100644 (file)
@@ -83,8 +83,6 @@ const char* const BLOOM_SATURATION_PROPERTY_NAME = "uBloomSaturation";
 const char* const IMAGE_INTENSITY_PROPERTY_NAME = "uImageIntensity";
 const char* const IMAGE_SATURATION_PROPERTY_NAME = "uImageSaturation";
 
-const char* const EFFECT_IMAGE_NAME( "sEffect" );
-
 ///////////////////////////////////////////////////////
 //
 // Bloom shaders
@@ -393,16 +391,8 @@ void BloomView::AllocateResources()
 
     // use the completed blur in the first buffer and composite with the original child actors render
     mCompositeImageActor.SetImage( mRenderTargetForRenderingChildren );
-    Material material = mCompositeImageActor.GetRendererAt(0).GetMaterial();
-    int textureIndex = material.GetTextureIndex( EFFECT_IMAGE_NAME );
-    if( textureIndex == -1 )
-    {
-      material.AddTexture( mBlurExtractTarget, EFFECT_IMAGE_NAME );
-    }
-    else
-    {
-      material.SetTextureImage( textureIndex, mBlurExtractTarget );
-    }
+    TextureSet textureSet = mCompositeImageActor.GetRendererAt(0).GetTextures();
+    textureSet.SetImage( 1u, mBlurExtractTarget );
 
     // set up target actor for rendering result, i.e. the blurred image
     mTargetImageActor.SetImage(mOutputRenderTarget);
index e1ef66c..f42b72b 100644 (file)
@@ -50,7 +50,7 @@ BubbleActor::BubbleActor( unsigned int numberOfBubble,
   mActor = Actor::New();
 }
 
-void BubbleActor::MakeRenderable( Geometry geometry, Material material  )
+void BubbleActor::MakeRenderable( Geometry geometry, TextureSet textureSet, Shader shader  )
 {
   if( mRenderer )
   {
@@ -58,7 +58,8 @@ void BubbleActor::MakeRenderable( Geometry geometry, Material material  )
     return;
   }
 
-  mRenderer = Renderer::New( geometry, material );
+  mRenderer = Renderer::New( geometry, shader );
+  mRenderer.SetTextures( textureSet );
 
   mActor.AddRenderer( mRenderer );
   mActor.SetSize( mMovementArea );
index 357cddf..6d5ef93 100644 (file)
@@ -61,9 +61,10 @@ public:
   /**
    * Prepare for the rendering: create and add renderer, and register properties
    * @param[in] geometry The geometry to be used by the renderer
-   * @param[in] material The material to be used by the renderer
+   * @param[in] textureSet The texture set to be used by the renderer
+   * @param[in] textureSet The shader set to be used by the renderer
    */
-  void MakeRenderable( Geometry geometry, Material material  );
+  void MakeRenderable( Geometry geometry, TextureSet textureSet, Shader shader  );
 
   /**
    * Return the mesh actor which is used to display the bubbles
index 9d0e24f..9fc065a 100644 (file)
@@ -32,7 +32,7 @@ namespace Internal
 {
 
 /**
- * Create the shader to be used by the material
+ * Create the shader to be used by the renderer
  * @param[in] numberOfBubble How many groups of uniforms are used to control the bubble movement.
  * @return A handle to the newly created shader.
  */
@@ -108,7 +108,7 @@ inline Shader CreateBubbleShader( unsigned int numBubble )
   {\n
     // Get the emit pisition color, and Mix with the actor color
     mediump vec4 fragColor = texture2D(sBackground, vEffectTexCoord)*uColor;\n
-    // Apply the shape defined by the texture contained in the material
+    // Apply the shape defined by the texture contained sBubbleShape
     // And make the opacity being 0.7, and animate from 0.7 to 0 during the last 1/3 of movement
     fragColor.a  *= texture2D(sBubbleShape, vTexCoord).a * ( 2.1 - max( vPercentage*2.1, 1.4 ) );\n
     gl_FragColor = fragColor;\n
index 392fa9c..836a26d 100644 (file)
@@ -142,9 +142,9 @@ void BubbleEmitter::OnInitialize()
 
   Shader bubbleShader = CreateBubbleShader (mNumBubblePerActor );
 
-  mMaterial = Material::New( bubbleShader );
-  mMaterial.AddTexture( mEffectImage, "sBackground" );
-  mMaterial.AddTexture( mShapeImage,  "sBubbleShape" );
+  mTextureSet = TextureSet::New();
+  mTextureSet.SetImage( 0u, mEffectImage );
+  mTextureSet.SetImage( 1u, mShapeImage );
 
   mBubbleActors.resize( mNumActor );
 
@@ -152,7 +152,7 @@ void BubbleEmitter::OnInitialize()
   for(unsigned int i=0; i < mNumActor; i++ )
   {
     mBubbleActors[i] = new BubbleActor( mNumBubblePerActor, mMovementArea );
-    (mBubbleActors[i])->MakeRenderable( mMeshGeometry, mMaterial );
+    (mBubbleActors[i])->MakeRenderable( mMeshGeometry, mTextureSet, bubbleShader );
     mBubbleRoot.Add( (mBubbleActors[i])->GetMeshActor() );
   }
 
@@ -200,7 +200,7 @@ void BubbleEmitter::SetBackground( Image bgImage, const Vector3& hsvDelta )
 
 void BubbleEmitter::SetShapeImage( Image shapeImage )
 {
-  mMaterial.SetTextureImage( 1, shapeImage );
+  mTextureSet.SetImage( 1, shapeImage );
 }
 
 void BubbleEmitter::SetBubbleScale( float scale )
index 1509248..ef94386 100644 (file)
@@ -158,7 +158,7 @@ private:
   CameraActor                 mCameraActor;         ///< The render task views the scene from the perspective of this actor.
 
   Geometry                    mMeshGeometry;         ///< The mesh geometry which contains the vertices and indices data
-  Material                    mMaterial;             ///< The material which controls the bubble display
+  TextureSet                  mTextureSet;           ///< The texture set which controls the bubble display
   std::vector<BubbleActorPtr> mBubbleActors;         ///< The meshActor vector, its size is mNumShader.
 
   Vector2                     mMovementArea;        ///< The size of the bubble moving area, usually the same size as the background image actor.
diff --git a/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp b/dali-toolkit/internal/controls/flex-container/flex-container-impl.cpp
new file mode 100644 (file)
index 0000000..323a2cd
--- /dev/null
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit/internal/controls/flex-container/flex-container-impl.h>
+
+// EXTERNAL INCLUDES
+#include <sstream>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/object/type-registry-helper.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
+#include <dali/integration-api/debug.h>
+
+using namespace Dali;
+
+namespace
+{
+/*
+ * Custom properties for how to lay out the actor.
+ *
+ * When an actor is add to the flex container, the following custom properties of the actor
+ * are checked to decide how to lay out the actor inside the flex container.
+ *
+ * These non-animatable properties should be registered to the child which would be added
+ * to the flex container, and once added their values can not be changed.
+ */
+const char * const FLEX_PROPERTY_NAME("flex");
+const char * const ALIGN_SELF_PROPERTY_NAME("alignSelf");
+const char * const FLEX_PADDING_PROPERTY_NAME("flexPadding");
+const char * const FLEX_BORDER_PROPERTY_NAME("flexBorder");
+const char * const FLEX_MARGIN_PROPERTY_NAME("flexMargin");
+
+#if defined(DEBUG_ENABLED)
+// debugging support, very useful when new features are added or bugs are hunted down
+// currently not called from code so compiler will optimize these away, kept here for future debugging
+
+#define FLEX_CONTAINER_TAG "DALI Toolkit::FlexContainer "
+#define FC_LOG(fmt, args...) Debug::LogMessage(Debug::DebugInfo, FLEX_CONTAINER_TAG fmt, ## args)
+//#define FLEX_CONTAINER_DEBUG 1
+
+#if defined(FLEX_CONTAINER_DEBUG)
+void PrintNode( Toolkit::Internal::FlexContainer::FlexItemNodeContainer itemNodes )
+{
+  // Print the style property and layout of all the children
+  for( unsigned int i = 0; i < itemNodes.size(); ++i )
+  {
+    FC_LOG( "Item %d style: \n", i );
+    print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_STYLE | CSS_PRINT_CHILDREN ) );
+    FC_LOG( "Item %d layout: \n", i );
+    print_css_node( itemNodes[i].node, (css_print_options_t)( CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN ) );
+    FC_LOG( "\n" );
+  }
+}
+
+#endif // defined(FLEX_CONTAINER_DEBUG)
+#endif // defined(DEBUG_ENABLED)
+
+
+} // namespace
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Type registration
+BaseHandle Create()
+{
+  return Toolkit::FlexContainer::New();
+}
+
+// Setup properties, signals and actions using the type-registry.
+DALI_TYPE_REGISTRATION_BEGIN( Toolkit::FlexContainer, Toolkit::Control, Create );
+
+DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "contentDirection",   INTEGER, CONTENT_DIRECTION )
+DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "flexDirection",      INTEGER, FLEX_DIRECTION    )
+DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "flexWrap",           INTEGER, FLEX_WRAP         )
+DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "justifyContent",     INTEGER, JUSTIFY_CONTENT   )
+DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "alignItems",         INTEGER, ALIGN_ITEMS       )
+DALI_PROPERTY_REGISTRATION( Toolkit, FlexContainer, "alignContent",       INTEGER, ALIGN_CONTENT     )
+
+DALI_TYPE_REGISTRATION_END()
+
+const Scripting::StringEnum ALIGN_SELF_STRING_TABLE[] =
+{
+  { "auto",        Toolkit::FlexContainer::ALIGN_AUTO        },
+  { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
+  { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
+  { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
+  { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
+};
+const unsigned int ALIGN_SELF_STRING_TABLE_COUNT = sizeof( ALIGN_SELF_STRING_TABLE ) / sizeof( ALIGN_SELF_STRING_TABLE[0] );
+
+const Scripting::StringEnum CONTENT_DIRECTION_STRING_TABLE[] =
+{
+  { "inherit",     Toolkit::FlexContainer::INHERIT           },
+  { "LTR",         Toolkit::FlexContainer::LTR               },
+  { "RTL",         Toolkit::FlexContainer::RTL               }
+};
+const unsigned int CONTENT_DIRECTION_STRING_TABLE_COUNT = sizeof( CONTENT_DIRECTION_STRING_TABLE ) / sizeof( CONTENT_DIRECTION_STRING_TABLE[0] );
+
+const Scripting::StringEnum FLEX_DIRECTION_STRING_TABLE[] =
+{
+  { "column",          Toolkit::FlexContainer::COLUMN          },
+  { "columnReverse",   Toolkit::FlexContainer::COLUMN_REVERSE  },
+  { "row",             Toolkit::FlexContainer::ROW             },
+  { "rowReverse",      Toolkit::FlexContainer::ROW_REVERSE     }
+};
+const unsigned int FLEX_DIRECTION_STRING_TABLE_COUNT = sizeof( FLEX_DIRECTION_STRING_TABLE ) / sizeof( FLEX_DIRECTION_STRING_TABLE[0] );
+
+const Scripting::StringEnum FLEX_WRAP_STRING_TABLE[] =
+{
+  { "noWrap",          Toolkit::FlexContainer::NO_WRAP         },
+  { "wrap",            Toolkit::FlexContainer::WRAP            }
+};
+const unsigned int FLEX_WRAP_STRING_TABLE_COUNT = sizeof( FLEX_WRAP_STRING_TABLE ) / sizeof( FLEX_WRAP_STRING_TABLE[0] );
+
+const Scripting::StringEnum JUSTIFY_CONTENT_STRING_TABLE[] =
+{
+  { "flexStart",       Toolkit::FlexContainer::JUSTIFY_FLEX_START     },
+  { "center",          Toolkit::FlexContainer::JUSTIFY_CENTER         },
+  { "flexEnd",         Toolkit::FlexContainer::JUSTIFY_FLEX_END       },
+  { "spaceBetween",    Toolkit::FlexContainer::JUSTIFY_SPACE_BETWEEN  },
+  { "spaceAround",     Toolkit::FlexContainer::JUSTIFY_SPACE_AROUND   }
+};
+const unsigned int JUSTIFY_CONTENT_STRING_TABLE_COUNT = sizeof( JUSTIFY_CONTENT_STRING_TABLE ) / sizeof( JUSTIFY_CONTENT_STRING_TABLE[0] );
+
+const Scripting::StringEnum ALIGN_ITEMS_STRING_TABLE[] =
+{
+  { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
+  { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
+  { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
+  { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
+};
+const unsigned int ALIGN_ITEMS_STRING_TABLE_COUNT = sizeof( ALIGN_ITEMS_STRING_TABLE ) / sizeof( ALIGN_ITEMS_STRING_TABLE[0] );
+
+const Scripting::StringEnum ALIGN_CONTENT_STRING_TABLE[] =
+{
+  { "flexStart",   Toolkit::FlexContainer::ALIGN_FLEX_START  },
+  { "center",      Toolkit::FlexContainer::ALIGN_CENTER      },
+  { "flexEnd",     Toolkit::FlexContainer::ALIGN_FLEX_END    },
+  { "stretch",     Toolkit::FlexContainer::ALIGN_STRETCH     }
+};
+const unsigned int ALIGN_CONTENT_STRING_TABLE_COUNT = sizeof( ALIGN_CONTENT_STRING_TABLE ) / sizeof( ALIGN_CONTENT_STRING_TABLE[0] );
+
+/**
+ * The function used by the layout algorithm to be get the style properties
+ * and layout information of the child at the given index.
+ */
+css_node_t* GetChildNodeAtIndex( void *childrenNodes, int i )
+{
+  FlexContainer::FlexItemNodeContainer childrenNodeContainer = *( static_cast<FlexContainer::FlexItemNodeContainer*>( childrenNodes ) );
+  return childrenNodeContainer[i].node;
+}
+
+/**
+ * The function used by the layout algorithm to check whether the node is dirty
+ * for relayout.
+ */
+bool IsNodeDirty( void *itemNodes )
+{
+  // We only calculate the layout when the child is added or removed, or when
+  // style properties are changed. So should always return true here.
+  return true;
+}
+
+} // Unnamed namespace
+
+Toolkit::FlexContainer FlexContainer::New()
+{
+  // Create the implementation, temporarily owned by this handle on stack
+  IntrusivePtr< FlexContainer > impl = new FlexContainer();
+
+  // Pass ownership to CustomActor handle
+  Toolkit::FlexContainer handle( *impl );
+
+  // Second-phase init of the implementation
+  // This can only be done after the CustomActor connection has been made...
+  impl->Initialize();
+
+  return handle;
+}
+
+FlexContainer::~FlexContainer()
+{
+  free_css_node( mRootNode.node );
+
+  for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
+  {
+    free_css_node( mChildrenNodes[i].node );
+  }
+
+  mChildrenNodes.clear();
+}
+
+void FlexContainer::SetContentDirection( Toolkit::FlexContainer::ContentDirection contentDirection )
+{
+  if( mContentDirection != contentDirection )
+  {
+    mContentDirection = contentDirection;
+    mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
+
+    RelayoutRequest();
+  }
+}
+
+Toolkit::FlexContainer::ContentDirection FlexContainer::GetContentDirection()
+{
+  return mContentDirection;
+}
+
+void FlexContainer::SetFlexDirection( Toolkit::FlexContainer::FlexDirection flexDirection )
+{
+  if( mFlexDirection != flexDirection )
+  {
+    mFlexDirection = flexDirection;
+    mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
+
+    RelayoutRequest();
+  }
+}
+
+Toolkit::FlexContainer::FlexDirection FlexContainer::GetFlexDirection()
+{
+  return mFlexDirection;
+}
+
+void FlexContainer::SetFlexWrap( Toolkit::FlexContainer::WrapType flexWrap )
+{
+  if( mFlexWrap != flexWrap )
+  {
+    mFlexWrap = flexWrap;
+    mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
+
+    RelayoutRequest();
+  }
+}
+
+Toolkit::FlexContainer::WrapType FlexContainer::GetFlexWrap()
+{
+  return mFlexWrap;
+}
+
+void FlexContainer::SetJustifyContent( Toolkit::FlexContainer::Justification justifyContent )
+{
+  if( mJustifyContent != justifyContent )
+  {
+    mJustifyContent = justifyContent;
+    mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
+
+    RelayoutRequest();
+  }
+}
+
+Toolkit::FlexContainer::Justification FlexContainer::GetJustifyContent()
+{
+  return mJustifyContent;
+}
+
+void FlexContainer::SetAlignItems( Toolkit::FlexContainer::Alignment alignItems )
+{
+  if( mAlignItems != alignItems )
+  {
+    mAlignItems = alignItems;
+    mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
+
+    RelayoutRequest();
+  }
+}
+
+Toolkit::FlexContainer::Alignment FlexContainer::GetAlignItems()
+{
+  return mAlignItems;
+}
+
+void FlexContainer::SetAlignContent( Toolkit::FlexContainer::Alignment alignContent )
+{
+  if( mAlignContent != alignContent )
+  {
+    mAlignContent = alignContent;
+    mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
+
+    RelayoutRequest();
+  }
+}
+
+Toolkit::FlexContainer::Alignment FlexContainer::GetAlignContent()
+{
+  return mAlignContent;
+}
+
+void FlexContainer::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+  Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
+
+  if( flexContainer )
+  {
+    FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
+    switch( index )
+    {
+      case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
+      {
+        Toolkit::FlexContainer::ContentDirection contentDirection( Toolkit::FlexContainer::INHERIT );
+
+        if( value.GetType() == Property::INTEGER )
+        {
+          flexContainerImpl.SetContentDirection( static_cast<Toolkit::FlexContainer::ContentDirection>( value.Get< int >() ) );
+        }
+        else if( Scripting::GetEnumeration< Toolkit::FlexContainer::ContentDirection >( value.Get< std::string >().c_str(),
+                                                                                   CONTENT_DIRECTION_STRING_TABLE,
+                                                                                   CONTENT_DIRECTION_STRING_TABLE_COUNT,
+                                                                                   contentDirection ) )
+        {
+          flexContainerImpl.SetContentDirection(contentDirection);
+        }
+        break;
+      }
+      case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
+      {
+        Toolkit::FlexContainer::FlexDirection flexDirection( Toolkit::FlexContainer::COLUMN );
+
+        if( value.GetType() == Property::INTEGER )
+        {
+          flexContainerImpl.SetFlexDirection( static_cast<Toolkit::FlexContainer::FlexDirection>( value.Get< int >() ) );
+        }
+        else if( Scripting::GetEnumeration< Toolkit::FlexContainer::FlexDirection >( value.Get< std::string >().c_str(),
+                                                                                FLEX_DIRECTION_STRING_TABLE,
+                                                                                FLEX_DIRECTION_STRING_TABLE_COUNT,
+                                                                                flexDirection ) )
+        {
+          flexContainerImpl.SetFlexDirection(flexDirection);
+        }
+        break;
+      }
+      case Toolkit::FlexContainer::Property::FLEX_WRAP:
+      {
+        Toolkit::FlexContainer::WrapType flexWrap( Toolkit::FlexContainer::NO_WRAP );
+
+        if( value.GetType() == Property::INTEGER )
+        {
+          flexContainerImpl.SetFlexWrap( static_cast<Toolkit::FlexContainer::WrapType>( value.Get< int >() ) );
+        }
+        else if( Scripting::GetEnumeration< Toolkit::FlexContainer::WrapType >( value.Get< std::string >().c_str(),
+                                                                           FLEX_WRAP_STRING_TABLE,
+                                                                           FLEX_WRAP_STRING_TABLE_COUNT,
+                                                                           flexWrap ) )
+        {
+          flexContainerImpl.SetFlexWrap(flexWrap);
+        }
+        break;
+      }
+      case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
+      {
+        Toolkit::FlexContainer::Justification justifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START );
+
+        if( value.GetType() == Property::INTEGER )
+        {
+          flexContainerImpl.SetJustifyContent( static_cast<Toolkit::FlexContainer::Justification>( value.Get< int >() ) );
+        }
+        else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Justification >( value.Get< std::string >().c_str(),
+                                                                                JUSTIFY_CONTENT_STRING_TABLE,
+                                                                                JUSTIFY_CONTENT_STRING_TABLE_COUNT,
+                                                                                justifyContent ) )
+        {
+          flexContainerImpl.SetJustifyContent(justifyContent);
+        }
+        break;
+      }
+      case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
+      {
+        Toolkit::FlexContainer::Alignment alignItems( Toolkit::FlexContainer::ALIGN_STRETCH );
+
+        if( value.GetType() == Property::INTEGER )
+        {
+          flexContainerImpl.SetAlignItems( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
+        }
+        else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
+                                                                            ALIGN_ITEMS_STRING_TABLE,
+                                                                            ALIGN_ITEMS_STRING_TABLE_COUNT,
+                                                                            alignItems ) )
+        {
+          flexContainerImpl.SetAlignItems(alignItems);
+        }
+        break;
+      }
+      case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
+      {
+        Toolkit::FlexContainer::Alignment alignContent( Toolkit::FlexContainer::ALIGN_FLEX_START );
+
+        if( value.GetType() == Property::INTEGER )
+        {
+          flexContainerImpl.SetAlignContent( static_cast<Toolkit::FlexContainer::Alignment>( value.Get< int >() ) );
+        }
+        else if( Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.Get< std::string >().c_str(),
+                                                                            ALIGN_CONTENT_STRING_TABLE,
+                                                                            ALIGN_CONTENT_STRING_TABLE_COUNT,
+                                                                            alignContent ) )
+        {
+          flexContainerImpl.SetAlignContent(alignContent);
+        }
+        break;
+      }
+    }
+  }
+}
+
+Property::Value FlexContainer::GetProperty( BaseObject* object, Property::Index index )
+{
+  Property::Value value;
+
+  Toolkit::FlexContainer flexContainer = Toolkit::FlexContainer::DownCast( Dali::BaseHandle( object ) );
+
+  if( flexContainer )
+  {
+    FlexContainer& flexContainerImpl( GetImpl( flexContainer ) );
+    switch( index )
+    {
+      case Toolkit::FlexContainer::Property::CONTENT_DIRECTION:
+      {
+        value = flexContainerImpl.GetContentDirection();
+        break;
+      }
+      case Toolkit::FlexContainer::Property::FLEX_DIRECTION:
+      {
+        value = flexContainerImpl.GetFlexDirection();
+        break;
+      }
+      case Toolkit::FlexContainer::Property::FLEX_WRAP:
+      {
+        value = flexContainerImpl.GetFlexWrap();
+        break;
+      }
+      case Toolkit::FlexContainer::Property::JUSTIFY_CONTENT:
+      {
+        value = flexContainerImpl.GetJustifyContent();
+        break;
+      }
+      case Toolkit::FlexContainer::Property::ALIGN_ITEMS:
+      {
+        value = flexContainerImpl.GetAlignItems();
+        break;
+      }
+      case Toolkit::FlexContainer::Property::ALIGN_CONTENT:
+      {
+        value = flexContainerImpl.GetAlignContent();
+        break;
+      }
+    }
+  }
+
+  return value;
+}
+
+void FlexContainer::OnChildAdd( Actor& child )
+{
+  Control::OnChildAdd( child );
+
+  // Anchor actor to top left of the container
+  child.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  child.SetParentOrigin( ParentOrigin::TOP_LEFT );
+
+  // Create a new node for the child.
+  FlexItemNode childNode;
+  childNode.actor = child;
+  childNode.node = new_css_node();
+  childNode.node->get_child = GetChildNodeAtIndex;
+  childNode.node->is_dirty = IsNodeDirty;
+  mChildrenNodes.push_back(childNode);
+}
+
+void FlexContainer::OnChildRemove( Actor& child )
+{
+  for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
+  {
+    if( mChildrenNodes[i].actor.GetHandle() == child )
+    {
+      free_css_node( mChildrenNodes[i].node );
+      mChildrenNodes.erase( mChildrenNodes.begin() + i );
+
+      // Relayout the container only if instances were found
+      RelayoutRequest();
+      break;
+    }
+  }
+
+  Control::OnChildRemove( child );
+}
+
+void FlexContainer::OnRelayout( const Vector2& size, RelayoutContainer& container )
+{
+  for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
+  {
+    Actor child = mChildrenNodes[i].actor.GetHandle();
+    if( child )
+    {
+      float negotiatedWidth = child.GetRelayoutSize(Dimension::WIDTH);
+      float negotiatedHeight = child.GetRelayoutSize(Dimension::HEIGHT);
+
+      if( negotiatedWidth > 0 )
+      {
+        mChildrenNodes[i].node->style.dimensions[CSS_WIDTH] = negotiatedWidth;
+      }
+      if( negotiatedHeight > 0 )
+      {
+        mChildrenNodes[i].node->style.dimensions[CSS_HEIGHT] = negotiatedHeight;
+      }
+    }
+  }
+
+  // Relayout the container
+  RelayoutChildren();
+
+  for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
+  {
+    Actor child = mChildrenNodes[i].actor.GetHandle();
+    if( child )
+    {
+      if( child.GetResizePolicy( Dimension::WIDTH ) != ResizePolicy::USE_ASSIGNED_SIZE )
+      {
+        child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::WIDTH );
+      }
+      if( child.GetResizePolicy( Dimension::HEIGHT ) != ResizePolicy::USE_ASSIGNED_SIZE )
+      {
+        child.SetResizePolicy( ResizePolicy::USE_ASSIGNED_SIZE, Dimension::HEIGHT );
+      }
+
+      container.Add( child, Vector2(mChildrenNodes[i].node->layout.dimensions[CSS_WIDTH], mChildrenNodes[i].node->layout.dimensions[CSS_HEIGHT] ) );
+    }
+  }
+}
+
+bool FlexContainer::RelayoutDependentOnChildren( Dimension::Type dimension )
+{
+  return true;
+}
+
+void FlexContainer::OnSizeSet( const Vector3& size )
+{
+  if( mRootNode.node )
+  {
+    Actor self = Self();
+
+    mRootNode.node->style.dimensions[CSS_WIDTH] = size.x;
+    mRootNode.node->style.dimensions[CSS_HEIGHT] = size.y;
+
+    RelayoutRequest();
+  }
+}
+
+void FlexContainer::OnSizeAnimation( Animation& animation, const Vector3& targetSize )
+{
+  // @todo Animate the children to their target size and position
+}
+
+void FlexContainer::ComputeLayout()
+{
+  if( mRootNode.node )
+  {
+    mRootNode.node->children_count = mChildrenNodes.size();
+
+    // Intialize the layout.
+    mRootNode.node->layout.position[CSS_LEFT] = 0;
+    mRootNode.node->layout.position[CSS_TOP] = 0;
+    mRootNode.node->layout.position[CSS_BOTTOM] = 0;
+    mRootNode.node->layout.position[CSS_RIGHT] = 0;
+    mRootNode.node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
+    mRootNode.node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+
+    for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
+    {
+      css_node_t* childNode = mChildrenNodes[i].node;
+      Actor childActor = mChildrenNodes[i].actor.GetHandle();
+
+      childNode->layout.position[CSS_LEFT] = 0;
+      childNode->layout.position[CSS_TOP] = 0;
+      childNode->layout.position[CSS_BOTTOM] = 0;
+      childNode->layout.position[CSS_RIGHT] = 0;
+      childNode->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
+      childNode->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+
+      // Intialize the style of the child.
+      childNode->style.minDimensions[CSS_WIDTH] = childActor.GetMinimumSize().x;
+      childNode->style.minDimensions[CSS_HEIGHT] = childActor.GetMinimumSize().y;
+      childNode->style.maxDimensions[CSS_WIDTH] = childActor.GetMaximumSize().x;
+      childNode->style.maxDimensions[CSS_HEIGHT] = childActor.GetMaximumSize().y;
+
+      // Test custom properties on the child
+      if( childActor.GetPropertyIndex( FLEX_PROPERTY_NAME ) != Property::INVALID_INDEX )
+      {
+        childNode->style.flex = childActor.GetProperty( childActor.GetPropertyIndex(FLEX_PROPERTY_NAME) ).Get<float>();
+      }
+
+      Property::Index alignSelfPropertyIndex = childActor.GetPropertyIndex( ALIGN_SELF_PROPERTY_NAME );
+      if( alignSelfPropertyIndex != Property::INVALID_INDEX )
+      {
+        Property::Value alignSelfPropertyValue = childActor.GetProperty( alignSelfPropertyIndex );
+
+        Toolkit::FlexContainer::Alignment alignSelf( Toolkit::FlexContainer::ALIGN_AUTO );
+        if( alignSelfPropertyValue.GetType() == Property::INTEGER )
+        {
+          alignSelf = static_cast<Toolkit::FlexContainer::Alignment>( alignSelfPropertyValue.Get< int >() );
+        }
+        else if( alignSelfPropertyValue.GetType() == Property::STRING )
+        {
+          std::string value = alignSelfPropertyValue.Get<std::string>();
+          Scripting::GetEnumeration< Toolkit::FlexContainer::Alignment >( value.c_str(),
+                                                                          ALIGN_SELF_STRING_TABLE,
+                                                                          ALIGN_SELF_STRING_TABLE_COUNT,
+                                                                          alignSelf );
+        }
+        childNode->style.align_self = static_cast<css_align_t>(alignSelf);
+      }
+
+      if( childActor.GetPropertyIndex( FLEX_PADDING_PROPERTY_NAME ) != Property::INVALID_INDEX )
+      {
+        Vector4 flexPadding = childActor.GetProperty( childActor.GetPropertyIndex(FLEX_PADDING_PROPERTY_NAME) ).Get<Vector4>();
+        childNode->style.padding[CSS_LEFT] = flexPadding.x;
+        childNode->style.padding[CSS_TOP] = flexPadding.y;
+        childNode->style.padding[CSS_RIGHT] = flexPadding.z;
+        childNode->style.padding[CSS_BOTTOM] = flexPadding.w;
+      }
+
+      if( childActor.GetPropertyIndex( FLEX_BORDER_PROPERTY_NAME ) != Property::INVALID_INDEX )
+      {
+        Vector4 flexBorder = childActor.GetProperty( childActor.GetPropertyIndex(FLEX_BORDER_PROPERTY_NAME) ).Get<Vector4>();
+        childNode->style.border[CSS_LEFT] = flexBorder.x;
+        childNode->style.border[CSS_TOP] = flexBorder.y;
+        childNode->style.border[CSS_RIGHT] = flexBorder.z;
+        childNode->style.border[CSS_BOTTOM] = flexBorder.w;
+      }
+
+      if( childActor.GetPropertyIndex( FLEX_MARGIN_PROPERTY_NAME ) != Property::INVALID_INDEX )
+      {
+        Vector4 flexMargin = childActor.GetProperty( childActor.GetPropertyIndex(FLEX_MARGIN_PROPERTY_NAME) ).Get<Vector4>();
+        childNode->style.margin[CSS_LEFT] = flexMargin.x;
+        childNode->style.margin[CSS_TOP] = flexMargin.y;
+        childNode->style.margin[CSS_RIGHT] = flexMargin.z;
+        childNode->style.margin[CSS_BOTTOM] = flexMargin.w;
+      }
+    }
+
+    // Calculate the layout
+    layoutNode( mRootNode.node, Self().GetMaximumSize().x, Self().GetMaximumSize().y, mRootNode.node->style.direction );
+  }
+}
+
+void FlexContainer::RelayoutChildren()
+{
+  ComputeLayout();
+
+  // Set size and position of children according to the layout calculation
+  for( unsigned int i = 0; i < mChildrenNodes.size(); i++ )
+  {
+    Dali::Actor child = mChildrenNodes[i].actor.GetHandle();
+    if( child )
+    {
+      child.SetX( mChildrenNodes[i].node->layout.position[CSS_LEFT] );
+      child.SetY( mChildrenNodes[i].node->layout.position[CSS_TOP] );
+    }
+  }
+}
+
+Actor FlexContainer::GetNextKeyboardFocusableActor(Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled)
+{
+  Actor nextFocusableActor;
+
+  // First check whether there is any items in the container
+  if( mChildrenNodes.size() > 0 )
+  {
+    if ( !currentFocusedActor || currentFocusedActor == Self() )
+    {
+      // Nothing is currently focused, so the first child in the container should be focused.
+      nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
+    }
+    else
+    {
+      // Check whether the current focused actor is within flex container
+      int currentFocusedActorIndex = -1;
+      for( unsigned int index = 0; index < mChildrenNodes.size(); index++ )
+      {
+        if( currentFocusedActor == mChildrenNodes[index].actor.GetHandle() )
+        {
+          currentFocusedActorIndex = index;
+          break;
+        }
+      }
+
+      if( currentFocusedActorIndex > -1 )
+      {
+        int previousCheckedActorIndex = -1;
+        int nextFocusedActorIndex = currentFocusedActorIndex;
+        switch ( direction )
+        {
+          case Toolkit::Control::KeyboardFocus::LEFT:
+          case Toolkit::Control::KeyboardFocus::UP:
+          {
+            // Search the next focusable actor in the backward direction
+            do
+            {
+              nextFocusedActorIndex--;
+              if( nextFocusedActorIndex < 0 )
+              {
+                nextFocusedActorIndex = loopEnabled ? mChildrenNodes.size() - 1 : 0;
+              }
+              if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
+              {
+                previousCheckedActorIndex = nextFocusedActorIndex;
+              }
+              else
+              {
+                break;
+              }
+            } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().IsKeyboardFocusable() );
+            break;
+          }
+          case Toolkit::Control::KeyboardFocus::RIGHT:
+          case Toolkit::Control::KeyboardFocus::DOWN:
+          {
+            // Search the next focusable actor in the forward direction
+            do
+            {
+              nextFocusedActorIndex++;
+              if( nextFocusedActorIndex > static_cast<int>(mChildrenNodes.size() - 1) )
+              {
+                nextFocusedActorIndex = loopEnabled ? 0 : mChildrenNodes.size() - 1;
+              }
+              if( nextFocusedActorIndex != previousCheckedActorIndex && nextFocusedActorIndex != currentFocusedActorIndex )
+              {
+                previousCheckedActorIndex = nextFocusedActorIndex;
+              }
+              else
+              {
+                break;
+              }
+            } while ( !mChildrenNodes[nextFocusedActorIndex].actor.GetHandle().IsKeyboardFocusable() );
+            break;
+          }
+        }
+
+        if( nextFocusedActorIndex != currentFocusedActorIndex )
+        {
+          nextFocusableActor = mChildrenNodes[nextFocusedActorIndex].actor.GetHandle();
+        }
+        else
+        {
+          // No focusble child in the container
+          nextFocusableActor = Actor();
+        }
+      }
+      else
+      {
+        // The current focused actor is not within flex container, so the first child in the container should be focused.
+        nextFocusableActor = mChildrenNodes[0].actor.GetHandle();
+      }
+    }
+  }
+
+  return nextFocusableActor;
+}
+
+FlexContainer::FlexContainer()
+: Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
+  mContentDirection( Toolkit::FlexContainer::INHERIT ),
+  mFlexDirection( Toolkit::FlexContainer::COLUMN ),
+  mFlexWrap( Toolkit::FlexContainer::NO_WRAP ),
+  mJustifyContent( Toolkit::FlexContainer::JUSTIFY_FLEX_START ),
+  mAlignItems( Toolkit::FlexContainer::ALIGN_STRETCH ),
+  mAlignContent( Toolkit::FlexContainer::ALIGN_FLEX_START )
+{
+  SetKeyboardNavigationSupport( true );
+}
+
+void FlexContainer::OnInitialize()
+{
+  // Initialize the node for the flex container itself
+  Dali::Actor self = Self();
+  mRootNode.actor = self;
+  mRootNode.node = new_css_node();
+  mRootNode.node->context = &mChildrenNodes;
+
+  // Set default style
+  mRootNode.node->style.direction = static_cast<css_direction_t>( mContentDirection );
+  mRootNode.node->style.flex_direction = static_cast<css_flex_direction_t>( mFlexDirection );
+  mRootNode.node->style.flex_wrap = static_cast<css_wrap_type_t>( mFlexWrap );
+  mRootNode.node->style.justify_content = static_cast<css_justify_t>( mJustifyContent );
+  mRootNode.node->style.align_items = static_cast<css_align_t>( mAlignItems );
+  mRootNode.node->style.align_content = static_cast<css_align_t>( mAlignContent );
+
+  // Set callbacks.
+  mRootNode.node->get_child = GetChildNodeAtIndex;
+  mRootNode.node->is_dirty = IsNodeDirty;
+
+  // Make self as keyboard focusable and focus group
+  self.SetKeyboardFocusable( true );
+  SetAsKeyboardFocusGroup( true );
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/controls/flex-container/flex-container-impl.h b/dali-toolkit/internal/controls/flex-container/flex-container-impl.h
new file mode 100644 (file)
index 0000000..58c25b6
--- /dev/null
@@ -0,0 +1,275 @@
+#ifndef __DALI_TOOLKIT_INTERNAL_FLEX_CONTAINER_H__
+#define __DALI_TOOLKIT_INTERNAL_FLEX_CONTAINER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/devel-api/object/weak-handle.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/controls/control-impl.h>
+#include <dali-toolkit/devel-api/controls/flex-container/flex-container.h>
+extern "C"
+{
+#include "layout.h"
+}
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/**
+ * FlexContainer is a custom control for laying out actors in a flexbox layout
+ * @see Dali::Toolkit:FlexContainer for more details
+ */
+class FlexContainer : public Control
+{
+public:
+
+  /**
+   * The structure to store the style properties and layout information of flex item
+   */
+  struct FlexItemNode
+  {
+    WeakHandle< Dali::Actor > actor;      ///< Actor handle of the flex item
+    css_node_t* node;                     ///< The style properties and layout information
+  };
+
+  typedef std::vector< FlexItemNode > FlexItemNodeContainer;
+
+public:
+
+  /**
+   * Construct a new FlexContainer.
+   */
+  FlexContainer();
+
+  /**
+   * Create a new FlexContainer.
+   * @return A smart-pointer to the newly allocated FlexContainer.
+   */
+  static Toolkit::FlexContainer New();
+
+  /**
+   * @brief Set the primary direction in which content is ordered.
+   * @param[in] contentDirection The direction of the content.
+   */
+  void SetContentDirection(Toolkit::FlexContainer::ContentDirection contentDirection);
+
+  /**
+   * @brief Get the direction of the content.
+   * @return The direction of the content.
+   */
+  Toolkit::FlexContainer::ContentDirection GetContentDirection();
+
+  /**
+   * @brief Set the direction flex items are laid out.
+   * @param[in] flexDirection The direction flex items are laid out.
+   */
+  void SetFlexDirection(Toolkit::FlexContainer::FlexDirection flexDirection);
+
+  /**
+   * @brief Get the direction flex items are laid out.
+   * @return The direction flex items are laid out.
+   */
+  Toolkit::FlexContainer::FlexDirection GetFlexDirection();
+
+  /**
+   * @brief Set whether the flex items should wrap or not, if there
+   * is no enough room for them on one flex line.
+   * @param[in] flexWrap The wrap type.
+   */
+  void SetFlexWrap(Toolkit::FlexContainer::WrapType flexWrap);
+
+  /**
+   * @brief Get whether the flex items should wrap or not, if there
+   * is no enough room for them on one flex line.
+   * @return The wrap type.
+   */
+  Toolkit::FlexContainer::WrapType GetFlexWrap();
+
+  /**
+   * @brief Set the horizontal alignment of the flex items when the items
+   * do not use all available space on the main-axis.
+   * @param[in] justifyContent The horizontal alignment of flex items.
+   */
+  void SetJustifyContent(Toolkit::FlexContainer::Justification justifyContent);
+
+  /**
+   * @brief Get the horizontal alignment of the flex items when the items
+   * do not use all available space on the main-axis.
+   * @return The horizontal alignment of flex items.
+   */
+  Toolkit::FlexContainer::Justification GetJustifyContent();
+
+  /**
+   * @brief Set the vertical alignment of the flex items when the items
+   * do not use all available space on the cross-axis.
+   * @param[in] alignItems The vertical alignment of flex items.
+   */
+  void SetAlignItems(Toolkit::FlexContainer::Alignment alignItems);
+
+  /**
+   * @brief Get the vertical alignment of the flex items when the items
+   * do not use all available space on the cross-axis.
+   * @return The vertical alignment of flex items.
+   */
+  Toolkit::FlexContainer::Alignment GetAlignItems();
+
+  /**
+   * @brief Set the vertical alignment of the flex lines when the lines
+   * do not use all available space on the cross-axis.
+   * @param[in] alignItems The vertical alignment of flex lines.
+   */
+  void SetAlignContent(Toolkit::FlexContainer::Alignment alignContent);
+
+  /**
+   * @brief Get the vertical alignment of the flex lines when the lines
+   * do not use all available space on the cross-axis.
+   * @return The vertical alignment of flex lines.
+   */
+  Toolkit::FlexContainer::Alignment GetAlignContent();
+
+  // Properties
+
+  /**
+   * Called when a property of an object of this type is set.
+   * @param[in] object The object whose property is set.
+   * @param[in] index The property index.
+   * @param[in] value The new property value.
+   */
+  static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value );
+
+  /**
+   * Called to retrieve a property of an object of this type.
+   * @param[in] object The object whose property is to be retrieved.
+   * @param[in] index The property index.
+   * @return The current value of the property.
+   */
+  static Property::Value GetProperty( BaseObject* object, Property::Index index );
+
+private: // From Control
+
+  /**
+   * @copydoc Control::OnInitialize()
+   */
+  virtual void OnInitialize();
+
+  /**
+   * @copydoc Control::OnChildAdd(Actor& child)
+   */
+  virtual void OnChildAdd( Actor& child );
+
+  /**
+   * @copydoc Control::OnChildRemove(Actor& child)
+   */
+  virtual void OnChildRemove( Actor& child );
+
+  /**
+   * @copydoc Control::OnRelayout
+   */
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container );
+
+  /**
+   * @copydoc Control::RelayoutDependentOnChildren()
+   */
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @copydoc Control::GetNextKeyboardFocusableActor
+   */
+  virtual Actor GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled );
+
+  /**
+   * @copydoc CustomActorImpl::OnSizeSet( const Vector3& size )
+   */
+  virtual void OnSizeSet( const Vector3& size );
+
+  /**
+   * @copydoc CustomActorImpl::OnSizeAnimation(Animation&, const Vector3&)
+   */
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize);
+
+private: // Implementation
+
+  /**
+   * Calculate the layout properties of all the children
+   */
+  void ComputeLayout();
+
+  /**
+   * Calculate the layout of the children and relayout them with their new size and position
+   */
+  void RelayoutChildren();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~FlexContainer();
+
+private:
+
+  // Undefined copy constructor and assignment operators
+  FlexContainer(const FlexContainer&);
+  FlexContainer& operator=(const FlexContainer& rhs);
+
+private: // Data
+
+  FlexItemNode mRootNode;                    ///< Style properties and layout information of flex container
+  FlexItemNodeContainer mChildrenNodes;      ///< Style properties and layout information of flex items in the container
+
+  Toolkit::FlexContainer::ContentDirection mContentDirection;        ///< The content direction of the container
+  Toolkit::FlexContainer::FlexDirection mFlexDirection;              ///< The flex direction of the container
+  Toolkit::FlexContainer::WrapType mFlexWrap;                        ///< The wrap type of the container
+  Toolkit::FlexContainer::Justification mJustifyContent;             ///< The alignment of flex items in the container on the main-axis
+  Toolkit::FlexContainer::Alignment mAlignItems;                     ///< The alignment of flex items in the container on the cross-axis
+  Toolkit::FlexContainer::Alignment mAlignContent;                   ///< The alignment of flex lines in the container on the cross-axis
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Toolkit::Internal::FlexContainer& GetImpl( Toolkit::FlexContainer& tableView )
+{
+  DALI_ASSERT_ALWAYS(tableView);
+
+  Dali::RefObject& handle = tableView.GetImplementation();
+
+  return static_cast<Toolkit::Internal::FlexContainer&>(handle);
+}
+
+inline const Toolkit::Internal::FlexContainer& GetImpl( const Toolkit::FlexContainer& tableView )
+{
+  DALI_ASSERT_ALWAYS(tableView);
+
+  const Dali::RefObject& handle = tableView.GetImplementation();
+
+  return static_cast<const Toolkit::Internal::FlexContainer&>(handle);
+}
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_INTERNAL_FLEX_CONTAINER_H__
diff --git a/dali-toolkit/internal/controls/flex-container/layout.c b/dali-toolkit/internal/controls/flex-container/layout.c
new file mode 100644 (file)
index 0000000..618d01b
--- /dev/null
@@ -0,0 +1,1371 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// in concatenated header, don't include Layout.h it's already at the top
+#ifndef CSS_LAYOUT_IMPLEMENTATION
+#include "layout.h"
+#endif
+
+#ifdef _MSC_VER
+#include <float.h>
+#define isnan _isnan
+
+/* define fmaxf if < VC12 */
+#if _MSC_VER < 1800
+__forceinline const float fmaxf(const float a, const float b) {
+  return (a > b) ? a : b;
+}
+#endif
+#endif
+
+bool isUndefined(float value) {
+  return isnan(value);
+}
+
+static bool eq(float a, float b) {
+  if (isUndefined(a)) {
+    return isUndefined(b);
+  }
+  return fabs(a - b) < 0.0001;
+}
+
+void init_css_node(css_node_t *node) {
+  node->style.align_items = CSS_ALIGN_STRETCH;
+  node->style.align_content = CSS_ALIGN_FLEX_START;
+
+  node->style.direction = CSS_DIRECTION_INHERIT;
+  node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
+
+  // Some of the fields default to undefined and not 0
+  node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
+  node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+
+  node->style.minDimensions[CSS_WIDTH] = CSS_UNDEFINED;
+  node->style.minDimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+
+  node->style.maxDimensions[CSS_WIDTH] = CSS_UNDEFINED;
+  node->style.maxDimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+
+  node->style.position[CSS_LEFT] = CSS_UNDEFINED;
+  node->style.position[CSS_TOP] = CSS_UNDEFINED;
+  node->style.position[CSS_RIGHT] = CSS_UNDEFINED;
+  node->style.position[CSS_BOTTOM] = CSS_UNDEFINED;
+
+  node->style.margin[CSS_START] = CSS_UNDEFINED;
+  node->style.margin[CSS_END] = CSS_UNDEFINED;
+  node->style.padding[CSS_START] = CSS_UNDEFINED;
+  node->style.padding[CSS_END] = CSS_UNDEFINED;
+  node->style.border[CSS_START] = CSS_UNDEFINED;
+  node->style.border[CSS_END] = CSS_UNDEFINED;
+
+  node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
+  node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+
+  // Such that the comparison is always going to be false
+  node->layout.last_requested_dimensions[CSS_WIDTH] = -1;
+  node->layout.last_requested_dimensions[CSS_HEIGHT] = -1;
+  node->layout.last_parent_max_width = -1;
+  node->layout.last_parent_max_height = -1;
+  node->layout.last_direction = (css_direction_t)-1;
+  node->layout.should_update = true;
+}
+
+css_node_t *new_css_node() {
+  css_node_t *node = (css_node_t *)calloc(1, sizeof(*node));
+  init_css_node(node);
+  return node;
+}
+
+void free_css_node(css_node_t *node) {
+  free(node);
+}
+
+static void indent(int n) {
+  int i;
+  for (i = 0; i < n; ++i) {
+    printf("  ");
+  }
+}
+
+static void print_number_0(const char *str, float number) {
+  if (!eq(number, 0)) {
+    printf("%s: %g, ", str, number);
+  }
+}
+
+static void print_number_nan(const char *str, float number) {
+  if (!isnan(number)) {
+    printf("%s: %g, ", str, number);
+  }
+}
+
+static bool four_equal(float four[4]) {
+  return
+    eq(four[0], four[1]) &&
+    eq(four[0], four[2]) &&
+    eq(four[0], four[3]);
+}
+
+
+static void print_css_node_rec(
+  css_node_t *node,
+  css_print_options_t options,
+  int level
+) {
+  indent(level);
+  printf("{");
+
+  if (node->print) {
+    node->print(node->context);
+  }
+
+  if (options & CSS_PRINT_LAYOUT) {
+    printf("layout: {");
+    printf("width: %g, ", node->layout.dimensions[CSS_WIDTH]);
+    printf("height: %g, ", node->layout.dimensions[CSS_HEIGHT]);
+    printf("top: %g, ", node->layout.position[CSS_TOP]);
+    printf("left: %g", node->layout.position[CSS_LEFT]);
+    printf("}, ");
+  }
+
+  if (options & CSS_PRINT_STYLE) {
+    if (node->style.direction == CSS_DIRECTION_INHERIT) {
+      printf("direction: 'inherit', ");
+    } else if (node->style.direction == CSS_DIRECTION_LTR) {
+      printf("direction: 'LTR', ");
+    } else if (node->style.direction == CSS_DIRECTION_RTL) {
+      printf("direction: 'RTL', ");
+    }
+
+    if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN) {
+      printf("flexDirection: 'column', ");
+    } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+      printf("flexDirection: 'columnReverse', ");
+    } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) {
+      printf("flexDirection: 'row', ");
+    } else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
+      printf("flexDirection: 'rowReverse', ");
+    }
+
+    if (node->style.justify_content == CSS_JUSTIFY_FLEX_START) {
+      printf("justifyContent: 'flex-start', ");
+    } else if (node->style.justify_content == CSS_JUSTIFY_CENTER) {
+      printf("justifyContent: 'center', ");
+    } else if (node->style.justify_content == CSS_JUSTIFY_FLEX_END) {
+      printf("justifyContent: 'flex-end', ");
+    } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_AROUND) {
+      printf("justifyContent: 'space-around', ");
+    } else if (node->style.justify_content == CSS_JUSTIFY_SPACE_BETWEEN) {
+      printf("justifyContent: 'space-between', ");
+    }
+
+    if (node->style.align_items == CSS_ALIGN_FLEX_START) {
+      printf("alignItems: 'flex-start', ");
+    } else if (node->style.align_items == CSS_ALIGN_CENTER) {
+      printf("alignItems: 'center', ");
+    } else if (node->style.align_items == CSS_ALIGN_FLEX_END) {
+      printf("alignItems: 'flex-end', ");
+    } else if (node->style.align_items == CSS_ALIGN_STRETCH) {
+      printf("alignItems: 'stretch', ");
+    }
+
+    if (node->style.align_content == CSS_ALIGN_FLEX_START) {
+      printf("alignContent: 'flex-start', ");
+    } else if (node->style.align_content == CSS_ALIGN_CENTER) {
+      printf("alignContent: 'center', ");
+    } else if (node->style.align_content == CSS_ALIGN_FLEX_END) {
+      printf("alignContent: 'flex-end', ");
+    } else if (node->style.align_content == CSS_ALIGN_STRETCH) {
+      printf("alignContent: 'stretch', ");
+    }
+
+    if (node->style.align_self == CSS_ALIGN_FLEX_START) {
+      printf("alignSelf: 'flex-start', ");
+    } else if (node->style.align_self == CSS_ALIGN_CENTER) {
+      printf("alignSelf: 'center', ");
+    } else if (node->style.align_self == CSS_ALIGN_FLEX_END) {
+      printf("alignSelf: 'flex-end', ");
+    } else if (node->style.align_self == CSS_ALIGN_STRETCH) {
+      printf("alignSelf: 'stretch', ");
+    } else if (node->style.align_self == CSS_ALIGN_AUTO) {
+      printf("alignSelf: 'auto', ");
+    }
+
+    if (node->style.flex_wrap == CSS_NOWRAP) {
+      printf("flexWrap: 'no-wrap', ");
+    } else if (node->style.flex_wrap == CSS_WRAP) {
+      printf("flexWrap: 'wrap', ");
+    }
+
+    print_number_nan("flex", node->style.flex);
+
+    if (four_equal(node->style.margin)) {
+      print_number_0("margin", node->style.margin[CSS_LEFT]);
+    } else {
+      print_number_0("marginLeft", node->style.margin[CSS_LEFT]);
+      print_number_0("marginRight", node->style.margin[CSS_RIGHT]);
+      print_number_0("marginTop", node->style.margin[CSS_TOP]);
+      print_number_0("marginBottom", node->style.margin[CSS_BOTTOM]);
+      print_number_0("marginStart", node->style.margin[CSS_START]);
+      print_number_0("marginEnd", node->style.margin[CSS_END]);
+    }
+
+    if (four_equal(node->style.padding)) {
+      print_number_0("padding", node->style.margin[CSS_LEFT]);
+    } else {
+      print_number_0("paddingLeft", node->style.padding[CSS_LEFT]);
+      print_number_0("paddingRight", node->style.padding[CSS_RIGHT]);
+      print_number_0("paddingTop", node->style.padding[CSS_TOP]);
+      print_number_0("paddingBottom", node->style.padding[CSS_BOTTOM]);
+      print_number_0("paddingStart", node->style.padding[CSS_START]);
+      print_number_0("paddingEnd", node->style.padding[CSS_END]);
+    }
+
+    if (four_equal(node->style.border)) {
+      print_number_0("borderWidth", node->style.border[CSS_LEFT]);
+    } else {
+      print_number_0("borderLeftWidth", node->style.border[CSS_LEFT]);
+      print_number_0("borderRightWidth", node->style.border[CSS_RIGHT]);
+      print_number_0("borderTopWidth", node->style.border[CSS_TOP]);
+      print_number_0("borderBottomWidth", node->style.border[CSS_BOTTOM]);
+      print_number_0("borderStartWidth", node->style.border[CSS_START]);
+      print_number_0("borderEndWidth", node->style.border[CSS_END]);
+    }
+
+    print_number_nan("width", node->style.dimensions[CSS_WIDTH]);
+    print_number_nan("height", node->style.dimensions[CSS_HEIGHT]);
+
+    if(node->style.minDimensions[CSS_WIDTH] != CSS_UNDEFINED) {
+      print_number_nan("minWidth", node->style.minDimensions[CSS_WIDTH]);
+    }
+    if(node->style.minDimensions[CSS_HEIGHT] != CSS_UNDEFINED) {
+      print_number_nan("minHeight", node->style.minDimensions[CSS_HEIGHT]);
+    }
+    if(node->style.maxDimensions[CSS_WIDTH] != CSS_UNDEFINED) {
+      print_number_nan("maxWidth", node->style.maxDimensions[CSS_WIDTH]);
+    }
+    if(node->style.maxDimensions[CSS_HEIGHT] != CSS_UNDEFINED) {
+      print_number_nan("maxHeight", node->style.maxDimensions[CSS_HEIGHT]);
+    }
+
+    if (node->style.position_type == CSS_POSITION_ABSOLUTE) {
+      printf("position: 'absolute', ");
+    }
+    else if (node->style.position_type == CSS_POSITION_RELATIVE) {
+      printf("position: 'relative', ");
+    }
+
+    print_number_nan("position-left", node->style.position[CSS_LEFT]);
+    print_number_nan("position-right", node->style.position[CSS_RIGHT]);
+    print_number_nan("position-top", node->style.position[CSS_TOP]);
+    print_number_nan("position-bottom", node->style.position[CSS_BOTTOM]);
+  }
+
+  if (options & CSS_PRINT_CHILDREN && node->children_count > 0) {
+    printf("children: [\n");
+    int i;
+    for (i = 0; i < node->children_count; ++i) {
+      print_css_node_rec(node->get_child(node->context, i), options, level + 1);
+    }
+    indent(level);
+    printf("]},\n");
+  } else {
+    printf("},\n");
+  }
+}
+
+void print_css_node(css_node_t *node, css_print_options_t options) {
+  print_css_node_rec(node, options, 0);
+}
+
+
+static css_position_t leading[4] = {
+  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
+  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
+  /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
+  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
+};
+static css_position_t trailing[4] = {
+  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM,
+  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_TOP,
+  /* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT,
+  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_LEFT
+};
+static css_position_t pos[4] = {
+  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
+  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
+  /* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
+  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
+};
+static css_dimension_t dim[4] = {
+  /* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT,
+  /* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_HEIGHT,
+  /* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH,
+  /* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_WIDTH
+};
+
+static bool isRowDirection(css_flex_direction_t flex_direction) {
+  return flex_direction == CSS_FLEX_DIRECTION_ROW ||
+         flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE;
+}
+
+static bool isColumnDirection(css_flex_direction_t flex_direction) {
+  return flex_direction == CSS_FLEX_DIRECTION_COLUMN ||
+         flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE;
+}
+
+static float getLeadingMargin(css_node_t *node, css_flex_direction_t axis) {
+  if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_START])) {
+    return node->style.margin[CSS_START];
+  }
+
+  return node->style.margin[leading[axis]];
+}
+
+static float getTrailingMargin(css_node_t *node, css_flex_direction_t axis) {
+  if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_END])) {
+    return node->style.margin[CSS_END];
+  }
+
+  return node->style.margin[trailing[axis]];
+}
+
+static float getLeadingPadding(css_node_t *node, css_flex_direction_t axis) {
+  if (isRowDirection(axis) &&
+      !isUndefined(node->style.padding[CSS_START]) &&
+      node->style.padding[CSS_START] >= 0) {
+    return node->style.padding[CSS_START];
+  }
+
+  if (node->style.padding[leading[axis]] >= 0) {
+    return node->style.padding[leading[axis]];
+  }
+
+  return 0;
+}
+
+static float getTrailingPadding(css_node_t *node, css_flex_direction_t axis) {
+  if (isRowDirection(axis) &&
+      !isUndefined(node->style.padding[CSS_END]) &&
+      node->style.padding[CSS_END] >= 0) {
+    return node->style.padding[CSS_END];
+  }
+
+  if (node->style.padding[trailing[axis]] >= 0) {
+    return node->style.padding[trailing[axis]];
+  }
+
+  return 0;
+}
+
+static float getLeadingBorder(css_node_t *node, css_flex_direction_t axis) {
+  if (isRowDirection(axis) &&
+      !isUndefined(node->style.border[CSS_START]) &&
+      node->style.border[CSS_START] >= 0) {
+    return node->style.border[CSS_START];
+  }
+
+  if (node->style.border[leading[axis]] >= 0) {
+    return node->style.border[leading[axis]];
+  }
+
+  return 0;
+}
+
+static float getTrailingBorder(css_node_t *node, css_flex_direction_t axis) {
+  if (isRowDirection(axis) &&
+      !isUndefined(node->style.border[CSS_END]) &&
+      node->style.border[CSS_END] >= 0) {
+    return node->style.border[CSS_END];
+  }
+
+  if (node->style.border[trailing[axis]] >= 0) {
+    return node->style.border[trailing[axis]];
+  }
+
+  return 0;
+}
+
+static float getLeadingPaddingAndBorder(css_node_t *node, css_flex_direction_t axis) {
+  return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
+}
+
+static float getTrailingPaddingAndBorder(css_node_t *node, css_flex_direction_t axis) {
+  return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
+}
+
+static float getBorderAxis(css_node_t *node, css_flex_direction_t axis) {
+  return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);
+}
+
+static float getMarginAxis(css_node_t *node, css_flex_direction_t axis) {
+  return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
+}
+
+static float getPaddingAndBorderAxis(css_node_t *node, css_flex_direction_t axis) {
+  return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis);
+}
+
+static css_align_t getAlignItem(css_node_t *node, css_node_t *child) {
+  if (child->style.align_self != CSS_ALIGN_AUTO) {
+    return child->style.align_self;
+  }
+  return node->style.align_items;
+}
+
+static css_direction_t resolveDirection(css_node_t *node, css_direction_t parentDirection) {
+  css_direction_t direction = node->style.direction;
+
+  if (direction == CSS_DIRECTION_INHERIT) {
+    direction = parentDirection > CSS_DIRECTION_INHERIT ? parentDirection : CSS_DIRECTION_LTR;
+  }
+
+  return direction;
+}
+
+static css_flex_direction_t getFlexDirection(css_node_t *node) {
+  return node->style.flex_direction;
+}
+
+static css_flex_direction_t resolveAxis(css_flex_direction_t flex_direction, css_direction_t direction) {
+  if (direction == CSS_DIRECTION_RTL) {
+    if (flex_direction == CSS_FLEX_DIRECTION_ROW) {
+      return CSS_FLEX_DIRECTION_ROW_REVERSE;
+    } else if (flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
+      return CSS_FLEX_DIRECTION_ROW;
+    }
+  }
+
+  return flex_direction;
+}
+
+static css_flex_direction_t getCrossFlexDirection(css_flex_direction_t flex_direction, css_direction_t direction) {
+  if (isColumnDirection(flex_direction)) {
+    return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
+  } else {
+    return CSS_FLEX_DIRECTION_COLUMN;
+  }
+}
+
+static float getFlex(css_node_t *node) {
+  return node->style.flex;
+}
+
+static bool isFlex(css_node_t *node) {
+  return (
+    node->style.position_type == CSS_POSITION_RELATIVE &&
+    getFlex(node) > 0
+  );
+}
+
+static bool isFlexWrap(css_node_t *node) {
+  return node->style.flex_wrap == CSS_WRAP;
+}
+
+static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) {
+  return node->layout.dimensions[dim[axis]] +
+    getLeadingMargin(node, axis) +
+    getTrailingMargin(node, axis);
+}
+
+static bool isStyleDimDefined(css_node_t *node, css_flex_direction_t axis) {
+  float value = node->style.dimensions[dim[axis]];
+  return !isUndefined(value) && value >= 0.0;
+}
+
+static bool isLayoutDimDefined(css_node_t *node, css_flex_direction_t axis) {
+  float value = node->layout.dimensions[dim[axis]];
+  return !isUndefined(value) && value >= 0.0;
+}
+
+static bool isPosDefined(css_node_t *node, css_position_t position) {
+  return !isUndefined(node->style.position[position]);
+}
+
+static bool isMeasureDefined(css_node_t *node) {
+  return node->measure;
+}
+
+static float getPosition(css_node_t *node, css_position_t position) {
+  float result = node->style.position[position];
+  if (!isUndefined(result)) {
+    return result;
+  }
+  return 0;
+}
+
+static float boundAxis(css_node_t *node, css_flex_direction_t axis, float value) {
+  float min = CSS_UNDEFINED;
+  float max = CSS_UNDEFINED;
+
+  if (isColumnDirection(axis)) {
+    min = node->style.minDimensions[CSS_HEIGHT];
+    max = node->style.maxDimensions[CSS_HEIGHT];
+  } else if (isRowDirection(axis)) {
+    min = node->style.minDimensions[CSS_WIDTH];
+    max = node->style.maxDimensions[CSS_WIDTH];
+  }
+
+  float boundValue = value;
+
+  if (!isUndefined(max) && max >= 0.0 && boundValue > max) {
+    boundValue = max;
+  }
+  if (!isUndefined(min) && min >= 0.0 && boundValue < min) {
+    boundValue = min;
+  }
+
+  return boundValue;
+}
+
+// When the user specifically sets a value for width or height
+static void setDimensionFromStyle(css_node_t *node, css_flex_direction_t axis) {
+  // The parent already computed us a width or height. We just skip it
+  if (isLayoutDimDefined(node, axis)) {
+    return;
+  }
+  // We only run if there's a width or height defined
+  if (!isStyleDimDefined(node, axis)) {
+    return;
+  }
+
+  // The dimensions can never be smaller than the padding and border
+  node->layout.dimensions[dim[axis]] = fmaxf(
+    boundAxis(node, axis, node->style.dimensions[dim[axis]]),
+    getPaddingAndBorderAxis(node, axis)
+  );
+}
+
+static void setTrailingPosition(css_node_t *node, css_node_t *child, css_flex_direction_t axis) {
+    child->layout.position[trailing[axis]] = node->layout.dimensions[dim[axis]] -
+      child->layout.dimensions[dim[axis]] - child->layout.position[pos[axis]];
+  }
+
+// If both left and right are defined, then use left. Otherwise return
+// +left or -right depending on which is defined.
+static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
+  float lead = node->style.position[leading[axis]];
+  if (!isUndefined(lead)) {
+    return lead;
+  }
+  return -getPosition(node, trailing[axis]);
+}
+
+static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentMaxHeight, css_direction_t parentDirection) {
+  /** START_GENERATED **/
+  css_direction_t direction = resolveDirection(node, parentDirection);
+  css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
+  css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
+  css_flex_direction_t resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
+
+  // Handle width and height style attributes
+  setDimensionFromStyle(node, mainAxis);
+  setDimensionFromStyle(node, crossAxis);
+
+  // Set the resolved resolution in the node's layout
+  node->layout.direction = direction;
+
+  // The position is set by the parent, but we need to complete it with a
+  // delta composed of the margin and left/top/right/bottom
+  node->layout.position[leading[mainAxis]] += getLeadingMargin(node, mainAxis) +
+    getRelativePosition(node, mainAxis);
+  node->layout.position[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) +
+    getRelativePosition(node, mainAxis);
+  node->layout.position[leading[crossAxis]] += getLeadingMargin(node, crossAxis) +
+    getRelativePosition(node, crossAxis);
+  node->layout.position[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) +
+    getRelativePosition(node, crossAxis);
+
+  // Inline immutable values from the target node to avoid excessive method
+  // invocations during the layout calculation.
+  int childCount = node->children_count;
+  float paddingAndBorderAxisResolvedRow = getPaddingAndBorderAxis(node, resolvedRowAxis);
+  float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
+
+  if (isMeasureDefined(node)) {
+    bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis);
+
+    float width = CSS_UNDEFINED;
+    css_measure_mode_t widthMode = CSS_MEASURE_MODE_UNDEFINED;
+    if (isStyleDimDefined(node, resolvedRowAxis)) {
+      width = node->style.dimensions[CSS_WIDTH];
+      widthMode = CSS_MEASURE_MODE_EXACTLY;
+    } else if (isResolvedRowDimDefined) {
+      width = node->layout.dimensions[dim[resolvedRowAxis]];
+      widthMode = CSS_MEASURE_MODE_EXACTLY;
+    } else {
+      width = parentMaxWidth -
+        getMarginAxis(node, resolvedRowAxis);
+      widthMode = CSS_MEASURE_MODE_AT_MOST;
+    }
+    width -= paddingAndBorderAxisResolvedRow;
+    if (isUndefined(width)) {
+      widthMode = CSS_MEASURE_MODE_UNDEFINED;
+    }
+
+    float height = CSS_UNDEFINED;
+    css_measure_mode_t heightMode = CSS_MEASURE_MODE_UNDEFINED;
+    if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
+      height = node->style.dimensions[CSS_HEIGHT];
+      heightMode = CSS_MEASURE_MODE_EXACTLY;
+    } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
+      height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
+      heightMode = CSS_MEASURE_MODE_EXACTLY;
+    } else {
+      height = parentMaxHeight -
+        getMarginAxis(node, resolvedRowAxis);
+      heightMode = CSS_MEASURE_MODE_AT_MOST;
+    }
+    height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
+    if (isUndefined(height)) {
+      heightMode = CSS_MEASURE_MODE_UNDEFINED;
+    }
+
+    // We only need to give a dimension for the text if we haven't got any
+    // for it computed yet. It can either be from the style attribute or because
+    // the element is flexible.
+    bool isRowUndefined = !isStyleDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined;
+    bool isColumnUndefined = !isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
+      isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);
+
+    // Let's not measure the text if we already know both dimensions
+    if (isRowUndefined || isColumnUndefined) {
+      css_dim_t measureDim = node->measure(
+        node->context,
+        width,
+        widthMode,
+        height,
+        heightMode
+      );
+      if (isRowUndefined) {
+        node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
+          paddingAndBorderAxisResolvedRow;
+      }
+      if (isColumnUndefined) {
+        node->layout.dimensions[CSS_HEIGHT] = measureDim.dimensions[CSS_HEIGHT] +
+          paddingAndBorderAxisColumn;
+      }
+    }
+    if (childCount == 0) {
+      return;
+    }
+  }
+
+  bool isNodeFlexWrap = isFlexWrap(node);
+
+  css_justify_t justifyContent = node->style.justify_content;
+
+  float leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);
+  float leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
+  float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
+  float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
+
+  bool isMainDimDefined = isLayoutDimDefined(node, mainAxis);
+  bool isCrossDimDefined = isLayoutDimDefined(node, crossAxis);
+  bool isMainRowDirection = isRowDirection(mainAxis);
+
+  int i;
+  int ii;
+  css_node_t* child;
+  css_flex_direction_t axis;
+
+  css_node_t* firstAbsoluteChild = NULL;
+  css_node_t* currentAbsoluteChild = NULL;
+
+  float definedMainDim = CSS_UNDEFINED;
+  if (isMainDimDefined) {
+    definedMainDim = node->layout.dimensions[dim[mainAxis]] - paddingAndBorderAxisMain;
+  }
+
+  // We want to execute the next two loops one per line with flex-wrap
+  int startLine = 0;
+  int endLine = 0;
+  // int nextOffset = 0;
+  int alreadyComputedNextLayout = 0;
+  // We aggregate the total dimensions of the container in those two variables
+  float linesCrossDim = 0;
+  float linesMainDim = 0;
+  int linesCount = 0;
+  while (endLine < childCount) {
+    // <Loop A> Layout non flexible children and count children by type
+
+    // mainContentDim is accumulation of the dimensions and margin of all the
+    // non flexible children. This will be used in order to either set the
+    // dimensions of the node if none already exist, or to compute the
+    // remaining space left for the flexible children.
+    float mainContentDim = 0;
+
+    // There are three kind of children, non flexible, flexible and absolute.
+    // We need to know how many there are in order to distribute the space.
+    int flexibleChildrenCount = 0;
+    float totalFlexible = 0;
+    int nonFlexibleChildrenCount = 0;
+
+    // Use the line loop to position children in the main axis for as long
+    // as they are using a simple stacking behaviour. Children that are
+    // immediately stacked in the initial loop will not be touched again
+    // in <Loop C>.
+    bool isSimpleStackMain =
+        (isMainDimDefined && justifyContent == CSS_JUSTIFY_FLEX_START) ||
+        (!isMainDimDefined && justifyContent != CSS_JUSTIFY_CENTER);
+    int firstComplexMain = (isSimpleStackMain ? childCount : startLine);
+
+    // Use the initial line loop to position children in the cross axis for
+    // as long as they are relatively positioned with alignment STRETCH or
+    // FLEX_START. Children that are immediately stacked in the initial loop
+    // will not be touched again in <Loop D>.
+    bool isSimpleStackCross = true;
+    int firstComplexCross = childCount;
+
+    css_node_t* firstFlexChild = NULL;
+    css_node_t* currentFlexChild = NULL;
+
+    float mainDim = leadingPaddingAndBorderMain;
+    float crossDim = 0;
+
+    float maxWidth = CSS_UNDEFINED;
+    float maxHeight = CSS_UNDEFINED;
+    for (i = startLine; i < childCount; ++i) {
+      child = node->get_child(node->context, i);
+      child->line_index = linesCount;
+
+      child->next_absolute_child = NULL;
+      child->next_flex_child = NULL;
+
+      css_align_t alignItem = getAlignItem(node, child);
+
+      // Pre-fill cross axis dimensions when the child is using stretch before
+      // we call the recursive layout pass
+      if (alignItem == CSS_ALIGN_STRETCH &&
+          child->style.position_type == CSS_POSITION_RELATIVE &&
+          isCrossDimDefined &&
+          !isStyleDimDefined(child, crossAxis)) {
+        child->layout.dimensions[dim[crossAxis]] = fmaxf(
+          boundAxis(child, crossAxis, node->layout.dimensions[dim[crossAxis]] -
+            paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
+          // You never want to go smaller than padding
+          getPaddingAndBorderAxis(child, crossAxis)
+        );
+      } else if (child->style.position_type == CSS_POSITION_ABSOLUTE) {
+        // Store a private linked list of absolutely positioned children
+        // so that we can efficiently traverse them later.
+        if (firstAbsoluteChild == NULL) {
+          firstAbsoluteChild = child;
+        }
+        if (currentAbsoluteChild != NULL) {
+          currentAbsoluteChild->next_absolute_child = child;
+        }
+        currentAbsoluteChild = child;
+
+        // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
+        // left and right or top and bottom).
+        for (ii = 0; ii < 2; ii++) {
+          axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
+          if (isLayoutDimDefined(node, axis) &&
+              !isStyleDimDefined(child, axis) &&
+              isPosDefined(child, leading[axis]) &&
+              isPosDefined(child, trailing[axis])) {
+            child->layout.dimensions[dim[axis]] = fmaxf(
+              boundAxis(child, axis, node->layout.dimensions[dim[axis]] -
+                getPaddingAndBorderAxis(node, axis) -
+                getMarginAxis(child, axis) -
+                getPosition(child, leading[axis]) -
+                getPosition(child, trailing[axis])),
+              // You never want to go smaller than padding
+              getPaddingAndBorderAxis(child, axis)
+            );
+          }
+        }
+      }
+
+      float nextContentDim = 0;
+
+      // It only makes sense to consider a child flexible if we have a computed
+      // dimension for the node->
+      if (isMainDimDefined && isFlex(child)) {
+        flexibleChildrenCount++;
+        totalFlexible += child->style.flex;
+
+        // Store a private linked list of flexible children so that we can
+        // efficiently traverse them later.
+        if (firstFlexChild == NULL) {
+          firstFlexChild = child;
+        }
+        if (currentFlexChild != NULL) {
+          currentFlexChild->next_flex_child = child;
+        }
+        currentFlexChild = child;
+
+        // Even if we don't know its exact size yet, we already know the padding,
+        // border and margin. We'll use this partial information, which represents
+        // the smallest possible size for the child, to compute the remaining
+        // available space.
+        nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +
+          getMarginAxis(child, mainAxis);
+
+      } else {
+        maxWidth = CSS_UNDEFINED;
+        maxHeight = CSS_UNDEFINED;
+
+        if (!isMainRowDirection) {
+          if (isLayoutDimDefined(node, resolvedRowAxis)) {
+            maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
+              paddingAndBorderAxisResolvedRow;
+          } else {
+            maxWidth = parentMaxWidth -
+              getMarginAxis(node, resolvedRowAxis) -
+              paddingAndBorderAxisResolvedRow;
+          }
+        } else {
+          if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
+            maxHeight = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] -
+                paddingAndBorderAxisColumn;
+          } else {
+            maxHeight = parentMaxHeight -
+              getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN) -
+              paddingAndBorderAxisColumn;
+          }
+        }
+
+        // This is the main recursive call. We layout non flexible children.
+        if (alreadyComputedNextLayout == 0) {
+          layoutNode(child, maxWidth, maxHeight, direction);
+        }
+
+        // Absolute positioned elements do not take part of the layout, so we
+        // don't use them to compute mainContentDim
+        if (child->style.position_type == CSS_POSITION_RELATIVE) {
+          nonFlexibleChildrenCount++;
+          // At this point we know the final size and margin of the element.
+          nextContentDim = getDimWithMargin(child, mainAxis);
+        }
+      }
+
+      // The element we are about to add would make us go to the next line
+      if (isNodeFlexWrap &&
+          isMainDimDefined &&
+          mainContentDim + nextContentDim > definedMainDim &&
+          // If there's only one element, then it's bigger than the content
+          // and needs its own line
+          i != startLine) {
+        nonFlexibleChildrenCount--;
+        alreadyComputedNextLayout = 1;
+        break;
+      }
+
+      // Disable simple stacking in the main axis for the current line as
+      // we found a non-trivial child-> The remaining children will be laid out
+      // in <Loop C>.
+      if (isSimpleStackMain &&
+          (child->style.position_type != CSS_POSITION_RELATIVE || isFlex(child))) {
+        isSimpleStackMain = false;
+        firstComplexMain = i;
+      }
+
+      // Disable simple stacking in the cross axis for the current line as
+      // we found a non-trivial child-> The remaining children will be laid out
+      // in <Loop D>.
+      if (isSimpleStackCross &&
+          (child->style.position_type != CSS_POSITION_RELATIVE ||
+              (alignItem != CSS_ALIGN_STRETCH && alignItem != CSS_ALIGN_FLEX_START) ||
+              (alignItem == CSS_ALIGN_STRETCH && !isCrossDimDefined))) {
+        isSimpleStackCross = false;
+        firstComplexCross = i;
+      }
+
+      if (isSimpleStackMain) {
+        child->layout.position[pos[mainAxis]] += mainDim;
+        if (isMainDimDefined) {
+          setTrailingPosition(node, child, mainAxis);
+        }
+
+        mainDim += getDimWithMargin(child, mainAxis);
+        crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
+      }
+
+      if (isSimpleStackCross) {
+        child->layout.position[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;
+        if (isCrossDimDefined) {
+          setTrailingPosition(node, child, crossAxis);
+        }
+      }
+
+      alreadyComputedNextLayout = 0;
+      mainContentDim += nextContentDim;
+      endLine = i + 1;
+    }
+
+    // <Loop B> Layout flexible children and allocate empty space
+
+    // In order to position the elements in the main axis, we have two
+    // controls. The space between the beginning and the first element
+    // and the space between each two elements.
+    float leadingMainDim = 0;
+    float betweenMainDim = 0;
+
+    // The remaining available space that needs to be allocated
+    float remainingMainDim = 0;
+    if (isMainDimDefined) {
+      remainingMainDim = definedMainDim - mainContentDim;
+    } else {
+      remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;
+    }
+
+    // If there are flexible children in the mix, they are going to fill the
+    // remaining space
+    if (flexibleChildrenCount != 0) {
+      float flexibleMainDim = remainingMainDim / totalFlexible;
+      float baseMainDim;
+      float boundMainDim;
+
+      // If the flex share of remaining space doesn't meet min/max bounds,
+      // remove this child from flex calculations.
+      currentFlexChild = firstFlexChild;
+      while (currentFlexChild != NULL) {
+        baseMainDim = flexibleMainDim * currentFlexChild->style.flex +
+            getPaddingAndBorderAxis(currentFlexChild, mainAxis);
+        boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);
+
+        if (baseMainDim != boundMainDim) {
+          remainingMainDim -= boundMainDim;
+          totalFlexible -= currentFlexChild->style.flex;
+        }
+
+        currentFlexChild = currentFlexChild->next_flex_child;
+      }
+      flexibleMainDim = remainingMainDim / totalFlexible;
+
+      // The non flexible children can overflow the container, in this case
+      // we should just assume that there is no space available.
+      if (flexibleMainDim < 0) {
+        flexibleMainDim = 0;
+      }
+
+      currentFlexChild = firstFlexChild;
+      while (currentFlexChild != NULL) {
+        // At this point we know the final size of the element in the main
+        // dimension
+        currentFlexChild->layout.dimensions[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis,
+          flexibleMainDim * currentFlexChild->style.flex +
+              getPaddingAndBorderAxis(currentFlexChild, mainAxis)
+        );
+
+        maxWidth = CSS_UNDEFINED;
+        if (isLayoutDimDefined(node, resolvedRowAxis)) {
+          maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
+            paddingAndBorderAxisResolvedRow;
+        } else if (!isMainRowDirection) {
+          maxWidth = parentMaxWidth -
+            getMarginAxis(node, resolvedRowAxis) -
+            paddingAndBorderAxisResolvedRow;
+        }
+        maxHeight = CSS_UNDEFINED;
+        if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
+          maxHeight = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] -
+            paddingAndBorderAxisColumn;
+        } else if (isMainRowDirection) {
+          maxHeight = parentMaxHeight -
+            getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN) -
+            paddingAndBorderAxisColumn;
+        }
+
+        // And we recursively call the layout algorithm for this child
+        layoutNode(currentFlexChild, maxWidth, maxHeight, direction);
+
+        child = currentFlexChild;
+        currentFlexChild = currentFlexChild->next_flex_child;
+        child->next_flex_child = NULL;
+      }
+
+    // We use justifyContent to figure out how to allocate the remaining
+    // space available
+    } else if (justifyContent != CSS_JUSTIFY_FLEX_START) {
+      if (justifyContent == CSS_JUSTIFY_CENTER) {
+        leadingMainDim = remainingMainDim / 2;
+      } else if (justifyContent == CSS_JUSTIFY_FLEX_END) {
+        leadingMainDim = remainingMainDim;
+      } else if (justifyContent == CSS_JUSTIFY_SPACE_BETWEEN) {
+        remainingMainDim = fmaxf(remainingMainDim, 0);
+        if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 != 0) {
+          betweenMainDim = remainingMainDim /
+            (flexibleChildrenCount + nonFlexibleChildrenCount - 1);
+        } else {
+          betweenMainDim = 0;
+        }
+      } else if (justifyContent == CSS_JUSTIFY_SPACE_AROUND) {
+        // Space on the edges is half of the space between elements
+        betweenMainDim = remainingMainDim /
+          (flexibleChildrenCount + nonFlexibleChildrenCount);
+        leadingMainDim = betweenMainDim / 2;
+      }
+    }
+
+    // <Loop C> Position elements in the main axis and compute dimensions
+
+    // At this point, all the children have their dimensions set. We need to
+    // find their position. In order to do that, we accumulate data in
+    // variables that are also useful to compute the total dimensions of the
+    // container!
+    mainDim += leadingMainDim;
+
+    for (i = firstComplexMain; i < endLine; ++i) {
+      child = node->get_child(node->context, i);
+
+      if (child->style.position_type == CSS_POSITION_ABSOLUTE &&
+          isPosDefined(child, leading[mainAxis])) {
+        // In case the child is position absolute and has left/top being
+        // defined, we override the position to whatever the user said
+        // (and margin/border).
+        child->layout.position[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +
+          getLeadingBorder(node, mainAxis) +
+          getLeadingMargin(child, mainAxis);
+      } else {
+        // If the child is position absolute (without top/left) or relative,
+        // we put it at the current accumulated offset.
+        child->layout.position[pos[mainAxis]] += mainDim;
+
+        // Define the trailing position accordingly.
+        if (isMainDimDefined) {
+          setTrailingPosition(node, child, mainAxis);
+        }
+
+        // Now that we placed the element, we need to update the variables
+        // We only need to do that for relative elements. Absolute elements
+        // do not take part in that phase.
+        if (child->style.position_type == CSS_POSITION_RELATIVE) {
+          // The main dimension is the sum of all the elements dimension plus
+          // the spacing.
+          mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
+          // The cross dimension is the max of the elements dimension since there
+          // can only be one element in that cross dimension.
+          crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
+        }
+      }
+    }
+
+    float containerCrossAxis = node->layout.dimensions[dim[crossAxis]];
+    if (!isCrossDimDefined) {
+      containerCrossAxis = fmaxf(
+        // For the cross dim, we add both sides at the end because the value
+        // is aggregate via a max function. Intermediate negative values
+        // can mess this computation otherwise
+        boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross),
+        paddingAndBorderAxisCross
+      );
+    }
+
+    // <Loop D> Position elements in the cross axis
+    for (i = firstComplexCross; i < endLine; ++i) {
+      child = node->get_child(node->context, i);
+
+      if (child->style.position_type == CSS_POSITION_ABSOLUTE &&
+          isPosDefined(child, leading[crossAxis])) {
+        // In case the child is absolutely positionned and has a
+        // top/left/bottom/right being set, we override all the previously
+        // computed positions to set it correctly.
+        child->layout.position[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +
+          getLeadingBorder(node, crossAxis) +
+          getLeadingMargin(child, crossAxis);
+
+      } else {
+        float leadingCrossDim = leadingPaddingAndBorderCross;
+
+        // For a relative children, we're either using alignItems (parent) or
+        // alignSelf (child) in order to determine the position in the cross axis
+        if (child->style.position_type == CSS_POSITION_RELATIVE) {
+          /*eslint-disable */
+          // This variable is intentionally re-defined as the code is transpiled to a block scope language
+          css_align_t alignItem = getAlignItem(node, child);
+          /*eslint-enable */
+          if (alignItem == CSS_ALIGN_STRETCH) {
+            // You can only stretch if the dimension has not already been defined
+            // previously.
+            if (!isStyleDimDefined(child, crossAxis)) {
+              float dimCrossAxis = child->layout.dimensions[dim[crossAxis]];
+              child->layout.dimensions[dim[crossAxis]] = fmaxf(
+                boundAxis(child, crossAxis, containerCrossAxis -
+                  paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),
+                // You never want to go smaller than padding
+                getPaddingAndBorderAxis(child, crossAxis)
+              );
+
+              // If the size has changed, and this child has children we need to re-layout this child
+              if (dimCrossAxis != child->layout.dimensions[dim[crossAxis]] && child->children_count > 0) {
+                // Reset child margins before re-layout as they are added back in layoutNode and would be doubled
+                child->layout.position[leading[mainAxis]] -= getLeadingMargin(child, mainAxis) +
+                  getRelativePosition(child, mainAxis);
+                child->layout.position[trailing[mainAxis]] -= getTrailingMargin(child, mainAxis) +
+                  getRelativePosition(child, mainAxis);
+                child->layout.position[leading[crossAxis]] -= getLeadingMargin(child, crossAxis) +
+                  getRelativePosition(child, crossAxis);
+                child->layout.position[trailing[crossAxis]] -= getTrailingMargin(child, crossAxis) +
+                  getRelativePosition(child, crossAxis);
+
+                layoutNode(child, maxWidth, maxHeight, direction);
+              }
+            }
+          } else if (alignItem != CSS_ALIGN_FLEX_START) {
+            // The remaining space between the parent dimensions+padding and child
+            // dimensions+margin.
+            float remainingCrossDim = containerCrossAxis -
+              paddingAndBorderAxisCross - getDimWithMargin(child, crossAxis);
+
+            if (alignItem == CSS_ALIGN_CENTER) {
+              leadingCrossDim += remainingCrossDim / 2;
+            } else { // CSS_ALIGN_FLEX_END
+              leadingCrossDim += remainingCrossDim;
+            }
+          }
+        }
+
+        // And we apply the position
+        child->layout.position[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
+
+        // Define the trailing position accordingly.
+        if (isCrossDimDefined) {
+          setTrailingPosition(node, child, crossAxis);
+        }
+      }
+    }
+
+    linesCrossDim += crossDim;
+    linesMainDim = fmaxf(linesMainDim, mainDim);
+    linesCount += 1;
+    startLine = endLine;
+  }
+
+  // <Loop E>
+  //
+  // Note(prenaux): More than one line, we need to layout the crossAxis
+  // according to alignContent.
+  //
+  // Note that we could probably remove <Loop D> and handle the one line case
+  // here too, but for the moment this is safer since it won't interfere with
+  // previously working code.
+  //
+  // See specs:
+  // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm
+  // section 9.4
+  //
+  if (linesCount > 1 && isCrossDimDefined) {
+    float nodeCrossAxisInnerSize = node->layout.dimensions[dim[crossAxis]] -
+        paddingAndBorderAxisCross;
+    float remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;
+
+    float crossDimLead = 0;
+    float currentLead = leadingPaddingAndBorderCross;
+
+    css_align_t alignContent = node->style.align_content;
+    if (alignContent == CSS_ALIGN_FLEX_END) {
+      currentLead += remainingAlignContentDim;
+    } else if (alignContent == CSS_ALIGN_CENTER) {
+      currentLead += remainingAlignContentDim / 2;
+    } else if (alignContent == CSS_ALIGN_STRETCH) {
+      if (nodeCrossAxisInnerSize > linesCrossDim) {
+        crossDimLead = (remainingAlignContentDim / linesCount);
+      }
+    }
+
+    int endIndex = 0;
+    for (i = 0; i < linesCount; ++i) {
+      int startIndex = endIndex;
+
+      // compute the line's height and find the endIndex
+      float lineHeight = 0;
+      for (ii = startIndex; ii < childCount; ++ii) {
+        child = node->get_child(node->context, ii);
+        if (child->style.position_type != CSS_POSITION_RELATIVE) {
+          continue;
+        }
+        if (child->line_index != i) {
+          break;
+        }
+        if (isLayoutDimDefined(child, crossAxis)) {
+          lineHeight = fmaxf(
+            lineHeight,
+            child->layout.dimensions[dim[crossAxis]] + getMarginAxis(child, crossAxis)
+          );
+        }
+      }
+      endIndex = ii;
+      lineHeight += crossDimLead;
+
+      for (ii = startIndex; ii < endIndex; ++ii) {
+        child = node->get_child(node->context, ii);
+        if (child->style.position_type != CSS_POSITION_RELATIVE) {
+          continue;
+        }
+
+        css_align_t alignContentAlignItem = getAlignItem(node, child);
+        if (alignContentAlignItem == CSS_ALIGN_FLEX_START) {
+          child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
+        } else if (alignContentAlignItem == CSS_ALIGN_FLEX_END) {
+          child->layout.position[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child->layout.dimensions[dim[crossAxis]];
+        } else if (alignContentAlignItem == CSS_ALIGN_CENTER) {
+          float childHeight = child->layout.dimensions[dim[crossAxis]];
+          child->layout.position[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;
+        } else if (alignContentAlignItem == CSS_ALIGN_STRETCH) {
+          child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
+          // TODO(prenaux): Correctly set the height of items with undefined
+          //                (auto) crossAxis dimension.
+        }
+      }
+
+      currentLead += lineHeight;
+    }
+  }
+
+  bool needsMainTrailingPos = false;
+  bool needsCrossTrailingPos = false;
+
+  // If the user didn't specify a width or height, and it has not been set
+  // by the container, then we set it via the children.
+  if (!isMainDimDefined) {
+    node->layout.dimensions[dim[mainAxis]] = fmaxf(
+      // We're missing the last padding at this point to get the final
+      // dimension
+      boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),
+      // We can never assign a width smaller than the padding and borders
+      paddingAndBorderAxisMain
+    );
+
+    if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
+        mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+      needsMainTrailingPos = true;
+    }
+  }
+
+  if (!isCrossDimDefined) {
+    node->layout.dimensions[dim[crossAxis]] = fmaxf(
+      // For the cross dim, we add both sides at the end because the value
+      // is aggregate via a max function. Intermediate negative values
+      // can mess this computation otherwise
+      boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross),
+      paddingAndBorderAxisCross
+    );
+
+    if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||
+        crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
+      needsCrossTrailingPos = true;
+    }
+  }
+
+  // <Loop F> Set trailing position if necessary
+  if (needsMainTrailingPos || needsCrossTrailingPos) {
+    for (i = 0; i < childCount; ++i) {
+      child = node->get_child(node->context, i);
+
+      if (needsMainTrailingPos) {
+        setTrailingPosition(node, child, mainAxis);
+      }
+
+      if (needsCrossTrailingPos) {
+        setTrailingPosition(node, child, crossAxis);
+      }
+    }
+  }
+
+  // <Loop G> Calculate dimensions for absolutely positioned elements
+  currentAbsoluteChild = firstAbsoluteChild;
+  while (currentAbsoluteChild != NULL) {
+    // Pre-fill dimensions when using absolute position and both offsets for
+    // the axis are defined (either both left and right or top and bottom).
+    for (ii = 0; ii < 2; ii++) {
+      axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
+
+      if (isLayoutDimDefined(node, axis) &&
+          !isStyleDimDefined(currentAbsoluteChild, axis) &&
+          isPosDefined(currentAbsoluteChild, leading[axis]) &&
+          isPosDefined(currentAbsoluteChild, trailing[axis])) {
+        currentAbsoluteChild->layout.dimensions[dim[axis]] = fmaxf(
+          boundAxis(currentAbsoluteChild, axis, node->layout.dimensions[dim[axis]] -
+            getBorderAxis(node, axis) -
+            getMarginAxis(currentAbsoluteChild, axis) -
+            getPosition(currentAbsoluteChild, leading[axis]) -
+            getPosition(currentAbsoluteChild, trailing[axis])
+          ),
+          // You never want to go smaller than padding
+          getPaddingAndBorderAxis(currentAbsoluteChild, axis)
+        );
+      }
+
+      if (isPosDefined(currentAbsoluteChild, trailing[axis]) &&
+          !isPosDefined(currentAbsoluteChild, leading[axis])) {
+        currentAbsoluteChild->layout.position[leading[axis]] =
+          node->layout.dimensions[dim[axis]] -
+          currentAbsoluteChild->layout.dimensions[dim[axis]] -
+          getPosition(currentAbsoluteChild, trailing[axis]);
+      }
+    }
+
+    child = currentAbsoluteChild;
+    currentAbsoluteChild = currentAbsoluteChild->next_absolute_child;
+    child->next_absolute_child = NULL;
+  }
+  /** END_GENERATED **/
+}
+
+void layoutNode(css_node_t *node, float parentMaxWidth, float parentMaxHeight, css_direction_t parentDirection) {
+  css_layout_t *layout = &node->layout;
+  css_direction_t direction = node->style.direction;
+  layout->should_update = true;
+
+  bool skipLayout =
+    !node->is_dirty(node->context) &&
+    eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) &&
+    eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) &&
+    eq(layout->last_parent_max_width, parentMaxWidth) &&
+    eq(layout->last_parent_max_height, parentMaxHeight) &&
+    eq(layout->last_direction, direction);
+
+  if (skipLayout) {
+    layout->dimensions[CSS_WIDTH] = layout->last_dimensions[CSS_WIDTH];
+    layout->dimensions[CSS_HEIGHT] = layout->last_dimensions[CSS_HEIGHT];
+    layout->position[CSS_TOP] = layout->last_position[CSS_TOP];
+    layout->position[CSS_LEFT] = layout->last_position[CSS_LEFT];
+  } else {
+    layout->last_requested_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
+    layout->last_requested_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
+    layout->last_parent_max_width = parentMaxWidth;
+    layout->last_parent_max_height = parentMaxHeight;
+    layout->last_direction = direction;
+
+    int i, childCount;
+    for (i = 0, childCount = node->children_count; i < childCount; i++) {
+      resetNodeLayout(node->get_child(node->context, i));
+    }
+
+    layoutNodeImpl(node, parentMaxWidth, parentMaxHeight, parentDirection);
+
+    layout->last_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
+    layout->last_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
+    layout->last_position[CSS_TOP] = layout->position[CSS_TOP];
+    layout->last_position[CSS_LEFT] = layout->position[CSS_LEFT];
+  }
+
+#if defined(FLEXBOX_LAYOUT_NODE_DEBUG)
+  printf("Input:    ");
+  print_css_node(node, (css_print_options_t)(CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
+  printf("Output:   ");
+  print_css_node(node, (css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_CHILDREN));
+  printf("\n");
+#endif // defined(FLEXBOX_LAYOUT_NODE_DEBUG)
+}
+
+void resetNodeLayout(css_node_t *node) {
+  node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
+  node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+  node->layout.position[CSS_LEFT] = 0;
+  node->layout.position[CSS_TOP] = 0;
+}
diff --git a/dali-toolkit/internal/controls/flex-container/layout.h b/dali-toolkit/internal/controls/flex-container/layout.h
new file mode 100644 (file)
index 0000000..d6ad495
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#ifndef __LAYOUT_H
+#define __LAYOUT_H
+
+#include <math.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+// Not defined in MSVC++
+#ifndef NAN
+static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
+#define NAN (*(const float *)__nan)
+#endif
+
+#define CSS_UNDEFINED NAN
+
+typedef enum {
+  CSS_DIRECTION_INHERIT = 0,
+  CSS_DIRECTION_LTR,
+  CSS_DIRECTION_RTL
+} css_direction_t;
+
+typedef enum {
+  CSS_FLEX_DIRECTION_COLUMN = 0,
+  CSS_FLEX_DIRECTION_COLUMN_REVERSE,
+  CSS_FLEX_DIRECTION_ROW,
+  CSS_FLEX_DIRECTION_ROW_REVERSE
+} css_flex_direction_t;
+
+typedef enum {
+  CSS_JUSTIFY_FLEX_START = 0,
+  CSS_JUSTIFY_CENTER,
+  CSS_JUSTIFY_FLEX_END,
+  CSS_JUSTIFY_SPACE_BETWEEN,
+  CSS_JUSTIFY_SPACE_AROUND
+} css_justify_t;
+
+// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
+// alignItems.
+typedef enum {
+  CSS_ALIGN_AUTO = 0,
+  CSS_ALIGN_FLEX_START,
+  CSS_ALIGN_CENTER,
+  CSS_ALIGN_FLEX_END,
+  CSS_ALIGN_STRETCH
+} css_align_t;
+
+typedef enum {
+  CSS_POSITION_RELATIVE = 0,
+  CSS_POSITION_ABSOLUTE
+} css_position_type_t;
+
+typedef enum {
+  CSS_NOWRAP = 0,
+  CSS_WRAP
+} css_wrap_type_t;
+
+// Note: left and top are shared between position[2] and position[4], so
+// they have to be before right and bottom.
+typedef enum {
+  CSS_LEFT = 0,
+  CSS_TOP,
+  CSS_RIGHT,
+  CSS_BOTTOM,
+  CSS_START,
+  CSS_END,
+  CSS_POSITION_COUNT
+} css_position_t;
+
+typedef enum {
+  CSS_MEASURE_MODE_UNDEFINED = 0,
+  CSS_MEASURE_MODE_EXACTLY,
+  CSS_MEASURE_MODE_AT_MOST
+} css_measure_mode_t;
+
+typedef enum {
+  CSS_WIDTH = 0,
+  CSS_HEIGHT
+} css_dimension_t;
+
+typedef struct {
+  float position[4];
+  float dimensions[2];
+  css_direction_t direction;
+
+  // Instead of recomputing the entire layout every single time, we
+  // cache some information to break early when nothing changed
+  bool should_update;
+  float last_requested_dimensions[2];
+  float last_parent_max_width;
+  float last_parent_max_height;
+  float last_dimensions[2];
+  float last_position[2];
+  css_direction_t last_direction;
+} css_layout_t;
+
+typedef struct {
+  float dimensions[2];
+} css_dim_t;
+
+typedef struct {
+  css_direction_t direction;
+  css_flex_direction_t flex_direction;
+  css_justify_t justify_content;
+  css_align_t align_content;
+  css_align_t align_items;
+  css_align_t align_self;
+  css_position_type_t position_type;
+  css_wrap_type_t flex_wrap;
+  float flex;
+  float margin[6];
+  float position[4];
+  /**
+   * You should skip all the rules that contain negative values for the
+   * following attributes. For example:
+   *   {padding: 10, paddingLeft: -5}
+   * should output:
+   *   {left: 10 ...}
+   * the following two are incorrect:
+   *   {left: -5 ...}
+   *   {left: 0 ...}
+   */
+  float padding[6];
+  float border[6];
+  float dimensions[2];
+  float minDimensions[2];
+  float maxDimensions[2];
+} css_style_t;
+
+typedef struct css_node css_node_t;
+struct css_node {
+  css_style_t style;
+  css_layout_t layout;
+  int children_count;
+  int line_index;
+
+  css_node_t *next_absolute_child;
+  css_node_t *next_flex_child;
+
+  css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
+  void (*print)(void *context);
+  struct css_node* (*get_child)(void *context, int i);
+  bool (*is_dirty)(void *context);
+  void *context;
+};
+
+// Lifecycle of nodes and children
+css_node_t *new_css_node(void);
+void init_css_node(css_node_t *node);
+void free_css_node(css_node_t *node);
+
+// Print utilities
+typedef enum {
+  CSS_PRINT_LAYOUT = 1,
+  CSS_PRINT_STYLE = 2,
+  CSS_PRINT_CHILDREN = 4,
+} css_print_options_t;
+void print_css_node(css_node_t *node, css_print_options_t options);
+
+bool isUndefined(float value);
+
+// Function that computes the layout!
+void layoutNode(css_node_t *node, float maxWidth, float maxHeight, css_direction_t parentDirection);
+
+// Reset the calculated layout values for a given node. You should call this before `layoutNode`.
+void resetNodeLayout(css_node_t *node);
+
+#endif // __LAYOUT_H
index 7799287..75af670 100644 (file)
@@ -313,7 +313,7 @@ void Model3dView::SetProperty( BaseObject* object, Property::Index index, const
       }
       case Toolkit::Model3dView::Property::MATERIAL_URL:
       {
-        if( value.Get(impl.mMaterialUrl) )
+        if( value.Get(impl.mTextureSetUrl) )
         {
           impl.LoadMaterial();
           impl.CreateMaterial();
@@ -377,7 +377,7 @@ Property::Value Model3dView::GetProperty( BaseObject* object, Property::Index in
       }
       case Toolkit::Model3dView::Property::MATERIAL_URL:
       {
-        value = impl.mMaterialUrl;
+        value = impl.mTextureSetUrl;
         break;
       }
       case Toolkit::Model3dView::Property::IMAGES_URL:
@@ -449,8 +449,8 @@ void Model3dView::OnInitialize()
   //Create empty versions of the geometry and material so we always have a Renderer
   Geometry mesh = Geometry::New();
   Shader shader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
-  Material material = Material::New( shader );
-  mRenderer = Renderer::New( mesh, material );
+  mRenderer = Renderer::New( mesh, shader );
+
 }
 
 void Model3dView::LoadGeometry()
@@ -482,7 +482,7 @@ void Model3dView::LoadMaterial()
   std::streampos fileSize;
   Dali::Vector<char> fileContent;
 
-  if( FileLoader::ReadFile(mMaterialUrl, fileSize, fileContent, FileLoader::TEXT) )
+  if( FileLoader::ReadFile(mTextureSetUrl, fileSize, fileContent, FileLoader::TEXT) )
   {
     mObjLoader.LoadMaterial(fileContent.Begin(), fileSize, mTexture0Url, mTexture1Url, mTexture2Url);
   }
@@ -573,11 +573,12 @@ void Model3dView::CreateMaterial()
     mShader = Shader::New( SIMPLE_VERTEX_SHADER, SIMPLE_FRAGMENT_SHADER, (Shader::ShaderHints)(Shader::HINT_REQUIRES_SELF_DEPTH_TEST | Shader::HINT_MODIFIES_GEOMETRY) );
   }
 
-  mMaterial = Material::New( mShader );
+  mTextureSet = TextureSet::New();
 
   if( mRenderer )
   {
-    mRenderer.SetMaterial( mMaterial );
+    mRenderer.SetTextures( mTextureSet );
+    mRenderer.SetShader( mShader );
     mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, Renderer::NONE);
   }
 
@@ -586,7 +587,7 @@ void Model3dView::CreateMaterial()
 
 void Model3dView::LoadTextures()
 {
-  if( !mMaterial )
+  if( !mTextureSet )
     return ;
 
   if( mTexture0Url != "" )
@@ -597,7 +598,7 @@ void Model3dView::LoadTextures()
     Image tex0 = ResourceImage::New( imgUrl );
     if( tex0 )
     {
-      mMaterial.AddTexture( tex0, "sDiffuse" );
+      mTextureSet.SetImage( 0u, tex0 );
     }
   }
 
@@ -609,7 +610,7 @@ void Model3dView::LoadTextures()
     Image tex1 = ResourceImage::New( imgUrl );
     if (tex1)
     {
-      mMaterial.AddTexture( tex1, "sNormal" );
+      mTextureSet.SetImage( 1u, tex1 );
     }
   }
 
@@ -621,7 +622,7 @@ void Model3dView::LoadTextures()
     Image tex2 = ResourceImage::New( imgUrl );
     if( tex2 )
     {
-      mMaterial.AddTexture( tex2, "sGloss" );
+      mTextureSet.SetImage( 2u, tex2 );
     }
   }
 }
index 2202409..8e44911 100644 (file)
@@ -150,7 +150,7 @@ private:
 
   //Properties
   std::string mObjUrl;
-  std::string mMaterialUrl;
+  std::string mTextureSetUrl;
   std::string mImagesUrl;
   std::string mTexture0Url;
   std::string mTexture1Url;
@@ -166,7 +166,7 @@ private:
 
   //Render members
   Shader mShader;
-  Material mMaterial;
+  TextureSet mTextureSet;
   Geometry mMesh;
   Renderer mRenderer;
 };
index 19e8421..2fea479 100644 (file)
@@ -47,9 +47,6 @@ const char * const CUSTOM_SHADER( "shader" );
 const char * const CUSTOM_VERTEX_SHADER( "vertexShader" );
 const char * const CUSTOM_FRAGMENT_SHADER( "fragmentShader" );
 
-// name of the texture in material
-const char * const TEXTURE_NAME( "sTexture" );
-
 // properties set on shader, these properties have the constant value in regardless of the page status
 const char * const PROPERTY_SPINE_SHADOW ( "uSpineShadowParameter" ); // uniform for both spine and turn effect
 
@@ -292,35 +289,37 @@ PageTurnView::Page::Page()
 
 void PageTurnView::Page::SetImage( Image image  )
 {
-  if( material.GetNumberOfTextures() > 0  )
-  {
-    material.SetTextureImage( 0u, image );
-  }
-  else
+  if( !textureSet )
   {
-    material.AddTexture(image, TEXTURE_NAME);
+    textureSet = TextureSet::New();
   }
+
+  textureSet.SetImage( 0u, image );
 }
 
-void PageTurnView::Page::UseEffect(Shader shader)
+void PageTurnView::Page::UseEffect(Shader newShader)
 {
-  if( material )
-  {
-    material.SetShader( shader );
-  }
-  else
+  shader = newShader;
+  if( renderer )
   {
-    material = Material::New( shader );
+    renderer.SetShader( shader );
   }
 }
 
-void PageTurnView::Page::UseEffect(Shader shader, Geometry geometry)
+void PageTurnView::Page::UseEffect(Shader newShader, Geometry geometry)
 {
-  UseEffect( shader );
+  UseEffect( newShader );
 
   if( !renderer )
   {
-    renderer = Renderer::New( geometry, material );
+    renderer = Renderer::New( geometry, shader );
+
+    if( !textureSet )
+    {
+      textureSet = TextureSet::New();
+    }
+
+    renderer.SetTextures( textureSet );
     actor.AddRenderer( renderer );
   }
 }
index e17f2a0..1f4bc16 100644 (file)
@@ -64,16 +64,16 @@ protected:
 
     /**
      * Apply an effect onto the page actor.
-     * @param[in] shader The shader for rendering effect.
+     * @param[in] newShader The shader for rendering effect.
      */
-    void UseEffect(Shader shader);
+    void UseEffect(Shader newShader);
 
     /**
      * Apply an effect onto the page actor.
-     * @param[in] shader The shader for rendering effect.
+     * @param[in] newShader The shader for rendering effect.
      * @param[in] geometry The geometry for rendering effect.
      */
-    void UseEffect(Shader shader, Geometry geometry);
+    void UseEffect(Shader newShader, Geometry geometry);
 
     /**
      * Change the page turning direction.
@@ -105,7 +105,8 @@ protected:
     void SetCurrentCenter( const Vector2& value );
 
     Actor actor;                              ///< The page actor
-    Material material;                        ///< The material of the actor
+    Shader shader;                            ///< The shader used by the actor
+    TextureSet textureSet;                    ///< The set of textures used by the actor
     Renderer renderer;                        ///< The renderer of the actor
     bool isTurnBack;                          ///< The turning direction
     Property::Index propertyPanDisplacement;  ///< The horizontal displacement of the pan
index 6432ae0..9ae46a1 100644 (file)
@@ -174,8 +174,10 @@ void BorderRenderer::InitializeRenderer()
     mFactoryCache.SaveGeometry( RendererFactoryCache::BORDER_GEOMETRY, geometry );
   }
 
-  Material material = Material::New( GetBorderShader() );
-  mImpl->mRenderer = Renderer::New( geometry, material );
+
+  Shader shader = GetBorderShader();
+  mImpl->mRenderer = Renderer::New( geometry, shader  );
+
 }
 
 void BorderRenderer::SetBorderColor(const Vector4& color)
@@ -209,9 +211,8 @@ void BorderRenderer::RequireAntiAliasing( bool antiAliasing )
     mAntiAliasing = antiAliasing;
     if( mImpl->mRenderer )
     {
-      Material material =  mImpl->mRenderer.GetMaterial();
-      Shader shader = GetBorderShader();
-      material.SetShader( shader );
+      Shader borderShader( GetBorderShader() );
+      mImpl->mRenderer.SetShader( borderShader );
       if( mAntiAliasing )
       {
         mImpl->mRenderer.SetProperty( Renderer::Property::BLENDING_MODE, BlendingMode::ON );
index ddc41f5..abdee4e 100644 (file)
@@ -131,8 +131,7 @@ void ColorRenderer::InitializeRenderer()
     mFactoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, shader );
   }
 
-  Material material = Material::New( shader );
-  mImpl->mRenderer = Renderer::New( geometry, material );
+  mImpl->mRenderer = Renderer::New( geometry, shader );
 
   mBlendColorIndex = mImpl->mRenderer.RegisterProperty( COLOR_NAME, mBlendColor );
   if( mBlendColor.a < 1.f )
index 7ab33c7..6c3c58a 100644 (file)
@@ -92,9 +92,8 @@ void DebugRenderer::InitializeRenderer()
   {
     Geometry geometry = CreateQuadWireframeGeometry();
     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
-    Material material = Material::New( shader );
-    mImpl->mRenderer = Renderer::New( geometry,
-                                      material );
+
+    mImpl->mRenderer = Renderer::New( geometry, shader);
     mFactoryCache.CacheDebugRenderer( mImpl->mRenderer );
   }
 }
index e11f3ff..f1838ae 100644 (file)
@@ -69,7 +69,6 @@ const char * const SPREAD_REPEAT("repeat");
 
 // uniform names
 const char * const UNIFORM_ALIGNMENT_MATRIX_NAME( "uAlignmentMatrix" );
-const char * const UNIFORM_TEXTULRE_NAME("sTexture");
 
 // default offset value
 const unsigned int DEFAULT_OFFSET_MINIMUM = 0.0f;
@@ -316,16 +315,17 @@ void GradientRenderer::InitializeRenderer()
     mFactoryCache.SaveShader( shaderType, shader );
   }
 
-  Material material;
-  material = Material::New( shader );
-  mImpl->mRenderer = Renderer::New( geometry, material );
-
+  //Set up the texture set
+  TextureSet textureSet = TextureSet::New();
   Dali::BufferImage lookupTexture = mGradient->GenerateLookupTexture();
-  Sampler sampler = Sampler::New();
+  textureSet.SetImage( 0u, lookupTexture );
   Dali::WrapMode::Type wrap = GetWrapMode( mGradient->GetSpreadMethod() );
+  Sampler sampler = Sampler::New();
   sampler.SetWrapMode(  wrap, wrap  );
+  textureSet.SetSampler( 0u, sampler );
 
-  material.AddTexture( lookupTexture, UNIFORM_TEXTULRE_NAME, sampler );
+  mImpl->mRenderer = Renderer::New( geometry, shader );
+  mImpl->mRenderer.SetTextures( textureSet );
 
   mImpl->mRenderer.RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform );
 }
index 7f6f4f6..03eb4a7 100644 (file)
@@ -37,10 +37,8 @@ const uint32_t MAX_ITEM_SIZE( 512u  );
 const uint32_t MAX_ITEM_AREA( MAX_ITEM_SIZE*MAX_ITEM_SIZE  );
 }
 
-ImageAtlasManager::ImageAtlasManager( Shader shader, const std::string& textureUniformName )
-: mShader( shader ),
-  mTextureUniformName( textureUniformName ),
-  mBrokenImageUrl( "" )
+ImageAtlasManager::ImageAtlasManager()
+: mBrokenImageUrl( "" )
 {
 }
 
@@ -48,7 +46,7 @@ ImageAtlasManager::~ImageAtlasManager()
 {
 }
 
-Material ImageAtlasManager::Add( Vector4& textureRect,
+TextureSet ImageAtlasManager::Add( Vector4& textureRect,
                                  const std::string& url,
                                  ImageDimensions size,
                                  FittingMode::Type fittingMode,
@@ -66,7 +64,7 @@ Material ImageAtlasManager::Add( Vector4& textureRect,
       || dimensions.GetWidth()>DEFAULT_ATLAS_SIZE
       || dimensions.GetHeight()>DEFAULT_ATLAS_SIZE)
   {
-    return Material();
+    return TextureSet();
   }
 
   unsigned int i = 0;
@@ -74,17 +72,17 @@ Material ImageAtlasManager::Add( Vector4& textureRect,
   {
     if( (*iter).Upload( textureRect, url, size, fittingMode, orientationCorrection ) )
     {
-      return mMaterialList[i];
+      return mTextureSetList[i];
     }
     i++;
   }
 
   CreateNewAtlas();
   mAtlasList.back().Upload( textureRect, url, size, fittingMode, orientationCorrection );
-  return mMaterialList.back();
+  return mTextureSetList.back();
 }
 
-Material ImageAtlasManager::Add( Vector4& textureRect,
+TextureSet ImageAtlasManager::Add( Vector4& textureRect,
                                  PixelDataPtr pixelData )
 {
 
@@ -93,7 +91,7 @@ Material ImageAtlasManager::Add( Vector4& textureRect,
       || pixelData->GetWidth()>DEFAULT_ATLAS_SIZE
       || pixelData->GetHeight()>DEFAULT_ATLAS_SIZE )
   {
-    return Material();
+    return TextureSet();
   }
 
   unsigned int i = 0;
@@ -101,23 +99,23 @@ Material ImageAtlasManager::Add( Vector4& textureRect,
   {
     if( (*iter).Upload( textureRect, pixelData ) )
     {
-      return mMaterialList[i];
+      return mTextureSetList[i];
     }
     i++;
   }
 
   CreateNewAtlas();
   mAtlasList.back().Upload( textureRect, pixelData );
-  return mMaterialList.back();
+  return mTextureSetList.back();
 
 }
 
-void ImageAtlasManager::Remove( Material material, const Vector4& textureRect )
+void ImageAtlasManager::Remove( TextureSet textureSet, const Vector4& textureRect )
 {
   unsigned int i = 0;
-  for( MaterialContainer::iterator iter = mMaterialList.begin(); iter != mMaterialList.end(); ++iter)
+  for( TextureSetContainer::iterator iter = mTextureSetList.begin(); iter != mTextureSetList.end(); ++iter)
   {
-    if( (*iter) == material )
+    if( (*iter) == textureSet )
     {
       mAtlasList[i].Remove(textureRect);
       return;
@@ -142,9 +140,9 @@ void ImageAtlasManager::CreateNewAtlas()
     newAtlas.SetBrokenImage( mBrokenImageUrl );
   }
   mAtlasList.push_back( newAtlas );
-  Material newMaterial = Material::New( mShader );
-  newMaterial.AddTexture( newAtlas.GetAtlas(), mTextureUniformName );
-  mMaterialList.push_back( newMaterial );
+  TextureSet textureSet = TextureSet::New();
+  textureSet.SetImage( 0u, newAtlas.GetAtlas() );
+  mTextureSetList.push_back( textureSet );
 }
 
 } // namespace Internal
index 8b562a9..e191351 100644 (file)
@@ -21,7 +21,7 @@
 #include <string>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/object/ref-object.h>
-#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/texture-set.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/devel-api/image-atlas/image-atlas.h>
@@ -42,17 +42,15 @@ class ImageAtlasManager : public RefObject
 {
 public:
   typedef std::vector< Toolkit::ImageAtlas > AtlasContainer;
-  typedef std::vector< Material > MaterialContainer;
+  typedef std::vector< TextureSet > TextureSetContainer;
 
 public:
 
   /**
    * Construtor
    *
-   * @param[in] shader The shader for material.
-   * @param[in] textureUniformName The texture uniform name for the atlas image.
    */
-  ImageAtlasManager( Shader shader, const std::string& textureUniformName );
+  ImageAtlasManager();
 
   /**
    * @brief Add an image to the atlas.
@@ -67,9 +65,9 @@ public:
    * @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] orientationCorrection Reorient the image to respect any orientation metadata in its header.
-   * @return The material containing the image.
+   * @return The texture set containing the image.
    */
-  Material Add( Vector4& textureRect,
+  TextureSet Add( Vector4& textureRect,
                 const std::string& url,
                 ImageDimensions size = ImageDimensions(),
                 FittingMode::Type fittingMode = FittingMode::DEFAULT,
@@ -80,18 +78,18 @@ public:
    *
    * @param [out] textureRect The texture area of the resource image in the atlas.
    * @param [in] pixelData The pixel data.
-   * @return The material containing the image.
+   * @return The texture set containing the image.
    */
-  Material Add( Vector4& textureRect,
+  TextureSet Add( Vector4& textureRect,
                 PixelDataPtr pixelData );
 
   /**
-   * Remove the image at the given rectangle from the material.
+   * Remove the image at the given rectangle from the texture set.
    *
-   * @param [in] material The material containing the atlas image.
+   * @param [in] textureSet The texture set containing the atlas image.
    * @param [in] textureRect The texture area to be removed.
    */
-  void Remove( Material material, const Vector4& textureRect );
+  void Remove( TextureSet textureSet, const Vector4& textureRect );
 
   /**
    * @brief Set the broken image which is used to replace the image if loading fails.
@@ -100,6 +98,11 @@ public:
    */
   void SetBrokenImage( const std::string& brokenImageUrl );
 
+  /**
+   * @brief Get shader
+   */
+  Shader GetShader() const;
+
 private:
 
   /**
@@ -130,9 +133,7 @@ protected:
 private:
 
   AtlasContainer    mAtlasList;
-  MaterialContainer mMaterialList;
-  Shader            mShader;
-  std::string       mTextureUniformName;
+  TextureSetContainer mTextureSetList;
   std::string       mBrokenImageUrl;
 
 };
index 17eae58..c2bec85 100644 (file)
@@ -71,7 +71,6 @@ const char * const BOX_THEN_LINEAR("boxThenLinear");
 const char * const NO_FILTER("noFilter");
 const char * const DONT_CARE("dontCare");
 
-const std::string TEXTURE_UNIFORM_NAME = "sTexture";
 const std::string ATLAS_RECT_UNIFORM_NAME = "uAtlasRect";
 const std::string PIXEL_AREA_UNIFORM_NAME = "pixelArea";
 
@@ -359,8 +358,12 @@ Renderer ImageRenderer::CreateRenderer() const
     }
   }
 
-  Material material = Material::New( shader );
-  return Renderer::New( geometry, material );
+  TextureSet textureSet = TextureSet::New();
+
+  Renderer renderer = Renderer::New( geometry, shader );
+  renderer.SetTextures( textureSet );
+
+  return renderer;
 }
 
 Renderer ImageRenderer::CreateNativeImageRenderer() const
@@ -396,8 +399,11 @@ Renderer ImageRenderer::CreateNativeImageRenderer() const
     }
   }
 
-  Material material = Material::New( shader );
-  return Renderer::New( geometry, material );
+  TextureSet textureSet = TextureSet::New();
+  Renderer renderer = Renderer::New( geometry, shader );
+  renderer.SetTextures( textureSet );
+
+  return renderer;
 }
 
 void ImageRenderer::InitializeRenderer( const std::string& imageUrl )
@@ -418,11 +424,13 @@ void ImageRenderer::InitializeRenderer( const std::string& imageUrl )
     if( !mImpl->mRenderer )
     {
       Vector4 atlasRect;
-      Material material = mAtlasManager.Add(atlasRect, imageUrl, mDesiredSize, mFittingMode, mSamplingMode );
-      if( material )
+      TextureSet textureSet = mAtlasManager.Add(atlasRect, imageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+      if( textureSet )
       {
         Geometry geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
-        mImpl->mRenderer = Renderer::New( geometry, material );
+        Shader shader( GetImageShader(mFactoryCache) );
+        mImpl->mRenderer = Renderer::New( geometry, shader );
+        mImpl->mRenderer.SetTextures( textureSet );
         mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect );
       }
       else // big image, atlasing is not applied
@@ -431,8 +439,8 @@ void ImageRenderer::InitializeRenderer( const std::string& imageUrl )
 
         ResourceImage image = Dali::ResourceImage::New( imageUrl, mDesiredSize, mFittingMode, mSamplingMode );
         image.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded );
-        Material material = mImpl->mRenderer.GetMaterial();
-        material.AddTexture( image, TEXTURE_UNIFORM_NAME );
+        TextureSet textureSet = mImpl->mRenderer.GetTextures();
+        textureSet.SetImage( 0u, image );
       }
 
       mFactoryCache.SaveRenderer( imageUrl, mImpl->mRenderer );
@@ -728,17 +736,10 @@ void ImageRenderer::ApplyImageToSampler( const Image& image )
 {
   if( image )
   {
-    Material material = mImpl->mRenderer.GetMaterial();
-    if( material )
+    TextureSet textureSet = mImpl->mRenderer.GetTextures();
+    if( textureSet )
     {
-      int index = material.GetTextureIndex( TEXTURE_UNIFORM_NAME );
-      if( index != -1 )
-      {
-        material.SetTextureImage( index, image );
-        return;
-      }
-
-      material.AddTexture( image, TEXTURE_UNIFORM_NAME );
+      textureSet.SetImage( 0u, image );
     }
   }
 }
@@ -757,7 +758,7 @@ void ImageRenderer::OnImageLoaded( ResourceImage image )
 
 void ImageRenderer::CleanCache(const std::string& url)
 {
-  Material material = mImpl->mRenderer.GetMaterial();
+  TextureSet textureSet = mImpl->mRenderer.GetTextures();
 
   Vector4 atlasRect( 0.f, 0.f, 1.f, 1.f );
   Property::Index index = mImpl->mRenderer.GetPropertyIndex( ATLAS_RECT_UNIFORM_NAME );
@@ -770,7 +771,7 @@ void ImageRenderer::CleanCache(const std::string& url)
   mImpl->mRenderer.Reset();
   if( mFactoryCache.CleanRendererCache( url ) && index != Property::INVALID_INDEX )
   {
-    mAtlasManager.Remove( material, atlasRect );
+    mAtlasManager.Remove( textureSet, atlasRect );
   }
 }
 
index a942f9a..1ae3e50 100644 (file)
@@ -167,9 +167,9 @@ public:
 private:
 
   /**
-   * @brief Applies the image to the material used for this renderer
+   * @brief Applies the image to the texture set used for this renderer
    *
-   * @param[in] image The Image to apply to the material used for this renderer
+   * @param[in] image The Image to apply to the texture set used for this renderer
    */
   void ApplyImageToSampler( const Image& image );
 
index 4f7fe40..df0e8f5 100644 (file)
@@ -47,8 +47,6 @@ const char * const RENDERER_TYPE_VALUE("nPatch");
 const char * const IMAGE_URL_NAME("imageUrl");
 const char * const BORDER_ONLY("borderOnly");
 
-std::string TEXTURE_UNIFORM_NAME = "sTexture";
-
 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
   attribute mediump vec2 aPosition;\n
   varying mediump vec2 vTexCoord;\n
@@ -172,7 +170,7 @@ void AddVertex( Vector< Vector2 >& vertices, unsigned int x, unsigned int y )
   vertices.PushBack( Vector2( x, y ) );
 }
 
-void RegisterStretchProperties( Material& material, const char * uniformName, const NinePatchImage::StretchRanges& stretchPixels, uint16_t imageExtent)
+void RegisterStretchProperties( TextureSet& textureSet, const char * uniformName, const NinePatchImage::StretchRanges& stretchPixels, uint16_t imageExtent)
 {
   uint16_t prevEnd = 0;
   uint16_t prevFix = 0;
@@ -188,7 +186,7 @@ void RegisterStretchProperties( Material& material, const char * uniformName, co
 
     std::stringstream uniform;
     uniform << uniformName << "[" << i << "]";
-    material.RegisterProperty( uniform.str(), Vector2( fix, stretch ) );
+    textureSet.RegisterProperty( uniform.str(), Vector2( fix, stretch ) );
 
     prevEnd = end;
     prevFix = fix;
@@ -199,7 +197,7 @@ void RegisterStretchProperties( Material& material, const char * uniformName, co
     prevFix += imageExtent - prevEnd;
     std::stringstream uniform;
     uniform << uniformName << "[" << i << "]";
-    material.RegisterProperty( uniform.str(), Vector2( prevFix, prevStretch ) );
+    textureSet.RegisterProperty( uniform.str(), Vector2( prevFix, prevStretch ) );
   }
 }
 
@@ -369,8 +367,9 @@ void NPatchRenderer::InitializeRenderer()
     InitializeFromBrokenImage();
   }
 
-  Material material = Material::New( shader );
-  mImpl->mRenderer = Renderer::New( geometry, material );
+  TextureSet textureSet = TextureSet::New();
+  mImpl->mRenderer = Renderer::New( geometry, shader );
+  mImpl->mRenderer.SetTextures( textureSet );
 }
 
 
@@ -443,19 +442,15 @@ void NPatchRenderer::ChangeRenderer( bool oldBorderOnly, size_t oldGridX, size_t
   if( gridChanged )
   {
     Shader shader = CreateShader();
-    Material material;
+    TextureSet textureSet;
     if( shader )
     {
-      material = mImpl->mRenderer.GetMaterial();
-      if( material )
+      textureSet = mImpl->mRenderer.GetTextures();
+      if( !textureSet )
       {
-        material.SetShader( shader );
+        InitializeFromBrokenImage();
       }
-    }
-
-    if( !material )
-    {
-      InitializeFromBrokenImage();
+      mImpl->mRenderer.SetShader( shader );
     }
   }
 }
@@ -543,18 +538,10 @@ void NPatchRenderer::InitializeFromBrokenImage()
 
 void NPatchRenderer::ApplyImageToSampler()
 {
-  Material material = mImpl->mRenderer.GetMaterial();
-  if( material )
+  TextureSet textureSet = mImpl->mRenderer.GetTextures();
+  if( textureSet )
   {
-    int index = material.GetTextureIndex( TEXTURE_UNIFORM_NAME );
-    if( index > -1 )
-    {
-      material.SetTextureImage( index, mCroppedImage );
-    }
-    else
-    {
-      material.AddTexture(  mCroppedImage, TEXTURE_UNIFORM_NAME );
-    }
+    textureSet.SetImage( 0u, mCroppedImage );
 
     if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 )
     {
@@ -565,18 +552,18 @@ void NPatchRenderer::ApplyImageToSampler()
       uint16_t stretchWidth = stretchX.GetY() - stretchX.GetX();
       uint16_t stretchHeight = stretchY.GetY() - stretchY.GetX();
 
-      material.RegisterProperty( "uFixed[0]", Vector2::ZERO );
-      material.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) );
-      material.RegisterProperty( "uFixed[2]", Vector2( mImageSize.GetWidth() - stretchWidth, mImageSize.GetHeight() - stretchHeight ) );
-      material.RegisterProperty( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) );
+      textureSet.RegisterProperty( "uFixed[0]", Vector2::ZERO );
+      textureSet.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) );
+      textureSet.RegisterProperty( "uFixed[2]", Vector2( mImageSize.GetWidth() - stretchWidth, mImageSize.GetHeight() - stretchHeight ) );
+      textureSet.RegisterProperty( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) );
     }
     else
     {
-      material.RegisterProperty( "uNinePatchFactorsX[0]", Vector2::ZERO );
-      material.RegisterProperty( "uNinePatchFactorsY[0]", Vector2::ZERO );
+      textureSet.RegisterProperty( "uNinePatchFactorsX[0]", Vector2::ZERO );
+      textureSet.RegisterProperty( "uNinePatchFactorsY[0]", Vector2::ZERO );
 
-      RegisterStretchProperties( material, "uNinePatchFactorsX", mStretchPixelsX, mImageSize.GetWidth() );
-      RegisterStretchProperties( material, "uNinePatchFactorsY", mStretchPixelsY, mImageSize.GetHeight() );
+      RegisterStretchProperties( textureSet, "uNinePatchFactorsX", mStretchPixelsX, mImageSize.GetWidth() );
+      RegisterStretchProperties( textureSet, "uNinePatchFactorsY", mStretchPixelsY, mImageSize.GetHeight() );
     }
   }
 }
index b6c22e8..44754d7 100644 (file)
@@ -189,7 +189,7 @@ private:
   void InitializeFromBrokenImage();
 
   /**
-   * @brief Applies this renderer's image to the sampler to the material used for this renderer
+   * @brief Applies this renderer's image to the sampler to the texture set used for this renderer
    */
   void ApplyImageToSampler();
 
index acb09bf..2c88562 100644 (file)
@@ -46,8 +46,6 @@ const char * const IMAGE_RENDERER("image");
 const char * const N_PATCH_RENDERER("nPatch");
 const char * const SVG_RENDERER("svg");
 
-const std::string TEXTURE_UNIFORM_NAME = "sTexture";
-
 const char * const BROKEN_RENDERER_IMAGE_URL( DALI_IMAGE_DIR "broken.png");
 
 }
@@ -423,7 +421,7 @@ void RendererFactory::CreateAtlasManager()
   if( !mAtlasManager )
   {
     Shader shader = ImageRenderer::GetImageShader( *( mFactoryCache.Get() ) );
-    mAtlasManager = new ImageAtlasManager(shader, TEXTURE_UNIFORM_NAME);
+    mAtlasManager = new ImageAtlasManager();
     mAtlasManager->SetBrokenImage( BROKEN_RENDERER_IMAGE_URL );
   }
 }
index 9e01462..5202d42 100644 (file)
 #include "nanosvg/nanosvgrast.h"
 #include "svg-renderer.h"
 
-namespace
-{
-const std::string TEXTURE_UNIFORM_NAME = "sTexture";
-}
-
 namespace Dali
 {
 
@@ -110,8 +105,8 @@ void SvgRasterizeThread::AddTask( RasterizingTaskPtr task )
     wasEmpty = mRasterizeTasks.empty();
     if( !wasEmpty && task != NULL)
     {
-      // Remove the tasks with the same material.
-      // Older task which waiting to rasterize and apply the svg to the same material is expired.
+      // Remove the tasks with the same renderer.
+      // Older task which waiting to rasterize and apply the svg to the same renderer is expired.
       for( std::vector< RasterizingTaskPtr >::iterator it = mRasterizeTasks.begin(), endIt = mRasterizeTasks.end(); it != endIt; ++it )
       {
         if( (*it) && (*it)->GetSvgRenderer() == task->GetSvgRenderer() )
index 8309674..e3b1ce2 100644 (file)
@@ -21,7 +21,7 @@
 #include <dali/devel-api/threading/conditional-wait.h>
 #include <dali/devel-api/threading/mutex.h>
 #include <dali/devel-api/threading/thread.h>
-#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/texture-set.h>
 #include <dali/devel-api/images/pixel-data.h>
 #include <dali/public-api/images/buffer-image.h>
 #include <dali/public-api/common/intrusive-ptr.h>
@@ -138,9 +138,9 @@ public:
   RasterizingTaskPtr NextCompletedTask();
 
   /**
-   * Remove the task with the given material from the waiting queue, called by main thread.
+   * Remove the task with the given renderer from the waiting queue, called by main thread.
    *
-   * Typically called when the actor is put off stage, so the material is not needed anymore.
+   * Typically called when the actor is put off stage, so the renderer is not needed anymore.
    *
    * @param[in] renderer The renderer pointer.
    */
@@ -181,7 +181,7 @@ protected:
 
   /**
    * The entry function of the worker thread.
-   * It fetches task from the Queue, rasterizes the image and apply to the material.
+   * It fetches task from the Queue, rasterizes the image and apply to the renderer.
    */
   virtual void Run();
 
index d3c128d..2642c74 100644 (file)
@@ -104,8 +104,9 @@ void SvgRenderer::DoSetOnStage( Actor& actor )
     geometry =  mFactoryCache.CreateQuadGeometry();
     mFactoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
   }
-  Material material = Material::New( shader );
-  mImpl->mRenderer = Renderer::New( geometry, material );
+  TextureSet textureSet = TextureSet::New();
+  mImpl->mRenderer = Renderer::New( geometry, shader );
+  mImpl->mRenderer.SetTextures( textureSet );
 
   if( mImpl->mSize != Vector2::ZERO && mParsedImage )
   {
@@ -197,19 +198,19 @@ void SvgRenderer::ApplyRasterizedImage( PixelDataPtr rasterizedPixelData )
 {
   if( GetIsOnStage()  )
   {
-    Material currentMaterial = mImpl->mRenderer.GetMaterial();
+    TextureSet currentTextureSet = mImpl->mRenderer.GetTextures();
     if( mAtlasRect != FULL_TEXTURE_RECT )
     {
-      mAtlasManager.Remove( currentMaterial, mAtlasRect );
+      mAtlasManager.Remove( currentTextureSet, mAtlasRect );
     }
 
     Vector4 atlasRect;
-    Material material = mAtlasManager.Add(atlasRect, rasterizedPixelData );
-    if( material ) // atlasing
+    TextureSet textureSet = mAtlasManager.Add(atlasRect, rasterizedPixelData );
+    if( textureSet ) // atlasing
     {
-      if( material != currentMaterial )
+      if( textureSet != currentTextureSet )
       {
-        mImpl->mRenderer.SetMaterial( material );
+        mImpl->mRenderer.SetTextures( textureSet );
       }
       mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect );
       mAtlasRect = atlasRect;
@@ -221,27 +222,20 @@ void SvgRenderer::ApplyRasterizedImage( PixelDataPtr rasterizedPixelData )
 
       if( mAtlasRect == FULL_TEXTURE_RECT )
       {
-        material = currentMaterial;
+        textureSet = currentTextureSet;
       }
       else
       {
-        material = Material::New( ImageRenderer::GetImageShader( mFactoryCache ) );
-        mImpl->mRenderer.SetMaterial( material );
+        textureSet = TextureSet::New();
+        mImpl->mRenderer.SetTextures( textureSet );
 
         mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT );
         mAtlasRect = FULL_TEXTURE_RECT;
       }
 
-      if( material )
+      if( textureSet )
       {
-        int index = material.GetTextureIndex( TEXTURE_UNIFORM_NAME );
-        if( index != -1 )
-        {
-          material.SetTextureImage( index, texture );
-          return;
-        }
-
-        material.AddTexture( texture, TEXTURE_UNIFORM_NAME );
+        textureSet.SetImage( 0u, texture );
       }
     }
   }
index 2c20ba1..d1437ff 100644 (file)
@@ -121,7 +121,7 @@ public:
 
 private:
   /**
-   * @bried Rasterize the svg with the given size, and add it to the material.
+   * @bried Rasterize the svg with the given size, and add it to the renderer.
    *
    * @param[in] size The target size of the SVG rasterization.
    */
index 2218ddc..91e556f 100644 (file)
@@ -23,7 +23,7 @@
 #include <dali/public-api/object/property-map.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/texture-set.h>
 #include <dali/devel-api/rendering/renderer.h>
 #include <dali/devel-api/rendering/shader.h>
 
@@ -127,12 +127,11 @@ Actor CreateBouncingEffectActor( Property::Index& bouncePropertyIndex )
   meshGeometry.AddVertexBuffer( vertices );
   meshGeometry.SetIndexBuffer( indices );
 
-  // Create material
+  // Create the shader
   Shader shader = Shader::New( MESH_VERTEX_SHADER, MESH_FRAGMENT_SHADER );
-  Material material = Material::New( shader );
 
   // Create renderer
-  Renderer renderer = Renderer::New( meshGeometry, material );
+  Renderer renderer = Renderer::New( meshGeometry, shader );
 
   // Create actor
   Actor meshActor= Actor::New();
index e1f79ca..3a4ad99 100644 (file)
@@ -49,8 +49,7 @@ DALI_TYPE_REGISTRATION_BEGIN( Toolkit::Scrollable, Toolkit::Control, Create );
 DALI_PROPERTY_REGISTRATION( Toolkit, Scrollable, "overshootEffectColor",      VECTOR4, OVERSHOOT_EFFECT_COLOR    )
 DALI_PROPERTY_REGISTRATION( Toolkit, Scrollable, "overshootAnimationSpeed",   FLOAT,   OVERSHOOT_ANIMATION_SPEED )
 DALI_PROPERTY_REGISTRATION( Toolkit, Scrollable, "overshootEnabled",          BOOLEAN, OVERSHOOT_ENABLED )
-const int OVERSHOOT_SIZE = Dali::Toolkit::Scrollable::Property::OVERSHOOT_ENABLED + 1; // OVERSHOOT_SIZE is not public yet
-Dali::PropertyRegistration p1( typeRegistration, "overshootSize",  OVERSHOOT_SIZE, Property::VECTOR2, Dali::Toolkit::Internal::Scrollable::SetProperty, Dali::Toolkit::Internal::Scrollable::GetProperty );
+DALI_PROPERTY_REGISTRATION( Toolkit, Scrollable, "overshootSize",             VECTOR2, OVERSHOOT_SIZE )
 
 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Scrollable, "scrollRelativePosition",   VECTOR2, SCROLL_RELATIVE_POSITION)
 DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Scrollable, "scrollPositionMin",        VECTOR2, SCROLL_POSITION_MIN)
@@ -200,7 +199,7 @@ void Scrollable::SetProperty( BaseObject* object, Property::Index index, const P
         scrollableImpl.SetOvershootEnabled( value.Get<bool>() );
         break;
       }
-      case OVERSHOOT_SIZE: // OVERSHOOT_SIZE is not public yet
+      case Toolkit::Scrollable::Property::OVERSHOOT_SIZE:
       {
         Vector2 input;
         if( value.Get( input ) )
@@ -240,7 +239,7 @@ Property::Value Scrollable::GetProperty( BaseObject* object, Property::Index ind
         value = scrollableImpl.IsOvershootEnabled();
         break;
       }
-      case OVERSHOOT_SIZE: // OVERSHOOT_SIZE is not public yet
+      case Toolkit::Scrollable::Property::OVERSHOOT_SIZE:
       {
         value = scrollableImpl.mOvershootSize;
         break;
index 981b228..082e7e5 100644 (file)
@@ -164,11 +164,23 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         int backend = value.Get< int >();
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "TextField %p RENDERING_BACKEND %d\n", impl.mController.Get(), backend );
 
+#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING
+        if( Text::RENDERING_VECTOR_BASED == backend )
+        {
+          backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering
+        }
+#endif
         if( impl.mRenderingBackend != backend )
         {
           impl.mRenderingBackend = backend;
           impl.mRenderer.Reset();
-          impl.RequestTextRelayout();
+
+          if( impl.mController )
+          {
+            // When using the vector-based rendering, the size of the GLyphs are different
+            TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
+            impl.mController->SetGlyphType( glyphType );
+          }
         }
         break;
       }
@@ -972,6 +984,10 @@ void TextField::OnInitialize()
 
   mController = Text::Controller::New( *this );
 
+  // When using the vector-based rendering, the size of the GLyphs are different
+  TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
+  mController->SetGlyphType( glyphType );
+
   mDecorator = Text::Decorator::New( *mController,
                                      *mController );
 
index 7ad0bfb..9d3fd45 100644 (file)
@@ -125,13 +125,25 @@ void TextLabel::SetProperty( BaseObject* object, Property::Index index, const Pr
     {
       case Toolkit::TextLabel::Property::RENDERING_BACKEND:
       {
-        const int backend = value.Get< int >();
+        int backend = value.Get< int >();
 
+#ifndef ENABLE_VECTOR_BASED_TEXT_RENDERING
+        if( Text::RENDERING_VECTOR_BASED == backend )
+        {
+          backend = TextAbstraction::BITMAP_GLYPH; // Fallback to bitmap-based rendering
+        }
+#endif
         if( impl.mRenderingBackend != backend )
         {
           impl.mRenderingBackend = backend;
           impl.mRenderer.Reset();
-          impl.RequestTextRelayout();
+
+          if( impl.mController )
+          {
+            // When using the vector-based rendering, the size of the GLyphs are different
+            TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == impl.mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
+            impl.mController->SetGlyphType( glyphType );
+          }
         }
         break;
       }
@@ -455,6 +467,10 @@ void TextLabel::OnInitialize()
 
   mController = Text::Controller::New( *this );
 
+  // When using the vector-based rendering, the size of the GLyphs are different
+  TextAbstraction::GlyphType glyphType = (Text::RENDERING_VECTOR_BASED == mRenderingBackend) ? TextAbstraction::VECTOR_GLYPH : TextAbstraction::BITMAP_GLYPH;
+  mController->SetGlyphType( glyphType );
+
   // Use height-for-width negotiation by default
   self.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::WIDTH );
   self.SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
index 742e111..51f9a97 100644 (file)
@@ -47,7 +47,7 @@ namespace Internal
 namespace
 {
 // todo Move this to adaptor??
-#define GET_LOCALE_TEXT(string) dgettext("sys_string", string)
+#define GET_LOCALE_TEXT(string) dgettext("dali-toolkit", string)
 
 const std::string TEXT_SELECTION_POPUP_BUTTON_STYLE_NAME( "textselectionpopupbutton" );
 const Dali::Vector4 DEFAULT_OPTION_PRESSED_COLOR( Dali::Vector4( 0.24f, 0.72f, 0.8f, 1.0f ) );
index 293531d..758160f 100644 (file)
@@ -38,6 +38,8 @@ toolkit_src_files = \
    $(toolkit_src_dir)/controls/buttons/push-button-impl.cpp \
    $(toolkit_src_dir)/controls/buttons/radio-button-impl.cpp \
    $(toolkit_src_dir)/controls/effects-view/effects-view-impl.cpp \
+   $(toolkit_src_dir)/controls/flex-container/layout.c \
+   $(toolkit_src_dir)/controls/flex-container/flex-container-impl.cpp \
    $(toolkit_src_dir)/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp \
    $(toolkit_src_dir)/controls/image-view/image-view-impl.cpp \
    $(toolkit_src_dir)/controls/magnifier/magnifier-impl.cpp \
@@ -89,6 +91,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/text/character-set-conversion.cpp \
    $(toolkit_src_dir)/text/clipping/text-clipper.cpp \
    $(toolkit_src_dir)/text/color-segmentation.cpp \
+   $(toolkit_src_dir)/text/glyph-metrics-helper.cpp \
    $(toolkit_src_dir)/text/logical-model-impl.cpp \
    $(toolkit_src_dir)/text/markup-processor.cpp \
    $(toolkit_src_dir)/text/markup-processor-color.cpp \
index 1b3a5f1..ed8dada 100644 (file)
@@ -184,16 +184,8 @@ void BlurTwoPassFilter::Enable()
   mRootActor.Add( mActorForBlending );
 
   // Add effect texture to blend-two-image custom shader
-  Material material = mActorForBlending.GetRendererAt(0).GetMaterial();
-  int textureIndex = material.GetTextureIndex( EFFECT_IMAGE_NAME );
-  if( textureIndex == -1 )
-  {
-    material.AddTexture( mInputImage, EFFECT_IMAGE_NAME );
-  }
-  else
-  {
-    material.SetTextureImage( textureIndex, mInputImage );
-  }
+  TextureSet textureSet = mActorForBlending.GetRendererAt(0).GetTextures();
+  textureSet.SetImage( 1u, mInputImage );
 
   SetupCamera();
   CreateRenderTasks();
index 43ccb78..bb393ff 100644 (file)
@@ -284,8 +284,7 @@ struct Decorator::Impl : public ConnectionTracker
   {
     mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
     mQuadIndexFormat[ "indices" ] = Property::INTEGER;
-    mHighlightMaterial = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
-
+    mHighlightShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
     SetupTouchEvents();
   }
 
@@ -1069,7 +1068,7 @@ struct Decorator::Impl : public ConnectionTracker
 
         if( !mHighlightRenderer )
         {
-          mHighlightRenderer = Dali::Renderer::New( mQuadGeometry, mHighlightMaterial );
+          mHighlightRenderer = Dali::Renderer::New( mQuadGeometry, mHighlightShader );
           mHighlightActor.AddRenderer( mHighlightRenderer );
         }
       }
@@ -1653,7 +1652,7 @@ struct Decorator::Impl : public ConnectionTracker
 
   Actor               mHighlightActor;            ///< Actor to display highlight
   Renderer            mHighlightRenderer;
-  Material            mHighlightMaterial;         ///< Material used for highlight
+  Shader              mHighlightShader;           ///< Shader used for highlight
   Property::Map       mQuadVertexFormat;
   Property::Map       mQuadIndexFormat;
   PopupImpl           mCopyPastePopup;
diff --git a/dali-toolkit/internal/text/glyph-metrics-helper.cpp b/dali-toolkit/internal/text/glyph-metrics-helper.cpp
new file mode 100644 (file)
index 0000000..9c7c8ec
--- /dev/null
@@ -0,0 +1,83 @@
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <dali-toolkit/internal/text/glyph-metrics-helper.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+Length GetNumberOfGlyphsOfGroup( GlyphIndex glyphIndex,
+                                 GlyphIndex lastGlyphPlusOne,
+                                 const Length* const charactersPerGlyphBuffer )
+{
+  Length numberOfGLyphsInGroup = 1u;
+
+  for( GlyphIndex index = glyphIndex; index < lastGlyphPlusOne; ++index )
+  {
+    if( 0u == *( charactersPerGlyphBuffer + index ) )
+    {
+      ++numberOfGLyphsInGroup;
+    }
+    else
+    {
+      break;
+    }
+  }
+
+  return numberOfGLyphsInGroup;
+}
+
+void GetGlyphsMetrics( GlyphIndex glyphIndex,
+                       Length numberOfGlyphs,
+                       GlyphMetrics& glyphMetrics,
+                       const GlyphInfo* const glyphsBuffer,
+                       MetricsPtr& metrics )
+{
+  const GlyphInfo& firstGlyph = *( glyphsBuffer + glyphIndex );
+
+  Text::FontMetrics fontMetrics;
+  metrics->GetFontMetrics( firstGlyph.fontId, fontMetrics );
+
+  glyphMetrics.fontId = firstGlyph.fontId;
+  glyphMetrics.fontHeight = fontMetrics.height;
+  glyphMetrics.width = firstGlyph.width;
+  glyphMetrics.advance = firstGlyph.advance;
+  glyphMetrics.ascender = fontMetrics.ascender;
+  glyphMetrics.xBearing = firstGlyph.xBearing;
+
+  for( unsigned int i = 1u; i < numberOfGlyphs; ++i )
+  {
+    const GlyphInfo& glyphInfo = *( glyphsBuffer + glyphIndex + i );
+
+    glyphMetrics.advance += glyphInfo.advance;
+    glyphMetrics.width += glyphInfo.width;
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/glyph-metrics-helper.h b/dali-toolkit/internal/text/glyph-metrics-helper.h
new file mode 100644 (file)
index 0000000..2c2c848
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __DALI_TOOLKIT_TEXT_GLYPH_METRICS_HELPER_H__
+#define __DALI_TOOLKIT_TEXT_GLYPH_METRICS_HELPER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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-toolkit/internal/text/metrics.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Some characters can be shaped in more than one glyph.
+ * This struct is used to retrieve metrics from these group of glyphs.
+ */
+struct GlyphMetrics
+{
+  GlyphMetrics()
+  : fontId( 0u ),
+    fontHeight( 0.f ),
+    width( 0.f ),
+    advance( 0.f ),
+    ascender( 0.f ),
+    xBearing( 0.f )
+  {}
+
+  ~GlyphMetrics()
+  {}
+
+  FontId fontId;     ///< The font id of the glyphs.
+  float  fontHeight; ///< The font's height of those glyphs.
+  float  width;      ///< The sum of all the widths of all the glyphs.
+  float  advance;    ///< The sum of all the advances of all the glyphs.
+  float  ascender;   ///< The font's ascender.
+  float  xBearing;   ///< The x bearing of the first glyph.
+};
+
+/**
+ * @brief Returns the number of glyphs of a group of glyphs.
+ *
+ * @param[in] glyphIndex The first glyph of the group.
+ * @param[in] lastGlyphPlusOne Index to one after the last glyph.
+ * @param[in] charactersPerGlyphBuffer The number of characters per glyph buffer.
+ *
+ * @return The number of glyphs of the group.
+ */
+Length GetNumberOfGlyphsOfGroup( GlyphIndex glyphIndex,
+                                 GlyphIndex lastGlyphPlusOne,
+                                 const Length* const charactersPerGlyphBuffer );
+
+/**
+ * @brief Get some glyph's metrics of a group of glyphs formed as a result of shaping one character.
+ *
+ * @param[in] glyphIndex The index to the first glyph.
+ * @param[in] numberOfGlyphs The number of glyphs.
+ * @param[out] glyphMetrics Some glyph metrics (font height, advance, ascender and x bearing).
+ * @param[in] glyphsBuffer The glyphs buffer.
+ * @param[in] metrics Used to access metrics from FontClient.
+ */
+void GetGlyphsMetrics( GlyphIndex glyphIndex,
+                       Length numberOfGlyphs,
+                       GlyphMetrics& glyphMetrics,
+                       const GlyphInfo* const glyphsBuffer,
+                       MetricsPtr& metrics );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_GLYPH_METRICS_HELPER_H__
index 9d81116..4182acd 100644 (file)
@@ -24,8 +24,9 @@
 #include <dali/devel-api/text-abstraction/font-client.h>
 
 // INTERNAL INCLUDES
-#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
+#include <dali-toolkit/internal/text/layouts/layout-parameters.h>
 
 namespace Dali
 {
@@ -47,26 +48,6 @@ const float MAX_FLOAT = std::numeric_limits<float>::max();
 const bool RTL = true;
 const float CURSOR_WIDTH = 1.f;
 
-Length CountParagraphs( const LayoutParameters& layoutParameters )
-{
-  Length numberOfParagraphs = 0u;
-
-  const CharacterIndex startCharacterIndex = *( layoutParameters.glyphsToCharactersBuffer + layoutParameters.startGlyphIndex );
-
-  const GlyphIndex lastGlyphIndex = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs - 1u;
-  const CharacterIndex lastCharacterIndexPlusOne = *( layoutParameters.glyphsToCharactersBuffer + lastGlyphIndex ) + *( layoutParameters.charactersPerGlyphBuffer + lastGlyphIndex );
-
-  for( CharacterIndex index = startCharacterIndex; index < lastCharacterIndexPlusOne; ++index )
-  {
-    if( TextAbstraction::LINE_MUST_BREAK == *( layoutParameters.lineBreakInfoBuffer + index ) )
-    {
-      ++numberOfParagraphs;
-    }
-  }
-
-  return numberOfParagraphs;
-}
-
 } //namespace
 
 /**
@@ -214,59 +195,81 @@ struct LayoutEngine::Impl
     LineLayout tmpLineLayout;
 
     const bool isMultiline = mLayout == MULTI_LINE_BOX;
-    const GlyphIndex lastGlyphIndex = parameters.totalNumberOfGlyphs - 1u;
+
+    // The last glyph to be laid-out.
+    const GlyphIndex lastGlyphOfParagraphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
 
     // If the first glyph has a negative bearing its absolute value needs to be added to the line length.
     // In the case the line starts with a right to left character, if the width is longer than the advance,
     // the difference needs to be added to the line length.
-    const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + lineLayout.glyphIndex );
+
+    // Check whether the first glyph comes from a character that is shaped in multiple glyphs.
+    const Length numberOfGLyphsInGroup = GetNumberOfGlyphsOfGroup( lineLayout.glyphIndex,
+                                                                   lastGlyphOfParagraphPlusOne,
+                                                                   parameters.charactersPerGlyphBuffer );
+
+    GlyphMetrics glyphMetrics;
+    GetGlyphsMetrics( lineLayout.glyphIndex,
+                      numberOfGLyphsInGroup,
+                      glyphMetrics,
+                      parameters.glyphsBuffer,
+                      mMetrics );
 
     // Set the direction of the first character of the line.
     lineLayout.characterIndex = *( parameters.glyphsToCharactersBuffer + lineLayout.glyphIndex );
     const CharacterDirection firstCharacterDirection = ( NULL == parameters.characterDirectionBuffer ) ? false : *( parameters.characterDirectionBuffer + lineLayout.characterIndex );
     CharacterDirection previousCharacterDirection = firstCharacterDirection;
 
-    const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+    const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
     float tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
 
-    float tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+    float tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
 
     tmpLineLayout.length += mCursorWidth; // Added to give some space to the cursor.
 
     // Calculate the line height if there is no characters.
-    FontId lastFontId = glyphInfo.fontId;
+    FontId lastFontId = glyphMetrics.fontId;
     UpdateLineHeight( lastFontId, tmpLineLayout );
 
     bool oneWordLaidOut = false;
 
-    const GlyphIndex lastGlyphPlusOne = parameters.startGlyphIndex + parameters.numberOfGlyphs;
     for( GlyphIndex glyphIndex = lineLayout.glyphIndex;
-         glyphIndex < lastGlyphPlusOne;
-         ++glyphIndex )
+         glyphIndex < lastGlyphOfParagraphPlusOne; )
     {
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  glyph index : %d\n", glyphIndex );
-      const bool isLastGlyph = glyphIndex == lastGlyphIndex;
 
-      // Get the glyph info.
-      const GlyphInfo& glyphInfo = *( parameters.glyphsBuffer + glyphIndex );
+      // Check whether this glyph comes from a character that is shaped in multiple glyphs.
+      const Length numberOfGLyphsInGroup = GetNumberOfGlyphsOfGroup( glyphIndex,
+                                                                     lastGlyphOfParagraphPlusOne,
+                                                                     parameters.charactersPerGlyphBuffer );
+
+      GlyphMetrics glyphMetrics;
+      GetGlyphsMetrics( glyphIndex,
+                        numberOfGLyphsInGroup,
+                        glyphMetrics,
+                        parameters.glyphsBuffer,
+                        mMetrics );
+
+      const bool isLastGlyph = glyphIndex + numberOfGLyphsInGroup  == parameters.totalNumberOfGlyphs;
 
       // Check if the font of the current glyph is the same of the previous one.
       // If it's different the ascender and descender need to be updated.
-      if( lastFontId != glyphInfo.fontId )
+      if( lastFontId != glyphMetrics.fontId )
       {
-        UpdateLineHeight( glyphInfo.fontId, tmpLineLayout );
-        lastFontId = glyphInfo.fontId;
+        UpdateLineHeight( glyphMetrics.fontId, tmpLineLayout );
+        lastFontId = glyphMetrics.fontId;
       }
 
       // Get the character indices for the current glyph. The last character index is needed
       // because there are glyphs formed by more than one character but their break info is
       // given only for the last character.
-      const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex );
+      const Length charactersPerGlyph = *( parameters.charactersPerGlyphBuffer + glyphIndex + numberOfGLyphsInGroup - 1u );
+      const bool hasCharacters = charactersPerGlyph > 0u;
       const CharacterIndex characterFirstIndex = *( parameters.glyphsToCharactersBuffer + glyphIndex );
-      const CharacterIndex characterLastIndex = characterFirstIndex + ( ( 1u > charactersPerGlyph ) ? 0u : charactersPerGlyph - 1u );
+      const CharacterIndex characterLastIndex = characterFirstIndex + ( hasCharacters ? charactersPerGlyph - 1u : 0u );
 
       // Get the line break info for the current character.
-      const LineBreakInfo lineBreakInfo = *( parameters.lineBreakInfoBuffer + characterLastIndex );
+      const LineBreakInfo lineBreakInfo = hasCharacters ? *( parameters.lineBreakInfoBuffer + characterLastIndex ) : TextAbstraction::LINE_NO_BREAK;
 
       // Get the word break info for the current character.
       const WordBreakInfo wordBreakInfo = *( parameters.wordBreakInfoBuffer + characterLastIndex );
@@ -275,7 +278,7 @@ struct LayoutEngine::Impl
       tmpLineLayout.numberOfCharacters += charactersPerGlyph;
 
       // Increase the number of glyphs.
-      tmpLineLayout.numberOfGlyphs++;
+      tmpLineLayout.numberOfGlyphs += numberOfGLyphsInGroup;
 
       // Check whether is a white space.
       const Character character = *( parameters.textBuffer + characterFirstIndex );
@@ -293,12 +296,12 @@ struct LayoutEngine::Impl
       if( isWhiteSpace )
       {
         // Add the length to the length of white spaces at the end of the line.
-        tmpLineLayout.wsLengthEndOfLine += glyphInfo.advance; // The advance is used as the width is always zero for the white spaces.
+        tmpLineLayout.wsLengthEndOfLine += glyphMetrics.advance; // The advance is used as the width is always zero for the white spaces.
       }
       else
       {
         // Add as well any previous white space length.
-        tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphInfo.advance;
+        tmpLineLayout.length += tmpLineLayout.wsLengthEndOfLine + glyphMetrics.advance;
 
         // An extra space may be added to the line for the first and last glyph of the line.
         // If the bearing of the first glyph is negative, its positive value needs to be added.
@@ -318,7 +321,7 @@ struct LayoutEngine::Impl
             // |     Rll|
             //
 
-            tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+            tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
           }
           else // LTR
           {
@@ -331,7 +334,7 @@ struct LayoutEngine::Impl
             // |rrL     |
             //
 
-            const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+            const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
             tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
           }
         }
@@ -344,7 +347,7 @@ struct LayoutEngine::Impl
               //  -->
               // |lllR    |
 
-              const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+              const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
               tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
             }
             else // LTR
@@ -352,7 +355,7 @@ struct LayoutEngine::Impl
               //       <--
               // |   Lrrrr|
 
-              tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+              tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
             }
           }
           else if( characterDirection == firstCharacterDirection )
@@ -363,7 +366,7 @@ struct LayoutEngine::Impl
               // |llllllrr|
               // |Rr      |
 
-              tmpExtraBearing = ( 0.f > glyphInfo.xBearing ) ? -glyphInfo.xBearing : 0.f;
+              tmpExtraBearing = ( 0.f > glyphMetrics.xBearing ) ? -glyphMetrics.xBearing : 0.f;
             }
             else // LTR
             {
@@ -371,7 +374,7 @@ struct LayoutEngine::Impl
               // |llllrrrr|
               // |     llL|
 
-              const float extraWidth = glyphInfo.xBearing + glyphInfo.width - glyphInfo.advance;
+              const float extraWidth = glyphMetrics.xBearing + glyphMetrics.width - glyphMetrics.advance;
               tmpExtraWidth = ( 0.f < extraWidth ) ? extraWidth : 0.f;
             }
           }
@@ -394,7 +397,7 @@ struct LayoutEngine::Impl
           if( tmpLineLayout.numberOfGlyphs > 0u )
           {
             tmpLineLayout.numberOfCharacters -= charactersPerGlyph;
-            --tmpLineLayout.numberOfGlyphs;
+            tmpLineLayout.numberOfGlyphs -= numberOfGLyphsInGroup;
             tmpLineLayout.length = previousTmpLineLength;
             tmpExtraBearing = previousTmpExtraBearing;
             tmpExtraWidth = previousTmpExtraWidth;
@@ -434,6 +437,7 @@ struct LayoutEngine::Impl
 
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "  Must break\n" );
         DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--GetLineLayoutForBox\n" );
+
         return;
       }
 
@@ -451,6 +455,7 @@ struct LayoutEngine::Impl
       }
 
       previousCharacterDirection = characterDirection;
+      glyphIndex += numberOfGLyphsInGroup;
     }
 
     lineLayout.extraBearing = tmpExtraBearing;
@@ -489,7 +494,6 @@ struct LayoutEngine::Impl
 
   void SetGlyphPositions( const GlyphInfo* const glyphsBuffer,
                           Length numberOfGlyphs,
-                          float penY,
                           Vector2* glyphPositionsBuffer )
   {
     // Traverse the glyphs and set the positions.
@@ -507,7 +511,7 @@ struct LayoutEngine::Impl
       Vector2& position = *( glyphPositionsBuffer + i );
 
       position.x = penX + glyph.xBearing;
-      position.y = penY - glyph.yBearing;
+      position.y = -glyph.yBearing;
 
       penX += glyph.advance;
     }
@@ -621,7 +625,6 @@ struct LayoutEngine::Impl
 
       SetGlyphPositions( layoutParameters.glyphsBuffer + lineRun->glyphRun.glyphIndex,
                          ellipsisLayout.numberOfGlyphs,
-                         penY,
                          glyphPositionsBuffer + lineRun->glyphRun.glyphIndex - layoutParameters.startGlyphIndex );
     }
 
@@ -691,17 +694,17 @@ struct LayoutEngine::Impl
    * @brief Updates the text layout with the last laid-out line.
    *
    * @param[in] layoutParameters The parameters needed to layout the text.
-   * @param[in] layout The line layout.
+   * @param[in] characterIndex The character index of the line.
+   * @param[in] glyphIndex The glyph index of the line.
    * @param[in,out] layoutSize The text's layout size.
    * @param[in,out] linesBuffer Pointer to the line's buffer.
-   * @param[in] index Index to the vector of glyphs.
    * @param[in,out] numberOfLines The number of laid-out lines.
    */
   void UpdateTextLayout( const LayoutParameters& layoutParameters,
-                         const LineLayout& layout,
+                         CharacterIndex characterIndex,
+                         GlyphIndex glyphIndex,
                          Size& layoutSize,
                          LineRun* linesBuffer,
-                         GlyphIndex index,
                          Length& numberOfLines )
   {
     // Need to add a new line with no characters but with height to increase the layoutSize.height
@@ -713,9 +716,9 @@ struct LayoutEngine::Impl
     LineRun& lineRun = *( linesBuffer + numberOfLines );
     ++numberOfLines;
 
-    lineRun.glyphRun.glyphIndex = index + layout.numberOfGlyphs;
+    lineRun.glyphRun.glyphIndex = glyphIndex;
     lineRun.glyphRun.numberOfGlyphs = 0u;
-    lineRun.characterRun.characterIndex = layout.characterIndex + layout.numberOfCharacters;
+    lineRun.characterRun.characterIndex = characterIndex;
     lineRun.characterRun.numberOfCharacters = 0u;
     lineRun.width = 0.f;
     lineRun.ascender = fontMetrics.ascender;
@@ -792,10 +795,49 @@ struct LayoutEngine::Impl
 
     if( 0u == layoutParameters.numberOfGlyphs )
     {
-      // Nothing to do if there are no glyphs to layout.
+      // Add an extra line if the last character is a new paragraph character and the last line doesn't have zero characters.
+      if( layoutParameters.isLastNewParagraph )
+      {
+        Length numberOfLines = lines.Count();
+        if( 0u != numberOfLines )
+        {
+          const LineRun& lastLine = *( lines.End() - 1u );
+
+          if( 0u != lastLine.characterRun.numberOfCharacters )
+          {
+            // Need to add a new line with no characters but with height to increase the layoutSize.height
+            LineRun newLine;
+            lines.PushBack( newLine );
+
+            UpdateTextLayout( layoutParameters,
+                              lastLine.characterRun.characterIndex + lastLine.characterRun.numberOfCharacters,
+                              lastLine.glyphRun.glyphIndex + lastLine.glyphRun.numberOfGlyphs,
+                              layoutSize,
+                              lines.Begin(),
+                              numberOfLines );
+          }
+        }
+      }
+
+      // Nothing else do if there are no glyphs to layout.
       return false;
     }
 
+    const GlyphIndex lastGlyphPlusOne = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs;
+
+    // In a previous layout, an extra line with no characters may have been added if the text ended with a new paragraph character.
+    // This extra line needs to be removed.
+    if( 0u != lines.Count() )
+    {
+      Vector<LineRun>::Iterator lastLine = lines.End() - 1u;
+
+      if( ( 0u == lastLine->characterRun.numberOfCharacters ) &&
+          ( lastGlyphPlusOne == layoutParameters.totalNumberOfGlyphs ) )
+      {
+        lines.Remove( lastLine );
+      }
+    }
+
     // Set the first paragraph's direction.
     CharacterDirection paragraphDirection = ( NULL != layoutParameters.characterDirectionBuffer ) ? *layoutParameters.characterDirectionBuffer : !RTL;
 
@@ -809,8 +851,7 @@ struct LayoutEngine::Impl
     Vector<LineRun> newLines;
 
     // Estimate the number of lines.
-    // TODO: In a next patch the paragraphs are properly managed and this can be removed.
-    Length linesCapacity = CountParagraphs( layoutParameters );
+    Length linesCapacity = layoutParameters.estimatedNumberOfLines;
     Length numberOfLines = 0u;
 
     if( updateCurrentBuffer )
@@ -832,7 +873,6 @@ struct LayoutEngine::Impl
     float penY = SetParagraphOffset( lines,
                                      layoutParameters.startLineIndex );
 
-    const GlyphIndex lastGlyphPlusOne = layoutParameters.startGlyphIndex + layoutParameters.numberOfGlyphs;
     for( GlyphIndex index = layoutParameters.startGlyphIndex; index < lastGlyphPlusOne; )
     {
       CharacterDirection currentParagraphDirection = paragraphDirection;
@@ -908,7 +948,9 @@ struct LayoutEngine::Impl
                           numberOfLines,
                           isLastLine );
 
-        if( isLastLine &&
+        const GlyphIndex nextIndex = index + layout.numberOfGlyphs;
+
+        if( ( nextIndex == layoutParameters.totalNumberOfGlyphs ) &&
             layoutParameters.isLastNewParagraph &&
             ( mLayout == MULTI_LINE_BOX ) )
         {
@@ -926,25 +968,23 @@ struct LayoutEngine::Impl
           }
 
           UpdateTextLayout( layoutParameters,
-                            layout,
+                            layout.characterIndex + layout.numberOfCharacters,
+                            index + layout.numberOfGlyphs,
                             layoutSize,
                             linesBuffer,
-                            index,
                             numberOfLines );
         } // whether to add a last line.
 
         // Sets the positions of the glyphs.
         SetGlyphPositions( layoutParameters.glyphsBuffer + index,
                            layout.numberOfGlyphs,
-                           penY,
                            glyphPositionsBuffer + index - layoutParameters.startGlyphIndex );
 
         // Updates the vertical pen's position.
         penY += -layout.descender;
 
         // Increase the glyph index.
-        index += layout.numberOfGlyphs;
-
+        index = nextIndex;
       } // no ellipsis
     } // end for() traversing glyphs.
 
@@ -953,6 +993,7 @@ struct LayoutEngine::Impl
       glyphPositions.Insert( glyphPositions.Begin() + layoutParameters.startGlyphIndex,
                              newGlyphPositions.Begin(),
                              newGlyphPositions.End() );
+      glyphPositions.Resize( layoutParameters.totalNumberOfGlyphs );
 
       newLines.Resize( numberOfLines );
 
index 238dade..8d875bf 100644 (file)
@@ -82,6 +82,7 @@ struct LayoutParameters
     numberOfGlyphs( 0u ),
     totalNumberOfGlyphs( totalNumberOfGlyphs ),
     startLineIndex( 0u ),
+    estimatedNumberOfLines( 0u ),
     isLastNewParagraph( false )
   {}
 
@@ -101,6 +102,7 @@ struct LayoutParameters
   Length                          numberOfGlyphs;                  ///< The number of glyphs to layout.
   Length                          totalNumberOfGlyphs;             ///< The number of glyphs.
   LineIndex                       startLineIndex;                  ///< The line index where to insert the new lines.
+  Length                          estimatedNumberOfLines;          ///< The estimated number of lines.
   bool                            isLastNewParagraph;              ///< Whether the last character is a new paragraph character.
 };
 
index 147ae79..232360e 100644 (file)
@@ -22,6 +22,9 @@
 #include <dali/public-api/common/intrusive-ptr.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
 namespace Dali
 {
 
@@ -50,6 +53,16 @@ public:
   }
 
   /**
+   * @brief Used to switch between bitmap & vector based glyphs
+   *
+   * @param[in] glyphType The type of glyph; note that metrics for bitmap & vector based glyphs are different.
+   */
+  void SetGlyphType( TextAbstraction::GlyphType glyphType )
+  {
+    mGlyphType = glyphType;
+  }
+
+  /**
    * @brief Set the maximum Emoji size.
    *
    * @param[in] emojiSize Emoticons will be scaled to fit this size in pixels.
@@ -91,7 +104,7 @@ public:
    */
   bool GetGlyphMetrics( GlyphInfo* array, uint32_t size )
   {
-    return mFontClient.GetGlyphMetrics( array, size, true, mEmojiSize ); // inline for performance
+    return mFontClient.GetGlyphMetrics( array, size, mGlyphType, true, mEmojiSize ); // inline for performance
   }
 
 protected:
@@ -108,6 +121,7 @@ private:
    */
   Metrics( TextAbstraction::FontClient& fontClient )
   : mFontClient( fontClient ),
+    mGlyphType( TextAbstraction::BITMAP_GLYPH ),
     mEmojiSize( 0 )
   {
   }
@@ -121,7 +135,7 @@ private:
 private:
 
   TextAbstraction::FontClient mFontClient;
-
+  TextAbstraction::GlyphType mGlyphType;
   int mEmojiSize;
 };
 
index 49dd310..f40b3a4 100644 (file)
@@ -96,12 +96,11 @@ void AtlasGlyphManager::Add( const Text::GlyphInfo& glyph,
 
   if ( mAtlasManager.Add( bitmap, slot ) )
   {
-    // A new atlas was created so set the material details for the atlas
+    // A new atlas was created so set the texture set details for the atlas
     Dali::Atlas atlas = mAtlasManager.GetAtlasContainer( slot.mAtlasId );
-    Pixel::Format pixelFormat = mAtlasManager.GetPixelFormat( slot.mAtlasId );
-    Material material = Material::New( pixelFormat == Pixel::L8 ? mShaderL8 : mShaderRgba );
-    material.AddTexture( atlas, "sTexture" );
-    mAtlasManager.SetMaterial( slot.mAtlasId, material );
+    TextureSet textureSet = TextureSet::New();
+    textureSet.SetImage( 0u, atlas );
+    mAtlasManager.SetTextures( slot.mAtlasId, textureSet );
   }
 
   GlyphRecordEntry record;
@@ -252,9 +251,15 @@ void AtlasGlyphManager::AdjustReferenceCount( Text::FontId fontId, Text::GlyphIn
   }
 }
 
-Material AtlasGlyphManager::GetMaterial( uint32_t atlasId ) const
+TextureSet AtlasGlyphManager::GetTextures( uint32_t atlasId ) const
 {
-  return mAtlasManager.GetMaterial( atlasId );
+  return mAtlasManager.GetTextures( atlasId );
+}
+
+Shader AtlasGlyphManager::GetShader( uint32_t atlasId ) const
+{
+  Pixel::Format pixelFormat = mAtlasManager.GetPixelFormat( atlasId );
+  return pixelFormat == Pixel::L8 ? mShaderL8 : mShaderRgba;
 }
 
 AtlasGlyphManager::~AtlasGlyphManager()
index 0c67501..90210f2 100644 (file)
@@ -108,9 +108,14 @@ public:
   void AdjustReferenceCount( Text::FontId fontId, Text::GlyphIndex index, int32_t delta );
 
   /**
-   * @copydoc Toolkit::AtlasGlyphManager::GetMaterial
+   * @copydoc Toolkit::AtlasGlyphManager::GetTextures
    */
-  Material GetMaterial( uint32_t atlasId ) const;
+  TextureSet GetTextures( uint32_t atlasId ) const;
+
+  /**
+   * @copydoc Toolkit::AtlasGlyphManager::GetShader
+   */
+  Shader GetShader( uint32_t atlasId ) const;
 
   /**
    * @copydoc Toolkit::AtlasGlyphManager::GetMetrics
index 5a46ef5..abcd391 100644 (file)
@@ -106,9 +106,14 @@ Pixel::Format AtlasGlyphManager::GetPixelFormat( uint32_t atlasId )
   return GetImplementation(*this).GetPixelFormat( atlasId );
 }
 
-Material AtlasGlyphManager::GetMaterial( uint32_t atlasId ) const
+TextureSet AtlasGlyphManager::GetTextures( uint32_t atlasId ) const
 {
-  return GetImplementation(*this).GetMaterial( atlasId );
+  return GetImplementation(*this).GetTextures( atlasId );
+}
+
+Shader AtlasGlyphManager::GetShader( uint32_t atlasId ) const
+{
+  return GetImplementation(*this).GetShader( atlasId );
 }
 
 const Toolkit::AtlasGlyphManager::Metrics& AtlasGlyphManager::GetMetrics()
index 1870bd5..3831589 100644 (file)
@@ -140,13 +140,22 @@ public:
   Pixel::Format GetPixelFormat( uint32_t atlasId );
 
   /**
-   * @brief Get the material used by an atlas
+   * @brief Get the texture set used by an atlas
    *
    * @param[in] atlasId Id of an atlas
    *
-   * @return The material used by the atlas
+   * @return The texture set used by the atlas
    */
-  Material GetMaterial( uint32_t atlasId ) const;
+  TextureSet GetTextures( uint32_t atlasId ) const;
+
+  /**
+   * @brief Get the shader used by an atlas
+   *
+   * @param[in] atlasId Id of an atlas
+   *
+   * @return The shader used by the atlas
+   */
+  Shader GetShader( uint32_t atlasId ) const;
 
   /**
    * @brief Get Glyph Manager metrics
index dacb141..8d3ae1b 100644 (file)
@@ -436,7 +436,7 @@ AtlasManager::SizeType AtlasManager::GetAtlasCount() const
   return mAtlasList.size();
 }
 
-Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas )
+Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) const
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
   Pixel::Format pixelFormat = Pixel::RGBA8888;
@@ -476,23 +476,23 @@ void AtlasManager::GetMetrics( Toolkit::AtlasManager::Metrics& metrics )
   metrics.mTextureMemoryUsed = textureMemoryUsed;
 }
 
-Material AtlasManager::GetMaterial( AtlasId atlas ) const
+TextureSet AtlasManager::GetTextures( AtlasId atlas ) const
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
-  Material material;
+  TextureSet textureSet;
   if ( atlas && atlas-- <= mAtlasList.size() )
   {
-    material = mAtlasList[ atlas ].mMaterial;
+    textureSet = mAtlasList[ atlas ].mTextureSet;
   }
-  return material;
+  return textureSet;
 }
 
-void AtlasManager::SetMaterial( AtlasId atlas, Material& material )
+void AtlasManager::SetTextures( AtlasId atlas, TextureSet& textureSet )
 {
   DALI_ASSERT_DEBUG( atlas && atlas <= mAtlasList.size() );
   if ( atlas && atlas-- <= mAtlasList.size() )
   {
-    mAtlasList[ atlas ].mMaterial = material;
+    mAtlasList[ atlas ].mTextureSet = textureSet;
   }
 }
 
index b4828a0..e86bda1 100644 (file)
@@ -64,7 +64,7 @@ public:
     Pixel::Format mPixelFormat;                                         // pixel format used by atlas
     BufferImage mHorizontalStrip;                                       // Image used to pad upload
     BufferImage mVerticalStrip;                                         // Image used to pad upload
-    Material mMaterial;                                                 // material used for atlas texture
+    TextureSet mTextureSet;                                             // Texture set used for atlas texture
     SizeType mTotalBlocks;                                              // total number of blocks in atlas
     SizeType mAvailableBlocks;                                          // number of blocks available in atlas
     Dali::Vector< SizeType > mFreeBlocksList;                           // unless there are any previously freed blocks
@@ -156,7 +156,7 @@ public:
   /**
    * @copydoc Toolkit::AtlasManager::GetPixelFormat
    */
-  Pixel::Format GetPixelFormat( AtlasId atlas );
+  Pixel::Format GetPixelFormat( AtlasId atlas ) const;
 
   /**
    * @copydoc Toolkit::AtlasManager::GetMetrics
@@ -164,14 +164,14 @@ public:
   void GetMetrics( Toolkit::AtlasManager::Metrics& metrics );
 
   /**
-   * @copydoc Toolkit::AtlasManager::GetMaterial
+   * @copydoc Toolkit::AtlasManager::GetTextures
    */
-  Material GetMaterial( AtlasId atlas ) const;
+  TextureSet GetTextures( AtlasId atlas ) const;
 
   /**
-   * @copydoc Toolkit::AtlasManager::SetMaterial
+   * @copydoc Toolkit::AtlasManager::SetTextures
    */
-  void SetMaterial( AtlasId atlas, Material& material );
+  void SetTextures( AtlasId atlas, TextureSet& textureSet );
 
 private:
 
index 2aa1bce..d28b586 100644 (file)
@@ -108,7 +108,7 @@ AtlasManager::SizeType AtlasManager::GetAtlasCount() const
   return GetImplementation(*this).GetAtlasCount();
 }
 
-Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas )
+Pixel::Format AtlasManager::GetPixelFormat( AtlasId atlas ) const
 {
   return GetImplementation(*this).GetPixelFormat( atlas );
 }
@@ -118,14 +118,14 @@ void AtlasManager::GetMetrics( Metrics& metrics )
   GetImplementation(*this).GetMetrics( metrics );
 }
 
-Material AtlasManager::GetMaterial( AtlasId atlas ) const
+TextureSet AtlasManager::GetTextures( AtlasId atlas ) const
 {
-  return GetImplementation(*this).GetMaterial( atlas );
+  return GetImplementation(*this).GetTextures( atlas );
 }
 
-void AtlasManager::SetMaterial( AtlasId atlas, Material& material )
+void AtlasManager::SetTextures( AtlasId atlas, TextureSet& textureSet )
 {
-  GetImplementation(*this).SetMaterial( atlas, material );
+  GetImplementation(*this).SetTextures( atlas, textureSet );
 }
 
 } // namespace Toolkit
index 3449362..75f117a 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/images/buffer-image.h>
 #include <dali/devel-api/images/atlas.h>
-#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/texture-set.h>
 
 namespace Dali
 {
@@ -247,7 +247,7 @@ public:
    *
    * @return Pixel format used by this atlas
    */
-  Pixel::Format GetPixelFormat( AtlasId atlas );
+  Pixel::Format GetPixelFormat( AtlasId atlas ) const;
 
   /**
    * @brief Fill in a metrics structure showing current status of this Atlas Manager
@@ -257,21 +257,21 @@ public:
   void GetMetrics( Metrics& metrics );
 
   /**
-   * @brief Get Material used by atlas
+   * @brief Get TextureSet used by atlas
    *
    * @param[in] atlas AtlasId
    *
-   * @return Material used by atlas
+   * @return TextureSet used by atlas
    */
-  Material GetMaterial( AtlasId atlas ) const;
+  TextureSet GetTextures( AtlasId atlas ) const;
 
   /**
-   * @brief Set the material used by an atlas
+   * @brief Set the texture set used by an atlas
    *
    * @param[in] atlas AtlasId
-   * @param[in] material The Material to assign
+   * @param[in] textureSet The texture set to assign
    */
-  void SetMaterial( AtlasId atlas, Material& material );
+  void SetTextures( AtlasId atlas, TextureSet& textureSet );
 
 private:
 
index 88b2857..7a76534 100644 (file)
@@ -488,8 +488,10 @@ struct AtlasRenderer::Impl
     quadGeometry.AddVertexBuffer( quadVertices );
     quadGeometry.SetIndexBuffer( quadIndices );
 
-    Material material = mGlyphManager.GetMaterial( meshRecord.mAtlasId );
-    Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, material );
+    TextureSet textureSet( mGlyphManager.GetTextures( meshRecord.mAtlasId ) );
+    Shader shader( mGlyphManager.GetShader( meshRecord.mAtlasId ) );
+    Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, shader );
+    renderer.SetTextures( textureSet );
     renderer.SetProperty( Dali::Renderer::Property::BLENDING_MODE, BlendingMode::ON );
     renderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, DepthIndex::CONTENT + mDepth );
     Actor actor = Actor::New();
index 776d408..10602c7 100644 (file)
@@ -25,6 +25,9 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/text/rendering-backend.h>
 #include <dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.h>
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+#include <dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h>
+#endif
 
 namespace Dali
 {
@@ -91,6 +94,16 @@ RendererPtr Backend::NewRenderer( unsigned int renderingType )
     }
     break;
 
+    case Dali::Toolkit::Text::RENDERING_VECTOR_BASED:
+    {
+#ifdef ENABLE_VECTOR_BASED_TEXT_RENDERING
+      renderer = Dali::Toolkit::Text::VectorBasedRenderer::New();
+#else
+      renderer = Dali::Toolkit::Text::AtlasRenderer::New(); // Fallback to bitmap-based rendering
+#endif
+    }
+    break;
+
     default:
     {
       DALI_LOG_WARNING( "Unknown renderer type: %d", renderingType );
diff --git a/dali-toolkit/internal/text/rendering/vector-based/file.list b/dali-toolkit/internal/text/rendering/vector-based/file.list
new file mode 100644 (file)
index 0000000..0772a37
--- /dev/null
@@ -0,0 +1,7 @@
+# Add local source files here
+
+vector_based_text_src_files = \
+   $(vector_based_text_src_dir)/vector-based-renderer.cpp \
+   $(vector_based_text_src_dir)/vector-blob-atlas.cpp \
+   $(vector_based_text_src_dir)/vector-blob-atlas-share.cpp \
+   $(vector_based_text_src_dir)/glyphy-shader/glyphy-shader.cpp
diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h
new file mode 100644 (file)
index 0000000..a3a1a30
--- /dev/null
@@ -0,0 +1,231 @@
+static const char *glyphy_common_glsl =
+"/*\n"
+" * Copyright 2012 Google, Inc. All Rights Reserved.\n"
+" *\n"
+" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+" * you may not use this file except in compliance with the License.\n"
+" * You may obtain a copy of the License at\n"
+" *\n"
+" *     http://www.apache.org/licenses/LICENSE-2.0\n"
+" *\n"
+" * Unless required by applicable law or agreed to in writing, software\n"
+" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+" * See the License for the specific language governing permissions and\n"
+" * limitations under the License.\n"
+" *\n"
+" * Google Author(s): Behdad Esfahbod, Maysum Panju\n"
+" */\n"
+"\n"
+"\n"
+"#ifndef GLYPHY_INFINITY\n"
+"#  define GLYPHY_INFINITY 1e9\n"
+"#endif\n"
+"#ifndef GLYPHY_EPSILON\n"
+"#  define GLYPHY_EPSILON  1e-5\n"
+"#endif\n"
+"\n"
+"#ifndef GLYPHY_RGBA\n"
+"#  ifdef GLYPHY_BGRA\n"
+"#    define GLYPHY_RGBA(v) glyphy_bgra (v)\n"
+"#  else\n"
+"#    define GLYPHY_RGBA(v) glyphy_rgba (v)\n"
+"#  endif\n"
+"#endif\n"
+"\n"
+"vec4\n"
+"glyphy_rgba (const vec4 v)\n"
+"{\n"
+"  return v.rgba;\n"
+"}\n"
+"\n"
+"vec4\n"
+"glyphy_bgra (const vec4 v)\n"
+"{\n"
+"  return v.bgra;\n"
+"}\n"
+"\n"
+"\n"
+"struct glyphy_arc_t {\n"
+"  vec2  p0;\n"
+"  vec2  p1;\n"
+"  float d;\n"
+"};\n"
+"\n"
+"struct glyphy_arc_endpoint_t {\n"
+"  /* Second arc endpoint */\n"
+"  vec2  p;\n"
+"  /* Infinity if this endpoint does not form an arc with the previous\n"
+"   * endpoint.  Ie. a \"move_to\".  Test with glyphy_isinf().\n"
+"   * Arc depth otherwise.  */\n"
+"  float d;\n"
+"};\n"
+"\n"
+"struct glyphy_arc_list_t {\n"
+"  /* Number of endpoints in the list.\n"
+"   * Will be zero if we're far away inside or outside, in which case side is set.\n"
+"   * Will be -1 if this arc-list encodes a single line, in which case line_* are set. */\n"
+"  int num_endpoints;\n"
+"\n"
+"  /* If num_endpoints is zero, this specifies whether we are inside (-1)\n"
+"   * or outside (+1).  Otherwise we're unsure (0). */\n"
+"  int side;\n"
+"  /* Offset to the arc-endpoints from the beginning of the glyph blob */\n"
+"  int offset;\n"
+"\n"
+"  /* A single line is all we care about.  It's right here. */\n"
+"  float line_angle;\n"
+"  float line_distance; /* From nominal glyph center */\n"
+"};\n"
+"\n"
+"bool\n"
+"glyphy_isinf (const float v)\n"
+"{\n"
+"  return abs (v) >= GLYPHY_INFINITY * .5;\n"
+"}\n"
+"\n"
+"bool\n"
+"glyphy_iszero (const float v)\n"
+"{\n"
+"  return abs (v) <= GLYPHY_EPSILON * 2.;\n"
+"}\n"
+"\n"
+"vec2\n"
+"glyphy_ortho (const vec2 v)\n"
+"{\n"
+"  return vec2 (-v.y, v.x);\n"
+"}\n"
+"\n"
+"int\n"
+"glyphy_float_to_byte (const float v)\n"
+"{\n"
+"  return int (v * (256. - GLYPHY_EPSILON));\n"
+"}\n"
+"\n"
+"ivec4\n"
+"glyphy_vec4_to_bytes (const vec4 v)\n"
+"{\n"
+"  return ivec4 (v * (256. - GLYPHY_EPSILON));\n"
+"}\n"
+"\n"
+"ivec2\n"
+"glyphy_float_to_two_nimbles (const float v)\n"
+"{\n"
+"  int f = glyphy_float_to_byte (v);\n"
+"  return ivec2 (f / 16, int(mod (float(f), 16.)));\n"
+"}\n"
+"\n"
+"/* returns tan (2 * atan (d)) */\n"
+"float\n"
+"glyphy_tan2atan (const float d)\n"
+"{\n"
+"  return 2. * d / (1. - d * d);\n"
+"}\n"
+"\n"
+"glyphy_arc_endpoint_t\n"
+"glyphy_arc_endpoint_decode (const vec4 v, const ivec2 nominal_size)\n"
+"{\n"
+"  vec2 p = (vec2 (glyphy_float_to_two_nimbles (v.a)) + v.gb) / 16.;\n"
+"  float d = v.r;\n"
+"  if (d == 0.)\n"
+"    d = GLYPHY_INFINITY;\n"
+"  else\n"
+"#define GLYPHY_MAX_D .5\n"
+"    d = float(glyphy_float_to_byte (d) - 128) * GLYPHY_MAX_D / 127.;\n"
+"#undef GLYPHY_MAX_D\n"
+"  return glyphy_arc_endpoint_t (p * vec2(nominal_size), d);\n"
+"}\n"
+"\n"
+"vec2\n"
+"glyphy_arc_center (const glyphy_arc_t a)\n"
+"{\n"
+"  return mix (a.p0, a.p1, .5) +\n"
+"       glyphy_ortho (a.p1 - a.p0) / (2. * glyphy_tan2atan (a.d));\n"
+"}\n"
+"\n"
+"bool\n"
+"glyphy_arc_wedge_contains (const glyphy_arc_t a, const vec2 p)\n"
+"{\n"
+"  float d2 = glyphy_tan2atan (a.d);\n"
+"  return dot (p - a.p0, (a.p1 - a.p0) * mat2(1,  d2, -d2, 1)) >= 0. &&\n"
+"       dot (p - a.p1, (a.p1 - a.p0) * mat2(1, -d2,  d2, 1)) <= 0.;\n"
+"}\n"
+"\n"
+"float\n"
+"glyphy_arc_wedge_signed_dist_shallow (const glyphy_arc_t a, const vec2 p)\n"
+"{\n"
+"  vec2 v = normalize (a.p1 - a.p0);\n"
+"  float line_d = dot (p - a.p0, glyphy_ortho (v));\n"
+"  if (a.d == 0.)\n"
+"    return line_d;\n"
+"\n"
+"  float d0 = dot ((p - a.p0), v);\n"
+"  if (d0 < 0.)\n"
+"    return sign (line_d) * distance (p, a.p0);\n"
+"  float d1 = dot ((a.p1 - p), v);\n"
+"  if (d1 < 0.)\n"
+"    return sign (line_d) * distance (p, a.p1);\n"
+"  float r = 2. * a.d * (d0 * d1) / (d0 + d1);\n"
+"  if (r * line_d > 0.)\n"
+"    return sign (line_d) * min (abs (line_d + r), min (distance (p, a.p0), distance (p, a.p1)));\n"
+"  return line_d + r;\n"
+"}\n"
+"\n"
+"float\n"
+"glyphy_arc_wedge_signed_dist (const glyphy_arc_t a, const vec2 p)\n"
+"{\n"
+"  if (abs (a.d) <= .03)\n"
+"    return glyphy_arc_wedge_signed_dist_shallow (a, p);\n"
+"  vec2 c = glyphy_arc_center (a);\n"
+"  return sign (a.d) * (distance (a.p0, c) - distance (p, c));\n"
+"}\n"
+"\n"
+"float\n"
+"glyphy_arc_extended_dist (const glyphy_arc_t a, const vec2 p)\n"
+"{\n"
+"  /* Note: this doesn't handle points inside the wedge. */\n"
+"  vec2 m = mix (a.p0, a.p1, .5);\n"
+"  float d2 = glyphy_tan2atan (a.d);\n"
+"  if (dot (p - m, a.p1 - m) < 0.)\n"
+"    return dot (p - a.p0, normalize ((a.p1 - a.p0) * mat2(+d2, -1, +1, +d2)));\n"
+"  else\n"
+"    return dot (p - a.p1, normalize ((a.p1 - a.p0) * mat2(-d2, -1, +1, -d2)));\n"
+"}\n"
+"\n"
+"int\n"
+"glyphy_arc_list_offset (const vec2 p, const ivec2 nominal_size)\n"
+"{\n"
+"  ivec2 cell = ivec2 (clamp (floor (p), vec2 (0.,0.), vec2(nominal_size - 1)));\n"
+"  return cell.y * nominal_size.x + cell.x;\n"
+"}\n"
+"\n"
+"glyphy_arc_list_t\n"
+"glyphy_arc_list_decode (const vec4 v, const ivec2 nominal_size)\n"
+"{\n"
+"  glyphy_arc_list_t l;\n"
+"  ivec4 iv = glyphy_vec4_to_bytes (v);\n"
+"  l.side = 0; /* unsure */\n"
+"  if (iv.r == 0) { /* arc-list encoded */\n"
+"    l.offset = (iv.g * 256) + iv.b;\n"
+"    l.num_endpoints = iv.a;\n"
+"    if (l.num_endpoints == 255) {\n"
+"      l.num_endpoints = 0;\n"
+"      l.side = -1;\n"
+"    } else if (l.num_endpoints == 0)\n"
+"      l.side = +1;\n"
+"  } else { /* single line encoded */\n"
+"    l.num_endpoints = -1;\n"
+/*"    l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 0x4000) / float (0x1FFF)\n"
+"                    * max (float (nominal_size.x), float (nominal_size.y));\n"
+"    l.line_angle = float(-((iv.b * 256 + iv.a) - 0x8000)) / float (0x7FFF) * 3.14159265358979;\n"*/
+/*"    l.line_distance = float(((iv.r - 128) * 256 + iv.g) - 16384) / 8191.0 \n"
+"                    * max (float (nominal_size.x), float (nominal_size.y));\n"
+"    l.line_angle = float(-((iv.b * 256 + iv.a) - 32768)) / 32767. * 3.14159;\n"*/
+
+"    l.line_distance = ( float(iv.r)/32. + 0.01*float(iv.g)/82.0 - 6.) \n"
+"                    * max (float (nominal_size.x), float (nominal_size.y));\n"
+"    l.line_angle = ( -float(iv.b)/40.74 - float( iv.a )*0.0001 )-3.142;\n"
+"  }\n"
+"  return l;\n"
+"}\n"
+;
diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h
new file mode 100644 (file)
index 0000000..5de751f
--- /dev/null
@@ -0,0 +1,152 @@
+static const char *glyphy_sdf_glsl =
+"/*\n"
+" * Copyright 2012 Google, Inc. All Rights Reserved.\n"
+" *\n"
+" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"
+" * you may not use this file except in compliance with the License.\n"
+" * You may obtain a copy of the License at\n"
+" *\n"
+" *     http://www.apache.org/licenses/LICENSE-2.0\n"
+" *\n"
+" * Unless required by applicable law or agreed to in writing, software\n"
+" * distributed under the License is distributed on an \"AS IS\" BASIS,\n"
+" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"
+" * See the License for the specific language governing permissions and\n"
+" * limitations under the License.\n"
+" *\n"
+" * Google Author(s): Behdad Esfahbod, Maysum Panju\n"
+" */\n"
+"\n"
+"#ifndef GLYPHY_TEXTURE1D_FUNC\n"
+"#define GLYPHY_TEXTURE1D_FUNC glyphy_texture1D_func\n"
+"#endif\n"
+"#ifndef GLYPHY_TEXTURE1D_EXTRA_DECLS\n"
+"#define GLYPHY_TEXTURE1D_EXTRA_DECLS\n"
+"#endif\n"
+"#ifndef GLYPHY_TEXTURE1D_EXTRA_ARGS\n"
+"#define GLYPHY_TEXTURE1D_EXTRA_ARGS\n"
+"#endif\n"
+"\n"
+"#ifndef GLYPHY_SDF_TEXTURE1D_FUNC\n"
+"#define GLYPHY_SDF_TEXTURE1D_FUNC GLYPHY_TEXTURE1D_FUNC\n"
+"#endif\n"
+"#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS\n"
+"#define GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS GLYPHY_TEXTURE1D_EXTRA_DECLS\n"
+"#endif\n"
+"#ifndef GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS\n"
+"#define GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS GLYPHY_TEXTURE1D_EXTRA_ARGS\n"
+"#endif\n"
+"#ifndef GLYPHY_SDF_TEXTURE1D\n"
+"#define GLYPHY_SDF_TEXTURE1D(offset) GLYPHY_RGBA(GLYPHY_SDF_TEXTURE1D_FUNC (offset GLYPHY_TEXTURE1D_EXTRA_ARGS))\n"
+"#endif\n"
+"\n"
+"#ifndef GLYPHY_MAX_NUM_ENDPOINTS\n"
+"#define GLYPHY_MAX_NUM_ENDPOINTS 32\n"
+"#endif\n"
+"\n"
+"glyphy_arc_list_t\n"
+"glyphy_arc_list (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n"
+"{\n"
+"  int cell_offset = glyphy_arc_list_offset (p, nominal_size);\n"
+"  vec4 arc_list_data = GLYPHY_SDF_TEXTURE1D (cell_offset);\n"
+"  return glyphy_arc_list_decode (arc_list_data, nominal_size);\n"
+"}\n"
+"\n"
+"float\n"
+"glyphy_sdf (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n"
+"{\n"
+"  glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size  GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);\n"
+"\n"
+"  /* Short-circuits */\n"
+"  if (arc_list.num_endpoints == 0) {\n"
+"    /* far-away cell */\n"
+"    return GLYPHY_INFINITY * float(arc_list.side);\n"
+"  } if (arc_list.num_endpoints == -1) {\n"
+"    /* single-line */\n"
+"    float angle = arc_list.line_angle;\n"
+"    vec2 n = vec2 (cos (angle), sin (angle));\n"
+"    return dot (p - (vec2(nominal_size) * .5), n) - arc_list.line_distance;\n"
+"  }\n"
+"\n"
+"  float side = float(arc_list.side);\n"
+"  float min_dist = GLYPHY_INFINITY;\n"
+"  glyphy_arc_t closest_arc;\n"
+"\n"
+"  glyphy_arc_endpoint_t endpoint_prev, endpoint;\n"
+"  endpoint_prev = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset), nominal_size);\n"
+"  for (int i = 1; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)\n"
+"  {\n"
+"    if (i >= arc_list.num_endpoints) {\n"
+"      break;\n"
+"    }\n"
+"    endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);\n"
+"    glyphy_arc_t a = glyphy_arc_t (endpoint_prev.p, endpoint.p, endpoint.d);\n"
+"    endpoint_prev = endpoint;\n"
+"    if (glyphy_isinf (a.d)) continue;\n"
+"\n"
+"    if (glyphy_arc_wedge_contains (a, p))\n"
+"    {\n"
+"      float sdist = glyphy_arc_wedge_signed_dist (a, p);\n"
+"      float udist = abs (sdist) * (1. - GLYPHY_EPSILON);\n"
+"      if (udist <= min_dist) {\n"
+"       min_dist = udist;\n"
+"       side = sign (sdist);"
+"      }\n"
+"    } else {\n"
+"      float udist = min (distance (p, a.p0), distance (p, a.p1));\n"
+"      if (udist < min_dist) {\n"
+"       min_dist = udist;\n"
+"       side = 0.; /* unsure */\n"
+"       closest_arc = a;\n"
+"      } else if (side == 0. && udist == min_dist) {\n"
+"       /* If this new distance is the same as the current minimum,\n"
+"        * compare extended distances.  Take the sign from the arc\n"
+"        * with larger extended distance. */\n"
+"       float old_ext_dist = glyphy_arc_extended_dist (closest_arc, p);\n"
+"       float new_ext_dist = glyphy_arc_extended_dist (a, p);\n"
+"\n"
+"       float ext_dist = abs (new_ext_dist) <= abs (old_ext_dist) ?\n"
+"                        old_ext_dist : new_ext_dist;\n"
+"\n"
+"#ifdef GLYPHY_SDF_PSEUDO_DISTANCE\n"
+"       /* For emboldening and stuff: */\n"
+"       min_dist = abs (ext_dist);\n"
+"#endif\n"
+"       side = sign (ext_dist);\n"
+"      }\n"
+"    }\n"
+"  }\n"
+"\n"
+"  if (side == 0.) {\n"
+"    // Technically speaking this should not happen, but it does.  So try to fix it.\n"
+"    float ext_dist = glyphy_arc_extended_dist (closest_arc, p);\n"
+"    side = sign (ext_dist);\n"
+"  }\n"
+"\n"
+"  return min_dist * side;\n"
+"}\n"
+"\n"
+"float\n"
+"glyphy_point_dist (const vec2 p, const ivec2 nominal_size GLYPHY_SDF_TEXTURE1D_EXTRA_DECLS)\n"
+"{\n"
+"  glyphy_arc_list_t arc_list = glyphy_arc_list (p, nominal_size  GLYPHY_SDF_TEXTURE1D_EXTRA_ARGS);\n"
+"\n"
+"  float side = float(arc_list.side);\n"
+"  float min_dist = GLYPHY_INFINITY;\n"
+"\n"
+"  if (arc_list.num_endpoints == 0)\n"
+"    return min_dist;\n"
+"\n"
+"  glyphy_arc_endpoint_t endpoint;\n"
+"  for (int i = 0; i < GLYPHY_MAX_NUM_ENDPOINTS; i++)\n"
+"  {\n"
+"    if (i >= arc_list.num_endpoints) {\n"
+"      break;\n"
+"    }\n"
+"    endpoint = glyphy_arc_endpoint_decode (GLYPHY_SDF_TEXTURE1D (arc_list.offset + i), nominal_size);\n"
+"    if (glyphy_isinf (endpoint.d)) continue;\n"
+"    min_dist = min (min_dist, distance (p, endpoint.p));\n"
+"  }\n"
+"  return min_dist;\n"
+"}\n"
+;
diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.cpp
new file mode 100644 (file)
index 0000000..53db8fb
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h>
+
+// EXTERNAL HEADERS
+#include <sstream>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-common-glsl.h>
+#include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-sdf-glsl.h>
+
+using namespace Dali;
+
+namespace
+{
+
+const char* const ENABLE_EXTENSION_PREFIX =
+"#extension GL_OES_standard_derivatives : enable\n"
+"precision highp float;\n"
+"precision highp int;\n";
+
+const char* const VERTEX_SHADER_MAIN =
+"uniform   mediump mat4    uProjection;\n"
+"uniform   mediump mat4    uModelView;\n"
+"uniform   mediump mat4    uMvpMatrix;\n"
+"uniform           bool    uTextureMapped;\n"
+"uniform   mediump vec4    uCustomTextureCoords;\n"
+"attribute highp   vec2    aTexCoord;\n"
+"varying   mediump vec2    vTexCoord;\n"
+"uniform   mat3            uModelViewIT;\n"
+"attribute mediump vec3    aNormal;\n"
+"varying   mediump vec3    vNormal;\n"
+"attribute mediump vec2    aPosition;\n"
+"varying   mediump vec4    vVertex;\n"
+"varying vec4 v_glyph;\n"
+"\n"
+"vec4\n"
+"glyph_vertex_transcode (vec2 v)\n"
+"{\n"
+"  ivec2 g = ivec2 (v);\n"
+"  ivec2 corner = ivec2 (mod (v, 2.));\n"
+"  g /= 2;\n"
+"  ivec2 nominal_size = ivec2 (mod (vec2(g), 64.));\n"
+"  return vec4 (corner * nominal_size, g * 4);\n"
+"}\n"
+"\n"
+"void\n"
+"main()\n"
+"{\n"
+"  gl_Position = uMvpMatrix * vec4 (aPosition, 0.0, 1.0);\n"
+"  v_glyph = glyph_vertex_transcode (aTexCoord);\n"
+"}\n"
+;
+
+const char* const FRAGMENT_SHADER_PREFIX =
+"struct Material\n"
+"{\n"
+"  mediump float mOpacity;\n"
+"  mediump float mShininess;\n"
+"  lowp    vec4  mAmbient;\n"
+"  lowp    vec4  mDiffuse;\n"
+"  lowp    vec4  mSpecular;\n"
+"  lowp    vec4  mEmissive;\n"
+"};\n"
+"uniform sampler2D     sTexture;\n"
+"uniform sampler2D     sOpacityTexture;\n"
+"uniform sampler2D     sNormalMapTexture;\n"
+"uniform sampler2D     sEffect;\n"
+"varying mediump vec2 vTexCoord;\n"
+"uniform Material      uMaterial;\n"
+"uniform lowp  vec4    uColor;\n"
+"varying highp vec4    vVertex;\n"
+"varying highp vec3    vNormal;\n"
+"uniform vec4 u_atlas_info;\n"
+"\n"
+"#define GLYPHY_TEXTURE1D_EXTRA_DECLS , sampler2D _tex, ivec4 _atlas_info, ivec2 _atlas_pos\n"
+"#define GLYPHY_TEXTURE1D_EXTRA_ARGS , _tex, _atlas_info, _atlas_pos\n"
+"#define GLYPHY_DEMO_EXTRA_ARGS , sTexture, uu_atlas_info, gi.atlas_pos\n"
+"\n"
+"vec4\n"
+"glyphy_texture1D_func (int offset GLYPHY_TEXTURE1D_EXTRA_DECLS)\n"
+"{\n"
+"  ivec2 item_geom = _atlas_info.zw;\n"
+"  vec2 pos = (vec2 (_atlas_pos.xy * item_geom +\n"
+"                    ivec2 (mod (float (offset), float (item_geom.x)), offset / item_geom.x)) +\n"
+"             + vec2 (.5, .5)) / vec2(_atlas_info.xy);\n"
+"  return texture2D (_tex, pos);\n"
+"}\n"
+;
+
+static const char* FRAGMENT_SHADER_MAIN =
+"uniform float u_contrast;\n"
+"uniform float u_gamma_adjust;\n"
+"uniform float u_outline_thickness;\n"
+"uniform float u_outline;\n"
+"uniform float u_boldness;\n"
+"\n"
+"varying vec4 v_glyph;\n"
+"\n"
+"\n"
+"#define SQRT2_2 0.70711 /* 1 / sqrt(2.) */\n"
+"#define SQRT2   1.41421\n"
+"\n"
+"struct glyph_info_t {\n"
+"  ivec2 nominal_size;\n"
+"  ivec2 atlas_pos;\n"
+"};\n"
+"\n"
+"glyph_info_t\n"
+"glyph_info_decode (vec4 v)\n"
+"{\n"
+"  glyph_info_t gi;\n"
+"  gi.nominal_size = (ivec2 (mod (v.zw, 256.)) + 2) / 4;\n"
+"  gi.atlas_pos = ivec2 (v_glyph.zw) / 256;\n"
+"  return gi;\n"
+"}\n"
+"\n"
+"\n"
+"float\n"
+"antialias (float d)\n"
+"{\n"
+"  return smoothstep (-.75, +.75, d);\n"
+"}\n"
+"\n"
+"vec4\n"
+"source_over (const vec4 src, const vec4 dst)\n"
+"{\n"
+"  // http://dev.w3.org/fxtf/compositing-1/#porterduffcompositingoperators_srcover\n"
+"  float alpha = src.a + (dst.a * (1. - src.a));\n"
+"  return vec4 (((src.rgb * src.a) + (dst.rgb * dst.a * (1. - src.a))) / alpha, alpha);\n"
+"}\n"
+"\n"
+"void\n"
+"main()\n"
+"{\n"
+"  vec2 p = v_glyph.xy;\n"
+"  glyph_info_t gi = glyph_info_decode (v_glyph);\n"
+"\n"
+"  /* isotropic antialiasing */\n"
+"  vec2 dpdx = dFdx (p);\n"
+"  vec2 dpdy = dFdy (p);\n"
+"  float m = length (vec2 (length (dpdx), length (dpdy))) * SQRT2_2;\n"
+"\n"
+"  vec4 color = uColor;\n"
+"\n"
+"  ivec4 uu_atlas_info = ivec4( u_atlas_info );"
+"  float gsdist = glyphy_sdf (p, gi.nominal_size GLYPHY_DEMO_EXTRA_ARGS);\n"
+"  float sdist = gsdist / m * u_contrast;\n"
+"\n"
+"    sdist -= u_boldness * 10.;\n"
+"    if ( glyphy_iszero( u_outline ) )\n"
+"      sdist = abs (sdist) - u_outline_thickness * .5;\n"
+"    if (sdist > 1.)\n"
+"      discard;\n"
+"    float alpha = antialias (-sdist);\n"
+"    if (u_gamma_adjust != 1.)\n"
+"      alpha = pow (alpha, 1./u_gamma_adjust);\n"
+"    color = vec4 (color.rgb,color.a * alpha);\n"
+"\n"
+"  gl_FragColor = color;\n"
+"}\n"
+;
+
+} // namespace
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+GlyphyShader::GlyphyShader()
+{
+}
+
+GlyphyShader::GlyphyShader( Shader handle )
+: Shader( handle )
+{
+}
+
+GlyphyShader::~GlyphyShader()
+{
+}
+
+GlyphyShader GlyphyShader::New( const Dali::Vector4& atlasInfo )
+{
+  std::ostringstream vertexShaderStringStream;
+  std::ostringstream fragmentShaderStringStream;
+
+  vertexShaderStringStream << ENABLE_EXTENSION_PREFIX << VERTEX_SHADER_MAIN;
+
+  fragmentShaderStringStream << ENABLE_EXTENSION_PREFIX
+                             << FRAGMENT_SHADER_PREFIX
+                             << glyphy_common_glsl
+                             << "#define GLYPHY_SDF_PSEUDO_DISTANCE 1\n"
+                             << glyphy_sdf_glsl
+                             << FRAGMENT_SHADER_MAIN;
+
+  Shader shaderEffectCustom = Shader::New( vertexShaderStringStream.str(),
+                                           fragmentShaderStringStream.str(),
+                                           Shader::ShaderHints( Shader::HINT_OUTPUT_IS_TRANSPARENT ) );
+
+  GlyphyShader handle( shaderEffectCustom );
+
+  handle.RegisterProperty( "u_atlas_info",  atlasInfo );
+  handle.RegisterProperty( "u_contrast",          1.f );
+  handle.RegisterProperty( "u_gamma_adjust",      1.f );
+  handle.RegisterProperty( "u_outline_thickness", 1.f );
+  handle.RegisterProperty( "u_outline",           1.f );
+  handle.RegisterProperty( "u_boldness",          0.f );
+
+  return handle;
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h b/dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h
new file mode 100644 (file)
index 0000000..b3bbcf7
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __DALI_TOOLKIT_TEXT_GLYPHY_SHADER_H__
+#define __DALI_TOOLKIT_TEXT_GLYPHY_SHADER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNEL INCLUDES
+#include <dali/public-api/math/vector4.h>
+#include <dali/devel-api/rendering/shader.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief A Shader based on GLyphy authored by Behdad Esfahbod & Maysum Panju.
+ *
+ * See https://github.com/behdad/glyphy for more details of GLyphy.
+ */
+class GlyphyShader : public Shader
+{
+public:
+
+  /**
+   * @brief Create the blob atlas.
+   *
+   * @param[in] atlasInfo The metrics of the texture atlas storing vector data.
+   */
+  static GlyphyShader New( const Vector4& atlasInfo );
+
+  /**
+   * @brief Create an uninitialized GlyphyShader handle.
+   */
+  GlyphyShader();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~GlyphyShader();
+
+private: // Not intended for application developer
+
+  GlyphyShader( Shader handle );
+
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_GLYPHY_SHADER_H__
diff --git a/dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.cpp b/dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.cpp
new file mode 100644 (file)
index 0000000..816a45d
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/devel-api/rendering/renderer.h>
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/glyph-run.h>
+#include <dali-toolkit/internal/text/text-view.h>
+#include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h>
+#include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
+#include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h>
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Toolkit::Text;
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
+#endif
+
+const float DEFAULT_POINT_SIZE = 13.f;
+
+struct Vertex2D
+{
+  float x;
+  float y;
+  float u;
+  float v;
+};
+
+void AddVertex( Vector<Vertex2D>& vertices, float x, float y, float u, float v )
+{
+  Vertex2D meshVertex;
+  meshVertex.x = x;
+  meshVertex.y = y;
+  meshVertex.u = u;
+  meshVertex.v = v;
+  vertices.PushBack( meshVertex );
+}
+
+void AddTriangle( Vector<unsigned int>& indices, unsigned int v0, unsigned int v1, unsigned int v2 )
+{
+  indices.PushBack( v0 );
+  indices.PushBack( v1 );
+  indices.PushBack( v2 );
+}
+
+bool CreateGeometry( const Vector<GlyphInfo>& glyphs,
+                     unsigned int numberOfGlyphs,
+                     const Vector<Vector2>& positions,
+                     float xOffset,
+                     float yOffset,
+                     VectorBlobAtlas& atlas,
+                     Dali::TextAbstraction::FontClient& fontClient,
+                     Vector< Vertex2D >& vertices,
+                     Vector< unsigned int >& indices )
+{
+  bool atlasFull( false );
+
+  for( unsigned int i=0, idx=0; i<numberOfGlyphs && !atlasFull; ++i )
+  {
+    if( glyphs[i].width  > 0 &&
+        glyphs[i].height > 0 )
+    {
+      bool foundBlob( true );
+
+      BlobCoordinate blobCoords[4];
+
+      if( ! atlas.FindGlyph( glyphs[i].fontId, glyphs[i].index, blobCoords )  )
+      {
+        // Add blob to atlas
+        VectorBlob* blob( NULL );
+        unsigned int blobLength( 0 );
+        unsigned int nominalWidth( 0 );
+        unsigned int nominalHeight( 0 );
+        fontClient.CreateVectorBlob( glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight );
+
+        if( 0 != blobLength )
+        {
+          bool glyphAdded = atlas.AddGlyph( glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight, blobCoords );
+
+          foundBlob = glyphAdded;
+          atlasFull = !glyphAdded;
+        }
+        else
+        {
+          foundBlob = false;
+        }
+      }
+
+      if( foundBlob )
+      {
+        const float x1( xOffset + positions[i].x );
+        const float x2( xOffset + positions[i].x + glyphs[i].width );
+        const float y1( yOffset + positions[i].y );
+        const float y2( yOffset + positions[i].y + glyphs[i].height );
+
+        AddVertex( vertices, x1, y2, blobCoords[0].u, blobCoords[0].v );
+        AddVertex( vertices, x1, y1, blobCoords[1].u, blobCoords[1].v );
+        AddVertex( vertices, x2, y2, blobCoords[2].u, blobCoords[2].v );
+        AddTriangle( indices, idx, idx+1, idx+2 );
+        idx+=3;
+
+        AddVertex( vertices, x1, y1, blobCoords[1].u, blobCoords[1].v );
+        AddVertex( vertices, x2, y2, blobCoords[2].u, blobCoords[2].v );
+        AddVertex( vertices, x2, y1, blobCoords[3].u, blobCoords[3].v );
+        AddTriangle( indices, idx, idx+1, idx+2 );
+        idx+=3;
+      }
+    }
+  }
+
+  // If the atlas is still partially empty, all the glyphs were added
+  return !atlasFull;
+}
+
+} // unnamed namespace
+
+struct VectorBasedRenderer::Impl
+{
+  Impl()
+  {
+    mFontClient = TextAbstraction::FontClient::Get();
+
+    mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
+    mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2;
+    mQuadIndexFormat[ "indices" ] = Property::INTEGER;
+  }
+
+  Actor mActor;                            ///< The actor parent which renders the text
+
+  TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
+
+  Property::Map mQuadVertexFormat;         ///> Describes the vertex format for text
+  Property::Map mQuadIndexFormat;          ///> Describes the index format for text
+
+  Shader mShaderEffect;
+
+  IntrusivePtr<VectorBlobAtlas> mAtlas;
+};
+
+Text::RendererPtr VectorBasedRenderer::New()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::VectorBasedRenderer::New()\n" );
+
+  return Text::RendererPtr( new VectorBasedRenderer() );
+}
+
+Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
+{
+  UnparentAndReset( mImpl->mActor );
+
+  mImpl->mActor = Actor::New();
+  mImpl->mActor.SetParentOrigin( ParentOrigin::CENTER );
+  mImpl->mActor.SetSize( view.GetControlSize() );
+  mImpl->mActor.SetColor( Color::BLACK );
+#if defined(DEBUG_ENABLED)
+  mImpl->mActor.SetName( "Text renderable actor" );
+#endif
+
+  Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+  if( numberOfGlyphs > 0u )
+  {
+    Vector<GlyphInfo> glyphs;
+    glyphs.Resize( numberOfGlyphs );
+
+    Vector<Vector2> positions;
+    positions.Resize( numberOfGlyphs );
+
+    Vector<Vector4> colors;
+    colors.Resize( numberOfGlyphs, view.GetTextColor() );
+
+    numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
+                                     positions.Begin(),
+                                     colors.Begin(),
+                                     0u,
+                                     numberOfGlyphs );
+    glyphs.Resize( numberOfGlyphs );
+    positions.Resize( numberOfGlyphs );
+
+    Vector< Vertex2D > vertices;
+    Vector< unsigned int > indices;
+
+    const Vector2& controlSize = view.GetControlSize();
+    float xOffset = controlSize.width  * -0.5f;
+    float yOffset = controlSize.height * -0.5f;
+
+    if( ! mImpl->mAtlas ||
+          mImpl->mAtlas->IsFull() )
+    {
+      VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
+      mImpl->mAtlas = atlasShare.GetCurrentAtlas();
+    }
+
+    // First try adding the glyphs to the previous shared atlas
+    bool allGlyphsAdded = CreateGeometry( glyphs, numberOfGlyphs, positions, xOffset, yOffset, *mImpl->mAtlas, mImpl->mFontClient, vertices, indices );
+
+    if( ! allGlyphsAdded )
+    {
+      // The current atlas is full, abandon it and use a new one
+      mImpl->mAtlas.Reset();
+      vertices.Clear();
+      indices.Clear();
+
+      VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
+      mImpl->mAtlas = atlasShare.GetNewAtlas();
+
+      CreateGeometry( glyphs, numberOfGlyphs, positions, xOffset, yOffset, *mImpl->mAtlas, mImpl->mFontClient, vertices, indices );
+      // Return value ignored; using more than an entire new atlas is not supported
+    }
+
+    if( 0 != vertices.Count() )
+    {
+      PropertyBuffer quadVertices = PropertyBuffer::New( mImpl->mQuadVertexFormat );
+      PropertyBuffer quadIndices = PropertyBuffer::New( mImpl->mQuadIndexFormat );
+
+      quadVertices.SetData( &vertices[ 0 ], vertices.Size() );
+      quadIndices.SetData( &indices[ 0 ], indices.Size() );
+
+      Geometry quadGeometry = Geometry::New();
+      quadGeometry.AddVertexBuffer( quadVertices );
+      quadGeometry.SetIndexBuffer( quadIndices );
+
+      TextureSet texture = mImpl->mAtlas->GetTextureSet();
+
+      const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
+      mImpl->mShaderEffect = GlyphyShader::New( atlasInfo );
+
+      Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mImpl->mShaderEffect );
+      renderer.SetTextures( texture );
+      mImpl->mActor.AddRenderer( renderer );
+    }
+  }
+
+  return mImpl->mActor;
+}
+
+VectorBasedRenderer::VectorBasedRenderer()
+{
+  mImpl = new Impl();
+}
+
+VectorBasedRenderer::~VectorBasedRenderer()
+{
+  delete mImpl;
+}
+
diff --git a/dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h b/dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h
new file mode 100644 (file)
index 0000000..0b7a44e
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef __DALI_TOOLKIT_TEXT_VECTOR_BASED_RENDERER_H__
+#define __DALI_TOOLKIT_TEXT_VECTOR_BASED_RENDERER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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-toolkit/internal/text/rendering/text-renderer.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief A vector-based renderer
+ *
+ */
+class VectorBasedRenderer : public Renderer
+{
+public:
+
+  /**
+   * @brief Create the renderer.
+   */
+  static RendererPtr New();
+
+  /**
+   * @brief Render the glyphs from a ViewInterface.
+   *
+   * @param[in] view The interface to a view.
+   * @param[in] depth The depth in the tree of the parent.
+   * @return The Renderable actor used to position the text.
+   */
+  virtual Actor Render( ViewInterface& view, int depth );
+
+protected:
+
+  /**
+   * @brief Constructor.
+   */
+  VectorBasedRenderer();
+
+  /**
+   * @brief A reference counted object may only be deleted by calling Unreference().
+   */
+  virtual ~VectorBasedRenderer();
+
+private:
+
+  // Undefined
+  VectorBasedRenderer( const VectorBasedRenderer& handle );
+
+  // Undefined
+  VectorBasedRenderer& operator=( const VectorBasedRenderer& handle );
+
+private:
+
+  struct Impl;
+  Impl* mImpl;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_VECTOR_BASED_RENDERER_H__
diff --git a/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.cpp b/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.cpp
new file mode 100644 (file)
index 0000000..81a2817
--- /dev/null
@@ -0,0 +1,150 @@
+ /*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/base-object.h>
+#include <dali/devel-api/adaptor-framework/singleton-service.h>
+
+namespace
+{
+
+const int INITIAL_VECTOR_BLOB_ATLAS_WIDTH = 512;
+const int INITIAL_VECTOR_BLOB_ATLAS_HEIGHT = 512;
+
+const int NEW_VECTOR_BLOB_ATLAS_WIDTH = 1024;
+const int NEW_VECTOR_BLOB_ATLAS_HEIGHT = 1024;
+
+const int VECTOR_BLOB_ATLAS_ITEM_WIDTH = 64;
+const int VECTOR_BLOB_ATLAS_HEIGHT_QUANTUM = 8;
+
+} // unnamed namespace
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+class VectorBlobAtlasShare::Impl : public Dali::BaseObject
+{
+public:
+
+  /**
+   * @brief Constructor
+   */
+  Impl()
+  {
+  }
+
+  VectorBlobAtlas* GetCurrentAtlas()
+  {
+    if( ! mCurrentAtlas )
+    {
+      mCurrentAtlas = new VectorBlobAtlas( INITIAL_VECTOR_BLOB_ATLAS_WIDTH, INITIAL_VECTOR_BLOB_ATLAS_HEIGHT, VECTOR_BLOB_ATLAS_ITEM_WIDTH, VECTOR_BLOB_ATLAS_HEIGHT_QUANTUM );
+    }
+
+    return mCurrentAtlas.Get();
+  }
+
+  VectorBlobAtlas* GetNewAtlas()
+  {
+    // The current atlas should have been filled, before asking for a new one
+    DALI_ASSERT_DEBUG( mCurrentAtlas->IsFull() && "Current atlas is not full yet" );
+
+    mCurrentAtlas = new VectorBlobAtlas( NEW_VECTOR_BLOB_ATLAS_WIDTH, NEW_VECTOR_BLOB_ATLAS_HEIGHT, VECTOR_BLOB_ATLAS_ITEM_WIDTH, VECTOR_BLOB_ATLAS_HEIGHT_QUANTUM );
+
+    return mCurrentAtlas.Get();
+  }
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Impl()
+  {
+  }
+
+private:
+
+  IntrusivePtr<VectorBlobAtlas> mCurrentAtlas;
+};
+
+VectorBlobAtlasShare::VectorBlobAtlasShare()
+{
+}
+
+VectorBlobAtlasShare::~VectorBlobAtlasShare()
+{
+}
+
+VectorBlobAtlasShare VectorBlobAtlasShare::Get()
+{
+  VectorBlobAtlasShare manager;
+
+  // Check whether the VectorBlobAtlasShare is already created
+  SingletonService singletonService( SingletonService::Get() );
+  if ( singletonService )
+  {
+    Dali::BaseHandle handle = singletonService.GetSingleton( typeid( VectorBlobAtlasShare ) );
+    if( handle )
+    {
+      // If so, downcast the handle of singleton to VectorBlobAtlasShare
+      manager = VectorBlobAtlasShare( dynamic_cast<VectorBlobAtlasShare::Impl*>( handle.GetObjectPtr() ) );
+    }
+
+    if( !manager )
+    {
+      // If not, create the VectorBlobAtlasShare and register it as a singleton
+      manager = VectorBlobAtlasShare( new VectorBlobAtlasShare::Impl() );
+      singletonService.Register( typeid( manager ), manager );
+    }
+  }
+
+  return manager;
+}
+
+VectorBlobAtlasShare::VectorBlobAtlasShare( VectorBlobAtlasShare::Impl* impl )
+: BaseHandle( impl )
+{
+}
+
+VectorBlobAtlas* VectorBlobAtlasShare::GetCurrentAtlas()
+{
+  VectorBlobAtlasShare::Impl& impl = static_cast<VectorBlobAtlasShare::Impl&>( GetBaseObject() );
+
+  return impl.GetCurrentAtlas();
+}
+
+VectorBlobAtlas* VectorBlobAtlasShare::GetNewAtlas()
+{
+  VectorBlobAtlasShare::Impl& impl = static_cast<VectorBlobAtlasShare::Impl&>( GetBaseObject() );
+
+  return impl.GetNewAtlas();
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h b/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h
new file mode 100644 (file)
index 0000000..a854089
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_TOOLKIT_VECTOR_BLOB_ATLAS_SHARE_H__
+#define __DALI_TOOLKIT_VECTOR_BLOB_ATLAS_SHARE_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief A singleton for sharing atlases containing vector data
+ *
+ */
+class VectorBlobAtlasShare : public BaseHandle
+{
+public:
+
+  /**
+   * @brief Create a VectorBlobAtlasShare handle.
+   *
+   * Calling member functions with an uninitialised handle is not allowed.
+   */
+  VectorBlobAtlasShare();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~VectorBlobAtlasShare();
+
+  /**
+   * @brief Create or retrieve VectorBlobAtlasShare singleton.
+   *
+   * @return A handle to the VectorBlobAtlasShare control.
+   */
+  static VectorBlobAtlasShare Get();
+
+  /**
+   * @brief Retrieve the current (empty or partially empty) atlas.
+   *
+   * @return The current atlas.
+   */
+  VectorBlobAtlas* GetCurrentAtlas();
+
+  /**
+   * @brief Retrieve a new empty atlas.
+   *
+   * @pre The current atlas should be full.
+   * @return A new atlas.
+   */
+  VectorBlobAtlas* GetNewAtlas();
+
+private:
+
+  class Impl;
+
+  explicit DALI_INTERNAL VectorBlobAtlasShare( VectorBlobAtlasShare::Impl* impl );
+
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_VECTOR_BLOB_ATLAS_SHARE_H__
diff --git a/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.cpp b/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.cpp
new file mode 100644 (file)
index 0000000..360cedf
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+  Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
+#endif
+
+}
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+static void
+EncodeBlobCoordinate( unsigned int cornerX, unsigned int cornerY,
+                      unsigned int atlasX, unsigned int atlasY,
+                      unsigned int nominalWidth, unsigned int nominalHeight,
+                      BlobCoordinate* v )
+{
+  DALI_ASSERT_DEBUG(0 == (atlasX & ~0x7F));
+  DALI_ASSERT_DEBUG(0 == (atlasY & ~0x7F));
+  DALI_ASSERT_DEBUG(0 == (cornerX & ~1));
+  DALI_ASSERT_DEBUG(0 == (cornerY & ~1));
+  DALI_ASSERT_DEBUG(0 == (nominalWidth & ~0x3F));
+  DALI_ASSERT_DEBUG(0 == (nominalHeight & ~0x3F));
+
+  unsigned int x = (((atlasX << 6) | nominalWidth) << 1)  | cornerX;
+  unsigned int y = (((atlasY << 6) | nominalHeight) << 1) | cornerY;
+
+  unsigned int encoded = (x << 16) | y;
+
+  v->u = encoded >> 16;
+  v->v = encoded & 0xFFFF;
+}
+
+VectorBlobAtlas::VectorBlobAtlas( unsigned int textureWidth,
+                                  unsigned int textureHeight,
+                                  unsigned int itemWidth,
+                                  unsigned int itemHeightQuantum )
+: mTextureWidth( textureWidth ),
+  mTextureHeight( textureHeight ),
+  mItemWidth( itemWidth ),
+  mItemHeightQuantum( itemHeightQuantum ),
+  mCursorX( 0 ),
+  mCursorY( 0 ),
+  mIsFull( false )
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p size %dx%d, item width %d, height quantum %d\n", this, textureWidth, textureHeight, itemWidth, itemHeightQuantum );
+
+  mAtlasTexture = BufferImage::New( textureWidth, textureHeight, Pixel::RGBA8888 );
+
+  mTextureSet = TextureSet::New();
+  mTextureSet.SetImage( 0, mAtlasTexture );
+}
+
+bool VectorBlobAtlas::IsFull() const
+{
+  return mIsFull;
+}
+
+bool VectorBlobAtlas::FindGlyph( FontId fontId,
+                                 GlyphIndex glyphIndex,
+                                 BlobCoordinate* coords )
+{
+  const unsigned int size( mItemLookup.size() );
+
+  for( unsigned int i=0; i<size; ++i )
+  {
+    if( mItemLookup[i].fontId     == fontId &&
+        mItemLookup[i].glyphIndex == glyphIndex )
+    {
+      const Item& item = mItemCache[ mItemLookup[i].cacheIndex ];
+
+      coords[0] = item.coords[0];
+      coords[1] = item.coords[1];
+      coords[2] = item.coords[2];
+      coords[3] = item.coords[3];
+
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool VectorBlobAtlas::AddGlyph( unsigned int fontId,
+                                unsigned int glyphIndex,
+                                VectorBlob* blob,
+                                unsigned int length,
+                                unsigned int nominalWidth,
+                                unsigned int nominalHeight,
+                                BlobCoordinate* coords )
+{
+  if( mIsFull )
+  {
+    return false;
+  }
+
+  unsigned int w, h, x, y;
+
+  w = mItemWidth;
+  h = (length + w - 1) / w;
+
+  if( mCursorY + h > mTextureHeight )
+  {
+    // Go to next column
+    mCursorX += mItemWidth;
+    mCursorY = 0;
+  }
+
+  if( mCursorX + w <= mTextureWidth && mCursorY + h <= mTextureHeight )
+  {
+    x = mCursorX;
+    y = mCursorY;
+    mCursorY += (h + mItemHeightQuantum - 1) & ~(mItemHeightQuantum - 1);
+  }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p is now FULL\n", this );
+
+    // The atlas is now considered to be full
+    mIsFull = true;
+    return false;
+  }
+
+  if (w * h == length)
+  {
+    TexSubImage( x, y, w, h, blob );
+  }
+  else
+  {
+    TexSubImage( x, y, w, h-1, blob );
+
+    // Upload the last row separately
+    TexSubImage( x, y + h - 1, length - (w * (h - 1)), 1 , blob + w * (h - 1));
+  }
+
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p capacity %d filled %d %f\%\n",
+                 this,
+                 mTextureWidth*mTextureHeight,
+                 mCursorY*mItemWidth + mCursorX*mTextureHeight,
+                 100.0f * (float)(mCursorY*mItemWidth + mCursorX*mTextureHeight) / (float)(mTextureWidth*mTextureHeight) );
+
+  Key key;
+  key.fontId = fontId;
+  key.glyphIndex = glyphIndex;
+  key.cacheIndex = mItemCache.size();
+  mItemLookup.push_back( key );
+
+  x /= mItemWidth;
+  y /= mItemHeightQuantum;
+
+  Item item;
+  EncodeBlobCoordinate( 0, 0, x, y, nominalWidth, nominalHeight, &item.coords[0] ); // BOTTOM_LEFT
+  EncodeBlobCoordinate( 0, 1, x, y, nominalWidth, nominalHeight, &item.coords[1] ); // TOP_LEFT
+  EncodeBlobCoordinate( 1, 0, x, y, nominalWidth, nominalHeight, &item.coords[2] ); // BOTTOM_RIGHT
+  EncodeBlobCoordinate( 1, 1, x, y, nominalWidth, nominalHeight, &item.coords[3] ); // TOP_RIGHT
+  mItemCache.push_back( item );
+
+  coords[0] = item.coords[0];
+  coords[1] = item.coords[1];
+  coords[2] = item.coords[2];
+  coords[3] = item.coords[3];
+
+  return true;
+}
+
+void VectorBlobAtlas::TexSubImage( unsigned int offsetX,
+                                   unsigned int offsetY,
+                                   unsigned int width,
+                                   unsigned int height,
+                                   VectorBlob* blob )
+{
+  PixelBuffer* pixbuf = mAtlasTexture.GetBuffer();
+  size_t pos;
+  size_t dataIndex = 0;
+  for( size_t y= offsetY; y< height + offsetY; y++ )
+  {
+    pos = y * mTextureWidth * 4;
+    for( size_t x = offsetX; x < width + offsetX; x++ )
+    {
+      pixbuf[pos+x*4] =  0xFF & blob[dataIndex].r;
+      pixbuf[pos+x*4+1] = 0xFF & blob[dataIndex].g;
+      pixbuf[pos+x*4+2] = 0xFF & blob[dataIndex].b;
+      pixbuf[pos+x*4+3] = 0xFF & blob[dataIndex].a;
+      dataIndex++;
+    }
+  }
+
+  mAtlasTexture.Update();
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h b/dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h
new file mode 100644 (file)
index 0000000..13b226d
--- /dev/null
@@ -0,0 +1,185 @@
+#ifndef __DALI_TOOLKIT_TEXT_VECTOR_BLOB_ATLAS_H__
+#define __DALI_TOOLKIT_TEXT_VECTOR_BLOB_ATLAS_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/object/ref-object.h>
+#include <dali/public-api/images/buffer-image.h>
+#include <dali/devel-api/rendering/texture-set.h>
+#include <dali/devel-api/rendering/shader.h>
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+typedef Dali::TextAbstraction::VectorBlob VectorBlob;
+
+struct BlobCoordinate
+{
+  float u;
+  float v;
+};
+
+/**
+ * @brief An atlas for vector blob data
+ *
+ */
+class VectorBlobAtlas : public RefObject
+{
+public:
+
+  /**
+   * @brief Create a blob atlas.
+   *
+   * @param[in] textureWidth The atlas width.
+   * @param[in] textureHeight The atlas height.
+   * @param[in] itemWidth The width of an item in the atlas.
+   * @param[in] itemHeightQuantum The item height quantum.
+   * When blobs are added to columns in the atlas, the Y position is advanced by a multiple of this value.
+   */
+  VectorBlobAtlas( unsigned int textureWidth,
+                   unsigned int textureHeight,
+                   unsigned int itemWidth,
+                   unsigned int itemHeightQuantum );
+
+  /**
+   * @brief Query whether the atlas is full.
+   *
+   * @return True if the atlas is full.
+   */
+  bool IsFull() const;
+
+  /**
+   * @brief Find the UV coordinates for a glyph in the atlas.
+   *
+   * @param[in] fontId The ID of the font containing the glyph.
+   * @param[in] glyphIndex The index of the glyph within the font.
+   * @param[out] coords If the glyph was found, an array of 4 UV coordinates will be returned.
+   * Otherwise coords will not be written into.
+   * @return True if the glyph was found.
+   */
+  bool FindGlyph( FontId fontId,
+                  GlyphIndex glyphIndex,
+                  BlobCoordinate* coords );
+
+  /**
+   * @brief Add a glyph to the atlas.
+   *
+   * @param[in] fontId The ID of the font containing the glyph.
+   * @param[in] glyphIndex The index of the glyph within the font.
+   * @param[in] blobData A blob of vector data representing the glyph.
+   * @param[in] length The length of the blob data.
+   * @param[in] nominalWidth The width of the blob.
+   * @param[in] nominalHeight The height of the blob.
+   * @param[out] coords An array of 4 UV coordinates will be returned.
+   * @return True if the glyph was added. Otherwise the atlas is now full.
+   */
+  bool AddGlyph( unsigned int fontId,
+                 unsigned int glyphIndex,
+                 VectorBlob* blob,
+                 unsigned int length,
+                 unsigned int nominalWidth,
+                 unsigned int nominalHeight,
+                 BlobCoordinate* coords );
+
+  /**
+   * @brief Get the info required by the GLyphy shader.
+   *
+   * @return The shader uniform value.
+   */
+  Vector4 GetInfo() const
+  {
+    return Vector4( mTextureWidth, mTextureHeight, mItemWidth, mItemHeightQuantum );
+  }
+
+  /**
+   * @brief Retrieve the atlas texture.
+   *
+   * @return The texture used for rendering.
+   */
+  TextureSet GetTextureSet()
+  {
+    return mTextureSet;
+  }
+
+private:
+
+  /**
+   * @brief Helper for uploading data to the texture atlas.
+   *
+   * @param[in] offsetX The x position within the atlas.
+   * @param[in] offsetY The y position within the atlas.
+   * @param[in] width The width of the data to upload.
+   * @param[in] height The height of the data to upload.
+   * @param[in] blob The blob of data to upload.
+   */
+  void TexSubImage( unsigned int offsetX,
+                    unsigned int offsetY,
+                    unsigned int width,
+                    unsigned int height,
+                    VectorBlob* blob );
+
+private:
+
+  unsigned int mTextureWidth;
+  unsigned int mTextureHeight;
+
+  unsigned int mItemWidth;
+  unsigned int mItemHeightQuantum;
+
+  unsigned int mCursorX;
+  unsigned int mCursorY;
+
+  BufferImage mAtlasTexture;
+
+  TextureSet mTextureSet;
+
+  struct Key
+  {
+    unsigned int fontId;
+    unsigned int glyphIndex;
+    unsigned int cacheIndex;
+  };
+
+  struct Item
+  {
+    BlobCoordinate coords[4];
+  };
+
+  std::vector< Key >  mItemLookup;
+  std::vector< Item > mItemCache;
+
+  bool mIsFull;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif //  __DALI_TOOLKIT_TEXT_VECTOR_BLOB_ATLAS_H__
index 5571f94..f64c266 100644 (file)
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/color-segmentation.h>
+#include <dali-toolkit/internal/text/glyph-metrics-helper.h>
 #include <dali-toolkit/internal/text/multi-language-support.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
 
 namespace
 {
@@ -37,28 +39,6 @@ namespace
   Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, true, "LOG_TEXT_CONTROLS");
 #endif
 
-/**
- * @brief Some characters can be shaped in more than one glyph.
- * This struct is used to retrieve metrics from these group of glyphs.
- */
-struct GlyphMetrics
-{
-  GlyphMetrics()
-  : fontHeight( 0.f ),
-    advance( 0.f ),
-    ascender( 0.f ),
-    xBearing( 0.f )
-  {}
-
-  ~GlyphMetrics()
-  {}
-
-  float fontHeight; ///< The font's height of that glyphs.
-  float advance;    ///< The sum of all the advances of all the glyphs.
-  float ascender;   ///< The font's ascender.
-  float xBearing;   ///< The x bearing of the first glyph.
-};
-
 } // namespace
 
 namespace Dali
@@ -70,41 +50,6 @@ namespace Toolkit
 namespace Text
 {
 
-/**
- * @brief Get some glyph's metrics of a group of glyphs formed as a result of shaping one character.
- *
- * @param[in] glyphIndex The index to the first glyph.
- * @param[in] numberOfGlyphs The number of glyphs.
- * @param[out] glyphMetrics Some glyph metrics (font height, advance, ascender and x bearing).
- * @param[in] visualModel The visual model.
- * @param[in] metrics Used to access metrics from FontClient.
- */
-void GetGlyphsMetrics( GlyphIndex glyphIndex,
-                       Length numberOfGlyphs,
-                       GlyphMetrics& glyphMetrics,
-                       VisualModelPtr& visualModel,
-                       MetricsPtr& metrics )
-{
-  const GlyphInfo* glyphsBuffer = visualModel->mGlyphs.Begin();
-
-  const GlyphInfo& firstGlyph = *( glyphsBuffer + glyphIndex );
-
-  Text::FontMetrics fontMetrics;
-  metrics->GetFontMetrics( firstGlyph.fontId, fontMetrics );
-
-  glyphMetrics.fontHeight = fontMetrics.height;
-  glyphMetrics.advance = firstGlyph.advance;
-  glyphMetrics.ascender = fontMetrics.ascender;
-  glyphMetrics.xBearing = firstGlyph.xBearing;
-
-  for( unsigned int i = 1u; i < numberOfGlyphs; ++i )
-  {
-    const GlyphInfo& glyphInfo = *( glyphsBuffer + glyphIndex + i );
-
-    glyphMetrics.advance += glyphInfo.advance;
-  }
-}
-
 EventData::EventData( DecoratorPtr decorator )
 : mDecorator( decorator ),
   mImfManager(),
@@ -313,6 +258,381 @@ bool Controller::Impl::ProcessInputEvents()
   return decoratorUpdated;
 }
 
+void Controller::Impl::CalculateTextUpdateIndices( Length& numberOfCharacters )
+{
+  mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+  mTextUpdateInfo.mStartGlyphIndex = 0u;
+  mTextUpdateInfo.mStartLineIndex = 0u;
+  numberOfCharacters = 0u;
+
+  const Length numberOfParagraphs = mLogicalModel->mParagraphInfo.Count();
+  if( 0u == numberOfParagraphs )
+  {
+    mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+    numberOfCharacters = 0u;
+
+    mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
+
+    // Nothing else to do if there are no paragraphs.
+    return;
+  }
+
+  // Find the paragraphs to be updated.
+  Vector<ParagraphRunIndex> paragraphsToBeUpdated;
+  if( mTextUpdateInfo.mCharacterIndex >= mTextUpdateInfo.mPreviousNumberOfCharacters )
+  {
+    // Text is being added at the end of the current text.
+    if( mTextUpdateInfo.mIsLastCharacterNewParagraph )
+    {
+      // Text is being added in a new paragraph after the last character of the text.
+      mTextUpdateInfo.mParagraphCharacterIndex = mTextUpdateInfo.mPreviousNumberOfCharacters;
+      numberOfCharacters = 0u;
+      mTextUpdateInfo.mRequestedNumberOfCharacters = mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
+
+      mTextUpdateInfo.mStartGlyphIndex = mVisualModel->mGlyphs.Count();
+      mTextUpdateInfo.mStartLineIndex = mVisualModel->mLines.Count() - 1u;
+
+      // Nothing else to do;
+      return;
+    }
+
+    paragraphsToBeUpdated.PushBack( numberOfParagraphs - 1u );
+  }
+  else
+  {
+    CharacterIndex lastIndex = 0u;
+    if( mTextUpdateInfo.mFullRelayoutNeeded )
+    {
+      lastIndex = mTextUpdateInfo.mPreviousNumberOfCharacters;
+    }
+    else
+    {
+      lastIndex = ( mTextUpdateInfo.mNumberOfCharactersToRemove > 0u ) ? mTextUpdateInfo.mNumberOfCharactersToRemove : 1u;
+    }
+    mLogicalModel->FindParagraphs( mTextUpdateInfo.mCharacterIndex,
+                                   lastIndex,
+                                   paragraphsToBeUpdated );
+  }
+
+  if( 0u != paragraphsToBeUpdated.Count() )
+  {
+    const ParagraphRunIndex firstParagraphIndex = *( paragraphsToBeUpdated.Begin() );
+    const ParagraphRun& firstParagraph = *( mLogicalModel->mParagraphInfo.Begin() + firstParagraphIndex );
+    mTextUpdateInfo.mParagraphCharacterIndex = firstParagraph.characterRun.characterIndex;
+
+    ParagraphRunIndex lastParagraphIndex = *( paragraphsToBeUpdated.End() - 1u );
+    const ParagraphRun& lastParagraph = *( mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex );
+
+    if( ( mTextUpdateInfo.mNumberOfCharactersToRemove > 0u ) &&                                            // Some character are removed.
+        ( lastParagraphIndex < numberOfParagraphs - 1u ) &&                                                // There is a next paragraph.
+        ( ( lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters ) == // The last removed character is the new paragraph character.
+          ( mTextUpdateInfo.mCharacterIndex + mTextUpdateInfo.mNumberOfCharactersToRemove ) ) )
+    {
+      // The new paragraph character of the last updated paragraph has been removed so is going to be merged with the next one.
+      const ParagraphRun& lastParagraph = *( mLogicalModel->mParagraphInfo.Begin() + lastParagraphIndex + 1u );
+
+      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
+    }
+    else
+    {
+      numberOfCharacters = lastParagraph.characterRun.characterIndex + lastParagraph.characterRun.numberOfCharacters - mTextUpdateInfo.mParagraphCharacterIndex;
+    }
+  }
+  mTextUpdateInfo.mRequestedNumberOfCharacters = numberOfCharacters + mTextUpdateInfo.mNumberOfCharactersToAdd - mTextUpdateInfo.mNumberOfCharactersToRemove;
+  mTextUpdateInfo.mStartGlyphIndex = *( mVisualModel->mCharactersToGlyph.Begin() + mTextUpdateInfo.mParagraphCharacterIndex );
+}
+
+void Controller::Impl::ClearFullModelData( OperationsMask operations )
+{
+  if( GET_LINE_BREAKS & operations )
+  {
+    mLogicalModel->mLineBreakInfo.Clear();
+    mLogicalModel->mParagraphInfo.Clear();
+  }
+
+  if( GET_WORD_BREAKS & operations )
+  {
+    mLogicalModel->mLineBreakInfo.Clear();
+  }
+
+  if( GET_SCRIPTS & operations )
+  {
+    mLogicalModel->mScriptRuns.Clear();
+  }
+
+  if( VALIDATE_FONTS & operations )
+  {
+    mLogicalModel->mFontRuns.Clear();
+  }
+
+  if( 0u != mLogicalModel->mBidirectionalParagraphInfo.Count() )
+  {
+    if( BIDI_INFO & operations )
+    {
+      mLogicalModel->mBidirectionalParagraphInfo.Clear();
+      mLogicalModel->mCharacterDirections.Clear();
+    }
+
+    if( REORDER & operations )
+    {
+      // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+      for( Vector<BidirectionalLineInfoRun>::Iterator it = mLogicalModel->mBidirectionalLineInfo.Begin(),
+             endIt = mLogicalModel->mBidirectionalLineInfo.End();
+           it != endIt;
+           ++it )
+      {
+        BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+        free( bidiLineInfo.visualToLogicalMap );
+        bidiLineInfo.visualToLogicalMap = NULL;
+      }
+      mLogicalModel->mBidirectionalLineInfo.Clear();
+
+      mLogicalModel->mLogicalToVisualMap.Clear();
+      mLogicalModel->mVisualToLogicalMap.Clear();
+    }
+  }
+
+  if( SHAPE_TEXT & operations )
+  {
+    mVisualModel->mGlyphs.Clear();
+    mVisualModel->mGlyphsToCharacters.Clear();
+    mVisualModel->mCharactersToGlyph.Clear();
+    mVisualModel->mCharactersPerGlyph.Clear();
+    mVisualModel->mGlyphsPerCharacter.Clear();
+    mVisualModel->mGlyphPositions.Clear();
+  }
+
+  if( LAYOUT & operations )
+  {
+    mVisualModel->mLines.Clear();
+  }
+}
+
+void Controller::Impl::ClearCharacterModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations )
+{
+  const CharacterIndex endIndexPlusOne = endIndex + 1u;
+
+  if( GET_LINE_BREAKS & operations )
+  {
+    // Clear the line break info.
+    LineBreakInfo* lineBreakInfoBuffer = mLogicalModel->mLineBreakInfo.Begin();
+
+    mLogicalModel->mLineBreakInfo.Erase( lineBreakInfoBuffer + startIndex,
+                                         lineBreakInfoBuffer + endIndexPlusOne );
+
+    // Clear the paragraphs.
+    ClearCharacterRuns( startIndex,
+                        endIndex,
+                        mLogicalModel->mParagraphInfo );
+  }
+
+  if( GET_WORD_BREAKS & operations )
+  {
+    // Clear the word break info.
+    WordBreakInfo* wordBreakInfoBuffer = mLogicalModel->mWordBreakInfo.Begin();
+
+    mLogicalModel->mWordBreakInfo.Erase( wordBreakInfoBuffer + startIndex,
+                                         wordBreakInfoBuffer + endIndexPlusOne );
+  }
+
+  if( GET_SCRIPTS & operations )
+  {
+    // Clear the scripts.
+    ClearCharacterRuns( startIndex,
+                        endIndex,
+                        mLogicalModel->mScriptRuns );
+  }
+
+  if( VALIDATE_FONTS & operations )
+  {
+    // Clear the fonts.
+    ClearCharacterRuns( startIndex,
+                        endIndex,
+                        mLogicalModel->mFontRuns );
+  }
+
+  if( 0u != mLogicalModel->mBidirectionalParagraphInfo.Count() )
+  {
+    if( BIDI_INFO & operations )
+    {
+      // Clear the bidirectional paragraph info.
+      ClearCharacterRuns( startIndex,
+                          endIndex,
+                          mLogicalModel->mBidirectionalParagraphInfo );
+
+      // Clear the character's directions.
+      CharacterDirection* characterDirectionsBuffer = mLogicalModel->mCharacterDirections.Begin();
+
+      mLogicalModel->mCharacterDirections.Erase( characterDirectionsBuffer + startIndex,
+                                                 characterDirectionsBuffer + endIndexPlusOne );
+    }
+
+    if( REORDER & operations )
+    {
+      uint32_t startRemoveIndex = mLogicalModel->mBidirectionalLineInfo.Count();
+      uint32_t endRemoveIndex = startRemoveIndex;
+      ClearCharacterRuns( startIndex,
+                          endIndex,
+                          mLogicalModel->mBidirectionalLineInfo,
+                          startRemoveIndex,
+                          endRemoveIndex );
+
+      BidirectionalLineInfoRun* bidirectionalLineInfoBuffer = mLogicalModel->mBidirectionalLineInfo.Begin();
+
+      // Free the allocated memory used to store the conversion table in the bidirectional line info run.
+      for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfoBuffer + startRemoveIndex,
+             endIt = bidirectionalLineInfoBuffer + endRemoveIndex;
+           it != endIt;
+           ++it )
+      {
+        BidirectionalLineInfoRun& bidiLineInfo = *it;
+
+        free( bidiLineInfo.visualToLogicalMap );
+        bidiLineInfo.visualToLogicalMap = NULL;
+      }
+
+      mLogicalModel->mBidirectionalLineInfo.Erase( bidirectionalLineInfoBuffer + startRemoveIndex,
+                                                   bidirectionalLineInfoBuffer + endRemoveIndex );
+
+      // Clear the logical to visual and the visual to logical conversion tables.
+      CharacterIndex* logicalToVisualMapBuffer = mLogicalModel->mLogicalToVisualMap.Begin();
+      mLogicalModel->mLogicalToVisualMap.Erase( logicalToVisualMapBuffer + startIndex,
+                                                logicalToVisualMapBuffer + endIndexPlusOne );
+
+      CharacterIndex* visualToLogicalMapBuffer = mLogicalModel->mVisualToLogicalMap.Begin();
+      mLogicalModel->mVisualToLogicalMap.Erase( visualToLogicalMapBuffer + startIndex,
+                                                visualToLogicalMapBuffer + endIndexPlusOne );
+    }
+  }
+}
+
+void Controller::Impl::ClearGlyphModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations )
+{
+  const CharacterIndex endIndexPlusOne = endIndex + 1u;
+  const Length numberOfCharactersRemoved = endIndexPlusOne - startIndex;
+
+  const bool clearShape = SHAPE_TEXT & operations;
+  const bool clearLayout = LAYOUT & operations;
+
+  if( clearShape || clearLayout )
+  {
+    // Convert the character index to glyph index before deleting the character to glyph and the glyphs per character buffers.
+    GlyphIndex* charactersToGlyphBuffer = mVisualModel->mCharactersToGlyph.Begin();
+    Length* glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin();
+
+    const GlyphIndex endGlyphIndex = *( charactersToGlyphBuffer + endIndex );
+    const GlyphIndex endGlyphIndexPlusOne = endGlyphIndex + *( glyphsPerCharacterBuffer + endIndex );
+    const Length numberOfGlyphsRemoved = endGlyphIndexPlusOne - mTextUpdateInfo.mStartGlyphIndex;
+
+    if( clearShape )
+    {
+      // Update the character to glyph indices.
+      for( Vector<GlyphIndex>::Iterator it =  charactersToGlyphBuffer + endIndexPlusOne,
+             endIt =  charactersToGlyphBuffer + mVisualModel->mCharactersToGlyph.Count();
+           it != endIt;
+           ++it )
+      {
+        CharacterIndex& index = *it;
+        index -= numberOfGlyphsRemoved;
+      }
+
+      // Clear the character to glyph conversion table.
+      mVisualModel->mCharactersToGlyph.Erase( charactersToGlyphBuffer + startIndex,
+                                              charactersToGlyphBuffer + endIndexPlusOne );
+
+      // Clear the glyphs per character table.
+      mVisualModel->mGlyphsPerCharacter.Erase( glyphsPerCharacterBuffer + startIndex,
+                                               glyphsPerCharacterBuffer + endIndexPlusOne );
+
+      // Clear the glyphs buffer.
+      GlyphInfo* glyphsBuffer = mVisualModel->mGlyphs.Begin();
+      mVisualModel->mGlyphs.Erase( glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                   glyphsBuffer + endGlyphIndexPlusOne );
+
+      CharacterIndex* glyphsToCharactersBuffer = mVisualModel->mGlyphsToCharacters.Begin();
+
+      // Update the glyph to character indices.
+      for( Vector<CharacterIndex>::Iterator it = glyphsToCharactersBuffer + endGlyphIndexPlusOne,
+             endIt = glyphsToCharactersBuffer + mVisualModel->mGlyphsToCharacters.Count();
+           it != endIt;
+           ++it )
+      {
+        CharacterIndex& index = *it;
+        index -= numberOfCharactersRemoved;
+      }
+
+      // Clear the glyphs to characters buffer.
+      mVisualModel->mGlyphsToCharacters.Erase( glyphsToCharactersBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                               glyphsToCharactersBuffer  + endGlyphIndexPlusOne );
+
+      // Clear the characters per glyph buffer.
+      Length* charactersPerGlyphBuffer = mVisualModel->mCharactersPerGlyph.Begin();
+      mVisualModel->mCharactersPerGlyph.Erase( charactersPerGlyphBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                               charactersPerGlyphBuffer + endGlyphIndexPlusOne );
+
+      // Clear the positions buffer.
+      Vector2* positionsBuffer = mVisualModel->mGlyphPositions.Begin();
+      mVisualModel->mGlyphPositions.Erase( positionsBuffer + mTextUpdateInfo.mStartGlyphIndex,
+                                           positionsBuffer + endGlyphIndexPlusOne );
+    }
+
+    if( clearLayout )
+    {
+      // Clear the lines.
+      uint32_t startRemoveIndex = mVisualModel->mLines.Count();
+      uint32_t endRemoveIndex = startRemoveIndex;
+      ClearCharacterRuns( startIndex,
+                          endIndex,
+                          mVisualModel->mLines,
+                          startRemoveIndex,
+                          endRemoveIndex );
+
+      // Will update the glyph runs.
+      uint32_t startRemoveGlyphIndex = mVisualModel->mLines.Count();
+      uint32_t endRemoveGlyphIndex = startRemoveIndex;
+      ClearGlyphRuns( mTextUpdateInfo.mStartGlyphIndex,
+                      endGlyphIndex,
+                      mVisualModel->mLines,
+                      startRemoveGlyphIndex,
+                      endRemoveGlyphIndex );
+
+      // Set the line index from where to insert the new laid-out lines.
+      mTextUpdateInfo.mStartLineIndex = startRemoveIndex;
+
+      LineRun* linesBuffer = mVisualModel->mLines.Begin();
+      mVisualModel->mLines.Erase( linesBuffer + startRemoveIndex,
+                                  linesBuffer + endRemoveIndex );
+    }
+  }
+}
+
+void Controller::Impl::ClearModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations )
+{
+  if( mTextUpdateInfo.mClearAll ||
+      ( ( 0u == startIndex ) &&
+        ( mTextUpdateInfo.mPreviousNumberOfCharacters == endIndex + 1u ) ) )
+  {
+    ClearFullModelData( operations );
+  }
+  else
+  {
+    // Clear the model data related with characters.
+    ClearCharacterModelData( startIndex, endIndex, operations );
+
+    // Clear the model data related with glyphs.
+    ClearGlyphModelData( startIndex, endIndex, operations );
+  }
+
+  // The estimated number of lines. Used to avoid reallocations when layouting.
+  mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mVisualModel->mLines.Count(), mLogicalModel->mParagraphInfo.Count() );
+
+  mVisualModel->ClearCaches();
+
+  // TODO finish the mark-up.
+  mVisualModel->mColorRuns.Clear();
+}
+
 void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
 {
   DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::UpdateModel\n" );
@@ -320,13 +640,35 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
   // Calculate the operations to be done.
   const OperationsMask operations = static_cast<OperationsMask>( mOperationsPending & operationsRequired );
 
+  if( NO_OPERATION == operations )
+  {
+    // Nothing to do if no operations are pending and required.
+    return;
+  }
+
   Vector<Character>& utf32Characters = mLogicalModel->mText;
 
   const Length numberOfCharacters = utf32Characters.Count();
 
-  Vector<LineBreakInfo>& lineBreakInfo = mLogicalModel->mLineBreakInfo;
+  // Index to the first character of the first paragraph to be updated.
   CharacterIndex startIndex = 0u;
-  Length requestedNumberOfCharacters = numberOfCharacters;
+  // Number of characters of the paragraphs to be removed.
+  Length paragraphCharacters = 0u;
+
+  CalculateTextUpdateIndices( paragraphCharacters );
+  startIndex = mTextUpdateInfo.mParagraphCharacterIndex;
+
+  if( mTextUpdateInfo.mClearAll ||
+      ( 0u != paragraphCharacters ) )
+  {
+    ClearModelData( startIndex, startIndex + ( ( paragraphCharacters > 0u ) ? paragraphCharacters - 1u : 0u ), operationsRequired );
+  }
+
+  mTextUpdateInfo.mClearAll = false;
+
+  Vector<LineBreakInfo>& lineBreakInfo = mLogicalModel->mLineBreakInfo;
+  const Length requestedNumberOfCharacters = mTextUpdateInfo.mRequestedNumberOfCharacters;
+
   if( GET_LINE_BREAKS & operations )
   {
     // Retrieves the line break info. The line break info is used to split the text in 'paragraphs' to
@@ -400,21 +742,9 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
 
   Vector<Character> mirroredUtf32Characters;
   bool textMirrored = false;
-  Length numberOfParagraphs = 0u;
+  const Length numberOfParagraphs = mLogicalModel->mParagraphInfo.Count();
   if( BIDI_INFO & operations )
   {
-    // Count the number of LINE_NO_BREAK to reserve some space for the vector of paragraph's
-    // bidirectional info.
-
-    const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin();
-    for( Length index = 0u; index < numberOfCharacters; ++index )
-    {
-      if( TextAbstraction::LINE_NO_BREAK == *( lineBreakInfoBuffer + index ) )
-      {
-        ++numberOfParagraphs;
-      }
-    }
-
     Vector<BidirectionalParagraphInfoRun>& bidirectionalInfo = mLogicalModel->mBidirectionalParagraphInfo;
     bidirectionalInfo.Reserve( numberOfParagraphs );
 
@@ -459,7 +789,7 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
   Vector<GlyphIndex> newParagraphGlyphs;
   newParagraphGlyphs.Reserve( numberOfParagraphs );
 
-  GlyphIndex startGlyphIndex = 0u;
+  const Length currentNumberOfGlyphs = glyphs.Count();
   if( SHAPE_TEXT & operations )
   {
     const Vector<Character>& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
@@ -469,7 +799,7 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                scripts,
                validFonts,
                startIndex,
-               startGlyphIndex,
+               mTextUpdateInfo.mStartGlyphIndex,
                requestedNumberOfCharacters,
                glyphs,
                glyphsToCharactersMap,
@@ -477,16 +807,16 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
                newParagraphGlyphs );
 
     // Create the 'number of glyphs' per character and the glyph to character conversion tables.
-    mVisualModel->CreateGlyphsPerCharacterTable( startIndex, startGlyphIndex, numberOfCharacters );
-    mVisualModel->CreateCharacterToGlyphTable( startIndex, startGlyphIndex, numberOfCharacters );
+    mVisualModel->CreateGlyphsPerCharacterTable( startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters );
+    mVisualModel->CreateCharacterToGlyphTable( startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters );
   }
 
-  const Length numberOfGlyphs = glyphs.Count();
+  const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
 
   if( GET_GLYPH_METRICS & operations )
   {
-    GlyphInfo* glyphsBuffer = glyphs.Begin() + startGlyphIndex;
-    mMetrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
+    GlyphInfo* glyphsBuffer = glyphs.Begin();
+    mMetrics->GetGlyphMetrics( glyphsBuffer + mTextUpdateInfo.mStartGlyphIndex, numberOfGlyphs );
 
     // Update the width and advance of all new paragraph characters.
     for( Vector<GlyphIndex>::ConstIterator it = newParagraphGlyphs.Begin(), endIt = newParagraphGlyphs.End(); it != endIt; ++it )
@@ -520,6 +850,12 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
     // TODO: At the moment the underline runs are only for pre-edit.
     mVisualModel->mUnderlineRuns.PushBack( underlineRun );
   }
+
+  // The estimated number of lines. Used to avoid reallocations when layouting.
+  mTextUpdateInfo.mEstimatedNumberOfLines = std::max( mVisualModel->mLines.Count(), mLogicalModel->mParagraphInfo.Count() );
+
+  // Set the previous number of characters for the next time the text is updated.
+  mTextUpdateInfo.mPreviousNumberOfCharacters = numberOfCharacters;
 }
 
 bool Controller::Impl::UpdateModelStyle( OperationsMask operationsRequired )
@@ -988,12 +1324,13 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete
   const CharacterIndex startOfSelectedText = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
   const Length lengthOfSelectedText = ( handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition ) - startOfSelectedText;
 
+  Vector<Character>& utf32Characters = mLogicalModel->mText;
+  const Length numberOfCharacters = utf32Characters.Count();
+
   // Validate the start and end selection points
-  if( ( startOfSelectedText + lengthOfSelectedText ) <= mLogicalModel->mText.Count() )
+  if( ( startOfSelectedText + lengthOfSelectedText ) <= numberOfCharacters )
   {
     //Get text as a UTF8 string
-    Vector<Character>& utf32Characters = mLogicalModel->mText;
-
     Utf32ToUtf8( &utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText );
 
     if( deleteAfterRetrieval ) // Only delete text if copied successfully
@@ -1003,12 +1340,14 @@ void Controller::Impl::RetrieveSelection( std::string& selectedText, bool delete
 
       mLogicalModel->UpdateTextStyleRuns( startOfSelectedText, -static_cast<int>( lengthOfSelectedText ) );
 
-      // Delete text between handles
-      Vector<Character>& currentText = mLogicalModel->mText;
+      // Mark the paragraphs to be updated.
+      mTextUpdateInfo.mCharacterIndex = startOfSelectedText;
+      mTextUpdateInfo.mNumberOfCharactersToRemove = lengthOfSelectedText;
 
-      Vector<Character>::Iterator first = currentText.Begin() + startOfSelectedText;
+      // Delete text between handles
+      Vector<Character>::Iterator first = utf32Characters.Begin() + startOfSelectedText;
       Vector<Character>::Iterator last  = first + lengthOfSelectedText;
-      currentText.Erase( first, last );
+      utf32Characters.Erase( first, last );
 
       // Scroll after delete.
       mEventData->mPrimaryCursorPosition = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
@@ -1585,6 +1924,9 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
   // Get the glyphs per character table.
   const Length* const glyphsPerCharacterBuffer = mVisualModel->mGlyphsPerCharacter.Begin();
 
+  // Get the glyph's info buffer.
+  const GlyphInfo* const glyphInfoBuffer = mVisualModel->mGlyphs.Begin();
+
   // If the vector is void, there is no right to left characters.
   const bool hasRightToLeftCharacters = NULL != visualToLogicalBuffer;
 
@@ -1623,7 +1965,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
       GetGlyphsMetrics( firstLogicalGlyphIndex,
                         numberOfGlyphs,
                         glyphMetrics,
-                        mVisualModel,
+                        glyphInfoBuffer,
                         mMetrics );
 
       // Get the position of the first glyph.
@@ -1802,6 +2144,7 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
   const Length* const charactersPerGlyphBuffer = mVisualModel->mCharactersPerGlyph.Begin();
   const CharacterIndex* const glyphsToCharactersBuffer = mVisualModel->mGlyphsToCharacters.Begin();
   const Vector2* const glyphPositionsBuffer = mVisualModel->mGlyphPositions.Begin();
+  const GlyphInfo* const glyphInfoBuffer = mVisualModel->mGlyphs.Begin();
 
   // Convert the cursor position into the glyph position.
   const GlyphIndex primaryGlyphIndex = *( charactersToGlyphBuffer + index );
@@ -1813,7 +2156,7 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
   GetGlyphsMetrics( primaryGlyphIndex,
                     primaryNumberOfGlyphs,
                     glyphMetrics,
-                    mVisualModel,
+                    glyphInfoBuffer,
                     mMetrics );
 
   // Whether to add the glyph's advance to the cursor position.
@@ -1903,7 +2246,7 @@ void Controller::Impl::GetCursorPosition( CharacterIndex logical,
     GetGlyphsMetrics( secondaryGlyphIndex,
                       secondaryNumberOfGlyphs,
                       glyphMetrics,
-                      mVisualModel,
+                      glyphInfoBuffer,
                       mMetrics );
 
     // Set the secondary cursor's position.
index f88ca8d..2f14702 100644 (file)
@@ -223,6 +223,63 @@ struct FontDefaults
   bool   sizeDefined:1; ///< Whether the default font's point size is defined.
 };
 
+/**
+ * @brief Stores indices used to update the text.
+ * Stores the character index where the text is updated and the number of characters removed and added.
+ * Stores as well indices to the first and the last paragraphs to be updated.
+ */
+struct TextUpdateInfo
+{
+  TextUpdateInfo()
+  : mCharacterIndex( 0u ),
+    mNumberOfCharactersToRemove( 0u ),
+    mNumberOfCharactersToAdd( 0u ),
+    mPreviousNumberOfCharacters( 0u ),
+    mParagraphCharacterIndex( 0u ),
+    mRequestedNumberOfCharacters( 0u ),
+    mStartGlyphIndex( 0u ),
+    mStartLineIndex( 0u ),
+    mEstimatedNumberOfLines( 0u ),
+    mClearAll( true ),
+    mFullRelayoutNeeded( true ),
+    mIsLastCharacterNewParagraph( false )
+  {}
+
+  ~TextUpdateInfo()
+  {}
+
+  CharacterIndex    mCharacterIndex;                ///< Index to the first character to be updated.
+  Length            mNumberOfCharactersToRemove;    ///< The number of characters to be removed.
+  Length            mNumberOfCharactersToAdd;       ///< The number of characters to be added.
+  Length            mPreviousNumberOfCharacters;    ///< The number of characters before the text update.
+
+  CharacterIndex    mParagraphCharacterIndex;       ///< Index of the first character of the first paragraph to be updated.
+  Length            mRequestedNumberOfCharacters;   ///< The requested number of characters.
+  GlyphIndex        mStartGlyphIndex;
+  LineIndex         mStartLineIndex;
+  Length            mEstimatedNumberOfLines;         ///< The estimated number of lines. Used to avoid reallocations when layouting.
+
+  bool              mClearAll:1;                    ///< Whether the whole text is cleared. i.e. when the text is reset.
+  bool              mFullRelayoutNeeded:1;          ///< Whether a full re-layout is needed. i.e. when a new size is set to the text control.
+  bool              mIsLastCharacterNewParagraph:1; ///< Whether the last character is a new paragraph character.
+
+  void Clear()
+  {
+    // Clear all info except the mPreviousNumberOfCharacters member.
+    mCharacterIndex = static_cast<CharacterIndex>( -1 );
+    mNumberOfCharactersToRemove = 0u;
+    mNumberOfCharactersToAdd = 0u;
+    mParagraphCharacterIndex = 0u;
+    mRequestedNumberOfCharacters = 0u;
+    mStartGlyphIndex = 0u;
+    mStartLineIndex = 0u;
+    mEstimatedNumberOfLines = 0u;
+    mClearAll = false;
+    mFullRelayoutNeeded = false;
+    mIsLastCharacterNewParagraph = false;
+  }
+};
+
 struct Controller::Impl
 {
   Impl( ControlInterface& controlInterface )
@@ -239,6 +296,7 @@ struct Controller::Impl
     mModifyEvents(),
     mTextColor( Color::BLACK ),
     mAlignmentOffset(),
+    mTextUpdateInfo(),
     mOperationsPending( NO_OPERATION ),
     mMaximumNumberOfCharacters( 50u ),
     mRecalculateNaturalSize( true ),
@@ -367,10 +425,59 @@ struct Controller::Impl
   bool IsClipboardEmpty()
   {
     bool result( mClipboard && mClipboard.NumberOfItems() );
-    return !result; // // If NumberOfItems greater than 0, return false
+    return !result; // If NumberOfItems greater than 0, return false
   }
 
   /**
+   * @brief Calculates the start character index of the first paragraph to be updated and
+   * the end character index of the last paragraph to be updated.
+   *
+   * @param[out] numberOfCharacters The number of characters to be updated.
+   */
+  void CalculateTextUpdateIndices( Length& numberOfCharacters );
+
+  /**
+   * @brief Helper to clear completely the parts of the model specified by the given @p operations.
+   *
+   * @note It never clears the text stored in utf32.
+   */
+  void ClearFullModelData( OperationsMask operations );
+
+  /**
+   * @brief Helper to clear completely the parts of the model related with the characters specified by the given @p operations.
+   *
+   * @note It never clears the text stored in utf32.
+   *
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  void ClearCharacterModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations );
+
+  /**
+   * @brief Helper to clear completely the parts of the model related with the glyphs specified by the given @p operations.
+   *
+   * @note It never clears the text stored in utf32.
+   * @note Character indices are transformed to glyph indices.
+   *
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  void ClearGlyphModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations );
+
+  /**
+   * @brief Helper to clear the parts of the model specified by the given @p operations and from @p startIndex to @p endIndex.
+   *
+   * @note It never clears the text stored in utf32.
+   *
+   * @param[in] startIndex Index to the first character to be cleared.
+   * @param[in] endIndex Index to the last character to be cleared.
+   * @param[in] operations The operations required.
+   */
+  void ClearModelData( CharacterIndex startIndex, CharacterIndex endIndex, OperationsMask operations );
+
+  /**
    * @brief Updates the logical and visual models.
    *
    * When text or style changes the model is set with some operations pending.
@@ -541,6 +648,7 @@ struct Controller::Impl
   Vector<ModifyEvent> mModifyEvents;       ///< Temporary stores the text set until the next relayout.
   Vector4 mTextColor;                      ///< The regular text color
   Vector2 mAlignmentOffset;                ///< Vertical and horizontal offset of the whole text inside the control due to alignment.
+  TextUpdateInfo mTextUpdateInfo;          ///< Info of the characters updated.
   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
   Length mMaximumNumberOfCharacters;       ///< Maximum number of characters that can be inserted.
 
index ab41790..b32b20e 100644 (file)
@@ -107,6 +107,20 @@ void Controller::EnableTextInput( DecoratorPtr decorator )
   }
 }
 
+void Controller::SetGlyphType( TextAbstraction::GlyphType glyphType )
+{
+  // Metrics for bitmap & vector based glyphs are different
+  mImpl->mMetrics->SetGlyphType( glyphType );
+
+  // Clear the font-specific data
+  ClearFontData();
+
+  mImpl->mOperationsPending = ALL_OPERATIONS;
+  mImpl->mRecalculateNaturalSize = true;
+
+  mImpl->RequestRelayout();
+}
+
 void Controller::SetMarkupProcessorEnabled( bool enable )
 {
   mImpl->mMarkupProcessorEnabled = enable;
@@ -179,6 +193,9 @@ void Controller::SetText( const std::string& text )
     DALI_ASSERT_DEBUG( textSize >= characterCount && "Invalid UTF32 conversion length" );
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, textSize, mImpl->mLogicalModel->mText.Count() );
 
+    // The characters to be added.
+    mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = mImpl->mLogicalModel->mText.Count();
+
     // To reset the cursor position
     lastCursorIndex = characterCount;
 
@@ -530,8 +547,12 @@ bool Controller::RemoveText( int cursorOffset, int numberOfCharacters )
       numberOfCharacters = currentText.Count() - cursorIndex;
     }
 
-    if( ( cursorIndex + numberOfCharacters ) <= currentText.Count() )
+    if( ( cursorIndex + numberOfCharacters ) <= mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters )
     {
+      // Mark the paragraphs to be updated.
+      mImpl->mTextUpdateInfo.mCharacterIndex = std::min( cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex );
+      mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove += numberOfCharacters;
+
       // Update the input style and remove the text's style before removing the text.
 
       // Set first the default input style.
@@ -963,20 +984,28 @@ Vector3 Controller::GetNaturalSize()
     // Make sure the model is up-to-date before layouting
     mImpl->UpdateModel( onlyOnceOperations );
 
-    // Operations that need to be done if the size changes.
-    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
-                                                                        ALIGN  |
-                                                                        REORDER );
+    // Layout the text for the new width.
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT );
+
+    // Set the update info to relayout the whole text.
+    mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+    mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
+
+    // Store the actual control's width.
+    const float actualControlWidth = mImpl->mVisualModel->mControlSize.width;
 
     DoRelayout( Size( MAX_FLOAT, MAX_FLOAT ),
                 static_cast<OperationsMask>( onlyOnceOperations |
-                                             sizeOperations ),
+                                             LAYOUT ),
                 naturalSize.GetVectorXY() );
 
     // Do not do again the only once operations.
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
 
     // Do the size related operations again.
+    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
+                                                                        ALIGN  |
+                                                                        REORDER );
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
 
     // Stores the natural size to avoid recalculate it again
@@ -985,6 +1014,12 @@ Vector3 Controller::GetNaturalSize()
 
     mImpl->mRecalculateNaturalSize = false;
 
+    // Clear the update info. This info will be set the next time the text is updated.
+    mImpl->mTextUpdateInfo.Clear();
+
+    // Restore the actual control's width.
+    mImpl->mVisualModel->mControlSize.width = actualControlWidth;
+
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetNaturalSize calculated %f,%f,%f\n", naturalSize.x, naturalSize.y, naturalSize.z );
   }
   else
@@ -1021,21 +1056,38 @@ float Controller::GetHeightForWidth( float width )
     // Make sure the model is up-to-date before layouting
     mImpl->UpdateModel( onlyOnceOperations );
 
-    // Operations that need to be done if the size changes.
-    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
-                                                                        ALIGN  |
-                                                                        REORDER );
+
+    // Layout the text for the new width.
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | LAYOUT );
+
+    // Set the update info to relayout the whole text.
+    mImpl->mTextUpdateInfo.mParagraphCharacterIndex = 0u;
+    mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
+
+    // Store the actual control's width.
+    const float actualControlWidth = mImpl->mVisualModel->mControlSize.width;
 
     DoRelayout( Size( width, MAX_FLOAT ),
                 static_cast<OperationsMask>( onlyOnceOperations |
-                                             sizeOperations ),
+                                             LAYOUT ),
                 layoutSize );
 
     // Do not do again the only once operations.
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending & ~onlyOnceOperations );
 
     // Do the size related operations again.
+    const OperationsMask sizeOperations =  static_cast<OperationsMask>( LAYOUT |
+                                                                        ALIGN  |
+                                                                        REORDER );
+
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | sizeOperations );
+
+    // Clear the update info. This info will be set the next time the text is updated.
+    mImpl->mTextUpdateInfo.Clear();
+
+    // Restore the actual control's width.
+    mImpl->mVisualModel->mControlSize.width = actualControlWidth;
+
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::GetHeightForWidth calculated %f\n", layoutSize.height );
   }
   else
@@ -1059,6 +1111,10 @@ bool Controller::Relayout( const Size& size )
       mImpl->mVisualModel->mGlyphPositions.Clear();
       glyphsRemoved = true;
     }
+
+    // Clear the update info. This info will be set the next time the text is updated.
+    mImpl->mTextUpdateInfo.Clear();
+
     // Not worth to relayout if width or height is equal to zero.
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::Relayout (skipped)\n" );
     return glyphsRemoved;
@@ -1077,8 +1133,9 @@ bool Controller::Relayout( const Size& size )
                                                              ALIGN                     |
                                                              UPDATE_ACTUAL_SIZE        |
                                                              REORDER );
-
-    mImpl->mVisualModel->mControlSize = size;
+    // Set the update info to relayout the whole text.
+    mImpl->mTextUpdateInfo.mFullRelayoutNeeded = true;
+    mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
   }
 
   // Whether there are modify events.
@@ -1100,7 +1157,7 @@ bool Controller::Relayout( const Size& size )
 
   // Layout the text.
   Size layoutSize;
-  updated = DoRelayout( mImpl->mVisualModel->mControlSize,
+  updated = DoRelayout( size,
                         mImpl->mOperationsPending,
                         layoutSize ) || updated;
 
@@ -1135,6 +1192,9 @@ bool Controller::Relayout( const Size& size )
     updated = mImpl->ProcessInputEvents() || updated;
   }
 
+  // Clear the update info. This info will be set the next time the text is updated.
+  mImpl->mTextUpdateInfo.Clear();
+
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::Relayout\n" );
   return updated;
 }
@@ -1191,11 +1251,17 @@ void Controller::ResetText()
 {
   // Reset buffers.
   mImpl->mLogicalModel->mText.Clear();
-  ClearModelData();
 
   // We have cleared everything including the placeholder-text
   mImpl->PlaceholderCleared();
 
+  mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
+  mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+  mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = 0u;
+
+  // Clear any previous text.
+  mImpl->mTextUpdateInfo.mClearAll = true;
+
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
 
@@ -1230,19 +1296,11 @@ void Controller::ResetScrollPosition()
 
 void Controller::TextReplacedEvent()
 {
-  // Reset buffers.
-  ClearModelData();
-
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
 
   // Apply modifications to the model
   mImpl->mOperationsPending = ALL_OPERATIONS;
-  mImpl->UpdateModel( ALL_OPERATIONS );
-  mImpl->mOperationsPending = static_cast<OperationsMask>( LAYOUT             |
-                                                           ALIGN              |
-                                                           UPDATE_ACTUAL_SIZE |
-                                                           REORDER );
 }
 
 void Controller::TextInsertedEvent()
@@ -1254,19 +1312,11 @@ void Controller::TextInsertedEvent()
     return;
   }
 
-  // TODO - Optimize this
-  ClearModelData();
-
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
 
   // Apply modifications to the model; TODO - Optimize this
   mImpl->mOperationsPending = ALL_OPERATIONS;
-  mImpl->UpdateModel( ALL_OPERATIONS );
-  mImpl->mOperationsPending = static_cast<OperationsMask>( LAYOUT             |
-                                                           ALIGN              |
-                                                           UPDATE_ACTUAL_SIZE |
-                                                           REORDER );
 
   // Queue a cursor reposition event; this must wait until after DoRelayout()
   if( EventData::IsEditingState( mImpl->mEventData->mState ) )
@@ -1285,19 +1335,11 @@ void Controller::TextDeletedEvent()
     return;
   }
 
-  // TODO - Optimize this
-  ClearModelData();
-
   // The natural size needs to be re-calculated.
   mImpl->mRecalculateNaturalSize = true;
 
   // Apply modifications to the model; TODO - Optimize this
   mImpl->mOperationsPending = ALL_OPERATIONS;
-  mImpl->UpdateModel( ALL_OPERATIONS );
-  mImpl->mOperationsPending = static_cast<OperationsMask>( LAYOUT             |
-                                                           ALIGN              |
-                                                           UPDATE_ACTUAL_SIZE |
-                                                           REORDER );
 
   // Queue a cursor reposition event; this must wait until after DoRelayout()
   mImpl->mEventData->mUpdateCursorPosition = true;
@@ -1317,15 +1359,27 @@ bool Controller::DoRelayout( const Size& size,
   // Calculate the operations to be done.
   const OperationsMask operations = static_cast<OperationsMask>( mImpl->mOperationsPending & operationsRequired );
 
+  const CharacterIndex startIndex = mImpl->mTextUpdateInfo.mParagraphCharacterIndex;
+  const Length requestedNumberOfCharacters = mImpl->mTextUpdateInfo.mRequestedNumberOfCharacters;
+
   if( LAYOUT & operations )
   {
     // Some vectors with data needed to layout and reorder may be void
     // after the first time the text has been laid out.
     // Fill the vectors again.
 
-    const Length numberOfGlyphs = mImpl->mVisualModel->mGlyphs.Count();
+    // Calculate the number of glyphs to layout.
+    const Vector<GlyphIndex>& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph;
+    const Vector<Length>& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter;
+    const GlyphIndex* const charactersToGlyphBuffer = charactersToGlyph.Begin();
+    const Length* const glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
+
+    const CharacterIndex lastIndex = startIndex + ( ( requestedNumberOfCharacters > 0u ) ? requestedNumberOfCharacters - 1u : 0u );
+    const GlyphIndex startGlyphIndex = mImpl->mTextUpdateInfo.mStartGlyphIndex;
+    const Length numberOfGlyphs = ( requestedNumberOfCharacters > 0u ) ? *( charactersToGlyphBuffer + lastIndex ) + *( glyphsPerCharacterBuffer + lastIndex ) - startGlyphIndex : 0u;
+    const Length totalNumberOfGlyphs = mImpl->mVisualModel->mGlyphs.Count();
 
-    if( 0u == numberOfGlyphs )
+    if( 0u == totalNumberOfGlyphs )
     {
       if( UPDATE_ACTUAL_SIZE & operations )
       {
@@ -1344,8 +1398,6 @@ bool Controller::DoRelayout( const Size& size,
     const Vector<CharacterIndex>& glyphsToCharactersMap = mImpl->mVisualModel->mGlyphsToCharacters;
     const Vector<Length>& charactersPerGlyph = mImpl->mVisualModel->mCharactersPerGlyph;
     const Character* const textBuffer = mImpl->mLogicalModel->mText.Begin();
-    const Vector<GlyphIndex>& charactersToGlyph = mImpl->mVisualModel->mCharactersToGlyph;
-    const Vector<Length>& glyphsPerCharacter = mImpl->mVisualModel->mGlyphsPerCharacter;
 
     // Set the layout parameters.
     LayoutParameters layoutParameters( size,
@@ -1356,37 +1408,28 @@ bool Controller::DoRelayout( const Size& size,
                                        glyphs.Begin(),
                                        glyphsToCharactersMap.Begin(),
                                        charactersPerGlyph.Begin(),
-                                       charactersToGlyph.Begin(),
-                                       glyphsPerCharacter.Begin(),
-                                       numberOfGlyphs );
-
-    // The laid-out lines.
-    // It's not possible to know in how many lines the text is going to be laid-out,
-    // but it can be resized at least with the number of 'paragraphs' to avoid
-    // some re-allocations.
-    Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
-
-    // Delete any previous laid out lines before setting the new ones.
-    lines.Clear();
-
-    // The capacity of the bidirectional paragraph info is the number of paragraphs.
-    lines.Reserve( mImpl->mLogicalModel->mBidirectionalParagraphInfo.Capacity() );
+                                       charactersToGlyphBuffer,
+                                       glyphsPerCharacterBuffer,
+                                       totalNumberOfGlyphs );
 
     // Resize the vector of positions to have the same size than the vector of glyphs.
     Vector<Vector2>& glyphPositions = mImpl->mVisualModel->mGlyphPositions;
-    glyphPositions.Resize( numberOfGlyphs );
+    glyphPositions.Resize( totalNumberOfGlyphs );
 
     // Whether the last character is a new paragraph character.
-    layoutParameters.isLastNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mLogicalModel->mText.Count() - 1u ) ) );
+    mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph =  TextAbstraction::IsNewParagraph( *( textBuffer + ( mImpl->mLogicalModel->mText.Count() - 1u ) ) );
+    layoutParameters.isLastNewParagraph = mImpl->mTextUpdateInfo.mIsLastCharacterNewParagraph;
 
     // The initial glyph and the number of glyphs to layout.
-    layoutParameters.startGlyphIndex = 0u;
+    layoutParameters.startGlyphIndex = startGlyphIndex;
     layoutParameters.numberOfGlyphs = numberOfGlyphs;
+    layoutParameters.startLineIndex = mImpl->mTextUpdateInfo.mStartLineIndex;
+    layoutParameters.estimatedNumberOfLines = mImpl->mTextUpdateInfo.mEstimatedNumberOfLines;
 
     // Update the visual model.
     viewUpdated = mImpl->mLayoutEngine.LayoutText( layoutParameters,
                                                    glyphPositions,
-                                                   lines,
+                                                   mImpl->mVisualModel->mLines,
                                                    layoutSize );
 
     if( viewUpdated )
@@ -1402,26 +1445,28 @@ bool Controller::DoRelayout( const Size& size,
         {
           // Get the lines
           const Length numberOfLines = mImpl->mVisualModel->mLines.Count();
-          const CharacterIndex startIndex = 0u;
-          const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
 
           // Reorder the lines.
           bidirectionalLineInfo.Reserve( numberOfLines ); // Reserve because is not known yet how many lines have right to left characters.
           ReorderLines( bidirectionalInfo,
                         startIndex,
                         requestedNumberOfCharacters,
-                        lines,
+                        mImpl->mVisualModel->mLines,
                         bidirectionalLineInfo );
 
           // Set the bidirectional info per line into the layout parameters.
           layoutParameters.lineBidirectionalInfoRunsBuffer = bidirectionalLineInfo.Begin();
           layoutParameters.numberOfBidirectionalInfoRuns = bidirectionalLineInfo.Count();
 
+          // TODO: update the conversion map instead creating it from scratch.
+          //       Note this tables store indices to characters, so update the table means modify all the indices of the text after the last updated character.
+          //       It's better to refactor this. Store this table per line and don't update the indices.
+          //       For the cursor position probably is better to use the function instead creating a table.
           // Set the bidirectional info into the model.
           mImpl->mLogicalModel->SetVisualToLogicalMap( layoutParameters.lineBidirectionalInfoRunsBuffer,
                                                        layoutParameters.numberOfBidirectionalInfoRuns,
-                                                       startIndex,
-                                                       requestedNumberOfCharacters );
+                                                       0u,
+                                                       mImpl->mLogicalModel->mText.Count() );
 
           // Re-layout the text. Reorder those lines with right to left characters.
           mImpl->mLayoutEngine.ReLayoutRightToLeftLines( layoutParameters,
@@ -1429,19 +1474,6 @@ bool Controller::DoRelayout( const Size& size,
                                                          requestedNumberOfCharacters,
                                                          glyphPositions );
 
-          // Free the allocated memory used to store the conversion table in the bidirectional line info run.
-          for( Vector<BidirectionalLineInfoRun>::Iterator it = bidirectionalLineInfo.Begin(),
-                 endIt = bidirectionalLineInfo.End();
-               it != endIt;
-               ++it )
-          {
-            BidirectionalLineInfoRun& bidiLineInfo = *it;
-
-            free( bidiLineInfo.visualToLogicalMap );
-            bidiLineInfo.visualToLogicalMap = NULL;
-          }
-
-          bidirectionalLineInfo.Clear();
         }
       } // REORDER
 
@@ -1451,6 +1483,9 @@ bool Controller::DoRelayout( const Size& size,
         mImpl->mVisualModel->SetLayoutSize( layoutSize );
       }
     } // view updated
+
+    // Store the size used to layout the text.
+    mImpl->mVisualModel->mControlSize = size;
   }
   else
   {
@@ -1462,9 +1497,6 @@ bool Controller::DoRelayout( const Size& size,
     // The laid-out lines.
     Vector<LineRun>& lines = mImpl->mVisualModel->mLines;
 
-    const CharacterIndex startIndex = 0u;
-    const Length requestedNumberOfCharacters = mImpl->mLogicalModel->mText.Count();
-
     mImpl->mLayoutEngine.Align( size,
                                 startIndex,
                                 requestedNumberOfCharacters,
@@ -1944,6 +1976,11 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
       modifyText.Insert( modifyText.End(), utf32Characters.Begin(), utf32Characters.Begin() + maxSizeOfNewText );
     }
 
+    // Mark the first paragraph to be updated.
+    mImpl->mTextUpdateInfo.mCharacterIndex = std::min( cursorIndex, mImpl->mTextUpdateInfo.mCharacterIndex );
+    mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd += maxSizeOfNewText;
+
+    // Update the cursor index.
     cursorIndex += maxSizeOfNewText;
 
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Inserted %d characters, new size %d new cursor %d\n", maxSizeOfNewText, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition );
@@ -2500,9 +2537,11 @@ void Controller::ShowPlaceholderText()
       size = mImpl->mEventData->mPlaceholderTextInactive.size();
     }
 
+    mImpl->mTextUpdateInfo.mCharacterIndex = 0u;
+    mImpl->mTextUpdateInfo.mNumberOfCharactersToRemove = mImpl->mTextUpdateInfo.mPreviousNumberOfCharacters;
+
     // Reset model for showing placeholder.
     mImpl->mLogicalModel->mText.Clear();
-    ClearModelData();
     mImpl->mVisualModel->SetTextColor( mImpl->mEventData->mPlaceholderTextColor );
 
     // Convert text into UTF-32
@@ -2517,6 +2556,9 @@ void Controller::ShowPlaceholderText()
     const Length characterCount = Utf8ToUtf32( utf8, size, utf32Characters.Begin() );
     utf32Characters.Resize( characterCount );
 
+    // The characters to be added.
+    mImpl->mTextUpdateInfo.mNumberOfCharactersToAdd = characterCount;
+
     // Reset the cursor position
     mImpl->mEventData->mPrimaryCursorPosition = 0;
 
@@ -2531,32 +2573,12 @@ void Controller::ShowPlaceholderText()
   }
 }
 
-void Controller::ClearModelData()
-{
-  // n.b. This does not Clear the mText from mLogicalModel
-  mImpl->mLogicalModel->mScriptRuns.Clear();
-  mImpl->mLogicalModel->mFontRuns.Clear();
-  mImpl->mLogicalModel->mLineBreakInfo.Clear();
-  mImpl->mLogicalModel->mWordBreakInfo.Clear();
-  mImpl->mLogicalModel->mBidirectionalParagraphInfo.Clear();
-  mImpl->mLogicalModel->mCharacterDirections.Clear();
-  mImpl->mLogicalModel->mBidirectionalLineInfo.Clear();
-  mImpl->mLogicalModel->mLogicalToVisualMap.Clear();
-  mImpl->mLogicalModel->mVisualToLogicalMap.Clear();
-  mImpl->mVisualModel->mGlyphs.Clear();
-  mImpl->mVisualModel->mGlyphsToCharacters.Clear();
-  mImpl->mVisualModel->mCharactersToGlyph.Clear();
-  mImpl->mVisualModel->mCharactersPerGlyph.Clear();
-  mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
-  mImpl->mVisualModel->mGlyphPositions.Clear();
-  mImpl->mVisualModel->mLines.Clear();
-  mImpl->mVisualModel->mColorRuns.Clear();
-  mImpl->mVisualModel->ClearCaches();
-}
-
 void Controller::ClearFontData()
 {
-  mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
+  if( mImpl->mFontDefaults )
+  {
+    mImpl->mFontDefaults->mFontId = 0u; // Remove old font ID
+  }
   mImpl->mLogicalModel->mFontRuns.Clear();
   mImpl->mVisualModel->mGlyphs.Clear();
   mImpl->mVisualModel->mGlyphsToCharacters.Clear();
index 7e22134..546389c 100644 (file)
@@ -115,6 +115,13 @@ public:
   void EnableTextInput( DecoratorPtr decorator );
 
   /**
+   * @brief Used to switch between bitmap & vector based glyphs
+   *
+   * @param[in] glyphType The type of glyph; note that metrics for bitmap & vector based glyphs are different.
+   */
+  void SetGlyphType( TextAbstraction::GlyphType glyphType );
+
+  /**
    * @brief Enables/disables the mark-up processor.
    *
    * By default is disabled.
@@ -769,11 +776,6 @@ private:
   void ShowPlaceholderText();
 
   /**
-   * @brief Helper to clear all the model data except for LogicalModel::mText.
-   */
-  void ClearModelData();
-
-  /**
    * @brief Helper to clear font-specific data (only).
    */
   void ClearFontData();
index d57b2ec..130c8af 100644 (file)
@@ -181,19 +181,28 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
         GlyphIndex lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
 
         // Add the alignment offset to the glyph's position.
+
+        float penY = line->ascender;
         for( Length index = 0u; index < numberOfLaidOutGlyphs; ++index )
         {
-          ( *( glyphPositions + index ) ).x += line->alignmentOffset;
+          Vector2& position =  *( glyphPositions + index );
+          position.x += line->alignmentOffset;
+          position.y += penY;
 
           if( lastGlyphIndexOfLine == index )
           {
+            penY += -line->descender;
+
             // Get the next line.
             ++lineIndex;
 
             if( lineIndex < numberOfLines )
             {
               line = lineBuffer + lineIndex;
+
               lastGlyphIndexOfLine = line->glyphRun.glyphIndex + line->glyphRun.numberOfGlyphs - 1u;
+
+              penY += line->ascender;
             }
           }
         }
index 5a76197..1cee6e1 100644 (file)
@@ -275,13 +275,14 @@ void CubeTransitionEffect::OnStageConnection( int depth )
   Geometry geometry = CreateQuadGeometry();
   Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
 
-  Material material = Material::New( shader );
+  TextureSet textureSet = TextureSet::New();
 
   if( mCurrentImage )
   {
-    material.AddTexture( mCurrentImage, "sTexture" );
+    textureSet.SetImage( 0u, mCurrentImage );
   }
-  mCurrentRenderer = Renderer::New( geometry, material );
+  mCurrentRenderer = Renderer::New( geometry, shader );
+  mCurrentRenderer.SetTextures( textureSet );
 
   mCurrentRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depth );
   Self().AddRenderer( mCurrentRenderer );
@@ -340,20 +341,10 @@ bool CubeTransitionEffect::IsTransitioning()
 void CubeTransitionEffect::SetCurrentImage( Image image )
 {
   mCurrentImage = image;
-
   if( mCurrentRenderer )
   {
-    Material material = mCurrentRenderer.GetMaterial();
-
-    int index = material.GetTextureIndex("sTexture" );
-    if( index != -1 )
-    {
-      material.SetTextureImage( index, mCurrentImage );
-    }
-    else
-    {
-      material.AddTexture( mCurrentImage, "sTexture" );
-    }
+    TextureSet textureSet = mCurrentRenderer.GetTextures();
+    textureSet.SetImage( 0u, mCurrentImage );
   }
 }
 
@@ -363,8 +354,8 @@ void CubeTransitionEffect::SetTargetImage( Image image )
 
   if( mTargetRenderer )
   {
-    Material material = mTargetRenderer.GetMaterial();
-    material.AddTexture( mTargetImage, "sTexture" );
+    TextureSet textureSet = mTargetRenderer.GetTextures();
+    textureSet.SetImage( 0u, mTargetImage );
   }
 }
 
@@ -390,13 +381,15 @@ void CubeTransitionEffect::StartTransition( Vector2 panPosition, Vector2 panDisp
   }
 
   //create the target renderer
-  Material material = Material::New( mCurrentRenderer.GetMaterial().GetShader() );
+  TextureSet textureSet = TextureSet::New();
   if( mTargetImage )
   {
-    material.AddTexture( mTargetImage, "sTexture" );
+    textureSet.SetImage( 0u, mTargetImage );
   }
   Geometry geometry = mCurrentRenderer.GetGeometry();
-  mTargetRenderer = Renderer::New( geometry, material );
+  Shader shader( mCurrentRenderer.GetShader() );
+  mTargetRenderer = Renderer::New( geometry, shader );
+  mTargetRenderer.SetTextures( textureSet );
 
   int depthIndex = mCurrentRenderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX);
   mTargetRenderer.SetProperty( Dali::Renderer::Property::DEPTH_INDEX, depthIndex );
diff --git a/dali-toolkit/po/ar.po b/dali-toolkit/po/ar.po
new file mode 100755 (executable)
index 0000000..a31e003
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "اختيار الكل"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "نسخ"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "اختيار"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "قص"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "لصق"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "الحافظة"
+
diff --git a/dali-toolkit/po/az.po b/dali-toolkit/po/az.po
new file mode 100755 (executable)
index 0000000..6581e52
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Hamısını seç"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Köçür"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Göndər"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Kəs"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Yapışdır"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Mübadilə buferi"
+
diff --git a/dali-toolkit/po/bg.po b/dali-toolkit/po/bg.po
new file mode 100755 (executable)
index 0000000..52a2d78
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Избери всички"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Копиране"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Избери"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Отрежи"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Поставяне"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Системен буфер"
+
diff --git a/dali-toolkit/po/ca.po b/dali-toolkit/po/ca.po
new file mode 100755 (executable)
index 0000000..34c6125
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Seleccioni-ho tot"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copia"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Selec."
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Tallar"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Enganxar"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Porta-retalls"
+
diff --git a/dali-toolkit/po/cs.po b/dali-toolkit/po/cs.po
new file mode 100755 (executable)
index 0000000..c8c68f9
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Vybrat vše"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopírovat"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Vybrat"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Vyjmout"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Vložit"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Schránka"
+
diff --git a/dali-toolkit/po/da.po b/dali-toolkit/po/da.po
new file mode 100755 (executable)
index 0000000..0898d64
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Vælg alle"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiér"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Vælg"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Klip"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Indsæt"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Udklipsholder"
+
diff --git a/dali-toolkit/po/de.po b/dali-toolkit/po/de.po
new file mode 100755 (executable)
index 0000000..3082bbb
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Alle auswählen"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopieren"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Auswählen"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Ausschneiden"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Einfügen"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Zwischenablage"
+
diff --git a/dali-toolkit/po/el_GR.po b/dali-toolkit/po/el_GR.po
new file mode 100755 (executable)
index 0000000..8f93b05
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Επιλογή όλων"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Αντιγραφή"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Επιλογή"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Αποκοπή"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Επικόλληση"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Πρόχειρο"
+
diff --git a/dali-toolkit/po/en.po b/dali-toolkit/po/en.po
new file mode 100755 (executable)
index 0000000..2579c1c
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Select all"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copy"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Select"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cut"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Paste"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Clipboard"
+
diff --git a/dali-toolkit/po/en_PH.po b/dali-toolkit/po/en_PH.po
new file mode 100755 (executable)
index 0000000..2579c1c
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Select all"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copy"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Select"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cut"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Paste"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Clipboard"
+
diff --git a/dali-toolkit/po/en_US.po b/dali-toolkit/po/en_US.po
new file mode 100755 (executable)
index 0000000..2579c1c
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Select all"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copy"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Select"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cut"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Paste"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Clipboard"
+
diff --git a/dali-toolkit/po/es_ES.po b/dali-toolkit/po/es_ES.po
new file mode 100755 (executable)
index 0000000..5fed085
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Seleccionar todo"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copiar"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Seleccionar"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cortar"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Pegar"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Portapapeles"
+
diff --git a/dali-toolkit/po/es_US.po b/dali-toolkit/po/es_US.po
new file mode 100755 (executable)
index 0000000..fdb40d8
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Todo"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copiar"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Seleccionar"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cortar"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Pegar"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Portapapeles"
+
diff --git a/dali-toolkit/po/et.po b/dali-toolkit/po/et.po
new file mode 100755 (executable)
index 0000000..361b88a
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Vali kõik"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopeeri"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Vali"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Lõika"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Kleebi"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Lõikelaud"
+
diff --git a/dali-toolkit/po/eu.po b/dali-toolkit/po/eu.po
new file mode 100755 (executable)
index 0000000..86fe6e5
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Hautatu denak"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiatu"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Aukeratu"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Moztu"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Itsatsi"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Arbela"
+
diff --git a/dali-toolkit/po/fi.po b/dali-toolkit/po/fi.po
new file mode 100755 (executable)
index 0000000..fd23422
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Valitse kaikki"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopioi"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Valitse"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Poimi"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Liitä"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Leikepöytä"
+
diff --git a/dali-toolkit/po/fr.po b/dali-toolkit/po/fr.po
new file mode 100755 (executable)
index 0000000..e217eef
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Sélect. tout"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copie"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Sélect."
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Couper"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Coller"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Presse-papier"
+
diff --git a/dali-toolkit/po/fr_CA.po b/dali-toolkit/po/fr_CA.po
new file mode 100755 (executable)
index 0000000..0a8fdd2
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Sélectionner tout"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copier"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Sélectionner"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Couper"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Coller"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Presse-papier"
+
diff --git a/dali-toolkit/po/ga.po b/dali-toolkit/po/ga.po
new file mode 100755 (executable)
index 0000000..99328c5
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Roghnaigh gach"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Cóipeáil"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Roghnaigh"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Gearr"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Greamaigh"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Gearrthaisce"
+
diff --git a/dali-toolkit/po/gl.po b/dali-toolkit/po/gl.po
new file mode 100755 (executable)
index 0000000..3e66cbf
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Seleccionar todo"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copiar"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Selecc."
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cortar"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Pegar"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Portapapeis"
+
diff --git a/dali-toolkit/po/hi.po b/dali-toolkit/po/hi.po
new file mode 100755 (executable)
index 0000000..1892408
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "सभी चुनें"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "कॉपी करें"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "चुनें"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "काटें"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "पेस्ट करें"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "क्लिपबोर्ड"
+
diff --git a/dali-toolkit/po/hr.po b/dali-toolkit/po/hr.po
new file mode 100755 (executable)
index 0000000..6c8a251
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Odaberi sve"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiraj"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Odaberi"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Izreži"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Zalijepi"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Međuspremnik"
+
diff --git a/dali-toolkit/po/hu.po b/dali-toolkit/po/hu.po
new file mode 100755 (executable)
index 0000000..accab91
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Összes kijelölése"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Másol"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Választ"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Kivág"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Beilleszt"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Vágólap"
+
diff --git a/dali-toolkit/po/hy.po b/dali-toolkit/po/hy.po
new file mode 100755 (executable)
index 0000000..9892948
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Ընտրել բոլորը"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Պատճենել"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Ընտրել"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Կտրել"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Տեղադրել"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Գզրոց"
+
diff --git a/dali-toolkit/po/is.po b/dali-toolkit/po/is.po
new file mode 100755 (executable)
index 0000000..bd1952e
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Velja allt"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Afrita"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Velja"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Klippa"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Líma"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Klippiborð"
+
diff --git a/dali-toolkit/po/it_IT.po b/dali-toolkit/po/it_IT.po
new file mode 100755 (executable)
index 0000000..f68a4f9
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Seleziona tutto"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copia"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Seleziona"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Taglia"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Incolla"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Appunti"
+
diff --git a/dali-toolkit/po/ja_JP.po b/dali-toolkit/po/ja_JP.po
new file mode 100755 (executable)
index 0000000..4cea292
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "全て選択"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "コピー"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "選択"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "切り取り"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "貼り付け"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "クリップボード"
+
diff --git a/dali-toolkit/po/ka.po b/dali-toolkit/po/ka.po
new file mode 100755 (executable)
index 0000000..5dd6d53
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "ყველას არჩევა"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "ასლი"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "არჩევა"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "მოჭრა"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "ჩასმა"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "ბუფერული მეხს."
+
diff --git a/dali-toolkit/po/kk.po b/dali-toolkit/po/kk.po
new file mode 100755 (executable)
index 0000000..6de1a32
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Бәрін бөлектеу"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Көшіру"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Таңдау"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Кесу"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Қою"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Буфер"
+
diff --git a/dali-toolkit/po/ko_KR.po b/dali-toolkit/po/ko_KR.po
new file mode 100755 (executable)
index 0000000..8ecb8d3
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "모두 선택"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "복사"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "선택"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "잘라내기"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "붙여넣기"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "클립보드"
+
diff --git a/dali-toolkit/po/lt.po b/dali-toolkit/po/lt.po
new file mode 100755 (executable)
index 0000000..d403fcc
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Pasirinkti visus"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopijuoti"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Rinktis"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Iškirpti"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Įklijuoti"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Iškarpinė"
+
diff --git a/dali-toolkit/po/lv.po b/dali-toolkit/po/lv.po
new file mode 100755 (executable)
index 0000000..519597b
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Izv. visu"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopēt"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Atlasīt"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Izgriezt"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Ielīmēt"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Starpliktuve"
+
diff --git a/dali-toolkit/po/mk.po b/dali-toolkit/po/mk.po
new file mode 100755 (executable)
index 0000000..d12d533
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Избери ги сите"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Копирај"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Избери"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Исечи"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Пресликај"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Посредна меморија"
+
diff --git a/dali-toolkit/po/nb.po b/dali-toolkit/po/nb.po
new file mode 100755 (executable)
index 0000000..0c15456
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Merk alt"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopier"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Velg"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Klipp ut"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Lim inn"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Utklippstavle"
+
diff --git a/dali-toolkit/po/nl.po b/dali-toolkit/po/nl.po
new file mode 100755 (executable)
index 0000000..48645c4
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Selecteer alles"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopieer"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Select."
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Knippen"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Plakken"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Klembord"
+
diff --git a/dali-toolkit/po/pl.po b/dali-toolkit/po/pl.po
new file mode 100755 (executable)
index 0000000..c87ec62
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Zaznacz wszystko"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiuj"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Wybierz"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Wytnij"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Wklej"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Schowek"
+
diff --git a/dali-toolkit/po/pt_BR.po b/dali-toolkit/po/pt_BR.po
new file mode 100755 (executable)
index 0000000..9c6743a
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Selecionar tudo"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copiar"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Selecionar"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cortar"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Colar"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Área de transferência"
+
diff --git a/dali-toolkit/po/pt_PT.po b/dali-toolkit/po/pt_PT.po
new file mode 100755 (executable)
index 0000000..e1a21da
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Seleccionar tudo"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copiar"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Selec."
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Cortar"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Colar"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Área transferência"
+
diff --git a/dali-toolkit/po/ro.po b/dali-toolkit/po/ro.po
new file mode 100755 (executable)
index 0000000..0d78703
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Selectare toate"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Copiere"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Selectare"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Decupare"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Lipire"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Clipboard"
+
diff --git a/dali-toolkit/po/ru_RU.po b/dali-toolkit/po/ru_RU.po
new file mode 100755 (executable)
index 0000000..8134f66
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Выделить все"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Копировать"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Выделить"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Вырезать"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Вставить"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Буфер обмена"
+
diff --git a/dali-toolkit/po/sk.po b/dali-toolkit/po/sk.po
new file mode 100755 (executable)
index 0000000..1944646
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Vybrať všetky"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopírovať"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Vybrať"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Vystrihnúť"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Vložiť"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Schránka"
+
diff --git a/dali-toolkit/po/sl.po b/dali-toolkit/po/sl.po
new file mode 100755 (executable)
index 0000000..4c8ad23
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Izberi vse"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiraj"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Izberi"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Izreži"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Prilepi"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Odložišče"
+
diff --git a/dali-toolkit/po/sr.po b/dali-toolkit/po/sr.po
new file mode 100755 (executable)
index 0000000..1be1832
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Izaberi sve"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiraj"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Izaberi"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Iseci"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Zalepi"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Privremena memorija"
+
diff --git a/dali-toolkit/po/sv.po b/dali-toolkit/po/sv.po
new file mode 100755 (executable)
index 0000000..13c587d
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Välj alla"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopiera"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Välj"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Klipp ut"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Klistra in"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Urklipp"
+
diff --git a/dali-toolkit/po/tr_TR.po b/dali-toolkit/po/tr_TR.po
new file mode 100755 (executable)
index 0000000..a360194
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Hepsini seç"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Kopyala"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Seç"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Kes"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Yapıştır"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Pano"
+
diff --git a/dali-toolkit/po/uk.po b/dali-toolkit/po/uk.po
new file mode 100755 (executable)
index 0000000..c41b559
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Вибрати всі"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Копіювати"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Вибрати"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Вирізати"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Вставити"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Буфер обміну"
+
diff --git a/dali-toolkit/po/uz.po b/dali-toolkit/po/uz.po
new file mode 100755 (executable)
index 0000000..bcad8b0
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "Barchasini tanlash"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "Nusxa olish"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "Tanlash"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "Qirqish"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "Qo‘shib qo‘yish"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "Bufer"
+
diff --git a/dali-toolkit/po/zh_CN.po b/dali-toolkit/po/zh_CN.po
new file mode 100755 (executable)
index 0000000..b80e9d9
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "全选"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "复制"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "选择"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "剪切"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "粘贴"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "剪贴板"
+
diff --git a/dali-toolkit/po/zh_HK.po b/dali-toolkit/po/zh_HK.po
new file mode 100755 (executable)
index 0000000..338a38a
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "選擇全部"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "複製"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "選擇"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "剪下"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "貼上"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "剪貼板"
+
diff --git a/dali-toolkit/po/zh_TW.po b/dali-toolkit/po/zh_TW.po
new file mode 100755 (executable)
index 0000000..0980255
--- /dev/null
@@ -0,0 +1,18 @@
+msgid "IDS_COM_BODY_SELECT_ALL"
+msgstr "全選"
+
+msgid "IDS_COM_BODY_COPY"
+msgstr "複製"
+
+msgid "IDS_COM_SK_SELECT"
+msgstr "選擇"
+
+msgid "IDS_COM_BODY_CUT"
+msgstr "剪下"
+
+msgid "IDS_COM_BODY_PASTE"
+msgstr "貼上"
+
+msgid "IDS_COM_BODY_CLIPBOARD"
+msgstr "剪貼簿"
+
index cd04e07..e8af489 100644 (file)
@@ -79,6 +79,7 @@ public:
       OVERSHOOT_EFFECT_COLOR = PROPERTY_START_INDEX, ///< Property, name "overshootEffectColor",      @see SetOvershootEffectColor(),    type Vector4 @SINCE_1_0.0
       OVERSHOOT_ANIMATION_SPEED,                     ///< Property, name "overshootAnimationSpeed",   @see SetOvershootAnimationSpeed(), type float @SINCE_1_0.0
       OVERSHOOT_ENABLED,                             ///< Property, name "overshootEnabled",          @see SetOvershootEnabled(),        type bool,    @SINCE_1_1.18
+      OVERSHOOT_SIZE,                                ///< Property, name "overshootSize",                                                type Vector2, @SINCE_1_1.31
 
       // Animatable properties
       SCROLL_RELATIVE_POSITION = ANIMATABLE_PROPERTY_START_INDEX, ///< Property, name "scrollRelativePosition",   type Vector2 @SINCE_1_0.0
index ea5036c..f0197f0 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 30;
+const unsigned int TOOLKIT_MICRO_VERSION = 31;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 5640a83..97abfb8 100644 (file)
@@ -30,7 +30,8 @@ namespace Text
 // The type of text renderer required
 enum RenderingType
 {
-  RENDERING_SHARED_ATLAS ///< A bitmap-based solution where renderers can share a texture atlas @SINCE_1_0.0
+  RENDERING_SHARED_ATLAS, ///< A bitmap-based solution where renderers can share a texture atlas @SINCE_1_0.0
+  RENDERING_VECTOR_BASED  ///< A solution where glyphs are stored as vectors (scalable). Requires highp shader support. @SINCE_1_1.31
 };
 
 const unsigned int DEFAULT_RENDERING_BACKEND = RENDERING_SHARED_ATLAS;
index d29846d..a5925af 100644 (file)
@@ -89,8 +89,8 @@ add_library(dali_addon SHARED
   ${PLUGING_SRC_DIR}/render-tasks/render-task-wrapper.cpp
   ${PLUGING_SRC_DIR}/rendering/geometry-api.cpp
   ${PLUGING_SRC_DIR}/rendering/geometry-wrapper.cpp
-  ${PLUGING_SRC_DIR}/rendering/material-api.cpp
-  ${PLUGING_SRC_DIR}/rendering/material-wrapper.cpp
+  ${PLUGING_SRC_DIR}/rendering/texture-set-api.cpp
+  ${PLUGING_SRC_DIR}/rendering/texture-set-wrapper.cpp
   ${PLUGING_SRC_DIR}/rendering/renderer-api.cpp
   ${PLUGING_SRC_DIR}/rendering/renderer-wrapper.cpp
   ${PLUGING_SRC_DIR}/rendering/sampler-api.cpp
index c00ee57..da2e8eb 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    The OpenGLES Canvas Core Library Toolkit
-Version:    1.1.30
+Version:    1.1.31
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-2-Clause and MIT
@@ -13,6 +13,7 @@ Requires(postun): /sbin/ldconfig
 BuildRequires:  pkgconfig
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(dali-core)
+BuildRequires: gettext
 
 # dali-toolkit only need to know the interfaces(APIs) of dali-adaptor(the devel package).
 # It doesn't need to know which adaptor will be used by applications.
@@ -63,6 +64,16 @@ Application development package for the OpenGLES Canvas toolkit - headers and pa
 %define dali_toolkit_style_files    %{dali_data_ro_dir}/toolkit/styles/
 %define dev_include_path %{_includedir}
 
+# PO
+{
+cd %{_builddir}/dali-toolkit-%{version}/dali-toolkit/po
+for language in *.po
+do
+  language=${language%.po}
+  msgfmt -o ${language}.mo ${language}.po
+done
+} &> /dev/null
+
 ##############################
 # Build
 ##############################
@@ -91,6 +102,17 @@ cd build/tizen
 mkdir -p %{buildroot}/usr/share/license
 cp -af %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/usr/share/license/%{name}
 
+# PO
+{
+cd %{_builddir}/dali-toolkit-%{version}/dali-toolkit/po
+for language in *.mo
+do
+  language=${language%.mo}
+  mkdir -p %{buildroot}/%{_datadir}/locale/${language}/LC_MESSAGES/
+  cp ${language}.mo %{buildroot}/%{_datadir}/locale/${language}/LC_MESSAGES/dali-toolkit.mo
+done
+} &> /dev/null
+
 ##############################
 # Post Install
 ##############################
@@ -120,6 +142,7 @@ exit 0
 %{dali_toolkit_sound_files}/*
 %{dali_toolkit_style_files}/*
 %{_datadir}/license/%{name}
+%{_datadir}/locale/*/LC_MESSAGES/*
 
 %files devel
 %defattr(-,root,root,-)
index d648d9b..3c50077 100644 (file)
@@ -46,8 +46,8 @@ script_v8_plugin_src_files = \
    $(v8_plugin_dir)/render-tasks/render-task-wrapper.cpp \
    $(v8_plugin_dir)/rendering/geometry-api.cpp \
    $(v8_plugin_dir)/rendering/geometry-wrapper.cpp \
-   $(v8_plugin_dir)/rendering/material-api.cpp \
-   $(v8_plugin_dir)/rendering/material-wrapper.cpp \
+   $(v8_plugin_dir)/rendering/texture-set-api.cpp \
+   $(v8_plugin_dir)/rendering/texture-set-wrapper.cpp \
    $(v8_plugin_dir)/rendering/renderer-api.cpp \
    $(v8_plugin_dir)/rendering/renderer-wrapper.cpp \
    $(v8_plugin_dir)/rendering/sampler-api.cpp \
index e47285b..9459a46 100644 (file)
@@ -721,7 +721,7 @@ void ActorApi::ScaleBy( const v8::FunctionCallbackInfo<v8::Value>& args )
  * Add a renderer to this actor.
  * @example
  *
- *     var renderer = new dali.Renderer( geometry, material );
+ *     var renderer = new dali.Renderer( geometry, shader );
  *     actor.addRenderer( renderer );
  *
  * @for Actor
index 92719c7..ef9d285 100644 (file)
@@ -34,7 +34,7 @@
 #include <events/pan-gesture-detector-wrapper.h>
 #include <object/property-buffer-wrapper.h>
 #include <rendering/geometry-wrapper.h>
-#include <rendering/material-wrapper.h>
+#include <rendering/texture-set-wrapper.h>
 #include <rendering/renderer-wrapper.h>
 #include <rendering/shader-wrapper.h>
 #include <rendering/sampler-wrapper.h>
@@ -80,7 +80,7 @@ const ApiFunction ConstructorFunctionTable[]=
     { "ItemFactory",        ItemFactoryWrapper::NewItemFactory},
     { "Shader",             ShaderWrapper::NewShader},
     { "Sampler",            SamplerWrapper::NewSampler},
-    { "Material",           MaterialWrapper::NewMaterial},
+    { "TextureSet",         TextureSetWrapper::NewTextureSet},
     { "Geometry",           GeometryWrapper::NewGeometry},
     { "Renderer",           RendererWrapper::NewRenderer},
     { "PropertyBuffer",     PropertyBufferWrapper::NewPropertyBuffer},
index a7e2998..8469d7f 100644 (file)
@@ -675,6 +675,10 @@ Dali::Property::Value PropertyValueWrapper::ExtractPropertyValue( v8::Isolate* i
       {
         daliPropertyValue = Dali::Property::Value(  v8Value->Int32Value()  ) ;//static_cast<int>( V8Utils::GetNumberValue( isolate, v8Value) ));
       }
+      else if( V8Utils::IsStringPrimitiveOrObject( v8Value) ) // Take string as value for properties that internally convert the string to an enum
+      {
+        daliPropertyValue = Dali::Property::Value( V8Utils::GetStringValue( isolate, v8Value) );
+      }
       break;
     }
     case Dali::Property::STRING:
diff --git a/plugins/dali-script-v8/src/rendering/material-api.cpp b/plugins/dali-script-v8/src/rendering/material-api.cpp
deleted file mode 100644 (file)
index b21c376..0000000
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "material-api.h"
-
-// EXTERNAL INCLUDES
-#include <dali/public-api/object/type-registry.h>
-
-// INTERNAL INCLUDES
-#include <v8-utils.h>
-#include <rendering/material-wrapper.h>
-#include <rendering/shader-wrapper.h>
-#include <rendering/shader-api.h>
-#include <rendering/sampler-wrapper.h>
-#include <rendering/sampler-api.h>
-#include <image/image-wrapper.h>
-
-namespace Dali
-{
-
-namespace V8Plugin
-{
-
-/**
- * ## Material API
- *
- * Material is a handle to an object that specifies the visual properties of the renderer.
- *
- * @class Material
- * @extends Handle
- */
-
-Material MaterialApi::GetMaterial( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::HandleScope handleScope( isolate );
-
-  v8::Local<v8::Object> object = args.This();
-  v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
-  void* ptr = field->Value();
-
-  MaterialWrapper* wrapper = static_cast< MaterialWrapper *>(ptr);
-  return wrapper->GetMaterial();
-}
-
-Material MaterialApi::GetMaterialFromParams( int paramIndex,
-                                               bool& found,
-                                               v8::Isolate* isolate,
-                                               const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  found = false;
-
-  v8::HandleScope handleScope( isolate );
-  BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::MATERIAL, isolate, args );
-  if( wrappedObject )
-  {
-    found = true;
-    MaterialWrapper* wrapper = static_cast< MaterialWrapper *>(wrappedObject);
-    return wrapper->GetMaterial();
-  }
-  else
-  {
-    return Material();
-  }
-}
-
-/**
- * Create a new material object.
- *
- * @constructor
- * @method Material
- * @for Material
- * @param {Object} shader The shader used by the material
- * @return {Object} Material
- */
-Material MaterialApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  bool found( false );
-  Shader shader = ShaderApi::GetShaderFromParams( 0, found, isolate, args );
-  if( found )
-  {
-    return Material::New( shader );
-  }
-  else
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing shader from param 0" );
-    return Material();
-  }
-}
-
-/**
- * Set the Shader used by this material
- *
- * @method setShader
- * @for Material
- * @param {Object} shader Handle to the shader
- */
-void MaterialApi::SetShader( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  Shader shader = ShaderApi::GetShaderFromParams( 0, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid shader parameter" );
-  }
-  else
-  {
-    return material.SetShader( shader );
-  }
-}
-
-/**
- * Get the Shader used by this material
- *
- * @method getShader
- * @for Material
- * @return {Object} Shader
- */
-void MaterialApi::GetShader( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-  Shader shader = material.GetShader();
-
-  // Wrap the shader
-  v8::Local<v8::Object> localObject = ShaderWrapper::WrapShader( isolate, shader );
-  args.GetReturnValue().Set( localObject );
-}
-
-/**
- * Add a new texture to be used by the material
- *
- * @method addTexture
- * @for Material
- * @param {Object} image The image used by this sampler
- * @param {String} uniformName The string with the name of the uniform
- * @param {Object} sampler The sampler to add to this material
- * @return {integer} The index of the texture in the array of textures or -1 if texture can not be added
- */
-void MaterialApi::AddTexture( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  Image image = V8Utils::GetImageParameter( PARAMETER_0, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing image from param 0" );
-    return;
-  }
-
-  found = false;
-  std::string uniformName = V8Utils::GetStringParameter( PARAMETER_1, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing uniform name from param 1" );
-    return;
-  }
-
-  found = false;
-  Sampler sampler = SamplerApi::GetSamplerFromParams( PARAMETER_2, found, isolate, args );
-  if( !found )
-  {
-    args.GetReturnValue().Set( v8::Integer::New( isolate, material.AddTexture( image, uniformName ) ) );
-  }
-  else
-  {
-    args.GetReturnValue().Set( v8::Integer::New( isolate, material.AddTexture( image, uniformName, sampler ) ) );
-  }
-}
-
-/**
- * Removes a texture from the material
- *
- * @method removeTexture
- * @for Material
- * @param {integer} index The index of the texture in the array of textures
- */
-void MaterialApi::RemoveTexture( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
-  }
-  else
-  {
-    material.RemoveTexture( index );
-  }
-}
-
-/**
- * Sets the image to be used by a given texture
- * @method setTextureImage
- * @for Material
- * @param {integer} index The index of the texture in the array of textures
- * @param {Object} image The image used by this sampler
- */
-void MaterialApi::SetTextureImage( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
-    return;
-  }
-
-  found = false;
-  Image image = V8Utils::GetImageParameter( PARAMETER_1, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing image from param 1" );
-  }
-  else
-  {
-    material.SetTextureImage(index, image);
-  }
-}
-
-/**
- * Set the sampler used by a given texture
- * @method setTextureSampler
- * @for Material
- * @param {integer} index The index of the texture in the array of textures
- * @param {Object} sampler The new sampler
- */
-void MaterialApi::SetTextureSampler( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
-    return;
-  }
-
-  found = false;
-  Sampler sampler = SamplerApi::GetSamplerFromParams( PARAMETER_1, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing sampler from param 1" );
-  }
-  else
-  {
-    material.SetTextureSampler(index, sampler);
-  }
-}
-
-/**
- * Set the uniform name of a given texture
- * @method setTextureUniformName
- * @for Material
- * @param {integer} index The index of the texture in the array of textures
- * @param {string} uniformName The new uniform name
- */
-void MaterialApi::SetTextureUniformName( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
-    return;
-  }
-
-  found = false;
-  std::string uniformName = V8Utils::GetStringParameter( PARAMETER_1, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid uniform name parameter" );
-  }
-  else
-  {
-    material.SetTextureUniformName(index, uniformName);
-  }
-}
-
-/**
- * Retrive the index of a texture given its uniform name
- * @method getTextureIndex
- * @for Material
- * @param {string} uniformName The uniform name
- * @return {integer} The index in the array of textures or -1 if the texture is not found
- */
-void MaterialApi::GetTextureIndex( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  bool found( false );
-  std::string uniformName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate, args );
-  if( !found )
-  {
-    DALI_SCRIPT_EXCEPTION( isolate, "invalid uniform name parameter" );
-  }
-  else
-  {
-    args.GetReturnValue().Set( v8::Integer::New( isolate, material.GetTextureIndex(uniformName) ) );
-  }
-}
-
-/**
- * Retrieve the number of textures used by the material
- *
- * @method getNumberOfTextures
- * @for Material
- * @return {integer} The number of textures
- */
-void MaterialApi::GetNumberOfTextures( const v8::FunctionCallbackInfo< v8::Value >& args )
-{
-  v8::Isolate* isolate = args.GetIsolate();
-  v8::HandleScope handleScope( isolate );
-
-  Material material = GetMaterial( isolate, args );
-
-  args.GetReturnValue().Set( v8::Integer::New( isolate, material.GetNumberOfTextures() ) );
-}
-
-} // namespace V8Plugin
-
-} // namespace Dali
diff --git a/plugins/dali-script-v8/src/rendering/material-api.h b/plugins/dali-script-v8/src/rendering/material-api.h
deleted file mode 100644 (file)
index 6cf64a0..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#ifndef __DALI_V8PLUGIN_MATERIAL_API_H__
-#define __DALI_V8PLUGIN_MATERIAL_API_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 <v8.h>
-#include <dali/devel-api/rendering/material.h>
-
-
-namespace Dali
-{
-
-namespace V8Plugin
-{
-
-namespace MaterialApi
-{
-
-  /**
-   * Helper to get material from args.This()
-   */
-  Material GetMaterial( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args );
-
-  /**
-   * @brief Helper to get material from the JavaScript object held in the given function argument
-   * @param[in] paramIndex Argument index the object is held in
-   * @param[in] found Whether material is found in the given function parameter
-   * @param[in] isolate v8 isolated instance
-   * @param[in] args v8 function call arguments interpreted
-   */
-  Material GetMaterialFromParams( int paramIndex,
-                                     bool& found,
-                                     v8::Isolate* isolate,
-                                     const v8::FunctionCallbackInfo< v8::Value >& args );
-
-  /**
-   * Constructor
-   */
-   Material New( const v8::FunctionCallbackInfo< v8::Value >& args );
-
-   /**
-    * Material API see material.h for a description
-    */
-   void SetShader( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void GetShader( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void AddTexture( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void RemoveTexture( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void SetTextureImage( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void SetTextureSampler( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void SetTextureUniformName( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void GetTextureIndex( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void GetNumberOfTextures( const v8::FunctionCallbackInfo< v8::Value >& args );
-
-}; // namespace MaterialApi
-
-} // namespace V8Plugin
-
-} // namespace Dali
-
-#endif // header __DALI_V8PLUGIN_MATERIAL_API_H__
diff --git a/plugins/dali-script-v8/src/rendering/material-wrapper.h b/plugins/dali-script-v8/src/rendering/material-wrapper.h
deleted file mode 100644 (file)
index 45e11ec..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef __DALI_V8PLUGIN_MATERIAL_WRAPPER_H__
-#define __DALI_V8PLUGIN_MATERIAL_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 <v8.h>
-#include <dali/devel-api/rendering/material.h>
-
-// INTERNAL INCLUDES
-#include <object/handle-wrapper.h>
-
-namespace Dali
-{
-
-namespace V8Plugin
-{
-
-
-/**
- * A Material wrapper.
- * Provides access to Material specific functionality and V8 memory handling.
- */
-class MaterialWrapper : public HandleWrapper
-{
-
-public:
-
-  /**
-   * @brief Constructor
-   * @param[in] material DALi material
-   * @param[in] gc garbage collection interface
-   */
-  MaterialWrapper( const Material& material,
-                GarbageCollectorInterface& gc );
-
-  /**
-   * @brief Destructor
-   */
-  virtual ~MaterialWrapper()
-  {
-  };
-
-  /**
-   * @brief Creates a new Material wrapped inside a Javascript Object.
-   * @param[in] args v8 function call arguments interpreted
-   */
-  static void NewMaterial( const v8::FunctionCallbackInfo< v8::Value >& args);
-
-  /**
-   * Wraps a sampler
-   */
-  static v8::Handle<v8::Object> WrapMaterial(v8::Isolate* isolate, const Dali::Material& );
-
-
-  // The MaterialAttribute ObjectTemplate, we cache templates so we don't have
-  // keep generating them everytime we want to create a Material
-  static v8::Persistent<v8::ObjectTemplate> mMaterialTemplate;
-
-  /**
-   * @brief Gets the handle of material
-   * @return the handle of material
-   */
-  Material GetMaterial();
-
-
-private:
-
-  // Material
-  Material mMaterial;
-
-  /**
-   * @brief Creates the object template that used to create material at runtime
-   * @param[in] isolate v8 isolated instance
-   * @return the object template
-   */
-  static v8::Handle<v8::ObjectTemplate> MakeMaterialTemplate( v8::Isolate* isolate );
-
-  /**
-   * @brief Gets the object template that used to create material at runtime
-   * @param[in] isolate v8 isolated instance
-   * @return the object template
-   */
-  static v8::Local<v8::ObjectTemplate> GetMaterialTemplate( v8::Isolate* isolate );
-
-};
-
-} // namespace V8Plugin
-
-} // namespace Dali
-
-#endif // __DALI_V8PLUGIN_MATERIAL_WRAPPER_H__
index 2ec736d..5efcd94 100644 (file)
@@ -27,8 +27,9 @@
 #include <rendering/renderer-wrapper.h>
 #include <rendering/geometry-api.h>
 #include <rendering/geometry-wrapper.h>
-#include <rendering/material-api.h>
-#include <rendering/material-wrapper.h>
+#include <rendering/texture-set-api.h>
+#include <rendering/texture-set-wrapper.h>
+#include <rendering/shader-api.h>
 
 namespace Dali
 {
@@ -85,7 +86,7 @@ Renderer RendererApi::GetRendererFromParams( int paramIndex,
  * @method Renderer
  * @for Renderer
  * @param {Object} geometry The geometry to be used by this renderer
- * @param {Object} material The material to be used by this renderer
+ * @param {Object} shader The shader to be used by this renderer
  * @return {Object} Renderer
  */
 Renderer RendererApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
@@ -102,14 +103,14 @@ Renderer RendererApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
   }
 
   found = false;
-  Material material = MaterialApi::GetMaterialFromParams( 1, found, isolate, args );
+  Shader shader = ShaderApi::GetShaderFromParams( 1, found, isolate, args );
   if( !found )
   {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing material from param 0" );
+    DALI_SCRIPT_EXCEPTION( isolate, "missing shader from param 0" );
     return Renderer();
   }
 
-  return Renderer::New(geometry, material);
+  return Renderer::New(geometry, shader);
 }
 
 /**
@@ -159,13 +160,13 @@ void RendererApi::GetGeometry( const v8::FunctionCallbackInfo<v8::Value>& args )
 }
 
 /**
- * Sets the material to be used by this renderer
+ * Sets the texture set to be used by this renderer
  *
- * @method setMaterial
+ * @method setTextures
  * @for Renderer
- * @param {Object} material The material to be used by this renderer
+ * @param {Object} textureSet The TextureSet to be used by this renderer
  */
-void RendererApi::SetMaterial( const v8::FunctionCallbackInfo< v8::Value >& args )
+void RendererApi::SetTextures( const v8::FunctionCallbackInfo< v8::Value >& args )
 {
   v8::Isolate* isolate = args.GetIsolate();
   v8::HandleScope handleScope( isolate );
@@ -173,34 +174,34 @@ void RendererApi::SetMaterial( const v8::FunctionCallbackInfo< v8::Value >& args
   Renderer renderer = GetRenderer( isolate, args );
 
   bool found( false );
-  Material material = MaterialApi::GetMaterialFromParams( 0, found, isolate, args );
+  TextureSet textureSet = TextureSetApi::GetTextureSetFromParams( 0, found, isolate, args );
   if( !found )
   {
-    DALI_SCRIPT_EXCEPTION( isolate, "missing material from param 0" );
+    DALI_SCRIPT_EXCEPTION( isolate, "missing texture set from param 0" );
   }
   else
   {
-    renderer.SetMaterial(material);
+    renderer.SetTextures(textureSet);
   }
 }
 
 /**
- * Gets the material used by this renderer
+ * Gets the texture set used by this renderer
  *
- * @method getMaterial
+ * @method getTextures
  * @for Renderer
- * @return {Object} The material used by this renderer
+ * @return {Object} The texture set used by this renderer
  */
-void RendererApi::GetMaterial( const v8::FunctionCallbackInfo<v8::Value>& args )
+void RendererApi::GetTextures( const v8::FunctionCallbackInfo<v8::Value>& args )
 {
   v8::Isolate* isolate = args.GetIsolate();
   v8::HandleScope handleScope( isolate );
 
   Renderer renderer = GetRenderer( isolate, args );
-  Material material = renderer.GetMaterial();
+  TextureSet textureSet = renderer.GetTextures();
 
-  // Wrap the material
-  v8::Local<v8::Object> localObject = MaterialWrapper::WrapMaterial( isolate, material );
+  // Wrap the textureset
+  v8::Local<v8::Object> localObject = TextureSetWrapper::WrapTextureSet( isolate, textureSet );
   args.GetReturnValue().Set( localObject );
 }
 
index 50e1874..f44eeb8 100644 (file)
@@ -59,8 +59,8 @@ namespace RendererApi
     */
    void SetGeometry( const v8::FunctionCallbackInfo< v8::Value >& args );
    void GetGeometry( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void SetMaterial( const v8::FunctionCallbackInfo< v8::Value >& args );
-   void GetMaterial( const v8::FunctionCallbackInfo< v8::Value >& args );
+   void SetTextures( const v8::FunctionCallbackInfo< v8::Value >& args );
+   void GetTextures( const v8::FunctionCallbackInfo< v8::Value >& args );
    void SetBlendFunc( const v8::FunctionCallbackInfo< v8::Value >& args );
    void GetBlendFunc( const v8::FunctionCallbackInfo< v8::Value >& args );
    void SetBlendEquation( const v8::FunctionCallbackInfo< v8::Value >& args );
index 3286b10..75bc2d3 100644 (file)
@@ -47,8 +47,8 @@ const ApiFunction RendererFunctionTable[]=
 
    { "SetGeometry"             , RendererApi::SetGeometry },
    { "GetGeometry"             , RendererApi::GetGeometry },
-   { "SetMaterial"             , RendererApi::SetMaterial },
-   { "GetMaterial"             , RendererApi::GetMaterial },
+   { "SetTextures"             , RendererApi::SetTextures },
+   { "GetTextures"             , RendererApi::GetTextures },
    { "SetBlendFunc"            , RendererApi::SetBlendFunc },
    { "GetBlendFunc"            , RendererApi::GetBlendFunc },
    { "SetBlendEquation"        , RendererApi::SetBlendEquation },
diff --git a/plugins/dali-script-v8/src/rendering/texture-set-api.cpp b/plugins/dali-script-v8/src/rendering/texture-set-api.cpp
new file mode 100644 (file)
index 0000000..30d8d47
--- /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 "texture-set-api.h"
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+#include <v8-utils.h>
+#include <rendering/texture-set-wrapper.h>
+#include <rendering/shader-wrapper.h>
+#include <rendering/shader-api.h>
+#include <rendering/sampler-wrapper.h>
+#include <rendering/sampler-api.h>
+#include <image/image-wrapper.h>
+
+namespace Dali
+{
+
+namespace V8Plugin
+{
+
+/**
+ * ## TextureSet API
+ *
+ * TextureSet is a handle to an object that contains the textures used by a renderer
+ *
+ * @class TextureSet
+ * @extends Handle
+ */
+
+TextureSet TextureSetApi::GetTextureSet( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args )
+{
+  v8::HandleScope handleScope( isolate );
+
+  v8::Local<v8::Object> object = args.This();
+  v8::Local<v8::External> field = v8::Local<v8::External>::Cast( object->GetInternalField(0) );
+  void* ptr = field->Value();
+
+  TextureSetWrapper* wrapper = static_cast< TextureSetWrapper *>(ptr);
+  return wrapper->GetTextureSet();
+}
+
+TextureSet TextureSetApi::GetTextureSetFromParams( int paramIndex,
+                                               bool& found,
+                                               v8::Isolate* isolate,
+                                               const v8::FunctionCallbackInfo< v8::Value >& args )
+{
+  found = false;
+
+  v8::HandleScope handleScope( isolate );
+  BaseWrappedObject* wrappedObject = V8Utils::GetWrappedDaliObjectParameter( paramIndex, BaseWrappedObject::TEXTURE_SET, isolate, args );
+  if( wrappedObject )
+  {
+    found = true;
+    TextureSetWrapper* wrapper = static_cast< TextureSetWrapper *>(wrappedObject);
+    return wrapper->GetTextureSet();
+  }
+  else
+  {
+    return TextureSet();
+  }
+}
+
+/**
+ * Create a new texture set object.
+ *
+ * @constructor
+ * @method TextureSet
+ * @for TextureSet
+ * @return {Object} TextureSet
+ */
+TextureSet TextureSetApi::New( const v8::FunctionCallbackInfo< v8::Value >& args )
+{
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope handleScope( isolate );
+  return TextureSet();
+}
+
+
+/**
+ * Sets the image to be used by a given texture
+ * @method setImage
+ * @for TextureSet
+ * @param {integer} index The index of the texture in the array of textures
+ * @param {Object} image The image used by this sampler
+ */
+void TextureSetApi::SetImage( const v8::FunctionCallbackInfo< v8::Value >& args )
+{
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope handleScope( isolate );
+
+  TextureSet textureSet = GetTextureSet( isolate, args );
+
+  bool found( false );
+  int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
+  if( !found )
+  {
+    DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
+    return;
+  }
+
+  found = false;
+  Image image = V8Utils::GetImageParameter( PARAMETER_1, found, isolate, args );
+  if( !found )
+  {
+    DALI_SCRIPT_EXCEPTION( isolate, "missing image from param 1" );
+  }
+  else
+  {
+    textureSet.SetImage(index, image);
+  }
+}
+
+/**
+ * Set the sampler used by a given texture
+ * @method setSampler
+ * @for TextureSet
+ * @param {integer} index The index of the texture in the array of textures
+ * @param {Object} sampler The new sampler
+ */
+void TextureSetApi::SetSampler( const v8::FunctionCallbackInfo< v8::Value >& args )
+{
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope handleScope( isolate );
+
+  TextureSet textureSet = GetTextureSet( isolate, args );
+
+  bool found( false );
+  int index = V8Utils::GetIntegerParameter( PARAMETER_0, found, isolate, args, 0 /* default */);
+  if( !found )
+  {
+    DALI_SCRIPT_EXCEPTION( isolate, "invalid index parameter" );
+    return;
+  }
+
+  found = false;
+  Sampler sampler = SamplerApi::GetSamplerFromParams( PARAMETER_1, found, isolate, args );
+  if( !found )
+  {
+    DALI_SCRIPT_EXCEPTION( isolate, "missing sampler from param 1" );
+  }
+  else
+  {
+    textureSet.SetSampler(index, sampler);
+  }
+}
+
+} // namespace V8Plugin
+
+} // namespace Dali
diff --git a/plugins/dali-script-v8/src/rendering/texture-set-api.h b/plugins/dali-script-v8/src/rendering/texture-set-api.h
new file mode 100644 (file)
index 0000000..c5dc357
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __DALI_V8PLUGIN_TEXURE_SET_API_H__
+#define __DALI_V8PLUGIN_TEXURE_SET_API_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <v8.h>
+#include <dali/devel-api/rendering/texture-set.h>
+
+
+namespace Dali
+{
+
+namespace V8Plugin
+{
+
+namespace TextureSetApi
+{
+
+  /**
+   * Helper to get TextureSet from args.This()
+   */
+  TextureSet GetTextureSet( v8::Isolate* isolate, const v8::FunctionCallbackInfo< v8::Value >& args );
+
+  /**
+   * @brief Helper to get texture set from the JavaScript object held in the given function argument
+   * @param[in] paramIndex Argument index the object is held in
+   * @param[in] found Whether texture set is found in the given function parameter
+   * @param[in] isolate v8 isolated instance
+   * @param[in] args v8 function call arguments interpreted
+   */
+  TextureSet GetTextureSetFromParams( int paramIndex,
+                                     bool& found,
+                                     v8::Isolate* isolate,
+                                     const v8::FunctionCallbackInfo< v8::Value >& args );
+
+  /**
+   * Constructor
+   */
+  TextureSet New( const v8::FunctionCallbackInfo< v8::Value >& args );
+
+   /**
+    * TextureSet API see texture-set.h for a description
+    */
+   void SetImage( const v8::FunctionCallbackInfo< v8::Value >& args );
+   void SetSampler( const v8::FunctionCallbackInfo< v8::Value >& args );
+
+}; // namespace TextureSetApi
+
+} // namespace V8Plugin
+
+} // namespace Dali
+
+#endif // header __DALI_V8PLUGIN_TEXURE_SET_API_H__
  */
 
 // CLASS HEADER
-#include "material-wrapper.h"
+#include "texture-set-wrapper.h"
 
 // INTERNAL INCLUDES
 #include <v8-utils.h>
-#include <rendering/material-api.h>
+#include <rendering/texture-set-api.h>
 #include <shared/api-function.h>
 #include <shared/object-template-helper.h>
 #include <dali-wrapper.h>
@@ -31,7 +31,7 @@ namespace Dali
 namespace V8Plugin
 {
 
-v8::Persistent<v8::ObjectTemplate> MaterialWrapper::mMaterialTemplate;
+v8::Persistent<v8::ObjectTemplate> TextureSetWrapper::mTextureSetTemplate;
 
 namespace // un-named name space
 {
@@ -39,45 +39,38 @@ namespace // un-named name space
 /**
  * Contains a list of all functions that can be called
  */
-const ApiFunction MaterialFunctionTable[]=
+const ApiFunction TextureSetFunctionTable[]=
 {
     /**************************************
-    * Material API (in order of Material.h)
+    * TextureSet API (in order of texture-set.h)
     **************************************/
 
-   { "SetShader"                       , MaterialApi::SetShader },
-   { "GetShader"                       , MaterialApi::GetShader },
-   { "AddTexture"                      , MaterialApi::AddTexture },
-   { "RemoveTexture"                   , MaterialApi::RemoveTexture },
-   { "SetTextureImage"                 , MaterialApi::SetTextureImage },
-   { "SetTextureSampler"               , MaterialApi::SetTextureSampler },
-   { "SetTextureUniformName"           , MaterialApi::SetTextureUniformName },
-   { "GetTextureIndex"                 , MaterialApi::GetTextureIndex },
-   { "GetNumberOfTextures"             , MaterialApi::GetNumberOfTextures },
+   { "SetImage"                        , TextureSetApi::SetImage },
+   { "SetSampler"                      , TextureSetApi::SetSampler },
 };
 
-const unsigned int MaterialFunctionTableCount = sizeof(MaterialFunctionTable)/sizeof(MaterialFunctionTable[0]);
+const unsigned int TextureSetFunctionTableCount = sizeof(TextureSetFunctionTable)/sizeof(TextureSetFunctionTable[0]);
 } //un-named space
 
 
-MaterialWrapper::MaterialWrapper( const Dali::Material& material, GarbageCollectorInterface& gc )
-:  HandleWrapper(  BaseWrappedObject::MATERIAL , material, gc )
+TextureSetWrapper::TextureSetWrapper( const Dali::TextureSet& textureSet, GarbageCollectorInterface& gc )
+:  HandleWrapper(  BaseWrappedObject::TEXTURE_SET , textureSet, gc )
 {
-    mMaterial = material;
+    mTextureSet = textureSet;
 }
 
-v8::Handle<v8::Object> MaterialWrapper::WrapMaterial(v8::Isolate* isolate, const Dali::Material& material )
+v8::Handle<v8::Object> TextureSetWrapper::WrapTextureSet(v8::Isolate* isolate, const Dali::TextureSet& textureSet )
 {
   v8::EscapableHandleScope handleScope( isolate );
   v8::Local<v8::ObjectTemplate> objectTemplate;
 
-  objectTemplate = GetMaterialTemplate( isolate);
+  objectTemplate = GetTextureSetTemplate( isolate);
 
   // create an instance of the template
   v8::Local<v8::Object> localObject = objectTemplate->NewInstance();
 
-  // create the Material wrapper
-  MaterialWrapper* pointer =  new MaterialWrapper( material, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
+  // create the texture set wrapper
+  TextureSetWrapper* pointer =  new TextureSetWrapper( textureSet, Dali::V8Plugin::DaliWrapper::Get().GetDaliGarbageCollector() );
 
   // assign the JavaScript object to the wrapper.
   pointer->SetJavascriptObject( isolate, localObject );
@@ -85,25 +78,25 @@ v8::Handle<v8::Object> MaterialWrapper::WrapMaterial(v8::Isolate* isolate, const
   return handleScope.Escape( localObject );
 }
 
-v8::Local<v8::ObjectTemplate> MaterialWrapper::GetMaterialTemplate( v8::Isolate* isolate)
+v8::Local<v8::ObjectTemplate> TextureSetWrapper::GetTextureSetTemplate( v8::Isolate* isolate)
 {
   v8::EscapableHandleScope handleScope( isolate );
   v8::Local<v8::ObjectTemplate> objectTemplate;
 
-  if( mMaterialTemplate.IsEmpty() )
+  if( mTextureSetTemplate.IsEmpty() )
   {
-    objectTemplate = MakeMaterialTemplate( isolate );
-    mMaterialTemplate.Reset( isolate, objectTemplate );
+    objectTemplate = MakeTextureSetTemplate( isolate );
+    mTextureSetTemplate.Reset( isolate, objectTemplate );
   }
   else
   {
     // get the object template
-    objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, mMaterialTemplate );
+    objectTemplate = v8::Local<v8::ObjectTemplate>::New( isolate, mTextureSetTemplate );
   }
   return handleScope.Escape( objectTemplate );
 }
 
-v8::Handle<v8::ObjectTemplate> MaterialWrapper::MakeMaterialTemplate( v8::Isolate* isolate )
+v8::Handle<v8::ObjectTemplate> TextureSetWrapper::MakeTextureSetTemplate( v8::Isolate* isolate )
 {
   v8::EscapableHandleScope handleScope( isolate );
 
@@ -115,34 +108,34 @@ v8::Handle<v8::ObjectTemplate> MaterialWrapper::MakeMaterialTemplate( v8::Isolat
   objTemplate->SetInternalFieldCount( BaseWrappedObject::FIELD_COUNT );
 
   // add our function properties
-  ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, MaterialFunctionTable, MaterialFunctionTableCount );
+  ObjectTemplateHelper::InstallFunctions( isolate, objTemplate, TextureSetFunctionTable, TextureSetFunctionTableCount );
 
   return handleScope.Escape( objTemplate );
 }
 
-void MaterialWrapper::NewMaterial( const v8::FunctionCallbackInfo< v8::Value >& args)
+void TextureSetWrapper::NewTextureSet( const v8::FunctionCallbackInfo< v8::Value >& args)
 {
   v8::Isolate* isolate = args.GetIsolate();
   v8::HandleScope handleScope( isolate);
 
   if(!args.IsConstructCall())
   {
-      DALI_SCRIPT_EXCEPTION( isolate, "Material constructor called without 'new'");
+      DALI_SCRIPT_EXCEPTION( isolate, "TextureSet constructor called without 'new'");
       return;
   }
-  Dali::Material material = MaterialApi::New( args );
+  Dali::TextureSet textureSet = TextureSetApi::New( args );
 
-  if(material)
+  if(textureSet)
   {
-    v8::Local<v8::Object> localObject = WrapMaterial( isolate, material );
+    v8::Local<v8::Object> localObject = WrapTextureSet( isolate, textureSet );
     args.GetReturnValue().Set( localObject );
   }
 }
 
 
-Material MaterialWrapper::GetMaterial()
+TextureSet TextureSetWrapper::GetTextureSet()
 {
-  return mMaterial;
+  return mTextureSet;
 }
 
 
diff --git a/plugins/dali-script-v8/src/rendering/texture-set-wrapper.h b/plugins/dali-script-v8/src/rendering/texture-set-wrapper.h
new file mode 100644 (file)
index 0000000..5826bbf
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __DALI_V8PLUGIN_TEXTURE_SET_WRAPPER_H__
+#define __DALI_V8PLUGIN_TEXTURE_SET_WRAPPER_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <v8.h>
+#include <dali/devel-api/rendering/texture-set.h>
+
+// INTERNAL INCLUDES
+#include <object/handle-wrapper.h>
+
+namespace Dali
+{
+
+namespace V8Plugin
+{
+
+
+/**
+ * A TextureSet wrapper.
+ * Provides access to TextureSet specific functionality and V8 memory handling.
+ */
+class TextureSetWrapper : public HandleWrapper
+{
+
+public:
+
+  /**
+   * @brief Constructor
+   * @param[in] textureSet DALi TextureSet
+   * @param[in] gc garbage collection interface
+   */
+  TextureSetWrapper( const TextureSet& textureSet,
+                GarbageCollectorInterface& gc );
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~TextureSetWrapper()
+  {
+  };
+
+  /**
+   * @brief Creates a new TextureSet wrapped inside a Javascript Object.
+   * @param[in] args v8 function call arguments interpreted
+   */
+  static void NewTextureSet( const v8::FunctionCallbackInfo< v8::Value >& args);
+
+  /**
+   * Wraps a TextureSet
+   */
+  static v8::Handle<v8::Object> WrapTextureSet(v8::Isolate* isolate, const Dali::TextureSet& );
+
+
+  // The TextureSetAttribute ObjectTemplate, we cache templates so we don't have
+  // keep generating them everytime we want to create a TextureSet
+  static v8::Persistent<v8::ObjectTemplate> mTextureSetTemplate;
+
+  /**
+   * @brief Gets the handle of TextureSet
+   * @return the handle of the TextureSet
+   */
+  TextureSet GetTextureSet();
+
+
+private:
+
+  // TextureSet
+  TextureSet mTextureSet;
+
+  /**
+   * @brief Creates the object template that used to create TextureSets at runtime
+   * @param[in] isolate v8 isolated instance
+   * @return the object template
+   */
+  static v8::Handle<v8::ObjectTemplate> MakeTextureSetTemplate( v8::Isolate* isolate );
+
+  /**
+   * @brief Gets the object template that used to create TextureSets at runtime
+   * @param[in] isolate v8 isolated instance
+   * @return the object template
+   */
+  static v8::Local<v8::ObjectTemplate> GetTextureSetTemplate( v8::Isolate* isolate );
+
+};
+
+} // namespace V8Plugin
+
+} // namespace Dali
+
+#endif // __DALI_V8PLUGIN_TEXTURE_SET_WRAPPER_H__
index 0efc17e..4cdc867 100644 (file)
@@ -88,7 +88,7 @@ public:
       TIMER,
       SHADER,
       SAMPLER,
-      MATERIAL,
+      TEXTURE_SET,
       GEOMETRY,
       RENDERER,
       PROPERTY_BUFFER,