[dali_1.1.15] Merge branch 'devel/master' 29/55429/1
authorAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 23 Dec 2015 17:22:31 +0000 (17:22 +0000)
committerAdeel Kazmi <adeel.kazmi@samsung.com>
Wed, 23 Dec 2015 17:22:31 +0000 (17:22 +0000)
Change-Id: I6c9392da70d5f18179af2e6fc93bca24153d2a72

79 files changed:
automated-tests/src/dali-toolkit/utc-Dali-Builder.cpp
automated-tests/src/dali-toolkit/utc-Dali-Control.cpp
automated-tests/src/dali-toolkit/utc-Dali-SuperBlurView.cpp
automated-tests/src/dali-toolkit/utc-Dali-TextField.cpp
dali-toolkit/devel-api/controls/super-blur-view/super-blur-view.h
dali-toolkit/devel-api/shader-effects/bendy-effect.h
dali-toolkit/devel-api/shader-effects/carousel-effect.h
dali-toolkit/devel-api/shader-effects/dissolve-local-effect.h
dali-toolkit/devel-api/shader-effects/image-region-effect.h
dali-toolkit/devel-api/shader-effects/iris-effect.h
dali-toolkit/devel-api/shader-effects/mirror-effect.h
dali-toolkit/devel-api/shader-effects/ripple-effect.h
dali-toolkit/devel-api/shader-effects/ripple2d-effect.h
dali-toolkit/devel-api/shader-effects/shear-effect.h
dali-toolkit/devel-api/shader-effects/soft-button-effect.h
dali-toolkit/devel-api/shader-effects/spot-effect.h
dali-toolkit/devel-api/shader-effects/swirl-effect.h
dali-toolkit/internal/controls/bloom-view/bloom-view-impl.cpp
dali-toolkit/internal/controls/bloom-view/bloom-view-impl.h
dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.cpp
dali-toolkit/internal/controls/gaussian-blur-view/gaussian-blur-view-impl.h
dali-toolkit/internal/controls/page-turn-view/page-turn-book-spine-effect.h
dali-toolkit/internal/controls/page-turn-view/page-turn-effect.cpp
dali-toolkit/internal/controls/popup/popup-impl.cpp
dali-toolkit/internal/controls/popup/popup-impl.h
dali-toolkit/internal/controls/renderers/image/image-renderer.cpp
dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.cpp
dali-toolkit/internal/controls/super-blur-view/super-blur-view-impl.h
dali-toolkit/internal/controls/text-controls/text-field-impl.cpp
dali-toolkit/internal/controls/text-controls/text-selection-popup-impl.cpp
dali-toolkit/internal/controls/text-controls/text-selection-toolbar-impl.cpp
dali-toolkit/internal/file.list
dali-toolkit/internal/focus-manager/keyboard-focus-manager-impl.cpp
dali-toolkit/internal/text/character-set-conversion.cpp
dali-toolkit/internal/text/character-set-conversion.h
dali-toolkit/internal/text/color-run.h [new file with mode: 0644]
dali-toolkit/internal/text/color-segmentation.cpp [new file with mode: 0644]
dali-toolkit/internal/text/color-segmentation.h [new file with mode: 0644]
dali-toolkit/internal/text/decorator/text-decorator.cpp
dali-toolkit/internal/text/input-style.h [new file with mode: 0644]
dali-toolkit/internal/text/logical-model-impl.cpp
dali-toolkit/internal/text/logical-model-impl.h
dali-toolkit/internal/text/markup-processor-color.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-color.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-helper-functions.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor-helper-functions.h [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor.cpp [new file with mode: 0644]
dali-toolkit/internal/text/markup-processor.h [new file with mode: 0644]
dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager-impl.cpp
dali-toolkit/internal/text/rendering/atlas/atlas-manager.h
dali-toolkit/internal/text/rendering/atlas/text-atlas-renderer.cpp
dali-toolkit/internal/text/segmentation.cpp
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-style-run-container.h [new file with mode: 0644]
dali-toolkit/internal/text/text-view-interface.h
dali-toolkit/internal/text/text-view.cpp
dali-toolkit/internal/text/text-view.h
dali-toolkit/internal/text/visual-model-impl.h
dali-toolkit/public-api/controls/control-impl.cpp
dali-toolkit/public-api/controls/control-impl.h
dali-toolkit/public-api/controls/control.h
dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h
dali-toolkit/public-api/controls/image-view/image-view.cpp
dali-toolkit/public-api/controls/text-controls/text-field.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec
plugins/dali-script-v8/docs/content/actor.js
plugins/dali-script-v8/docs/content/animation.js
plugins/dali-script-v8/docs/content/keyboard-focus-manager.js
plugins/dali-script-v8/docs/content/pan-gesture-detector.js
plugins/dali-script-v8/docs/content/resource-image.js
plugins/dali-script-v8/docs/content/stage.js
plugins/dali-script-v8/src/actors/actor-wrapper.cpp
plugins/dali-script-v8/src/actors/layer-api.cpp
plugins/dali-script-v8/src/actors/layer-api.h
plugins/dali-script-v8/src/shared/object-template-helper.cpp

index 653325c..deb3727 100644 (file)
@@ -948,7 +948,7 @@ int UtcDaliBuilderShaderEffectP(void)
     "        \"vertexPrefix\": \"\",\n"
     "        \"vertex\": \"void main(void)\\n{\\n  gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n  vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
     "        \"fragmentPrefix\": \"\",\n"
-    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = uTextureRect.zw - uTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
     "        \"geometryType\": \"GEOMETRY_TYPE_IMAGE\"\n"
     "      },\n"
     "      \"geometryHints\": \"HINT_NONE\",\n"
@@ -1058,7 +1058,7 @@ int UtcDaliBuilderShaderEffect2P(void)
     "        \"vertexPrefix\": \"\",\n"
     "        \"vertex\": \"void main(void)\\n{\\n  gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n  vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
     "        \"fragmentPrefix\": \"\",\n"
-    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = uTextureRect.zw - uTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
     "        \"geometryType\": \"GEOMETRY_TYPE_IMAGE\"\n"
     "      },\n"
     "      \"geometryHints\": \"HINT_NONE\",\n"
@@ -1241,7 +1241,7 @@ int UtcDaliBuilderFrameBufferP(void)
     "        \"vertexPrefix\": \"\",\n"
     "        \"vertex\": \"void main(void)\\n{\\n  gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n  vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
     "        \"fragmentPrefix\": \"\",\n"
-    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = uTextureRect.zw - uTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
     "        \"geometryType\": \"GEOMETRY_TYPE_IMAGE\"\n"
     "      },\n"
     "      \"geometryHints\": \"HINT_NONE\",\n"
@@ -1412,7 +1412,7 @@ int UtcDaliBuilderPathConstraintsP(void)
     "        \"vertexPrefix\": \"\",\n"
     "        \"vertex\": \"void main(void)\\n{\\n  gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\\n  vTexCoord = aTexCoord;\\n}\\n\\n\",\n"
     "        \"fragmentPrefix\": \"\",\n"
-    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
+    "        \"fragment\": \"precision mediump float;\\nuniform float uAmplitude; // 0.02; (< 1)\\nuniform float uTime;\\nvoid main()\\n{\\n  highp vec2 textureSize = uTextureRect.zw - uTextureRect.xy;\\n  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\\n  highp float len = length(pos);\\n  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude; \\n  gl_FragColor = texture2D(sTexture, texCoord) * uColor;\\n}\\n\\n\\n\",\n"
     "        \"geometryType\": \"GEOMETRY_TYPE_IMAGE\"\n"
     "      },\n"
     "      \"geometryHints\": \"HINT_NONE\",\n"
index 9f220de..de50f8c 100644 (file)
@@ -400,6 +400,8 @@ int UtcDaliControlBackgroundColor(void)
   DALI_TEST_CHECK( resultMap->Find( "blendColor" ) );
   DALI_TEST_CHECK( resultMap->Find( "blendColor" )->Get<Vector4>() == Color::RED );
 
+  DALI_TEST_EQUALS( control.GetBackgroundColor(), Color::RED, TEST_LOCATION );
+
   control.SetBackgroundColor( Color::YELLOW );
 
   propValue = control.GetProperty( Control::Property::BACKGROUND );
@@ -407,6 +409,8 @@ int UtcDaliControlBackgroundColor(void)
   DALI_TEST_CHECK( resultMap->Find( "blendColor" ) );
   DALI_TEST_CHECK( resultMap->Find( "blendColor" )->Get<Vector4>() == Color::YELLOW );
 
+  DALI_TEST_EQUALS( control.GetBackgroundColor(), Color::YELLOW, TEST_LOCATION );
+
   END_TEST;
 }
 
index de9a7d5..97592d7 100644 (file)
@@ -146,13 +146,17 @@ int UtcDaliSuperBlurViewSetImage(void)
   tet_infoline(" UtcDaliSuperBlurViewSetImage ");
 
   SuperBlurView blurView = SuperBlurView::New( BLUR_LEVELS );
-  // create image actors for the original image and each blurred image
-  DALI_TEST_CHECK( blurView.GetChildCount() == BLUR_LEVELS+1 );
+  blurView.SetSize( 100.f, 100.f );
 
   Image inputImage = CreateSolidColorImage( application, Color::GREEN, 50, 50 );
   blurView.SetImage( inputImage );
   // start multiple guassian blur call, each guassian blur creates two render tasks
-  DALI_TEST_CHECK( Stage::GetCurrent().GetRenderTaskList().GetTaskCount() ==  BLUR_LEVELS*2 + 1);
+  DALI_TEST_CHECK( Stage::GetCurrent().GetRenderTaskList().GetTaskCount() == 1+BLUR_LEVELS*2);
+
+  // create image actors for the original image and each blurred image
+  Stage::GetCurrent().Add( blurView );
+  Wait(application);
+  DALI_TEST_EQUALS(blurView.GetRendererCount(), BLUR_LEVELS+1, TEST_LOCATION );
   END_TEST;
 }
 
@@ -212,7 +216,7 @@ int UtcDaliSuperBlurViewGetBlurredImage(void)
   DALI_TEST_EQUALS( image2.GetHeight(), 25u, TEST_LOCATION );
 
   Image image3 = blurView.GetBlurredImage( 3 );
-  DALI_TEST_CHECK( FrameBufferImage::DownCast( image2 ) );
+  DALI_TEST_CHECK( FrameBufferImage::DownCast( image3 ) );
 
   END_TEST;
 }
index b6f5c71..b0e4269 100644 (file)
@@ -668,7 +668,7 @@ int utcDaliTextFieldEvent02(void)
   DALI_TEST_EQUALS( layer.GetChildCount(), 1u, TEST_LOCATION ); // The cursor.
   DALI_TEST_EQUALS( offscreenRoot.GetChildCount(), 2u, TEST_LOCATION ); // The camera actor and the renderer
 
-  ImageActor cursor = ImageActor::DownCast( layer.GetChildAt( 0u ) );
+  Control cursor = Control::DownCast( layer.GetChildAt( 0u ) );
   DALI_TEST_CHECK( cursor );
 
   CameraActor camera = CameraActor::DownCast( offscreenRoot.GetChildAt( 0u ) );
index ab9ec44..f63ddd5 100644 (file)
@@ -44,7 +44,7 @@ class SuperBlurView;
  *  Stage::GetCurrent().Add(blurView);\n
  *
  *  // Set the input image
- *  Image image = Image::New(...);\n
+ *  ResourceImage image = ResourceImage::New(...);\n
  *  blurView.SetImage(image);\n
  *
  *  // animate the strength of the blur - this can fade between no blur and full blur. .\n
index 71ed07c..9f9deb5 100644 (file)
@@ -52,7 +52,7 @@ inline ShaderEffect CreateBendyEffect()
       "void main()\n"
       "{\n"
       " mediump float lighting = 0.25;\n"
-      " mediump vec4 position = uModelView * vec4(aPosition,1.0);\n"
+      " mediump vec4 position = uModelView * vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
       "\n"
       " mediump vec2 d = position.xy - uCenter;\n"
       " mediump float dist = max( 0.0, dot(d,uDirection) );\n"
@@ -70,7 +70,7 @@ inline ShaderEffect CreateBendyEffect()
       "\n"
       "vShade = 1.0 - abs(sn) * lighting;\n"
       "\n"
-      "vTexCoord = aTexCoord;\n"
+      "vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
       "}" );
 
   std::string fragmentShader(
index dfe7018..67180bd 100644 (file)
@@ -63,14 +63,14 @@ inline ShaderEffect CreateCarouselEffect()
                 "\n"
                 "void main()\n"
                 "{\n"
-                "    mediump vec4 world = uModelView * vec4(aPosition,1.0);\n"
+                "    mediump vec4 world = uModelView * vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
                 "    mediump vec2 d = (world.xy - uCenter) * uAnglePerUnit;\n"
                 "    mediump float a = length(d);\n"
                 "    mediump float cs = cos(radians(a));\n"
                 "    world.z -= cs * uRadius;\n"
                 "    gl_Position = uProjection * world;\n"
                 "    \n"
-                "    vTexCoord = aTexCoord;\n"
+                "    vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
                 "}\n");
 
     ShaderEffect shaderEffect = ShaderEffect::New(
index 3a244fc..c91abdc 100644 (file)
@@ -54,7 +54,7 @@ inline ShaderEffect CreateDissolveLocalEffect( unsigned int numberOfDimples )
       "varying float vPercentage;\n"
       "void main()\n"
       "{\n"
-      "  vec4 position = uModelView * vec4( aPosition, 1.0 );\n"
+      "  vec4 position = uModelView * vec4( aPosition*uSize.xy, 0.0,  1.0 );\n"
       "  float percentage = 0.0;\n"
       "  for( int i=0; i<NUMBER_OF_DIMPLE; ++i )\n"
       "  {\n"
@@ -63,7 +63,7 @@ inline ShaderEffect CreateDissolveLocalEffect( unsigned int numberOfDimples )
       "  }\n"
       "  vPercentage = clamp( percentage, 0.0, 1.0 );\n"
       "  gl_Position = uProjection * position;\n"
-      "  vTexCoord = aTexCoord;\n"
+      "  vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
       "}\n");
   vertexShaderStringStream << vertexShader;
 
index 7d263d9..4f3f3f1 100644 (file)
@@ -59,10 +59,10 @@ inline Property::Map CreateImageRegionEffect()
       "  position.xyz *= uSize;\n"
       "  gl_Position = uMvpMatrix * position;\n"
       // The line below is doing the same as the following commented lines:
-      //"  vec2 imageSize = sTextureRect.zw - sTextureRect.xy;\n"
-      //"  vec2 topLeft = sTextureRect.xy + uTopLeft * imageSize;\n"
-      //"  vec2 bottomRight = sTextureRect.xy + uBottomRight * imageSize;\n"
-      //"  vec2 texCoord = (aTexCoord - sTextureRect.xy) / imageSize;\n"
+      //"  vec2 imageSize = uTextureRect.zw - uTextureRect.xy;\n"
+      //"  vec2 topLeft = uTextureRect.xy + uTopLeft * imageSize;\n"
+      //"  vec2 bottomRight = uTextureRect.xy + uBottomRight * imageSize;\n"
+      //"  vec2 texCoord = (aTexCoord - uTextureRect.xy) / imageSize;\n"
       //"  vTexCoord = topLeft + texCoord * ( bottomRight - topLeft );\n"
 
       "  vec2 texCoord = aPosition + vec2(0.5);\n"
index 2304748..48e6f11 100644 (file)
@@ -55,11 +55,11 @@ inline ShaderEffect CreateIrisEffect()
       "\n"
       "void main()\n"
       "{\n"
-      "    mediump vec4 world = uModelView * vec4(aPosition,1.0);\n"
+      "    mediump vec4 world = uModelView * vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
       "    gl_Position = uProjection * world;\n"
       "    \n"
-      "    vTexCoord = aTexCoord;\n"
-      "    vRelativePosition = aTexCoord - uCenter;\n"
+      "    vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );;\n"
+      "    vRelativePosition = vTexCoord - uCenter;\n"
       "}\n");
 
   std::string fragmentShader(
index 06eb019..edf7ffd 100644 (file)
@@ -43,11 +43,11 @@ inline ShaderEffect CreateMirrorEffect()
   std::string vertexShader(
       "void main()                                  \n"
       "{                                            \n"
-      "  mediump vec3 pos = aPosition;              \n"
+      "  mediump vec3 pos = vec3(aPosition, 0.0)*uSize;              \n"
       "  pos.y = pos.y * 3.0;                       \n"
       "  mediump vec4 world = uModelView * vec4(pos,1.0); \n"
       "  gl_Position = uProjection * world;         \n"
-      "  vTexCoord = aTexCoord;                     \n"
+      "  vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) ); \n"
       "}                                            \n" );
 
   std::string fragmentShader(
index 39d0a13..dd71982 100644 (file)
@@ -52,7 +52,7 @@ inline ShaderEffect CreateRippleEffect()
       "{\n"
       "float lighting = uAmplitude * 0.02;\n"
       "float waveLength = uAmplitude * 0.0016;\n"
-      "vec4 world = uModelView * vec4(aPosition,1.0);\n"
+      "vec4 world = uModelView * vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
       "vec2 d = vec2(world.x - uCenter.x, world.y - uCenter.y);\n"
       "float dist = length(d);\n"
       "float amplitude = cos(uTime - dist*waveLength);\n"
@@ -67,7 +67,7 @@ inline ShaderEffect CreateRippleEffect()
       "}\n"
       "vShade = 1.0 - (dot * slope);\n"
       "vLight = max(0.0, dot * -slope);\n"
-      "vTexCoord = aTexCoord;\n"
+      "vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
       "}" );
 
   // append the default version
index cbef85b..782c440 100644 (file)
@@ -47,7 +47,7 @@ inline ShaderEffect CreateRipple2DEffect()
       "uniform float uTime;\n"
       "void main()\n"
       "{\n"
-      "  highp vec2 textureSize = sTextureRect.zw - sTextureRect.xy;\n"
+      "  highp vec2 textureSize = uTextureRect.zw - uTextureRect.xy;\n"
       "  highp vec2 pos = -1.0 + 2.0 * vTexCoord.st/textureSize;\n"
       "  highp float len = length(pos);\n"
       "  highp vec2 texCoord = vTexCoord.st/textureSize + pos/len * sin( len * 12.0 - uTime * 4.0 ) * uAmplitude;\n"
index edea72e..5b8faf9 100644 (file)
@@ -49,14 +49,14 @@ inline ShaderEffect CreateShearEffect()
       "\n"
       "void main()\n"
       "{\n"
-      "mediump vec4 world = uModelView * vec4(aPosition,1.0);\n"
+      "mediump vec4 world = uModelView * vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
       "\n"
       "world.x = world.x + tan(radians(uAngleXAxis)) * (world.y - uCenter.y * world.w);\n"
       "world.y = world.y + tan(radians(uAngleYAxis)) * (world.x - uCenter.x * world.w);\n"
       "\n"
       "gl_Position = uProjection * world;\n"
       "\n"
-      "vTexCoord = aTexCoord;\n"
+      "vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
       "}" );
 
   // Create the implementation, temporarily owned on stack,
index 710537e..55adafb 100644 (file)
@@ -117,11 +117,11 @@ inline ShaderEffect CreateSoftButtonEffect(SoftButtonEffectType type)
 
       "void main()\n"
       "{\n"
-      "  vTexCoord = aTexCoord;\n"
+      "  vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
       // Get the rect coords of the effect region in -1..1 range, i.e. circle centred around the center of the rect
       // Done in the vertex shader itself to make use of gl interpolation for varying.
       "  vCentredCoord = vec2( ( (vTexCoord.x - uEffectRegion.x)/(uEffectRegion.z - uEffectRegion.x) * 2.0 - 1.0 ), ( (vTexCoord.y - uEffectRegion.y)/(uEffectRegion.w - uEffectRegion.y) * 2.0 - 1.0  ) );\n"
-      "  gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
+      "  gl_Position = uMvpMatrix * vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
       "}\n";
 
   std::string fragmentSourceFixed;
index 7880421..2cff9ee 100644 (file)
@@ -48,7 +48,7 @@ inline ShaderEffect CreateSpotEffect()
       "\n"
       "void main()\n"
       "{\n"
-      "  mediump vec4 world = vec4(aPosition, 1.0);\n"
+      "  mediump vec4 world = vec4(aPosition*uSize.xy, 0.0, 1.0);\n"
       "  \n"
       "  mediump vec2 d = vec2(world.xy - uCenter);\n"
       "  mediump float dist = length(d);\n"
@@ -57,7 +57,7 @@ inline ShaderEffect CreateSpotEffect()
       "  vRange = max(0.1, range);\n"
       "  \n"
       "  gl_Position = uMvpMatrix * world;\n"
-      "  vTexCoord = aTexCoord;\n"
+      "  vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;\n"
       "}");
 
   std::string fragmentShader(
index 020b320..3c8b36f 100644 (file)
@@ -50,7 +50,7 @@ inline ShaderEffect CreateSwirlEffect( bool warp )
       "uniform mediump vec2  uCenter;\n"
       "void main()\n"
       "{\n"
-      "  highp vec2 textureCenter = (sTextureRect.xy + sTextureRect.zw) * 0.5;\n"
+      "  highp vec2 textureCenter = (uTextureRect.xy + uTextureRect.zw) * 0.5;\n"
       "  textureCenter = vTexCoord.st - textureCenter;\n"
       "  highp float distance = length(textureCenter);\n"
       "  if (distance >= uRadius)\n"
index eab906c..3c6dca4 100644 (file)
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/devel-api/object/type-registry-helper.h>
 #include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/devel-api/rendering/renderer.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
@@ -81,23 +83,33 @@ 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
 //
 
 const char* const BLOOM_EXTRACT_FRAGMENT_SOURCE =
-  "uniform float uBloomThreshold;\n"
-  "uniform float uRecipOneMinusBloomThreshold;\n"
+  "varying mediump vec2 vTexCoord;\n"
+  "uniform sampler2D sTexture;\n"
+  "uniform lowp vec4 uColor;\n"
+  "uniform mediump float uBloomThreshold;\n"
+  "uniform mediump float uRecipOneMinusBloomThreshold;\n"
   "void main()\n"
   "{\n"
   "  mediump vec4 col;\n"
-  "  col = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y));\n"
+  "  col = texture2D(sTexture, vTexCoord);\n"
   "  col = (col - uBloomThreshold) * uRecipOneMinusBloomThreshold;\n" // remove intensities lower than the thresold and remap intensities above the threshold to [0..1]
   "  gl_FragColor = clamp(col, 0.0, 1.0);\n"
   "}\n";
 
 const char* const COMPOSITE_FRAGMENT_SOURCE =
+  "precision mediump float;\n"
+  "varying mediump vec2 vTexCoord;\n"
+  "uniform sampler2D sTexture;\n"
+  "uniform sampler2D sEffect;\n"
+  "uniform lowp vec4 uColor;\n"
   "uniform float uBloomIntensity;\n"
   "uniform float uImageIntensity;\n"
   "uniform float uBloomSaturation;\n"
@@ -113,8 +125,8 @@ const char* const COMPOSITE_FRAGMENT_SOURCE =
   "{\n"
   "  mediump vec4 image;\n"
   "  mediump vec4 bloom;\n"
-  "  image = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y));\n"
-  "  bloom = texture2D(sEffect, vec2(vTexCoord.x, vTexCoord.y));\n"
+  "  image = texture2D(sTexture, vTexCoord);\n"
+  "  bloom = texture2D(sEffect, vTexCoord);\n"
   "  image = ChangeSaturation(image, uImageSaturation) * uImageIntensity;\n"
   "  bloom = ChangeSaturation(bloom, uBloomSaturation) * uBloomIntensity;\n"
   "  image *= 1.0 - clamp(bloom, 0.0, 1.0);\n" // darken base where bloom is strong, to prevent excessive burn-out of result
@@ -143,6 +155,7 @@ BloomView::BloomView()
   , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
   , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
   , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
+  , mActivated( false )
 {
 }
 
@@ -165,6 +178,7 @@ BloomView::BloomView( const unsigned int blurNumSamples, const float blurBellCur
   , mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
   , mImageIntensityPropertyIndex(Property::INVALID_INDEX)
   , mImageSaturationPropertyIndex(Property::INVALID_INDEX)
+  , mActivated( false )
 {
 }
 
@@ -228,34 +242,32 @@ void BloomView::OnInitialize()
   mChildrenRoot.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
 
   //////////////////////////////////////////////////////
-  // Create shaders
-
-  // Create shader used for extracting the bright parts of an image
-  mBloomExtractShader = ShaderEffect::New( "", BLOOM_EXTRACT_FRAGMENT_SOURCE );
-
-  // Create shader used to composite bloom and original image to output render target
-  mCompositeShader = ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE );
-
-
-  //////////////////////////////////////////////////////
   // Create actors
 
   // Create an ImageActor for rendering from the scene texture to the bloom texture
-  mBloomExtractImageActor = ImageActor::New();
+  mBloomExtractImageActor = Toolkit::ImageView::New();
   mBloomExtractImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mBloomExtractImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
-  mBloomExtractImageActor.SetShaderEffect( mBloomExtractShader );
+
+  // Create shader used for extracting the bright parts of an image
+  Property::Map customShader;
+  customShader[ "fragmentShader" ] = BLOOM_EXTRACT_FRAGMENT_SOURCE;
+  Property::Map rendererMap;
+  rendererMap.Insert( "rendererType", "imageRenderer" );
+  rendererMap.Insert( "shader", customShader );
+  mBloomExtractImageActor.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
 
   // Create an ImageActor for compositing the result (scene and bloom textures) to output
-  mCompositeImageActor = ImageActor::New();
+  mCompositeImageActor = Toolkit::ImageView::New();
   mCompositeImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mCompositeImageActor.SetShaderEffect( mCompositeShader );
-  mCompositeImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
+
+  // Create shader used to composite bloom and original image to output render target
+  customShader[ "fragmentShader" ] = COMPOSITE_FRAGMENT_SOURCE;
+  rendererMap[ "shader" ] = customShader;
+  mCompositeImageActor.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );;
 
   // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
-  mTargetImageActor = ImageActor::New();
+  mTargetImageActor = Toolkit::ImageView::New();
   mTargetImageActor.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
-  mTargetImageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
 
 
   // Create the Gaussian Blur object + render tasks
@@ -270,9 +282,11 @@ void BloomView::OnInitialize()
   // Create cameras for the renders corresponding to the (potentially downsampled) render targets' size
   mRenderDownsampledCamera = CameraActor::New();
   mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
+  mRenderDownsampledCamera.SetInvertYAxis( true );
 
   mRenderFullSizeCamera = CameraActor::New();
   mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
+  mRenderFullSizeCamera.SetInvertYAxis( true );
 
 
   ////////////////////////////////
@@ -306,10 +320,11 @@ void BloomView::OnSizeSet(const Vector3& targetSize)
   float cameraPosConstraintScale = 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f);
   mRenderFullSizeCamera.SetZ( mTargetSize.height * cameraPosConstraintScale);
 
-  // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
-  if(Self().OnStage())
+  // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
+  if(mActivated)
   {
-    AllocateResources();
+    Deactivate();
+    Activate();
   }
 }
 
@@ -359,6 +374,7 @@ void BloomView::AllocateResources()
     // create off screen buffer of new size to render our child actors to
     mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
     mBloomExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
+    FrameBufferImage mBlurExtractTarget = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
     mOutputRenderTarget = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED);
 
 
@@ -369,11 +385,20 @@ void BloomView::AllocateResources()
     mBloomExtractImageActor.SetSize(mDownsampledWidth, mDownsampledHeight); // size needs to match render target
 
     // set GaussianBlurView to blur our extracted bloom
-    mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBloomExtractTarget);
+    mGaussianBlurView.SetUserImageAndOutputRenderTarget(mBloomExtractTarget, mBlurExtractTarget);
 
     // use the completed blur in the first buffer and composite with the original child actors render
     mCompositeImageActor.SetImage( mRenderTargetForRenderingChildren );
-    mCompositeShader.SetEffectImage( mBloomExtractTarget );
+    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 );
+    }
 
     // set up target actor for rendering result, i.e. the blurred image
     mTargetImageActor.SetImage(mOutputRenderTarget);
@@ -390,6 +415,8 @@ void BloomView::CreateRenderTasks()
   mRenderChildrenTask.SetExclusive(true);
   mRenderChildrenTask.SetInputEnabled( false );
   mRenderChildrenTask.SetClearEnabled( true );
+  mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
+  mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
 
   // Extract the bright part of the image and render to a new buffer. Downsampling also occurs at this stage to save pixel fill, if it is set up.
   mBloomExtractTask = taskList.CreateTask();
@@ -397,6 +424,8 @@ void BloomView::CreateRenderTasks()
   mBloomExtractTask.SetExclusive(true);
   mBloomExtractTask.SetInputEnabled( false );
   mBloomExtractTask.SetClearEnabled( true );
+  mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
+  mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
 
   // GaussianBlurView tasks must be created here, so they are executed in the correct order with respect to BloomView tasks
   GetImpl(mGaussianBlurView).CreateRenderTasks();
@@ -407,13 +436,7 @@ void BloomView::CreateRenderTasks()
   mCompositeTask.SetExclusive(true);
   mCompositeTask.SetInputEnabled( false );
   mCompositeTask.SetClearEnabled( true );
-
-  mRenderChildrenTask.SetCameraActor(mRenderFullSizeCamera); // use camera that covers render target exactly
-  mBloomExtractTask.SetCameraActor(mRenderDownsampledCamera);
   mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
-
-  mRenderChildrenTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
-  mBloomExtractTask.SetTargetFrameBuffer( mBloomExtractTarget );
   mCompositeTask.SetTargetFrameBuffer( mOutputRenderTarget );
 }
 
@@ -434,6 +457,7 @@ void BloomView::Activate()
   // make sure resources are allocated and start the render tasks processing
   AllocateResources();
   CreateRenderTasks();
+  mActivated = true;
 }
 
 void BloomView::Deactivate()
@@ -441,6 +465,7 @@ void BloomView::Deactivate()
   // stop render tasks processing
   // Note: render target resources are automatically freed since we set the Image::Unused flag
   RemoveRenderTasks();
+  mActivated = false;
 }
 
 /**
@@ -469,19 +494,19 @@ void BloomView::SetupProperties()
   // bloom threshold
 
   // set defaults, makes sure properties are registered with shader
-  mBloomExtractShader.SetUniform( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
-  mBloomExtractShader.SetUniform( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
+  mBloomExtractImageActor.RegisterProperty( BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT );
+  mBloomExtractImageActor.RegisterProperty( RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME, 1.0f / (1.0f - BLOOM_THRESHOLD_DEFAULT) );
 
   // Register a property that the user can control to change the bloom threshold
   mBloomThresholdPropertyIndex = self.RegisterProperty(BLOOM_THRESHOLD_PROPERTY_NAME, BLOOM_THRESHOLD_DEFAULT);
-  Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
-  Constraint bloomThresholdConstraint = Constraint::New<float>( mBloomExtractShader, shaderBloomThresholdPropertyIndex, EqualToConstraint());
+  Property::Index shaderBloomThresholdPropertyIndex = mBloomExtractImageActor.GetPropertyIndex(BLOOM_THRESHOLD_PROPERTY_NAME);
+  Constraint bloomThresholdConstraint = Constraint::New<float>( mBloomExtractImageActor, shaderBloomThresholdPropertyIndex, EqualToConstraint());
   bloomThresholdConstraint.AddSource( Source(self, mBloomThresholdPropertyIndex) );
   bloomThresholdConstraint.Apply();
 
   // precalc 1.0 / (1.0 - threshold) on CPU to save shader insns, using constraint to tie to the normal threshold property
-  Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractShader.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
-  Constraint thresholdConstraint = Constraint::New<float>( mBloomExtractShader, shaderRecipOneMinusBloomThresholdPropertyIndex, RecipOneMinusConstraint());
+  Property::Index shaderRecipOneMinusBloomThresholdPropertyIndex = mBloomExtractImageActor.GetPropertyIndex(RECIP_ONE_MINUS_BLOOM_THRESHOLD_PROPERTY_NAME);
+  Constraint thresholdConstraint = Constraint::New<float>( mBloomExtractImageActor, shaderRecipOneMinusBloomThresholdPropertyIndex, RecipOneMinusConstraint());
   thresholdConstraint.AddSource( LocalSource(shaderBloomThresholdPropertyIndex) );
   thresholdConstraint.Apply();
 
@@ -501,9 +526,9 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the bloom intensity via internally hidden shader
   mBloomIntensityPropertyIndex = self.RegisterProperty(BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT);
-  mCompositeShader.SetUniform( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
-  Property::Index shaderBloomIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
-  Constraint bloomIntensityConstraint = Constraint::New<float>( mCompositeShader, shaderBloomIntensityPropertyIndex, EqualToConstraint());
+  mCompositeImageActor.RegisterProperty( BLOOM_INTENSITY_PROPERTY_NAME, BLOOM_INTENSITY_DEFAULT );
+  Property::Index shaderBloomIntensityPropertyIndex = mCompositeImageActor.GetPropertyIndex(BLOOM_INTENSITY_PROPERTY_NAME);
+  Constraint bloomIntensityConstraint = Constraint::New<float>( mCompositeImageActor, shaderBloomIntensityPropertyIndex, EqualToConstraint());
   bloomIntensityConstraint.AddSource( Source(self, mBloomIntensityPropertyIndex) );
   bloomIntensityConstraint.Apply();
 
@@ -513,9 +538,9 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the bloom saturation via internally hidden shader
   mBloomSaturationPropertyIndex = self.RegisterProperty(BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT);
-  mCompositeShader.SetUniform( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
-  Property::Index shaderBloomSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
-  Constraint bloomSaturationConstraint = Constraint::New<float>( mCompositeShader, shaderBloomSaturationPropertyIndex, EqualToConstraint());
+  mCompositeImageActor.RegisterProperty( BLOOM_SATURATION_PROPERTY_NAME, BLOOM_SATURATION_DEFAULT );
+  Property::Index shaderBloomSaturationPropertyIndex = mCompositeImageActor.GetPropertyIndex(BLOOM_SATURATION_PROPERTY_NAME);
+  Constraint bloomSaturationConstraint = Constraint::New<float>( mCompositeImageActor, shaderBloomSaturationPropertyIndex, EqualToConstraint());
   bloomSaturationConstraint.AddSource( Source(self, mBloomSaturationPropertyIndex) );
   bloomSaturationConstraint.Apply();
 
@@ -525,9 +550,9 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the image intensity via internally hidden shader
   mImageIntensityPropertyIndex = self.RegisterProperty(IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT);
-  mCompositeShader.SetUniform( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
-  Property::Index shaderImageIntensityPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
-  Constraint imageIntensityConstraint = Constraint::New<float>( mCompositeShader, shaderImageIntensityPropertyIndex, EqualToConstraint());
+  mCompositeImageActor.RegisterProperty( IMAGE_INTENSITY_PROPERTY_NAME, IMAGE_INTENSITY_DEFAULT );
+  Property::Index shaderImageIntensityPropertyIndex = mCompositeImageActor.GetPropertyIndex(IMAGE_INTENSITY_PROPERTY_NAME);
+  Constraint imageIntensityConstraint = Constraint::New<float>( mCompositeImageActor, shaderImageIntensityPropertyIndex, EqualToConstraint());
   imageIntensityConstraint.AddSource( Source(self, mImageIntensityPropertyIndex) );
   imageIntensityConstraint.Apply();
 
@@ -537,9 +562,9 @@ void BloomView::SetupProperties()
 
   // Register a property that the user can control to fade the image saturation via internally hidden shader
   mImageSaturationPropertyIndex = self.RegisterProperty(IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT);
-  mCompositeShader.SetUniform( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
-  Property::Index shaderImageSaturationPropertyIndex = mCompositeShader.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
-  Constraint imageSaturationConstraint = Constraint::New<float>( mCompositeShader, shaderImageSaturationPropertyIndex, EqualToConstraint());
+  mCompositeImageActor.RegisterProperty( IMAGE_SATURATION_PROPERTY_NAME, IMAGE_SATURATION_DEFAULT );
+  Property::Index shaderImageSaturationPropertyIndex = mCompositeImageActor.GetPropertyIndex(IMAGE_SATURATION_PROPERTY_NAME);
+  Constraint imageSaturationConstraint = Constraint::New<float>( mCompositeImageActor, shaderImageSaturationPropertyIndex, EqualToConstraint());
   imageSaturationConstraint.AddSource( Source(self, mImageSaturationPropertyIndex) );
   imageSaturationConstraint.Apply();
 }
index 2da9293..207ce92 100644 (file)
 #include <dali/public-api/actors/camera-actor.h>
 #include <dali/public-api/actors/image-actor.h>
 #include <dali/public-api/render-tasks/render-task.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
 #include <dali-toolkit/devel-api/controls/bloom-view/bloom-view.h>
 
 namespace Dali
@@ -132,8 +132,7 @@ private:
   // for extracting bright parts of image to an offscreen target
   FrameBufferImage mBloomExtractTarget; // for rendering bright parts of image into separate texture, also used as target for gaussian blur
   RenderTask mBloomExtractTask;
-  ShaderEffect mBloomExtractShader;
-  ImageActor mBloomExtractImageActor;
+  Toolkit::ImageView mBloomExtractImageActor;
 
   /////////////////////////////////////////////////////////////
   // for blurring extracted bloom
@@ -142,13 +141,13 @@ private:
   /////////////////////////////////////////////////////////////
   // for compositing bloom and children renders to offscreen target
   RenderTask mCompositeTask;
-  ShaderEffect mCompositeShader;
-  ImageActor mCompositeImageActor;
+
+  Toolkit::ImageView mCompositeImageActor;
 
   /////////////////////////////////////////////////////////////
   // for holding blurred result
   FrameBufferImage mOutputRenderTarget;
-  ImageActor mTargetImageActor;
+  Toolkit::ImageView mTargetImageActor;
 
   /////////////////////////////////////////////////////////////
   // Properties for setting by user, e.g. by animations
@@ -159,6 +158,8 @@ private:
   Property::Index mImageIntensityPropertyIndex;
   Property::Index mImageSaturationPropertyIndex;
 
+  bool mActivated:1;
+
 private:
 
   // Undefined copy constructor.
index ddbb242..df03aaf 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/animation/constraints.h>
 #include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/devel-api/object/type-registry-helper.h>
 #include <dali/public-api/render-tasks/render-task-list.h>
@@ -98,17 +99,19 @@ const float GAUSSIAN_BLUR_VIEW_DEFAULT_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
 const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
 
 const char* const GAUSSIAN_BLUR_FRAGMENT_SOURCE =
+    "varying mediump vec2 vTexCoord;\n"
+    "uniform sampler2D sTexture;\n"
+    "uniform lowp vec4 uColor;\n"
     "uniform mediump vec2 uSampleOffsets[NUM_SAMPLES];\n"
     "uniform mediump float uSampleWeights[NUM_SAMPLES];\n"
 
     "void main()\n"
     "{\n"
-    "   mediump vec4 col;\n"
-    "   col = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y) + uSampleOffsets[0]) * uSampleWeights[0];     \n"
-    "   for (int i=1; i<NUM_SAMPLES; ++i)                                                                      \n"
-    "   {                                                                                                      \n"
-    "     col += texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y) + uSampleOffsets[i]) * uSampleWeights[i];  \n"
-    "   }                                                                                                      \n"
+    "   mediump vec4 col = texture2D(sTexture, vTexCoord + uSampleOffsets[0]) * uSampleWeights[0];\n"
+    "   for (int i=1; i<NUM_SAMPLES; ++i)\n"
+    "   {\n"
+    "     col += texture2D(sTexture, vTexCoord + uSampleOffsets[i]) * uSampleWeights[i];\n"
+    "   }\n"
     "   gl_FragColor = col;\n"
     "}\n";
 
@@ -131,6 +134,7 @@ GaussianBlurView::GaussianBlurView()
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
+  , mActivated( false )
 {
   SetBlurBellCurveWidth(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH);
 }
@@ -153,6 +157,7 @@ GaussianBlurView::GaussianBlurView( const unsigned int numSamples, const float b
   , mLastSize(Vector2::ZERO)
   , mChildrenRoot(Actor::New())
   , mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
+  , mActivated( false )
 {
   SetBlurBellCurveWidth(blurBellCurveWidth);
 }
@@ -249,32 +254,27 @@ void GaussianBlurView::OnInitialize()
   //////////////////////////////////////////////////////
   // Create shaders
 
-  // horiz
   std::ostringstream horizFragmentShaderStringStream;
   horizFragmentShaderStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
   horizFragmentShaderStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
-  mHorizBlurShader = ShaderEffect::New( "", horizFragmentShaderStringStream.str() );
-  // vert
-  std::ostringstream vertFragmentShaderStringStream;
-  vertFragmentShaderStringStream << "#define NUM_SAMPLES " << mNumSamples << "\n";
-  vertFragmentShaderStringStream << GAUSSIAN_BLUR_FRAGMENT_SOURCE;
-  mVertBlurShader = ShaderEffect::New( "", vertFragmentShaderStringStream.str() );
-
+  Property::Map customShader;
+  customShader[ "fragmentShader" ] = horizFragmentShaderStringStream.str();
+  Property::Map rendererMap;
+  rendererMap.Insert( "rendererType", "imageRenderer" );
+  rendererMap.Insert( "shader", customShader );
 
   //////////////////////////////////////////////////////
   // Create actors
 
   // Create an ImageActor for performing a horizontal blur on the texture
-  mImageActorHorizBlur = ImageActor::New();
+  mImageActorHorizBlur = Toolkit::ImageView::New();
   mImageActorHorizBlur.SetParentOrigin(ParentOrigin::CENTER);
-  mImageActorHorizBlur.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
-  mImageActorHorizBlur.SetShaderEffect( mHorizBlurShader );
+  mImageActorHorizBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
 
   // Create an ImageActor for performing a vertical blur on the texture
-  mImageActorVertBlur = ImageActor::New();
+  mImageActorVertBlur = Toolkit::ImageView::New();
   mImageActorVertBlur.SetParentOrigin(ParentOrigin::CENTER);
-  mImageActorVertBlur.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
-  mImageActorVertBlur.SetShaderEffect( mVertBlurShader );
+  mImageActorVertBlur.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
 
   // Register a property that the user can control to fade the blur in / out via the GaussianBlurView object
   mBlurStrengthPropertyIndex = Self().RegisterProperty(GAUSSIAN_BLUR_VIEW_STRENGTH_PROPERTY_NAME, GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH);
@@ -282,9 +282,8 @@ void GaussianBlurView::OnInitialize()
   // Create an ImageActor for compositing the blur and the original child actors render
   if(!mBlurUserImage)
   {
-    mImageActorComposite = ImageActor::New();
+    mImageActorComposite = Toolkit::ImageView::New();
     mImageActorComposite.SetParentOrigin(ParentOrigin::CENTER);
-    mImageActorComposite.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
     mImageActorComposite.SetOpacity(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_STRENGTH); // ensure alpha is enabled for this object and set default value
 
     Constraint blurStrengthConstraint = Constraint::New<float>( mImageActorComposite, Actor::Property::COLOR_ALPHA, EqualToConstraint());
@@ -292,14 +291,13 @@ void GaussianBlurView::OnInitialize()
     blurStrengthConstraint.Apply();
 
     // Create an ImageActor for holding final result, i.e. the blurred image. This will get rendered to screen later, via default / user render task
-    mTargetActor = ImageActor::New();
+    mTargetActor = Toolkit::ImageView::New();
     mTargetActor.SetParentOrigin(ParentOrigin::CENTER);
-    mTargetActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
-
 
     //////////////////////////////////////////////////////
     // Create cameras for the renders corresponding to the view size
     mRenderFullSizeCamera = CameraActor::New();
+    mRenderFullSizeCamera.SetInvertYAxis( true );
     mRenderFullSizeCamera.SetParentOrigin(ParentOrigin::CENTER);
 
 
@@ -314,6 +312,7 @@ void GaussianBlurView::OnInitialize()
   //////////////////////////////////////////////////////
   // Create camera for the renders corresponding to the (potentially downsampled) render targets' size
   mRenderDownsampledCamera = CameraActor::New();
+  mRenderDownsampledCamera.SetInvertYAxis( true );
   mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
 
 
@@ -346,10 +345,11 @@ void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
   }
 
 
-  // if we are already on stage, need to update render target sizes now to reflect the new size of this actor
-  if(Self().OnStage())
+  // if we have already activated the blur, need to update render target sizes now to reflect the new size of this actor
+  if(mActivated)
   {
-    AllocateResources();
+    Deactivate();
+    Activate();
   }
 }
 
@@ -387,13 +387,13 @@ void GaussianBlurView::AllocateResources()
       mRenderFullSizeCamera.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosConstraintScale);
 
       // create offscreen buffer of new size to render our child actors to
-      mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
+      mRenderTargetForRenderingChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat );
 
       // Set ImageActor for performing a horizontal blur on the texture
       mImageActorHorizBlur.SetImage( mRenderTargetForRenderingChildren );
 
       // Create offscreen buffer for vert blur pass
-      mRenderTarget1 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
+      mRenderTarget1 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat );
 
       // use the completed blur in the first buffer and composite with the original child actors render
       mImageActorComposite.SetImage( mRenderTarget1 );
@@ -403,7 +403,7 @@ void GaussianBlurView::AllocateResources()
     }
 
     // Create offscreen buffer for horiz blur pass
-    mRenderTarget2 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat, Dali::Image::UNUSED );
+    mRenderTarget2 = FrameBufferImage::New( mDownsampledWidth, mDownsampledHeight, mPixelFormat );
 
     // size needs to match render target
     mImageActorHorizBlur.SetSize(mDownsampledWidth, mDownsampledHeight);
@@ -442,6 +442,8 @@ void GaussianBlurView::CreateRenderTasks()
   mHorizBlurTask.SetInputEnabled( false );
   mHorizBlurTask.SetClearEnabled( true );
   mHorizBlurTask.SetClearColor( mBackgroundColor );
+  mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
+  mHorizBlurTask.SetTargetFrameBuffer( mRenderTarget2 );
   if( mRenderOnce && mBlurUserImage )
   {
     mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
@@ -454,6 +456,15 @@ void GaussianBlurView::CreateRenderTasks()
   mVertBlurTask.SetInputEnabled( false );
   mVertBlurTask.SetClearEnabled( true );
   mVertBlurTask.SetClearColor( mBackgroundColor );
+  mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
+  if(mUserOutputRenderTarget)
+  {
+    mVertBlurTask.SetTargetFrameBuffer( mUserOutputRenderTarget );
+  }
+  else
+  {
+    mVertBlurTask.SetTargetFrameBuffer( mRenderTarget1 );
+  }
   if( mRenderOnce && mBlurUserImage )
   {
     mVertBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
@@ -471,19 +482,6 @@ void GaussianBlurView::CreateRenderTasks()
     mCompositeTask.SetCameraActor(mRenderFullSizeCamera);
     mCompositeTask.SetTargetFrameBuffer( mRenderTargetForRenderingChildren );
   }
-
-  mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
-  mVertBlurTask.SetCameraActor(mRenderDownsampledCamera);
-
-  mHorizBlurTask.SetTargetFrameBuffer( mRenderTarget2 );
-  if(mUserOutputRenderTarget)
-  {
-    mVertBlurTask.SetTargetFrameBuffer( mUserOutputRenderTarget );
-  }
-  else
-  {
-    mVertBlurTask.SetTargetFrameBuffer( mRenderTarget1 );
-  }
 }
 
 void GaussianBlurView::RemoveRenderTasks()
@@ -501,6 +499,7 @@ void GaussianBlurView::Activate()
   // make sure resources are allocated and start the render tasks processing
   AllocateResources();
   CreateRenderTasks();
+  mActivated = true;
 }
 
 void GaussianBlurView::ActivateOnce()
@@ -515,7 +514,11 @@ void GaussianBlurView::Deactivate()
   // stop render tasks processing
   // Note: render target resources are automatically freed since we set the Image::Unused flag
   RemoveRenderTasks();
+  mRenderTargetForRenderingChildren.Reset();
+  mRenderTarget1.Reset();
+  mRenderTarget2.Reset();
   mRenderOnce = false;
+  mActivated = false;
 }
 
 void GaussianBlurView::SetBlurBellCurveWidth(float blurBellCurveWidth)
@@ -574,11 +577,11 @@ void GaussianBlurView::SetShaderConstants()
   Vector2 yAxis(0.0f, 1.0f);
   for (i = 0; i < mNumSamples; ++i )
   {
-    mHorizBlurShader.SetUniform( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
-    mHorizBlurShader.SetUniform( GetSampleWeightsPropertyName( i ), weights[ i ] );
+    mImageActorHorizBlur.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * xAxis );
+    mImageActorHorizBlur.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
 
-    mVertBlurShader.SetUniform( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
-    mVertBlurShader.SetUniform( GetSampleWeightsPropertyName( i ), weights[ i ] );
+    mImageActorVertBlur.RegisterProperty( GetSampleOffsetsPropertyName( i ), uvOffsets[ i ] * yAxis );
+    mImageActorVertBlur.RegisterProperty( GetSampleWeightsPropertyName( i ), weights[ i ] );
   }
 
   delete[] uvOffsets;
index 0afa61c..7f38489 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
 
 namespace Dali
 {
@@ -153,23 +154,20 @@ private:
   FrameBufferImage mRenderTarget1;
   FrameBufferImage mRenderTarget2;
 
-  ShaderEffect mHorizBlurShader;
-  ShaderEffect mVertBlurShader;
-
-  ImageActor mImageActorHorizBlur;
-  ImageActor mImageActorVertBlur;
+  Toolkit::ImageView mImageActorHorizBlur;
+  Toolkit::ImageView mImageActorVertBlur;
 
   RenderTask mHorizBlurTask;
   RenderTask mVertBlurTask;
 
   /////////////////////////////////////////////////////////////
   // for compositing blur and children renders to offscreen target
-  ImageActor mImageActorComposite;
+  Toolkit::ImageView mImageActorComposite;
   RenderTask mCompositeTask;
 
   /////////////////////////////////////////////////////////////
   // for holding blurred result
-  ImageActor mTargetActor;
+  Toolkit::ImageView mTargetActor;
 
   /////////////////////////////////////////////////////////////
   // for animating fade in / out of blur, hiding internal implementation but allowing user to set via GaussianBlurView interface
@@ -181,6 +179,8 @@ private:
   FrameBufferImage mUserOutputRenderTarget;
 
   Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal mFinishedSignal; ///< Signal emitted when blur has completed.
+
+  bool mActivated:1;
 private:
 
   // Undefined copy constructor.
index 3f6727f..532f553 100644 (file)
@@ -51,14 +51,6 @@ namespace Internal
  **/
 inline ShaderEffect CreatePageTurnBookSpineEffect()
 {
-  std::string vertexSource = DALI_COMPOSE_SHADER(
-      precision mediump float;\n
-      void main()\n
-      {\n
-          gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n
-          vTexCoord = aTexCoord;\n
-      }\n);
-
   // the simplified version of the fragment shader of page turn effect
   std::string fragmentSource = DALI_COMPOSE_SHADER(
       precision mediump float;\n
@@ -69,11 +61,11 @@ inline ShaderEffect CreatePageTurnBookSpineEffect()
       {\n
       // flip the image horizontally by changing the x component of the texture coordinate
         if( uIsBackImageVisible == 1.0 )\n
-          gl_FragColor = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) ) * uColor; \n
+          gl_FragColor = texture2D( sTexture, vec2( uTextureRect.p+uTextureRect.s-vTexCoord.x, vTexCoord.y ) ) * uColor; \n
         else\n
         gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
       // display book spine, a stripe of shadowed texture
-        float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageWidth; \n
+        float pixelPos = (vTexCoord.x-uTextureRect.s)*uPageWidth; \n
         if(pixelPos < uSpineShadowParameter.x) \n
         {\n
           float x = pixelPos - uSpineShadowParameter.x;\n
@@ -85,7 +77,7 @@ inline ShaderEffect CreatePageTurnBookSpineEffect()
 
   const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f);
 
-  ShaderEffect shaderEffect = ShaderEffect::New( vertexSource, fragmentSource );
+  ShaderEffect shaderEffect = ShaderEffect::New( "", fragmentSource );
 
   shaderEffect.SetUniform( "uIsBackImageVisible", -1.f );
   shaderEffect.SetUniform( "uSpineShadowParameter", DEFAULT_SPINE_SHADOW_PARAMETER );
index 3684e70..233a3a1 100644 (file)
@@ -127,7 +127,7 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
       \n
       void main()\n
       {\n
-        vec4 position = vec4( aPosition.xy, 0.0, 1.0);\n
+        vec4 position = vec4( aPosition*uSize.xy, 0.0, 1.0);\n
         vec2 currentCenter = vec2( uCommonParameters[1][2], uCommonParameters[1][3]);\n
         vec2 originalCenter = vec2( uCommonParameters[0][2], uCommonParameters[0][3]);\n
         vec3 normal = vec3(0.0,0.0,1.0);\n
@@ -246,10 +246,9 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
           // change the coordinate origin from the top-left of the page to its center
           position.xy -= uPageSize * 0.5; \n
         }\n
-        position.z += aPosition.z;\n
         gl_Position = uMvpMatrix * position;\n
         // varying parameters for fragment shader
-        vTexCoord = aTexCoord;
+        vTexCoord = mix( uTextureRect.xy, uTextureRect.zw, aPosition + vec2(0.5) );\n;
         vNormal = uNormalMatrix*normal;\n
         vPosition = uModelView * position;\n
       }\n
@@ -271,11 +270,11 @@ ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
         float spineShadowCoef = 1.0; \n
         // display page content
         // display back image of the page, flip the texture
-        if(  dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) );\n
+        if(  dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( uTextureRect.p+uTextureRect.s-vTexCoord.x, vTexCoord.y ) );\n
         // display front image of the page
         else texel = texture2D( sTexture, vTexCoord );\n
         // display book spine, a stripe of shadowed texture
-        float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageSize.x; \n
+        float pixelPos = (vTexCoord.x-uTextureRect.s)*uPageSize.x; \n
         if(pixelPos < uSpineShadowParameter.x) \n
         {\n
           float x = pixelPos - uSpineShadowParameter.x;\n
index 66eeca1..4862b1d 100755 (executable)
@@ -326,8 +326,6 @@ void Popup::OnInitialize()
   // Any content after this point which is added to Self() will be re-parented to mContent.
   mAlterAddedChild = true;
 
-  // Make self keyboard focusable and a focus group.
-  self.SetKeyboardFocusable( true );
   SetAsKeyboardFocusGroup( true );
 }
 
@@ -719,7 +717,6 @@ void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState )
 
     // Allow the popup to catch events.
     mPopupLayout.SetSensitive( true );
-    SetKeyInputFocus();
 
     // Handle the keyboard focus when popup is shown.
     Dali::Toolkit::KeyboardFocusManager keyboardFocusManager = Dali::Toolkit::KeyboardFocusManager::Get();
@@ -727,14 +724,30 @@ void Popup::SetDisplayState( Toolkit::Popup::DisplayState displayState )
     {
       mPreviousFocusedActor = keyboardFocusManager.GetCurrentFocusActor();
 
-      if( mContent && mContent.IsKeyboardFocusable() )
+      if( Self().IsKeyboardFocusable() )
       {
-        // If content is focusable, move the focus to content.
-        keyboardFocusManager.SetCurrentFocusActor( mContent );
-      }
-      else
-      {
-        DALI_LOG_WARNING( "There is no focusable in popup\n" );
+        // Setup the actgor to start focus from.
+        Actor focusActor;
+        if( mContent && mContent.IsKeyboardFocusable() )
+        {
+          // If the content is focusable, move the focus to the content.
+          focusActor = mContent;
+        }
+        else if( mFooter && mFooter.IsKeyboardFocusable() )
+        {
+          // If the footer is focusable, move the focus to the footer.
+          focusActor = mFooter;
+        }
+        else
+        {
+          DALI_LOG_WARNING( "There is no focusable in popup\n" );
+        }
+
+        if( focusActor )
+        {
+          SetKeyInputFocus();
+          keyboardFocusManager.SetCurrentFocusActor( focusActor );
+        }
       }
     }
   }
@@ -1732,114 +1745,145 @@ bool Popup::OnKeyEvent( const KeyEvent& event )
   return consumed;
 }
 
+void Popup::AddFocusableChildrenRecursive( Actor parent, std::vector< Actor >& focusableActors )
+{
+  if( parent )
+  {
+    Toolkit::Control control = Toolkit::Control::DownCast( parent );
+    bool layoutControl = control && GetImplementation( control ).IsKeyboardNavigationSupported();
+
+    if( parent.IsKeyboardFocusable() || layoutControl )
+    {
+      focusableActors.push_back( parent );
+
+      if( !layoutControl )
+      {
+        for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i )
+        {
+          Actor child( parent.GetChildAt( i ) );
+          AddFocusableChildrenRecursive( child, focusableActors );
+        }
+      }
+    }
+  }
+}
+
+void Popup::AddFocusableChildren( Actor parent, std::vector< Actor >& focusableActors )
+{
+  if( parent )
+  {
+    Toolkit::Control control = Toolkit::Control::DownCast( parent );
+    if( !GetImplementation( control ).IsKeyboardNavigationSupported() )
+    {
+      for( unsigned int i = 0, numberChildren = parent.GetChildCount(); i < numberChildren; ++i )
+      {
+        Actor child( parent.GetChildAt( i ) );
+        AddFocusableChildrenRecursive( child, focusableActors );
+      }
+    }
+    else
+    {
+      focusableActors.push_back( parent );
+    }
+  }
+}
+
 Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::Control::KeyboardFocus::Direction direction, bool loopEnabled )
 {
+  std::string currentStr;
+  if( currentFocusedActor )
+  {
+    currentStr = currentFocusedActor.GetName();
+  }
+
   Actor nextFocusableActor( currentFocusedActor );
+  Actor currentFocusGroup;
+  if( currentFocusedActor )
+  {
+    currentFocusGroup = KeyboardFocusManager::Get().GetFocusGroup( currentFocusedActor );
+  }
 
   // TODO: Needs to be optimised
-  if( !currentFocusedActor || ( currentFocusedActor && KeyboardFocusManager::Get().GetFocusGroup( currentFocusedActor ) != Self() ) )
+  // The following statement checks that if we have a current focused actor, then the current focus group is not the popup content or footer.
+  // This is to detect if the focus is currently outside the popup, and if so, move it inside.
+  if( !currentFocusedActor ||
+    ( currentFocusedActor && ( ( !mContent || ( currentFocusGroup != mContent ) ) && ( !mFooter || ( currentFocusGroup != mFooter ) ) ) ) )
   {
-    // The current focused actor is not within popup
+    // The current focused actor is not within popup.
     if( mContent && mContent.IsKeyboardFocusable() )
     {
-      // If content is focusable, move the focus to content
+      // If the content is focusable, move the focus to the content.
       nextFocusableActor = mContent;
     }
+    else if( mFooter && mFooter.IsKeyboardFocusable() )
+    {
+      // If the footer is focusable, move the focus to the footer.
+      nextFocusableActor = mFooter;
+    }
   }
   else
   {
     // Rebuild the focus chain because controls or content can be added or removed dynamically
     std::vector< Actor > focusableActors;
-    if( mContent && mContent.IsKeyboardFocusable() )
+
+    AddFocusableChildren( mContent, focusableActors );
+    AddFocusableChildren( mFooter, focusableActors );
+
+    std::vector< Actor >::iterator endIterator = focusableActors.end();
+    std::vector< Actor >::iterator currentIterator = focusableActors.begin();
+    for( std::vector< Actor >::iterator iterator = focusableActors.begin(); iterator != endIterator; ++iterator )
     {
-      focusableActors.push_back( mContent );
+      if( currentFocusedActor == *iterator )
+      {
+        currentIterator = iterator;
+      }
     }
 
-    for( std::vector< Actor >::iterator iter = focusableActors.begin(), end = focusableActors.end(); iter != end; ++iter )
+    if( currentIterator != endIterator )
     {
-      if( currentFocusedActor == *iter )
+      switch( direction )
       {
-        switch( direction )
+        case Toolkit::Control::KeyboardFocus::LEFT:
         {
-          case Toolkit::Control::KeyboardFocus::LEFT:
+          if( currentIterator == focusableActors.begin() )
           {
-            if( iter == focusableActors.begin() )
-            {
-              nextFocusableActor = *( focusableActors.end() - 1 );
-            }
-            else
-            {
-              nextFocusableActor = *( iter - 1 );
-            }
-            break;
+            nextFocusableActor = *( endIterator - 1 );
           }
-          case Toolkit::Control::KeyboardFocus::RIGHT:
+          else
           {
-            if( iter == focusableActors.end() - 1 )
-            {
-              nextFocusableActor = *( focusableActors.begin() );
-            }
-            else
-            {
-              nextFocusableActor = *( iter + 1 );
-            }
-            break;
+            nextFocusableActor = *( currentIterator - 1 );
           }
-
-          case Toolkit::Control::KeyboardFocus::UP:
+          break;
+        }
+        case Toolkit::Control::KeyboardFocus::RIGHT:
+        {
+          if( currentIterator == endIterator - 1 )
           {
-            if( mContent && *iter == mContent )
-            {
-              nextFocusableActor = *( focusableActors.end() - 1 );
-            }
-            else
-            {
-              if( mContent && mContent.IsKeyboardFocusable() )
-              {
-                nextFocusableActor = mContent;
-              }
-              else
-              {
-                if ( iter == focusableActors.begin() )
-                {
-                  nextFocusableActor = *( focusableActors.end() - 1 );
-                }
-                else
-                {
-                  nextFocusableActor = *( iter - 1 );
-                }
-              }
-            }
-            break;
+            nextFocusableActor = *( focusableActors.begin() );
           }
-
-          case Toolkit::Control::KeyboardFocus::DOWN:
+          else
           {
-            if( mContent && mContent.IsKeyboardFocusable() )
-            {
-              nextFocusableActor = mContent;
-            }
-            else
-            {
-              if( iter == focusableActors.end() - 1 )
-              {
-                nextFocusableActor = *( focusableActors.begin() );
-              }
-              else
-              {
-                nextFocusableActor = *( iter + 1 );
-              }
-            }
-            break;
+            nextFocusableActor = *( currentIterator + 1 );
           }
+          break;
         }
 
-        if( !nextFocusableActor )
+        case Toolkit::Control::KeyboardFocus::UP:
         {
-          DALI_LOG_WARNING( "Can not decide next focusable actor\n" );
+          nextFocusableActor = *(  focusableActors.begin() );
+          break;
         }
 
-        break;
+        case Toolkit::Control::KeyboardFocus::DOWN:
+        {
+          nextFocusableActor = *( endIterator - 1 );
+          break;
+        }
+      }
+
+      if( !nextFocusableActor )
+      {
+        DALI_LOG_WARNING( "Can not decide next focusable actor\n" );
       }
     }
   }
@@ -1847,6 +1891,7 @@ Actor Popup::GetNextKeyboardFocusableActor( Actor currentFocusedActor, Toolkit::
   return nextFocusableActor;
 }
 
+
 } // namespace Internal
 
 } // namespace Toolkit
index 884cab3..f01d498 100755 (executable)
@@ -478,6 +478,25 @@ private:
 
 private:
 
+  /**
+   * Recursively add any focusable actors or layout containers to the provided vector.
+   * Include the top level actor if it is a layout container.
+   *
+   * @param[in]     parent          The actor to start from
+   * @param[in/out] focusableActors The vector to add focusable actors to
+   */
+  void AddFocusableChildren( Actor parent, std::vector< Actor >& focusableActors );
+
+  /**
+   * Recursively add any focusable actors or layout containers to the provided vector.
+   *
+   * @param[in]     parent          The actor to start from
+   * @param[in/out] focusableActors The vector to add focusable actors to
+   */
+  void AddFocusableChildrenRecursive( Actor parent, std::vector< Actor >& focusableActors );
+
+private:
+
   // Undefined.
   Popup(const Popup&);
 
index 1453b73..da77f95 100644 (file)
@@ -474,14 +474,13 @@ void ImageRenderer::InitializeRenderer( const Image& image )
 {
   mImpl->mFlags &= ~Impl::IS_FROM_CACHE;
 
-  if( !image )
+  mImpl->mRenderer = CreateRenderer();
+
+  if( image )
   {
-    return;
+    ApplyImageToSampler( image );
   }
 
-  mImpl->mRenderer = CreateRenderer();
-  ApplyImageToSampler( image );
-
   // default shader or custom shader with the default image vertex shader
   if( !mImpl->mCustomShader || mImpl->mCustomShader->mVertexShader.empty() )
   {
@@ -497,7 +496,7 @@ void ImageRenderer::DoSetOnStage( Actor& actor )
   {
     InitializeRenderer( mImageUrl );
   }
-  else if( mImage )
+  else
   {
     InitializeRenderer( mImage );
   }
index cd36331..8251b69 100644 (file)
@@ -23,7 +23,9 @@
 #include <dali/public-api/animation/constraint.h>
 #include <dali/public-api/common/stage.h>
 #include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/property-map.h>
 #include <dali/devel-api/object/type-registry-helper.h>
+#include <dali/devel-api/rendering/renderer.h>
 #include <dali/devel-api/scripting/scripting.h>
 #include <dali/integration-api/debug.h>
 
@@ -37,10 +39,24 @@ const unsigned int GAUSSIAN_BLUR_DEFAULT_NUM_SAMPLES = 11;
 const unsigned int GAUSSIAN_BLUR_NUM_SAMPLES_INCREMENTATION = 10;
 const float GAUSSIAN_BLUR_BELL_CURVE_WIDTH = 4.5f;
 const float GAUSSIAN_BLUR_BELL_CURVE_WIDTH_INCREMENTATION = 5.f;
-const Pixel::Format GAUSSIAN_BLUR_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGB888;
+const Pixel::Format GAUSSIAN_BLUR_RENDER_TARGET_PIXEL_FORMAT = Pixel::RGBA8888;
 const float GAUSSIAN_BLUR_DOWNSAMPLE_WIDTH_SCALE = 0.5f;
 const float GAUSSIAN_BLUR_DOWNSAMPLE_HEIGHT_SCALE = 0.5f;
 
+const char* ALPHA_UNIFORM_NAME( "uAlpha" );
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+  varying mediump vec2 vTexCoord;\n
+  uniform sampler2D sTexture;\n
+  uniform lowp vec4 uColor;\n
+  uniform lowp float uAlpha;\n
+  \n
+  void main()\n
+  {\n
+    gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
+    gl_FragColor.a *= uAlpha;
+  }\n
+);
+
 /**
  * The constraint is used to blend the group of blurred images continuously with a unified blur strength property value which ranges from zero to one.
  */
@@ -56,17 +72,17 @@ struct ActorOpacityConstraint
   void operator()( float& current, const PropertyInputContainer& inputs )
   {
     float blurStrength = inputs[0]->GetFloat();
-    if(blurStrength <= mRange.x)
+    if(blurStrength < mRange.x)
     {
-      current = 1.f;
+      current = 0.f;
     }
     else if(blurStrength > mRange.y)
     {
-      current = 0.f;
+      current = 1.f;
     }
     else
     {
-      current = ( mRange.y - blurStrength) / ( mRange.y - mRange.x );
+      current = ( blurStrength - mRange.x) / ( mRange.y - mRange.x );
     }
   }
 
@@ -105,15 +121,15 @@ DALI_TYPE_REGISTRATION_END()
 
 SuperBlurView::SuperBlurView( unsigned int blurLevels )
 : Control( ControlBehaviour( DISABLE_SIZE_NEGOTIATION ) ),
-  mBlurLevels( blurLevels ),
+  mTargetSize( Vector2::ZERO ),
   mBlurStrengthPropertyIndex(Property::INVALID_INDEX),
-  mResourcesCleared( true ),
-  mTargetSize( Vector2::ZERO )
+  mBlurLevels( blurLevels ),
+  mResourcesCleared( true )
 {
   DALI_ASSERT_ALWAYS( mBlurLevels > 0 && " Minimal blur level is one, otherwise no blur is needed" );
-  mGaussianBlurView.assign( blurLevels, NULL );
+  mGaussianBlurView.assign( blurLevels, Toolkit::GaussianBlurView() );
   mBlurredImage.assign( blurLevels, FrameBufferImage() );
-  mImageActors.assign( blurLevels + 1, ImageActor() );
+  mRenderers.assign( blurLevels+1, Toolkit::ControlRenderer() );
 }
 
 SuperBlurView::~SuperBlurView()
@@ -139,50 +155,49 @@ void SuperBlurView::OnInitialize()
 {
   mBlurStrengthPropertyIndex = Self().RegisterProperty( "blurStrength", 0.f );
 
-  DALI_ASSERT_ALWAYS( mImageActors.size() == mBlurLevels+1 && "must synchronize the ImageActor group if blur levels got changed " );
-  for(unsigned int i=0; i<=mBlurLevels;i++)
-  {
-    mImageActors[i] = ImageActor::New(  );
-    mImageActors[i].SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
-    mImageActors[i].SetParentOrigin( ParentOrigin::CENTER );
-    mImageActors[i].SetZ(-static_cast<float>(i)*0.01f);
-    mImageActors[i].SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA );
-    Self().Add( mImageActors[i] );
-  }
+  Property::Map rendererMap;
+  rendererMap.Insert( "rendererType", "imageRenderer");
+
+  Property::Map shaderMap;
+  std::stringstream verterShaderString;
+  shaderMap[ "fragmentShader" ] = FRAGMENT_SHADER;
+  rendererMap.Insert( "shader", shaderMap );
 
-  for(unsigned int i=0; i < mBlurLevels; i++)
+  Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get();
+  for(unsigned int i=0; i<=mBlurLevels; i++)
   {
-    Constraint constraint = Constraint::New<float>( mImageActors[i], Actor::Property::COLOR_ALPHA, ActorOpacityConstraint(mBlurLevels, i) );
-    constraint.AddSource( ParentSource( mBlurStrengthPropertyIndex ) );
-    constraint.Apply();
+    mRenderers[i] = rendererFactory.GetControlRenderer( rendererMap );
+    mRenderers[i].SetDepthIndex(i);
   }
-
-  Self().SetSize(Stage::GetCurrent().GetSize());
 }
 
 void SuperBlurView::SetImage(Image inputImage)
 {
-  DALI_ASSERT_ALWAYS( mImageActors.size() == mBlurLevels+1 && "must synchronize the ImageActor group if blur levels got changed " );
-  DALI_ASSERT_ALWAYS( mBlurredImage.size() == mBlurLevels && "must synchronize the blurred image group if blur levels got changed " );
+  if( mTargetSize == Vector2::ZERO || mInputImage == inputImage)
+  {
+    return;
+  }
 
   ClearBlurResource();
 
-  mImageActors[0].SetImage( inputImage );
-
-  for(unsigned int i=1; i<=mBlurLevels;i++)
-  {
-    mImageActors[i].SetImage( mBlurredImage[i-1] );
-  }
+  mInputImage = inputImage;
+  Actor self = Self();
+  Toolkit::RendererFactory::Get().ResetRenderer( mRenderers[0], self, mInputImage );
 
   BlurImage( 0,  inputImage);
   for(unsigned int i=1; i<mBlurLevels;i++)
   {
-    BlurImage( i,  mBlurredImage[i-1]);
+    BlurImage( i, mBlurredImage[i-1]);
   }
 
   mResourcesCleared = false;
 }
 
+Image SuperBlurView::GetImage()
+{
+  return mInputImage;
+}
+
 Property::Index SuperBlurView::GetBlurStrengthPropertyIndex() const
 {
   return mBlurStrengthPropertyIndex;
@@ -221,13 +236,13 @@ void SuperBlurView::BlurImage( unsigned int idx, Image image )
                                                            GAUSSIAN_BLUR_DOWNSAMPLE_WIDTH_SCALE, GAUSSIAN_BLUR_DOWNSAMPLE_HEIGHT_SCALE, true );
   mGaussianBlurView[idx].SetParentOrigin(ParentOrigin::CENTER);
   mGaussianBlurView[idx].SetSize(mTargetSize);
+  Stage::GetCurrent().Add( mGaussianBlurView[idx] );
   mGaussianBlurView[idx].SetUserImageAndOutputRenderTarget( image, mBlurredImage[idx] );
+  mGaussianBlurView[idx].ActivateOnce();
   if( idx == mBlurLevels-1 )
   {
     mGaussianBlurView[idx].FinishedSignal().Connect( this, &SuperBlurView::OnBlurViewFinished );
   }
-  Stage::GetCurrent().Add( mGaussianBlurView[idx] );
-  mGaussianBlurView[idx].ActivateOnce();
 }
 
 void SuperBlurView::OnBlurViewFinished( Toolkit::GaussianBlurView blurView )
@@ -246,7 +261,6 @@ void SuperBlurView::ClearBlurResource()
     {
       Stage::GetCurrent().Remove( mGaussianBlurView[i] );
       mGaussianBlurView[i].Deactivate();
-      mGaussianBlurView[i].Reset();
     }
     mResourcesCleared = true;
   }
@@ -258,15 +272,79 @@ void SuperBlurView::OnSizeSet( const Vector3& targetSize )
   {
     mTargetSize = Vector2(targetSize);
 
-    for(unsigned int i=0; i<mBlurLevels;i++)
+    Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get();
+    Actor self = Self();
+    for(unsigned int i=1; i<=mBlurLevels;i++)
     {
-      float exponent = static_cast<float>(i+1);
-      mBlurredImage[i] = FrameBufferImage::New( mTargetSize.width/std::pow(2.f,exponent) , mTargetSize.height/std::pow(2.f,exponent),
+      float exponent = static_cast<float>(i);
+      mBlurredImage[i-1] = FrameBufferImage::New( mTargetSize.width/std::pow(2.f,exponent) , mTargetSize.height/std::pow(2.f,exponent),
                                                 GAUSSIAN_BLUR_RENDER_TARGET_PIXEL_FORMAT, Dali::Image::NEVER );
+      rendererFactory.ResetRenderer( mRenderers[i], self, mBlurredImage[i-1] );
+    }
+
+    if( mInputImage )
+    {
+      SetImage( mInputImage );
+    }
+
+    if( self.OnStage() )
+    {
+      for(unsigned int i=0; i<=mBlurLevels;i++)
+      {
+        mRenderers[i].SetOnStage( self );
+      }
     }
   }
 }
 
+void SuperBlurView::OnStageConnection( int depth )
+{
+  Control::OnStageConnection( depth );
+
+  if( mTargetSize == Vector2::ZERO )
+  {
+    return;
+  }
+
+  Actor self = Self();
+  mRenderers[0].SetOnStage( self );
+  for(unsigned int i=1; i<=mBlurLevels;i++)
+  {
+    mRenderers[i].SetOnStage( self );
+
+    Renderer renderer = self.GetRendererAt( i );
+    Property::Index index = renderer.RegisterProperty( ALPHA_UNIFORM_NAME, 0.f );
+    Constraint constraint = Constraint::New<float>( renderer, index, ActorOpacityConstraint(mBlurLevels, i-1) );
+    constraint.AddSource( Source( self, mBlurStrengthPropertyIndex ) );
+    constraint.Apply();
+  }
+}
+
+void SuperBlurView::OnStageDisconnection( )
+{
+  if( mTargetSize == Vector2::ZERO )
+  {
+    return;
+  }
+
+  Actor self = Self();
+  for(unsigned int i=0; i<mBlurLevels+1;i++)
+  {
+    mRenderers[i].SetOffStage( self );
+  }
+
+  Control::OnStageDisconnection();
+}
+
+Vector3 SuperBlurView::GetNaturalSize()
+{
+  if( mInputImage )
+  {
+    return Vector3( mInputImage.GetWidth(), mInputImage.GetHeight(), 0.f );
+  }
+  return Vector3::ZERO;
+}
+
 void SuperBlurView::SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
 {
   Toolkit::SuperBlurView superBlurView = Toolkit::SuperBlurView::DownCast( Dali::BaseHandle( object ) );
@@ -294,18 +372,19 @@ Property::Value SuperBlurView::GetProperty( BaseObject* object, Property::Index
 {
   Property::Value value;
 
-  Toolkit::SuperBlurView pushButton = Toolkit::SuperBlurView::DownCast( Dali::BaseHandle( object ) );
+  Toolkit::SuperBlurView blurView = Toolkit::SuperBlurView::DownCast( Dali::BaseHandle( object ) );
 
-  if( pushButton )
+  if( blurView )
   {
-    SuperBlurView& superBlurViewImpl( GetImpl( pushButton ) );
+    SuperBlurView& superBlurViewImpl( GetImpl( blurView ) );
 
     if( propertyIndex == Toolkit::SuperBlurView::Property::IMAGE )
     {
       Property::Map map;
-      if( !superBlurViewImpl.mImageActors.empty() && superBlurViewImpl.mImageActors[0] )
+      Image inputImage = superBlurViewImpl.GetImage();
+      if( !inputImage )
       {
-        Scripting::CreatePropertyMap( superBlurViewImpl.mImageActors[0], map );
+        Scripting::CreatePropertyMap( inputImage, map );
       }
       value = Property::Value( map );
     }
index 3488c2c..594693c 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali-toolkit/public-api/controls/control-impl.h>
 #include <dali-toolkit/devel-api/controls/super-blur-view/super-blur-view.h>
 #include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
+#include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
 
 namespace Dali
 {
@@ -53,6 +54,12 @@ public:
   void SetImage(Image inputImage);
 
   /**
+   * Get the image for blurring.
+   * @return The image for blurring.
+   */
+  Image GetImage();
+
+  /**
    * @copydoc Dali::Toolkit::SuperBlurView::GetBlurStrengthPropertyIndex
    */
   Property::Index GetBlurStrengthPropertyIndex() const;
@@ -119,6 +126,21 @@ private: // from Control
    */
   virtual void OnSizeSet(const Vector3& targetSize);
 
+  /**
+   * @copydoc CustomActorImpl::OnStageConnection()
+   */
+  virtual void OnStageConnection( int depth );
+
+  /**
+   * @copydoc CustomActorImpl::OnStageDisconnection()
+   */
+  virtual void OnStageDisconnection();
+
+  /**
+   * @copydoc CustomActorImpl::GetNaturalSize()
+   */
+  virtual Vector3 GetNaturalSize();
+
 private:
 
   /**
@@ -140,18 +162,17 @@ private:
   void ClearBlurResource();
 
 private:
-
-  unsigned int                           mBlurLevels;
-
-  Property::Index                        mBlurStrengthPropertyIndex;
-
   std::vector<Toolkit::GaussianBlurView> mGaussianBlurView;
   std::vector<FrameBufferImage>          mBlurredImage;
-  std::vector<ImageActor>                mImageActors;
-  bool                                   mResourcesCleared;
-
+  std::vector<Toolkit::ControlRenderer>  mRenderers;
+  Image                                  mInputImage;
   Vector2                                mTargetSize;
+
   Toolkit::SuperBlurView::SuperBlurViewSignal mBlurFinishedSignal; ///< Signal emitted when blur has completed.
+
+  Property::Index                        mBlurStrengthPropertyIndex;
+  unsigned int                           mBlurLevels;
+  bool                                   mResourcesCleared;
 };
 
 }
index c078a25..d15d488 100644 (file)
@@ -97,6 +97,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "horizontalAlignment",
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "verticalAlignment",                    STRING,    VERTICAL_ALIGNMENT                   )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "textColor",                            VECTOR4,   TEXT_COLOR                           )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "placeholderTextColor",                 VECTOR4,   PLACEHOLDER_TEXT_COLOR               )
+DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "inputColor",                           VECTOR4,   INPUT_COLOR                          )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadowOffset",                         VECTOR2,   SHADOW_OFFSET                        )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "shadowColor",                          VECTOR4,   SHADOW_COLOR                         )
 DALI_PROPERTY_REGISTRATION( Toolkit, TextField, "primaryCursorColor",                   VECTOR4,   PRIMARY_CURSOR_COLOR                 )
@@ -291,6 +292,7 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
           if( impl.mController->GetTextColor() != textColor )
           {
             impl.mController->SetTextColor( textColor );
+            impl.mController->SetInputColor( textColor );
             impl.mRenderer.Reset();
           }
         }
@@ -311,6 +313,17 @@ void TextField::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::TextField::Property::INPUT_COLOR:
+      {
+        if( impl.mController )
+        {
+          const Vector4 inputColor = value.Get< Vector4 >();
+          DALI_LOG_INFO( gLogFilter, Debug::General, "TextField %p INPUT_COLOR %f,%f,%f,%f\n", impl.mController.Get(), inputColor.r, inputColor.g, inputColor.b, inputColor.a );
+
+          impl.mController->SetInputColor( inputColor );
+        }
+        break;
+      }
       case Toolkit::TextField::Property::SHADOW_OFFSET:
       {
         if( impl.mController )
@@ -683,6 +696,14 @@ Property::Value TextField::GetProperty( BaseObject* object, Property::Index inde
         }
         break;
       }
+      case Toolkit::TextField::Property::INPUT_COLOR:
+      {
+        if( impl.mController )
+        {
+          value = impl.mController->GetInputColor();
+        }
+        break;
+      }
       case Toolkit::TextField::Property::SHADOW_OFFSET:
       {
         if ( impl.mController )
index 6c69704..6022879 100644 (file)
@@ -736,14 +736,13 @@ std::string TextSelectionPopup::GetPressedImage() const
    {
      const Size size( mOptionDividerSize.width, 0.0f ); // Height FILL_TO_PARENT
 
-     ImageActor divider = Toolkit::CreateSolidColorActor( Color::WHITE );
+     Toolkit::Control divider = Toolkit::Control::New();
 #ifdef DECORATOR_DEBUG
      divider.SetName("Text's popup divider");
 #endif
      divider.SetSize( size );
      divider.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::HEIGHT );
-     divider.SetColor( mDividerColor );
-     divider.SetSortModifier( DECORATION_DEPTH_INDEX );
+     divider.SetBackgroundColor( mDividerColor  );
      mToolbar.AddDivider( divider );
    }
  }
index 9ca5fb7..0c49761 100644 (file)
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/images/buffer-image.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector4.h>
 #include <dali/public-api/object/property-map.h>
@@ -156,22 +157,6 @@ void TextSelectionToolbar::OnStageConnection( int depth )
   // Call the Control::OnStageConnection() to set the depth of the background.
   Control::OnStageConnection( depth );
 
-  // Traverse the dividers and set the depth.
-  for( unsigned int i = 0; i < mDividerIndexes.Count(); ++i )
-  {
-    Actor divider = mTableOfButtons.GetChildAt( Toolkit::TableView::CellPosition( 0, mDividerIndexes[ i ] ) );
-
-    ImageActor dividerImageActor = ImageActor::DownCast( divider );
-    if( dividerImageActor )
-    {
-      dividerImageActor.SetSortModifier( DECORATION_DEPTH_INDEX + depth );
-    }
-    else
-    {
-      // TODO at the moment divider are image actors.
-    }
-  }
-
   // Texts are controls, they have their own OnStageConnection() implementation.
   // Icons are inside a TableView. It has it's own OnStageConnection() implementation.
 }
@@ -221,7 +206,8 @@ void TextSelectionToolbar::SetUp()
   mStencilLayer.SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
   mStencilLayer.SetParentOrigin( ParentOrigin::CENTER );
 
-  ImageActor stencil = CreateSolidColorActor( Color::RED );
+  BufferImage stencilImage = BufferImage::WHITE(); // ImageView needs an Image or does nothing
+  Toolkit::ImageView stencil = Toolkit::ImageView::New(stencilImage);
   stencil.SetDrawMode( DrawMode::STENCIL );
   stencil.SetVisible( true );
   stencil.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
index ad19367..6a8f4dc 100644 (file)
@@ -83,7 +83,11 @@ toolkit_src_files = \
    $(toolkit_src_dir)/text/bidirectional-support.cpp \
    $(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/logical-model-impl.cpp \
+   $(toolkit_src_dir)/text/markup-processor.cpp \
+   $(toolkit_src_dir)/text/markup-processor-color.cpp \
+   $(toolkit_src_dir)/text/markup-processor-helper-functions.cpp \
    $(toolkit_src_dir)/text/multi-language-support.cpp \
    $(toolkit_src_dir)/text/segmentation.cpp \
    $(toolkit_src_dir)/text/shaper.cpp \
index 1e55ba0..96d9554 100644 (file)
@@ -128,7 +128,7 @@ KeyboardFocusManager::~KeyboardFocusManager()
 {
 }
 
-bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
+bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor )
 {
   DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
 
@@ -140,41 +140,42 @@ bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
   return false;
 }
 
-bool KeyboardFocusManager::DoSetCurrentFocusActor(const unsigned int actorID)
+bool KeyboardFocusManager::DoSetCurrentFocusActor( const unsigned int actorID )
 {
   Actor rootActor = Stage::GetCurrent().GetRootLayer();
-  Actor actor = rootActor.FindChildById(actorID);
+  Actor actor = rootActor.FindChildById( actorID );
+  bool success = false;
 
-  // Check whether the actor is in the stage
-  if(actor)
+  // Check whether the actor is in the stage and is keyboard focusable.
+  if( actor && actor.IsKeyboardFocusable() )
   {
-    // Set the focus only when the actor is keyboard focusable
-    if(actor.IsKeyboardFocusable())
+    mIsFocusIndicatorEnabled = true;
+    // Draw the focus indicator upon the focused actor
+    if( mFocusIndicatorActor )
     {
-      // Draw the focus indicator upon the focused actor
-      if(mIsFocusIndicatorEnabled && mFocusIndicatorActor)
-      {
-        actor.Add(mFocusIndicatorActor);
-      }
+      actor.Add( mFocusIndicatorActor );
+    }
 
-      // Send notification for the change of focus actor
-      if( !mFocusChangedSignal.Empty() )
-      {
-        mFocusChangedSignal.Emit(GetCurrentFocusActor(), actor);
-      }
+    // Send notification for the change of focus actor
+    if( !mFocusChangedSignal.Empty() )
+    {
+      mFocusChangedSignal.Emit(GetCurrentFocusActor(), actor);
+    }
 
-      DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
+    DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] Focus Changed\n", __FUNCTION__, __LINE__);
 
-      // Save the current focused actor
-      mCurrentFocusActor = actorID;
+    // Save the current focused actor
+    mCurrentFocusActor = actorID;
 
-      DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
-      return true;
-    }
+    DALI_LOG_INFO( gLogFilter, Debug::General, "[%s:%d] SUCCEED\n", __FUNCTION__, __LINE__);
+    success = true;
+  }
+  else
+  {
+    DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
   }
 
-  DALI_LOG_WARNING("[%s:%d] FAILED\n", __FUNCTION__, __LINE__);
-  return false;
+  return success;
 }
 
 Actor KeyboardFocusManager::GetCurrentFocusActor()
@@ -458,8 +459,7 @@ void KeyboardFocusManager::CreateDefaultFocusIndicatorActor()
 {
   // Create a focus indicator actor shared by all the keyboard focusable actors
   Toolkit::ImageView focusIndicator = Toolkit::ImageView::New(FOCUS_BORDER_IMAGE_PATH);
-  focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
-  focusIndicator.SetPosition(Vector3(0.0f, 0.0f, 1.0f));
+  focusIndicator.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
 
   // Apply size constraint to the focus indicator
   focusIndicator.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
index 67c294b..ac8b317 100644 (file)
@@ -71,6 +71,11 @@ namespace
   };
 } // namespace
 
+uint8_t GetUtf8Length( uint8_t utf8LeadByte )
+{
+  return UTF8_LENGTH[utf8LeadByte];
+}
+
 uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length )
 {
   uint32_t numberOfCharacters = 0u;
index b60a344..730016b 100644 (file)
@@ -32,6 +32,15 @@ namespace Text
 {
 
 /**
+ * @brief Retrieves the number of bytes of a utf8 character.
+ *
+ * @param[in] utf8LeadByte The lead byte of the utf8 character.
+ *
+ * @return The number of bytes of the character.
+ */
+uint8_t GetUtf8Length( uint8_t utf8LeadByte );
+
+/**
  * @brief Retrieves the number of characters of the text array encoded in UTF8
  *
  * @param[in] utf8 The pointer to the UTF8 array.
diff --git a/dali-toolkit/internal/text/color-run.h b/dali-toolkit/internal/text/color-run.h
new file mode 100644 (file)
index 0000000..860ec7b
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __DALI_TOOLKIT_TEXT_COLOR_RUN_H__
+#define __DALI_TOOLKIT_TEXT_COLOR_RUN_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector4.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+#include <dali-toolkit/internal/text/glyph-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Run of characters with the same color.
+ */
+struct ColorRun
+{
+  CharacterRun characterRun; ///< The initial character index and the number of characters of the run.
+  Vector4      color;        ///< The color of the characters.
+};
+
+struct ColorGlyphRun
+{
+  GlyphRun glyphRun; ///< The initial glyph index and the number of glyphs of the run.
+  Vector4  color;    ///< The color of the glyphs.
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_COLOR_RUN_H__
diff --git a/dali-toolkit/internal/text/color-segmentation.cpp b/dali-toolkit/internal/text/color-segmentation.cpp
new file mode 100644 (file)
index 0000000..9169225
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/color-segmentation.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+
+#include <iostream>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+void SetColorSegmentationInfo( const Vector<ColorRun>& characterColorRuns,
+                               const Vector<GlyphIndex>& charactersToGlyph,
+                               const Vector<Length>& glyphsPerCharacter,
+                               Vector<ColorGlyphRun>& glyphColorRuns )
+{
+  const VectorBase::SizeType numberOfColorRuns = characterColorRuns.Count();
+
+  if( 0u == numberOfColorRuns )
+  {
+    // Nothing to do.
+    return;
+  }
+
+  // Resize the color runs for the glyphs.
+  glyphColorRuns.Resize( numberOfColorRuns );
+
+  // Get pointers to the buffers.
+  ColorGlyphRun* glyphColorRunsBuffer = glyphColorRuns.Begin();
+  const GlyphIndex* const charactersToGlyphBuffer = charactersToGlyph.Begin();
+  const Length* const glyphsPerCharacterBuffer = glyphsPerCharacter.Begin();
+
+  // Convert from characters to glyphs.
+  Length index = 0u;
+  for( Vector<ColorRun>::ConstIterator it = characterColorRuns.Begin(),
+         endIt = characterColorRuns.End();
+       it != endIt;
+       ++it, ++index )
+  {
+    const ColorRun& colorRun = *it;
+
+    if( 0u < colorRun.characterRun.numberOfCharacters )
+    {
+      // Get the next color glyph run.
+      ColorGlyphRun& colorGlyphRun = *( glyphColorRunsBuffer + index );
+      colorGlyphRun.color = colorRun.color;
+
+      // Convert the color run index from character to glyph.
+      colorGlyphRun.glyphRun.glyphIndex = *( charactersToGlyphBuffer + colorRun.characterRun.characterIndex );
+
+      // Get the index to the last character of the run.
+      const CharacterIndex lastIndex = colorRun.characterRun.characterIndex + colorRun.characterRun.numberOfCharacters - 1u;
+
+      // Calculate the number of glyphs.
+      colorGlyphRun.glyphRun.numberOfGlyphs = *( charactersToGlyphBuffer + lastIndex ) + *( glyphsPerCharacterBuffer + lastIndex ) - colorGlyphRun.glyphRun.glyphIndex;
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/color-segmentation.h b/dali-toolkit/internal/text/color-segmentation.h
new file mode 100644 (file)
index 0000000..9e52de1
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __DALI_TOOLKIT_TEXT_COLOR_SEGMENTATION_H__
+#define __DALI_TOOLKIT_TEXT_COLOR_SEGMENTATION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+class LogicalModel;
+
+/**
+ * @brief Creates color glyph runs.
+ *
+ * @param[in] characterColorRuns The color runs in characters (set in the mark-up string).
+ * @param[in] charactersToGlyph Conversion table from characters to glyphs.
+ * @param[in] glyphsPerCharacter Table with the number of glyphs for each character.
+ * @param[out] glyphColorRuns The color runs in glyphs.
+ */
+void SetColorSegmentationInfo( const Vector<ColorRun>& characterColorRuns,
+                               const Vector<GlyphIndex>& charactersToGlyph,
+                               const Vector<Length>& glyphsPerCharacter,
+                               Vector<ColorGlyphRun>& glyphColorRuns );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_COLOR_SEGMENTATION_H__
index 757eb4e..3e6e33d 100644 (file)
@@ -35,6 +35,8 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control-depth-index-ranges.h>
 #include <dali-toolkit/public-api/controls/default-controls/solid-color-actor.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
+#include <dali-toolkit/internal/controls/image-view/image-view-impl.h>
 
 #ifdef DEBUG_ENABLED
 #define DECORATOR_DEBUG
@@ -220,9 +222,9 @@ struct Decorator::Impl : public ConnectionTracker
     {
     }
 
-    ImageActor actor;
+    ImageView actor;
     Actor grabArea;
-    ImageActor markerActor;
+    ImageView markerActor;
 
     Vector2 position;
     Size    size;
@@ -523,10 +525,10 @@ struct Decorator::Impl : public ConnectionTracker
     DeterminePositionPopup();
   }
 
-  void CreateCursor( ImageActor& cursor, const Vector4& color )
+  void CreateCursor( Control& cursor, const Vector4& color )
   {
-    cursor = CreateSolidColorActor( color );
-    cursor.SetSortModifier( DECORATION_DEPTH_INDEX );
+    cursor = Control::New();
+    cursor.SetBackgroundColor( color );
     cursor.SetParentOrigin( ParentOrigin::TOP_LEFT ); // Need to set the default parent origin as CreateSolidColorActor() sets a different one.
     cursor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
   }
@@ -657,15 +659,17 @@ struct Decorator::Impl : public ConnectionTracker
     HandleImpl& grabHandle = mHandle[GRAB_HANDLE];
     if( !grabHandle.actor )
     {
-      grabHandle.actor = ImageActor::New( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] );
-      grabHandle.actor.SetSortModifier( DECORATION_DEPTH_INDEX );
+      grabHandle.actor = ImageView::New( mHandleImages[GRAB_HANDLE][HANDLE_IMAGE_RELEASED] );
+      GetImpl( grabHandle.actor).SetDepthIndex( DECORATION_DEPTH_INDEX );
       grabHandle.actor.SetAnchorPoint( AnchorPoint::TOP_CENTER );
       // Area that Grab handle responds to, larger than actual handle so easier to move
 #ifdef DECORATOR_DEBUG
       grabHandle.actor.SetName( "GrabHandleActor" );
       if ( Dali::Internal::gLogFilter->IsEnabledFor( Debug::Verbose ) )
       {
-        grabHandle.grabArea = Toolkit::CreateSolidColorActor( Vector4(0.0f, 0.0f, 0.0f, 0.0f), true, Color::RED, 1 );
+        grabHandle.grabArea = Control::New();
+        Toolkit::Control control = Toolkit::Control::DownCast( grabHandle.grabArea );
+        control.SetBackgroundColor( Vector4( 1.0f, 1.0f, 1.0f, 0.5f ) );
         grabHandle.grabArea.SetName( "GrabArea" );
       }
       else
@@ -701,7 +705,7 @@ struct Decorator::Impl : public ConnectionTracker
   {
     if( image )
     {
-      handle.markerActor = ImageActor::New( image );
+      handle.markerActor = ImageView::New( image );
       handle.markerActor.SetColor( mHandleColor );
       handle.actor.Add( handle.markerActor );
 
@@ -725,12 +729,12 @@ struct Decorator::Impl : public ConnectionTracker
     HandleImpl& primary = mHandle[ LEFT_SELECTION_HANDLE ];
     if( !primary.actor )
     {
-      primary.actor = ImageActor::New( mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
+      primary.actor = ImageView::New( mHandleImages[LEFT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
 #ifdef DECORATOR_DEBUG
       primary.actor.SetName("SelectionHandleOne");
 #endif
       primary.actor.SetAnchorPoint( AnchorPoint::TOP_RIGHT ); // Change to BOTTOM_RIGHT if Look'n'Feel requires handle above text.
-      primary.actor.SetSortModifier( DECORATION_DEPTH_INDEX );
+      GetImpl( primary.actor ).SetDepthIndex( DECORATION_DEPTH_INDEX );
       primary.actor.SetColor( mHandleColor );
 
       primary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move
@@ -759,12 +763,12 @@ struct Decorator::Impl : public ConnectionTracker
     HandleImpl& secondary = mHandle[ RIGHT_SELECTION_HANDLE ];
     if( !secondary.actor )
     {
-      secondary.actor = ImageActor::New( mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
+      secondary.actor = ImageView::New( mHandleImages[RIGHT_SELECTION_HANDLE][HANDLE_IMAGE_RELEASED] );
 #ifdef DECORATOR_DEBUG
       secondary.actor.SetName("SelectionHandleTwo");
 #endif
       secondary.actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); // Change to BOTTOM_LEFT if Look'n'Feel requires handle above text.
-      secondary.actor.SetSortModifier( DECORATION_DEPTH_INDEX );
+      GetImpl( secondary.actor ).SetDepthIndex( DECORATION_DEPTH_INDEX );
       secondary.actor.SetColor( mHandleColor );
 
       secondary.grabArea = Actor::New(); // Area that Grab handle responds to, larger than actual handle so easier to move
@@ -1635,8 +1639,8 @@ struct Decorator::Impl : public ConnectionTracker
   PropertyNotification mVerticalGreaterThanNotification;   ///< Notifies when the 'y' coord of the active layer is grater than a given value.
   PropertyNotification mHorizontalLessThanNotification;    ///< Notifies when the 'x' coord of the active layer is less than a given value.
   PropertyNotification mHorizontalGreaterThanNotification; ///< Notifies when the 'x' coord of the active layer is grater than a given value.
-  ImageActor           mPrimaryCursor;
-  ImageActor           mSecondaryCursor;
+  Control              mPrimaryCursor;
+  Control              mSecondaryCursor;
 
   Actor               mHighlightActor;            ///< Actor to display highlight
   Renderer            mHighlightRenderer;
@@ -1837,10 +1841,10 @@ void Decorator::SetHandleActive( HandleType handleType, bool active )
     // state when the power button is pressed and the application goes to background.
     mImpl->mHandle[handleType].pressed = false;
     Image imageReleased = mImpl->mHandleImages[handleType][HANDLE_IMAGE_RELEASED];
-    ImageActor imageActor = mImpl->mHandle[handleType].actor;
-    if( imageReleased && imageActor )
+    ImageView imageView = mImpl->mHandle[handleType].actor;
+    if( imageReleased && imageView )
     {
-       imageActor.SetImage( imageReleased );
+      imageView.SetImage( imageReleased );
     }
   }
 
diff --git a/dali-toolkit/internal/text/input-style.h b/dali-toolkit/internal/text/input-style.h
new file mode 100644 (file)
index 0000000..cd562ec
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_TOOLKIT_TEXT_INPUT_STYLE_H__
+#define __DALI_TOOLKIT_TEXT_INPUT_STYLE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * The input text's style.
+ */
+struct InputStyle
+{
+Vector4 textColor;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_INPUT_STYLE_H__
index e8e906f..10b2a49 100644 (file)
 // CLASS HEADER
 #include <dali-toolkit/internal/text/logical-model-impl.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/input-style.h>
+#include <dali-toolkit/internal/text/text-style-run-container.h>
+
 namespace Dali
 {
 
@@ -241,6 +245,51 @@ CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualChar
   return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
 }
 
+void LogicalModel::UpdateTextStyleRuns( CharacterIndex index, int numberOfCharacters )
+{
+  const Length totalNumberOfCharacters = mText.Count();
+
+  // Process the color runs.
+  Vector<ColorRun> removedColorRuns;
+  UpdateCharacterRuns<ColorRun>( index,
+                                 numberOfCharacters,
+                                 totalNumberOfCharacters,
+                                 mColorRuns,
+                                 removedColorRuns );
+}
+
+void LogicalModel::RetrieveStyle( CharacterIndex index, InputStyle& style )
+{
+  unsigned int runIndex = 0u;
+  unsigned int lastRunIndex = 0u;
+  bool overriden = false;
+
+  // Set the text color.
+  for( Vector<ColorRun>::ConstIterator it = mColorRuns.Begin(),
+         endIt = mColorRuns.End();
+       it != endIt;
+       ++it, ++runIndex )
+  {
+    const ColorRun& colorRun = *it;
+
+    if( ( colorRun.characterRun.characterIndex <= index ) &&
+        ( index < colorRun.characterRun.characterIndex + colorRun.characterRun.numberOfCharacters ) )
+    {
+      lastRunIndex = runIndex;
+      overriden = true;
+    }
+  }
+
+  // Set the text's color if it's overriden.
+  if( overriden )
+  {
+    style.textColor = ( *( mColorRuns.Begin() + lastRunIndex ) ).color;
+  }
+
+  runIndex = 0u;
+  overriden = false;
+}
+
 LogicalModel::~LogicalModel()
 {
 }
index 43ef817..6842cf6 100644 (file)
@@ -26,6 +26,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-line-info-run.h>
 #include <dali-toolkit/internal/text/bidirectional-paragraph-info-run.h>
+#include <dali-toolkit/internal/text/color-run.h>
 #include <dali-toolkit/internal/text/font-run.h>
 #include <dali-toolkit/internal/text/script-run.h>
 
@@ -40,6 +41,7 @@ namespace Text
 
 class LogicalModel;
 typedef IntrusivePtr<LogicalModel> LogicalModelPtr;
+struct InputStyle;
 
 /**
  * @brief A logical text model contains layout independent information.
@@ -106,6 +108,22 @@ public:
    */
   CharacterIndex GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const;
 
+  /**
+   * @brief Updates the text's style runs with the added or removed text.
+   *
+   * @param[in] index The character's index.
+   * @param[in] numberOfCharacters The number of characters added or removed. If the value is negative the characters are removed.
+   */
+  void UpdateTextStyleRuns( CharacterIndex index, int numberOfCharacters );
+
+  /**
+   * @brief Retrieves the text's style for the given character index.
+   *
+   * @param[in] index The character index.
+   * @param[out] style The text's style in the given style.
+   */
+  void RetrieveStyle( CharacterIndex index, InputStyle& style );
+
 protected:
 
   /**
@@ -131,6 +149,7 @@ public:
   Vector<Character>                     mText;
   Vector<ScriptRun>                     mScriptRuns;
   Vector<FontRun>                       mFontRuns;
+  Vector<ColorRun>                      mColorRuns;
   Vector<LineBreakInfo>                 mLineBreakInfo;
   Vector<WordBreakInfo>                 mWordBreakInfo;
   Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
diff --git a/dali-toolkit/internal/text/markup-processor-color.cpp b/dali-toolkit/internal/text/markup-processor-color.cpp
new file mode 100644 (file)
index 0000000..2fd826d
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor-color.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace
+{
+const std::string XHTML_VALUE_ATTRIBUTE("value");
+}
+
+void ProcessColorTag( const Tag& tag, ColorRun& colorRun )
+{
+  for( Vector<Attribute>::ConstIterator it = tag.attributes.Begin(),
+         endIt = tag.attributes.End();
+       it != endIt;
+       ++it )
+  {
+    const Attribute& attribute( *it );
+    if( TokenComparison( XHTML_VALUE_ATTRIBUTE, attribute.nameBuffer, attribute.nameLength ) )
+    {
+      ColorStringToVector4( attribute.valueBuffer, attribute.valueLength, colorRun.color );
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-color.h b/dali-toolkit/internal/text/markup-processor-color.h
new file mode 100644 (file)
index 0000000..bf3ea20
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H__
+#define __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+struct Tag;
+struct ColorRun;
+
+/**
+ * @brief Retrieves the color value from the tag and sets it to the color run.
+ *
+ * @param[in] tag The color tag and its attributes.
+ * @param[in,out] colorRun The color run.
+ */
+void ProcessColorTag( const Tag& tag, ColorRun& colorRun );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_COLOR_H__
diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.cpp b/dali-toolkit/internal/text/markup-processor-helper-functions.cpp
new file mode 100644 (file)
index 0000000..c460747
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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/markup-processor-helper-functions.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <stdlib.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace
+{
+const char WHITE_SPACE       = 0x20; // ASCII value of the white space.
+const char LAST_UPPER_CASE   = 0x5b; // ASCII value of the one after the last upper case character (Z).
+const char TO_LOWER_CASE     = 32;   // Value to add to a upper case character to transform it into a lower case.
+
+const char WEB_COLOR_TOKEN( '#' );
+const char* const HEX_COLOR_TOKEN( "0x" );
+const char* const ALPHA_ONE( "FF" );
+
+const std::string BLACK_COLOR( "black" );
+const std::string WHITE_COLOR( "white" );
+const std::string RED_COLOR( "red" );
+const std::string GREEN_COLOR( "green" );
+const std::string BLUE_COLOR( "blue" );
+const std::string YELLOW_COLOR( "yellow" );
+const std::string MAGENTA_COLOR( "magenta" );
+const std::string CYAN_COLOR( "cyan" );
+const std::string TRANSPARENT_COLOR( "transparent" );
+}
+
+bool TokenComparison( const std::string& string1, const char* const stringBuffer2, Length length )
+{
+  const Length stringSize = string1.size();
+  if( stringSize != length )
+  {
+    // Early return. Strings have different sizes.
+    return false;
+  }
+
+  const char* const stringBuffer1 = string1.c_str();
+
+  for( std::size_t index = 0; index < stringSize; ++index )
+  {
+    char character = *( stringBuffer2 + index );
+    if( *( stringBuffer1 + index ) != ( ( ( character < LAST_UPPER_CASE ) && ( '0' != character ) ) ? character + TO_LOWER_CASE : character ) )
+    {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void SkipWhiteSpace( const char*& markupStringBuffer,
+                     const char* const markupStringEndBuffer )
+{
+  for( ; ( WHITE_SPACE >= *markupStringBuffer ) && ( markupStringBuffer < markupStringEndBuffer ); ++markupStringBuffer );
+}
+
+unsigned int StringToHex( const char* const uintStr )
+{
+  return static_cast<unsigned int>( strtoul( uintStr, NULL, 16 ) );
+}
+
+void UintColorToVector4( unsigned int color, Vector4& retColor )
+{
+  retColor.a = static_cast<float>( ( color & 0xFF000000 ) >> 24u ) / 255.f;
+  retColor.r = static_cast<float>( ( color & 0x00FF0000 ) >> 16u ) / 255.f;
+  retColor.g = static_cast<float>( ( color & 0x0000FF00 ) >> 8u ) / 255.f;
+  retColor.b = static_cast<float>( color & 0x000000FF ) / 255.f;
+}
+
+void ColorStringToVector4( const char* const colorStr, Length length, Vector4& retColor )
+{
+  if( WEB_COLOR_TOKEN == *colorStr )
+  {
+    std::string webColor( colorStr + 1u, length - 1u );
+    if( 4u == length )                      // 3 component web color #F00 (red)
+    {
+      webColor.insert( 2u, &( webColor[2] ), 1u );
+      webColor.insert( 1u, &( webColor[1] ), 1u );
+      webColor.insert( 0u, &( webColor[0] ), 1u );
+      webColor.insert( 0u, ALPHA_ONE );
+    }
+    else if( 7u == length )                 // 6 component web color #FF0000 (red)
+    {
+      webColor.insert( 0u, ALPHA_ONE );
+    }
+
+    UintColorToVector4( StringToHex( webColor.c_str() ), retColor );
+  }
+  else if( TokenComparison( HEX_COLOR_TOKEN, colorStr, 2u ) )
+  {
+    UintColorToVector4( StringToHex( colorStr + 2u ), retColor );
+  }
+  else if( TokenComparison( BLACK_COLOR, colorStr, length ) )
+  {
+    retColor = Color::BLACK;
+  }
+  else if( TokenComparison( WHITE_COLOR, colorStr, length ) )
+  {
+    retColor = Color::WHITE;
+  }
+  else if( TokenComparison( RED_COLOR, colorStr, length ) )
+  {
+    retColor = Color::RED;
+  }
+  else if( TokenComparison( GREEN_COLOR, colorStr, length ) )
+  {
+    retColor = Color::GREEN;
+  }
+  else if( TokenComparison( BLUE_COLOR, colorStr, length ) )
+  {
+    retColor = Color::BLUE;
+  }
+  else if( TokenComparison( YELLOW_COLOR, colorStr, length ) )
+  {
+    retColor = Color::YELLOW;
+  }
+  else if( TokenComparison( MAGENTA_COLOR, colorStr, length ) )
+  {
+    retColor = Color::MAGENTA;
+  }
+  else if( TokenComparison( CYAN_COLOR, colorStr, length ) )
+  {
+    retColor = Color::CYAN;
+  }
+  else if( TokenComparison( TRANSPARENT_COLOR, colorStr, length ) )
+  {
+    retColor = Color::TRANSPARENT;
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor-helper-functions.h b/dali-toolkit/internal/text/markup-processor-helper-functions.h
new file mode 100644 (file)
index 0000000..5934467
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H__
+#define __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/text-definitions.h>
+
+namespace Dali
+{
+
+struct Vector4;
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Stores an attribute pair: name, value.
+ */
+struct Attribute
+{
+  const char* nameBuffer;
+  const char* valueBuffer;
+  Length nameLength;
+  Length valueLength;
+};
+
+/**
+ * @brief Stores a tag and its attributes.
+ */
+ struct Tag
+ {
+   Vector<Attribute> attributes;
+   const char* buffer;
+   Length length;
+   bool isEndTag;
+ };
+
+/**
+ * @brief Compare if two tokens are equal.
+ *
+ * @pre @p string1 must be lower case. (The html-ish constant tokens)
+ * The @p stringBuffer2 parameter is transformed to lower case.
+ * This function is used in the mark-up parser.
+ * It has no sense to transform the constants html-ish tokens to lower case when
+ * it's known they already are.
+ *
+ * @param[in] string1 The html-ish constant token.
+ * @param[in] stringBuffer2 Pointer to the html-ish token buffer.
+ * @param[in] length The length of the html-ish token.
+ *
+ * @return @e true if both strings are equal.
+ */
+bool TokenComparison( const std::string& string1, const char* const stringBuffer2, Length length );
+
+/**
+ * @brief Skips any unnecessary white space.
+ *
+ * @param[in,out] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character.
+ * @param[in] markupStringEndBuffer Pointer to one character after the end of the mark-up string buffer.
+ */
+void SkipWhiteSpace( const char*& markupStringBuffer,
+                     const char* const markupStringEndBuffer );
+
+/**
+ * @brief Converts a string into an hexadecimal unsigned int.
+ *
+ * @param[in] uintStr An hexadecimal unsigned int packed inside a string.
+ *
+ * @return The hexadecimal value.
+ */
+unsigned int StringToHex( const char* const uintStr );
+
+/**
+ * @brief Converts an ARGB color packed in 4 byte unsigned int into a Vector4 color used in Dali.
+ *
+ * @param[in] color An ARGB color packed in an unsigned int.
+ * @param[out] retColor A Vector4 with the converted color.
+ */
+void UintColorToVector4( unsigned int color, Vector4& retColor );
+
+/**
+ * @brief Converts a color packed inside a string into an ARGB Vector4 color.
+ *
+ * The string color could be in hexadecimal ( 0xFF0000FF ), webcolor ( #0000FF or #00F ) or some constant values:
+ * black, white, red, green, blue, yellow, magenta, cyan, transparent.
+ *
+ * @param[in] colorStr A color packed inside a string.
+ * @param[in] length The length of the color string.
+ * @param[out] retColor A color packed inside a Vector4.
+ */
+void ColorStringToVector4( const char* const colorStr, Length length, Vector4& retColor );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_HELPER_FUNCTIONS_H__
diff --git a/dali-toolkit/internal/text/markup-processor.cpp b/dali-toolkit/internal/text/markup-processor.cpp
new file mode 100644 (file)
index 0000000..51a1efb
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include <dali-toolkit/internal/text/markup-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-set-conversion.h>
+#include <dali-toolkit/internal/text/markup-processor-color.h>
+#include <dali-toolkit/internal/text/markup-processor-helper-functions.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace
+{
+// HTML-ISH tag and attribute constants.
+// Note they must be lower case in order to make the comparison to work
+// as the parser converts all the read tags to lower case.
+const std::string XHTML_COLOR_TAG("color");
+const std::string XHTML_FONT_TAG("font");
+const std::string XHTML_B_TAG("b");
+const std::string XHTML_I_TAG("i");
+const std::string XHTML_U_TAG("u");
+const std::string XHTML_SHADOW_TAG("shadow");
+const std::string XHTML_GLOW_TAG("glow");
+const std::string XHTML_OUTLINE_TAG("outline");
+
+const char LESS_THAN         = '<';
+const char GREATER_THAN      = '>';
+const char EQUAL             = '=';
+const char QUOTATION_MARK    = '\'';
+const char LINE_SEPARATOR_CR = 0x0D; // Carriage return character  CR
+const char LINE_SEPARATOR_LF = 0x0A; // New line character         LF
+const char SLASH             = '/';
+const char BACK_SLASH        = '\\';
+
+const char WHITE_SPACE       = 0x20; // ASCII value of the white space.
+
+const unsigned int MAX_NUM_OF_ATTRIBUTES =  5u; ///< The font tag has the 'family', 'size' 'weight', 'width' and 'slant' attrubutes.
+
+const unsigned int DEFAULT_VECTOR_SIZE   = 16u; ///< Default size of run vectors.
+
+/**
+ * @brief Struct used to retrieve the style runs from the mark-up string.
+ */
+struct StyleStack
+{
+  typedef VectorBase::SizeType RunIndex;
+
+  Vector<RunIndex>  stack;    ///< Use a vector as a style stack. Stores the indices pointing where the run is stored inside the logical model.
+  unsigned int topIndex; ///< Points the top of the stack.
+
+  StyleStack()
+  : stack(),
+    topIndex( 0u )
+  {
+    stack.Resize( DEFAULT_VECTOR_SIZE );
+  }
+
+  void Push( RunIndex index )
+  {
+    // Check if there is space inside the style stack.
+    const VectorBase::SizeType size = stack.Count();
+    if( topIndex >= size )
+    {
+      // Resize the style stack.
+      stack.Resize( 2u * size );
+    }
+
+    // Set the run index in the top of the stack.
+    *( stack.Begin() + topIndex ) = index;
+
+    // Reposition the pointer to the top of the stack.
+    ++topIndex;
+  }
+
+  RunIndex Pop()
+  {
+    // Pop the top of the stack.
+    --topIndex;
+    return *( stack.Begin() + topIndex );
+  }
+};
+
+/**
+ * @brief Splits the tag string into the tag name and its attributes.
+ *
+ * The attributes are stored in a vector in the tag.
+ *
+ * @param[in,out] tag The tag.
+ */
+void ParseAttributes( Tag& tag )
+{
+  tag.attributes.Resize( MAX_NUM_OF_ATTRIBUTES );
+
+  // Find first the tag name.
+  bool isQuotationOpen = false;
+
+  const char* tagBuffer = tag.buffer;
+  const char* const tagEndBuffer = tagBuffer + tag.length;
+  tag.length = 0u;
+  for( ; tagBuffer < tagEndBuffer; ++tagBuffer )
+  {
+    const char character = *tagBuffer;
+    if( WHITE_SPACE < character )
+    {
+      ++tag.length;
+    }
+    else
+    {
+      // Stops counting the length of the tag when a white space is found.
+      // @note a white space is the WHITE_SPACE character and anything below as 'tab', 'return' or 'control characters'.
+      break;
+    }
+  }
+  SkipWhiteSpace( tagBuffer, tagEndBuffer );
+
+  // Find the attributes.
+  unsigned int attributeIndex = 0u;
+  const char* nameBuffer = NULL;
+  const char* valueBuffer = NULL;
+  Length nameLength = 0u;
+  Length valueLength = 0u;
+
+  bool addToNameValue = true;
+  Length numberOfWhiteSpace = 0u;
+  for( ; tagBuffer < tagEndBuffer; ++tagBuffer )
+  {
+    const char character = *tagBuffer;
+    if( ( WHITE_SPACE >= character ) && !isQuotationOpen )
+    {
+      if( NULL != valueBuffer )
+      {
+        // Remove white spaces at the end of the value.
+        valueLength -= numberOfWhiteSpace;
+      }
+
+      if( ( NULL != nameBuffer ) && ( NULL != valueBuffer ) )
+      {
+        // Every time a white space is found, a new attribute is created and stored in the attributes vector.
+        Attribute& attribute = *( tag.attributes.Begin() + attributeIndex );
+        ++attributeIndex;
+
+        attribute.nameBuffer = nameBuffer;
+        attribute.valueBuffer = valueBuffer;
+        attribute.nameLength = nameLength;
+        attribute.valueLength = valueLength;
+
+        nameBuffer = NULL;
+        valueBuffer = NULL;
+        nameLength = 0u;
+        valueLength = 0u;
+
+        addToNameValue = true; // next read characters will be added to the name.
+      }
+    }
+    else if( EQUAL == character ) // '='
+    {
+      addToNameValue = false; // next read characters will be added to the value.
+      SkipWhiteSpace( tagBuffer, tagEndBuffer );
+    }
+    else if( QUOTATION_MARK == character ) // '\''
+    {
+      // Do not add quotation marks to neither name nor value.
+      isQuotationOpen = !isQuotationOpen;
+
+      if( isQuotationOpen )
+      {
+        ++tagBuffer;
+        SkipWhiteSpace( tagBuffer, tagEndBuffer );
+        --tagBuffer;
+      }
+    }
+    else
+    {
+      // Adds characters to the name or the value.
+      if( addToNameValue )
+      {
+        if( NULL == nameBuffer )
+        {
+          nameBuffer = tagBuffer;
+        }
+        ++nameLength;
+      }
+      else
+      {
+        if( isQuotationOpen )
+        {
+          if( WHITE_SPACE >= character )
+          {
+            ++numberOfWhiteSpace;
+          }
+          else
+          {
+            numberOfWhiteSpace = 0u;
+          }
+        }
+        if( NULL == valueBuffer )
+        {
+          valueBuffer = tagBuffer;
+        }
+        ++valueLength;
+      }
+    }
+  }
+
+  if( NULL != valueBuffer )
+  {
+    // Remove white spaces at the end of the value.
+    valueLength -= numberOfWhiteSpace;
+  }
+
+  if( ( NULL != nameBuffer ) && ( NULL != valueBuffer ) )
+  {
+    // Checks if the last attribute needs to be added.
+    Attribute& attribute = *( tag.attributes.Begin() + attributeIndex );
+    ++attributeIndex;
+
+    attribute.nameBuffer = nameBuffer;
+    attribute.valueBuffer = valueBuffer;
+    attribute.nameLength = nameLength;
+    attribute.valueLength = valueLength;
+  }
+
+  // Resize the vector of attributes.
+  tag.attributes.Resize( attributeIndex );
+}
+
+/**
+ * @brief It parses a tag and its attributes if the given iterator @e it is pointing at a tag beginning.
+ *
+ * @param[in,out] markupStringBuffer The mark-up string buffer. It's a const iterator pointing the current character.
+ * @param[in] markupStringEndBuffer Pointer to one character after the end of the mark-up string buffer.
+ * @param[out] tag The tag with its attributes.
+ *
+ * @return @e true if the iterator @e it is pointing a mark-up tag. Otherwise @e false.
+ */
+bool IsTag( const char*& markupStringBuffer,
+            const char* const markupStringEndBuffer,
+            Tag& tag )
+{
+  bool isTag = false;
+  bool isQuotationOpen = false;
+  bool attributesFound = false;
+  tag.isEndTag = false;
+
+  const char character = *markupStringBuffer;
+  if( LESS_THAN == character ) // '<'
+  {
+    tag.buffer = NULL;
+    tag.length = 0u;
+
+    // if the iterator is pointing to a '<' character, then check if it's a mark-up tag is needed.
+    ++markupStringBuffer;
+    if( markupStringBuffer < markupStringEndBuffer )
+    {
+      SkipWhiteSpace( markupStringBuffer, markupStringEndBuffer );
+
+      for( ; ( !isTag ) && ( markupStringBuffer < markupStringEndBuffer ); ++markupStringBuffer )
+      {
+        const char character = *markupStringBuffer;
+
+        if( SLASH == character ) // '/'
+        {
+          // if the tag has a '/' then it's an end or empty tag.
+          tag.isEndTag = true;
+
+          if( ( markupStringBuffer + 1u < markupStringEndBuffer ) && ( WHITE_SPACE >= *( markupStringBuffer + 1u ) ) && ( !isQuotationOpen ) )
+          {
+            ++markupStringBuffer;
+            SkipWhiteSpace( markupStringBuffer, markupStringEndBuffer );
+            --markupStringBuffer;
+          }
+        }
+        else if( GREATER_THAN == character ) // '>'
+        {
+          isTag = true;
+        }
+        else if( QUOTATION_MARK == character )
+        {
+          isQuotationOpen = !isQuotationOpen;
+          ++tag.length;
+        }
+        else if( WHITE_SPACE >= character ) // ' '
+        {
+          // If the tag contains white spaces then it may have attributes.
+          if( !isQuotationOpen )
+          {
+            attributesFound = true;
+          }
+          ++tag.length;
+        }
+        else
+        {
+          if( NULL == tag.buffer )
+          {
+            tag.buffer = markupStringBuffer;
+          }
+
+          // If it's not any of the 'special' characters then just add it to the tag string.
+          ++tag.length;
+        }
+      }
+    }
+
+    // If the tag string has white spaces, then parse the attributes is needed.
+    if( attributesFound )
+    {
+      ParseAttributes( tag );
+    }
+  }
+
+  return isTag;
+}
+
+} // namespace
+
+void ProcessMarkupString( const std::string& markupString, MarkupProcessData& markupProcessData )
+{
+  // Reserve space for the plain text.
+  const Length markupStringSize = markupString.size();
+  markupProcessData.markupProcessedText.reserve( markupStringSize );
+
+  // Stores a struct with the index to the first character of the run, the type of run and its parameters.
+  StyleStack styleStack;
+
+  // Points the next free position in the vector of runs.
+  StyleStack::RunIndex colorRunIndex = 0u;
+
+  // Give an initial default value to the model's vectors.
+  markupProcessData.colorRuns.Reserve( DEFAULT_VECTOR_SIZE );
+
+  // Get the mark-up string buffer.
+  const char* markupStringBuffer = markupString.c_str();
+  const char* const markupStringEndBuffer = markupStringBuffer + markupStringSize;
+
+  Tag tag;
+  CharacterIndex characterIndex = 0u;
+  for( ; markupStringBuffer < markupStringEndBuffer; )
+  {
+    if( IsTag( markupStringBuffer,
+               markupStringEndBuffer,
+               tag ) )
+    {
+      if( TokenComparison( XHTML_COLOR_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new color run.
+          ColorRun colorRun;
+          colorRun.characterRun.numberOfCharacters = 0u;
+
+          // Set the start character index.
+          colorRun.characterRun.characterIndex = characterIndex;
+
+          // Fill the run with the attributes.
+          ProcessColorTag( tag, colorRun );
+
+          // Push the color run in the logical model.
+          markupProcessData.colorRuns.PushBack( colorRun );
+
+          // Push the index of the run into the stack.
+          styleStack.Push( colorRunIndex );
+
+          // Point the next color run.
+          ++colorRunIndex;
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+          ColorRun& colorRun = *( markupProcessData.colorRuns.Begin() + styleStack.Pop() );
+          colorRun.characterRun.numberOfCharacters = characterIndex - colorRun.characterRun.characterIndex;
+        }
+      } // <color></color>
+      else if( TokenComparison( XHTML_I_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new font run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <i></i>
+      else if( TokenComparison( XHTML_U_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new underline run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <u></u>
+      else if( TokenComparison( XHTML_B_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new font run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <b></b>
+      else if( TokenComparison( XHTML_FONT_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new font run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <font></font>
+      else if( TokenComparison( XHTML_SHADOW_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new shadow run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <shadow></shadow>
+      else if( TokenComparison( XHTML_GLOW_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new glow run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <glow></glow>
+      else if( TokenComparison( XHTML_OUTLINE_TAG, tag.buffer, tag.length ) )
+      {
+        if( !tag.isEndTag )
+        {
+          // Create a new outline run.
+        }
+        else
+        {
+          // Pop the top of the stack and set the number of characters of the run.
+        }
+      } // <outline></outline>
+    }  // end if( IsTag() )
+    else
+    {
+      unsigned char character = *markupStringBuffer;
+
+      if( ( BACK_SLASH == character ) && ( markupStringBuffer + 1u < markupStringEndBuffer ) )
+      {
+        // Adding < or > special character.
+        const unsigned char nextCharacter = *( markupStringBuffer + 1u );
+        if( ( LESS_THAN == nextCharacter ) || ( GREATER_THAN == nextCharacter ) )
+        {
+          character = nextCharacter;
+          ++markupStringBuffer;
+        }
+      }
+      else if( ( LINE_SEPARATOR_CR == character ) && ( markupStringBuffer + 1u < markupStringEndBuffer ) )
+      {
+        // Replacing CR+LF end line by LF.
+        if( LINE_SEPARATOR_LF == *( markupStringBuffer + 1u ) )
+        {
+          character = LINE_SEPARATOR_LF;
+          ++markupStringBuffer;
+        }
+      }
+
+      const unsigned char numberOfBytes = GetUtf8Length( character );
+
+      markupProcessData.markupProcessedText.push_back( character );
+      for( unsigned char i = 1u; i < numberOfBytes; ++i )
+      {
+        ++markupStringBuffer;
+        markupProcessData.markupProcessedText.push_back( *markupStringBuffer );
+      }
+
+      ++characterIndex;
+      ++markupStringBuffer;
+    }
+  }
+
+  // Resize the model's vectors.
+  if( 0u == colorRunIndex )
+  {
+    markupProcessData.colorRuns.Clear();
+  }
+  else
+  {
+    markupProcessData.colorRuns.Resize( colorRunIndex );
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/text/markup-processor.h b/dali-toolkit/internal/text/markup-processor.h
new file mode 100644 (file)
index 0000000..966622e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
+#define __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/color-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Keeps the plain text and references to vectors from the model which stores runs with text styles.
+ */
+struct MarkupProcessData
+{
+  MarkupProcessData( Vector<ColorRun>& colorRuns )
+  : colorRuns( colorRuns ),
+    markupProcessedText()
+  {}
+
+  Vector<ColorRun>&           colorRuns;
+
+  std::string                 markupProcessedText;
+};
+
+/**
+ * @brief Process the mark-up string.
+ *
+ * @param[in] markupString The mark-up string.
+ * @param[out] markupProcessData The plain text and the style.
+ */
+void ProcessMarkupString( const std::string& markupString, MarkupProcessData& markupProcessData );
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_MARKUP_PROCESSOR_H__
index f2c328e..0a90ef2 100644 (file)
@@ -32,27 +32,30 @@ namespace
 const char* VERTEX_SHADER = MAKE_SHADER(
 attribute mediump vec2    aPosition;
 attribute mediump vec2    aTexCoord;
+attribute mediump vec4    aColor;
 uniform   mediump vec2    uOffset;
 uniform   mediump mat4    uMvpMatrix;
 varying   mediump vec2    vTexCoord;
+varying   mediump vec4    vColor;
 
 void main()
 {
   mediump vec4 position = vec4( aPosition.xy + uOffset, 0.0, 1.0 );
   gl_Position = uMvpMatrix * position;
   vTexCoord = aTexCoord;
+  vColor = aColor;
 }
 );
 
 const char* FRAGMENT_SHADER_L8 = MAKE_SHADER(
-uniform lowp    vec4      uColor;
 uniform         sampler2D sTexture;
 varying mediump vec2      vTexCoord;
+varying mediump vec4      vColor;
 
 void main()
 {
   mediump vec4 color = texture2D( sTexture, vTexCoord );
-  gl_FragColor = vec4( uColor.rgb, uColor.a * color.r );
+  gl_FragColor = vec4( vColor.rgb, vColor.a * color.r );
 }
 );
 
index cf774b3..3449362 100644 (file)
@@ -84,6 +84,7 @@ public:
   {
     Vector2 mPosition;        ///< Vertex posiiton
     Vector2 mTexCoords;       ///< Vertex texture co-ordinates
+    Vector4 mColor;           ///< Vertex color
   };
 
   struct Mesh2D
index 4cb19ed..33423eb 100644 (file)
@@ -59,12 +59,10 @@ struct AtlasRenderer::Impl
   struct MeshRecord
   {
     MeshRecord()
-    : mColor( Color::BLACK ),
-      mAtlasId( 0 )
+    : mAtlasId( 0u )
     {
     }
 
-    Vector4 mColor;
     uint32_t mAtlasId;
     AtlasManager::Mesh2D mMesh;
     FrameBufferImage mBuffer;
@@ -82,7 +80,7 @@ struct AtlasRenderer::Impl
       mRight( 0.0f ),
       mUnderlinePosition( 0.0f ),
       mUnderlineThickness( 0.0f ),
-      mMeshRecordIndex( 0 )
+      mMeshRecordIndex( 0u )
     {
     }
 
@@ -142,6 +140,7 @@ struct AtlasRenderer::Impl
 
     mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
     mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2;
+    mQuadVertexFormat[ "aColor" ] = Property::VECTOR4;
     mQuadIndexFormat[ "indices" ] = Property::INTEGER;
   }
 
@@ -167,6 +166,7 @@ struct AtlasRenderer::Impl
   void AddGlyphs( Text::ViewInterface& view,
                   const Vector<Vector2>& positions,
                   const Vector<GlyphInfo>& glyphs,
+                  const Vector<Vector4>& colors,
                   int depth )
   {
     AtlasManager::AtlasSlot slot;
@@ -177,7 +177,6 @@ struct AtlasRenderer::Impl
 
     const Vector2& actorSize( view.GetControlSize() );
     const Vector2 halfActorSize( actorSize * 0.5f );
-    const Vector4& textColor( view.GetTextColor() );
     const Vector2& shadowOffset( view.GetShadowOffset() );
     const Vector4& shadowColor( view.GetShadowColor() );
     const bool underlineEnabled( view.IsUnderlineEnabled() );
@@ -212,6 +211,7 @@ struct AtlasRenderer::Impl
     Vector< TextCacheEntry > newTextCache;
     const GlyphInfo* const glyphsBuffer = glyphs.Begin();
     const Vector2* const positionsBuffer = positions.Begin();
+    const Vector4* const colorsBuffer = colors.Begin();
 
     for( uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i )
     {
@@ -221,10 +221,10 @@ struct AtlasRenderer::Impl
       thereAreUnderlinedGlyphs = thereAreUnderlinedGlyphs || underlineGlyph;
 
       // No operation for white space
-      if ( glyph.width && glyph.height )
+      if( glyph.width && glyph.height )
       {
         // Are we still using the same fontId as previous
-        if ( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) )
+        if( underlineGlyph && ( glyph.fontId != lastUnderlinedFontId ) )
         {
           // We need to fetch fresh font underline metrics
           FontMetrics fontMetrics;
@@ -248,10 +248,11 @@ struct AtlasRenderer::Impl
           }
 
           // Clamp the underline position at the font descender and check for ( as EFL describes it ) a broken font
-          if ( currentUnderlinePosition > descender )
+          if( currentUnderlinePosition > descender )
           {
             currentUnderlinePosition = descender;
           }
+
           if( fabsf( currentUnderlinePosition ) < Math::MACHINE_EPSILON_1000 )
           {
             // Move offset down by one ( EFL behavior )
@@ -261,47 +262,54 @@ struct AtlasRenderer::Impl
           lastUnderlinedFontId = glyph.fontId;
         } // underline
 
-        if ( !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ) )
+        if( !mGlyphManager.IsCached( glyph.fontId, glyph.index, slot ) )
         {
           // Select correct size for new atlas if needed....?
-          if ( lastFontId != glyph.fontId )
+          if( lastFontId != glyph.fontId )
           {
-            for ( uint32_t j = 0; j < mBlockSizes.size(); ++j )
+            uint32_t index = 0u;
+            for( std::vector<MaxBlockSize>::const_iterator it = mBlockSizes.begin(),
+                   endIt = mBlockSizes.end();
+                 it != endIt;
+                 ++it, ++index )
             {
-              if ( mBlockSizes[ j ].mFontId == glyph.fontId )
+              const MaxBlockSize& blockSize = *it;
+              if( blockSize.mFontId == glyph.fontId )
               {
-                currentBlockSize = j;
+                currentBlockSize = index;
                 mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH,
                                                DEFAULT_ATLAS_HEIGHT,
-                                               mBlockSizes[ j ].mNeededBlockWidth,
-                                               mBlockSizes[ j ].mNeededBlockHeight );
+                                               blockSize.mNeededBlockWidth,
+                                               blockSize.mNeededBlockHeight );
               }
             }
           }
 
           // Create a new image for the glyph
           BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index );
-          if ( bitmap )
+          if( bitmap )
           {
+            MaxBlockSize& blockSize = mBlockSizes[currentBlockSize];
+
             // Ensure that the next image will fit into the current block size
             bool setSize = false;
-            if ( bitmap.GetWidth() > mBlockSizes[ currentBlockSize ].mNeededBlockWidth )
+            if( bitmap.GetWidth() > blockSize.mNeededBlockWidth )
             {
               setSize = true;
-              mBlockSizes[ currentBlockSize ].mNeededBlockWidth = bitmap.GetWidth();
+              blockSize.mNeededBlockWidth = bitmap.GetWidth();
             }
-            if ( bitmap.GetHeight() > mBlockSizes[ currentBlockSize ].mNeededBlockHeight )
+            if( bitmap.GetHeight() > blockSize.mNeededBlockHeight )
             {
               setSize = true;
-              mBlockSizes[ currentBlockSize ].mNeededBlockHeight = bitmap.GetHeight();
+              blockSize.mNeededBlockHeight = bitmap.GetHeight();
             }
 
-            if ( setSize )
+            if( setSize )
             {
               mGlyphManager.SetNewAtlasSize( DEFAULT_ATLAS_WIDTH,
                                              DEFAULT_ATLAS_HEIGHT,
-                                             mBlockSizes[ currentBlockSize ].mNeededBlockWidth,
-                                             mBlockSizes[ currentBlockSize ].mNeededBlockHeight );
+                                             blockSize.mNeededBlockWidth,
+                                             blockSize.mNeededBlockHeight );
             }
 
             // Locate a new slot for our glyph
@@ -315,7 +323,7 @@ struct AtlasRenderer::Impl
         }
 
         // Move the origin (0,0) of the mesh to the center of the actor
-        Vector2 position = *( positionsBuffer + i ) - halfActorSize;
+        const Vector2 position = *( positionsBuffer + i ) - halfActorSize;
 
         // Generate mesh data for this quad, plugging in our supplied position
         AtlasManager::Mesh2D newMesh;
@@ -325,21 +333,40 @@ struct AtlasRenderer::Impl
         textCacheEntry.mIndex = glyph.index;
         newTextCache.PushBack( textCacheEntry );
 
+        AtlasManager::Vertex2D* verticesBuffer = newMesh.mVertices.Begin();
+
         // Adjust the vertices if the fixed-size font should be down-scaled
         if( glyph.scaleFactor > 0 )
         {
-          for( unsigned int i=0; i<newMesh.mVertices.Count(); ++i )
+          for( unsigned int index = 0u, size = newMesh.mVertices.Count();
+               index < size;
+               ++index )
           {
-            newMesh.mVertices[i].mPosition.x = position.x + ( ( newMesh.mVertices[i].mPosition.x - position.x ) * glyph.scaleFactor );
-            newMesh.mVertices[i].mPosition.y = position.y + ( ( newMesh.mVertices[i].mPosition.y - position.y ) * glyph.scaleFactor );
+            AtlasManager::Vertex2D& vertex = *( verticesBuffer + index );
+
+            // Set the position of the vertex.
+            vertex.mPosition.x = position.x + ( ( vertex.mPosition.x - position.x ) * glyph.scaleFactor );
+            vertex.mPosition.y = position.y + ( ( vertex.mPosition.y - position.y ) * glyph.scaleFactor );
           }
         }
 
+        // Get the color of the character.
+        const Vector4& color = *( colorsBuffer + i );
+
+        for( unsigned int index = 0u, size = newMesh.mVertices.Count();
+             index < size;
+             ++index )
+        {
+          AtlasManager::Vertex2D& vertex = *( verticesBuffer + index );
+
+          // Set the color of the vertex.
+          vertex.mColor = color;
+        }
+
         // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
         StitchTextMesh( meshContainer,
                         newMesh,
                         extents,
-                        textColor,
                         position.y + glyph.yBearing,
                         underlineGlyph,
                         currentUnderlinePosition,
@@ -356,42 +383,51 @@ struct AtlasRenderer::Impl
     if( thereAreUnderlinedGlyphs )
     {
       // Check to see if any of the text needs an underline
-      GenerateUnderlines( meshContainer, extents, underlineColor, textColor );
+      GenerateUnderlines( meshContainer, extents, underlineColor );
     }
 
     // For each MeshData object, create a mesh actor and add to the renderable actor
-    if ( meshContainer.size() )
+    if( !meshContainer.empty() )
     {
-      for ( std::vector< MeshRecord >::iterator mIt = meshContainer.begin(); mIt != meshContainer.end(); ++mIt )
+      for( std::vector< MeshRecord >::iterator it = meshContainer.begin(),
+              endIt = meshContainer.end();
+            it != endIt; ++it )
       {
-        Actor actor = CreateMeshActor( *mIt, actorSize );
+        MeshRecord& meshRecord = *it;
+
+        Actor actor = CreateMeshActor( meshRecord, actorSize );
 
         // Create an effect if necessary
-        if ( style == STYLE_DROP_SHADOW )
+        if( style == STYLE_DROP_SHADOW )
         {
+          // Change the color of the vertices.
+          for( Vector<AtlasManager::Vertex2D>::Iterator vIt =  meshRecord.mMesh.mVertices.Begin(),
+                 vEndIt = meshRecord.mMesh.mVertices.End();
+               vIt != vEndIt;
+               ++vIt )
+          {
+            AtlasManager::Vertex2D& vertex = *vIt;
+
+            vertex.mColor = shadowColor;
+          }
+
           // Create a container actor to act as a common parent for text and shadow, to avoid color inheritence issues.
           Actor containerActor = Actor::New();
           containerActor.SetParentOrigin( ParentOrigin::CENTER );
           containerActor.SetSize( actorSize );
 
-          Actor shadowActor = Actor::New();
+          Actor shadowActor = CreateMeshActor( meshRecord, actorSize );
 #if defined(DEBUG_ENABLED)
           shadowActor.SetName( "Text Shadow renderable actor" );
 #endif
           // Offset shadow in x and y
           shadowActor.RegisterProperty("uOffset", shadowOffset );
-          if ( actor.GetRendererCount() )
+          if( actor.GetRendererCount() )
           {
-            Dali::Renderer renderer( actor.GetRendererAt( 0 ) );
-            Geometry geometry = renderer.GetGeometry();
-            Material material = renderer.GetMaterial();
-
-            Dali::Renderer shadowRenderer = Dali::Renderer::New( geometry, material );
-            shadowRenderer.SetDepthIndex( renderer.GetDepthIndex() - 1 );
-            shadowActor.AddRenderer( shadowRenderer );
+            Dali::Renderer renderer( shadowActor.GetRendererAt( 0 ) );
+            renderer.SetDepthIndex( renderer.GetDepthIndex() - 1 );
             shadowActor.SetParentOrigin( ParentOrigin::CENTER );
             shadowActor.SetSize( actorSize );
-            shadowActor.SetColor( shadowColor );
             containerActor.Add( shadowActor );
             containerActor.Add( actor );
             actor = containerActor;
@@ -417,7 +453,7 @@ struct AtlasRenderer::Impl
 
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "%s\n", metrics.mVerboseGlyphCounts.c_str() );
 
-    for ( uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i )
+    for( uint32_t i = 0; i < metrics.mAtlasMetrics.mAtlasCount; ++i )
     {
       DALI_LOG_INFO( gLogFilter, Debug::Verbose, "   Atlas [%i] %sPixels: %s Size: %ix%i, BlockSize: %ix%i, BlocksUsed: %i/%i\n",
                                                  i + 1, i > 8 ? "" : " ",
@@ -434,7 +470,7 @@ struct AtlasRenderer::Impl
 
   void RemoveText()
   {
-    for ( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter )
+    for( Vector< TextCacheEntry >::Iterator oldTextIter = mTextCache.Begin(); oldTextIter != mTextCache.End(); ++oldTextIter )
     {
       mGlyphManager.AdjustReferenceCount( oldTextIter->mFontId, oldTextIter->mIndex, -1/*decrement*/ );
     }
@@ -462,7 +498,6 @@ struct AtlasRenderer::Impl
     actor.AddRenderer( renderer );
     actor.SetParentOrigin( ParentOrigin::CENTER ); // Keep all of the origins aligned
     actor.SetSize( actorSize );
-    actor.SetColor( meshRecord.mColor );
     actor.RegisterProperty("uOffset", Vector2::ZERO );
     return actor;
   }
@@ -470,7 +505,6 @@ struct AtlasRenderer::Impl
   void StitchTextMesh( std::vector< MeshRecord >& meshContainer,
                        AtlasManager::Mesh2D& newMesh,
                        Vector< Extent >& extents,
-                       const Vector4& color,
                        float baseLine,
                        bool underlineGlyph,
                        float underlinePosition,
@@ -489,7 +523,7 @@ struct AtlasRenderer::Impl
             mIt != mEndIt;
             ++mIt, ++index )
       {
-        if ( slot.mAtlasId == mIt->mAtlasId && color == mIt->mColor )
+        if( slot.mAtlasId == mIt->mAtlasId )
         {
           // Append the mesh to the existing mesh and adjust any extents
           Toolkit::Internal::AtlasMeshFactory::AppendMesh( mIt->mMesh, newMesh );
@@ -514,7 +548,6 @@ struct AtlasRenderer::Impl
       MeshRecord meshRecord;
       meshRecord.mAtlasId = slot.mAtlasId;
       meshRecord.mMesh = newMesh;
-      meshRecord.mColor = color;
       meshContainer.push_back( meshRecord );
 
       if( underlineGlyph )
@@ -584,25 +617,36 @@ struct AtlasRenderer::Impl
 
   void CalculateBlocksSize( const Vector<GlyphInfo>& glyphs )
   {
-    MaxBlockSize maxBlockSize;
-    for ( uint32_t i = 0; i < glyphs.Size(); ++i )
+    for( Vector<GlyphInfo>::ConstIterator glyphIt = glyphs.Begin(),
+           glyphEndIt = glyphs.End();
+         glyphIt != glyphEndIt;
+         ++glyphIt )
     {
-      FontId fontId = glyphs[ i ].fontId;
+      const FontId fontId = (*glyphIt).fontId;
       bool foundFont = false;
-      for ( uint32_t j = 0; j < mBlockSizes.size(); ++j )
+
+      for( std::vector< MaxBlockSize >::const_iterator blockIt = mBlockSizes.begin(),
+             blockEndIt = mBlockSizes.end();
+           blockIt != blockEndIt;
+           ++blockIt )
       {
-        if ( mBlockSizes[ j ].mFontId == fontId )
+        if( (*blockIt).mFontId == fontId )
         {
           foundFont = true;
+          break;
         }
       }
+
       if ( !foundFont )
       {
         FontMetrics fontMetrics;
         mFontClient.GetFontMetrics( fontId, fontMetrics );
+
+        MaxBlockSize maxBlockSize;
         maxBlockSize.mNeededBlockWidth = static_cast< uint32_t >( fontMetrics.height );
-        maxBlockSize.mNeededBlockHeight = static_cast< uint32_t >( fontMetrics.height );
+        maxBlockSize.mNeededBlockHeight = maxBlockSize.mNeededBlockWidth;
         maxBlockSize.mFontId = fontId;
+
         mBlockSizes.push_back( maxBlockSize );
       }
     }
@@ -610,8 +654,7 @@ struct AtlasRenderer::Impl
 
   void GenerateUnderlines( std::vector< MeshRecord >& meshRecords,
                            Vector< Extent >& extents,
-                           const Vector4& underlineColor,
-                           const Vector4& textColor )
+                           const Vector4& underlineColor )
   {
     AtlasManager::Mesh2D newMesh;
     unsigned short faceIndex = 0;
@@ -663,18 +706,9 @@ struct AtlasRenderer::Impl
       newMesh.mIndices.PushBack( faceIndex + 1u );
       faceIndex += 4;
 
-      if ( underlineColor == textColor )
-      {
-        Toolkit::Internal::AtlasMeshFactory::AppendMesh( meshRecords[ index ].mMesh, newMesh );
-      }
-      else
-      {
-        MeshRecord record;
-        record.mMesh = newMesh;
-        record.mAtlasId = meshRecords[ index ].mAtlasId;
-        record.mColor = underlineColor;
-        meshRecords.push_back( record );
-      }
+      vert.mColor = underlineColor;
+
+      Toolkit::Internal::AtlasMeshFactory::AppendMesh( meshRecords[ index ].mMesh, newMesh );
     }
   }
 
@@ -709,20 +743,27 @@ Actor AtlasRenderer::Render( Text::ViewInterface& view, int depth )
     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 );
+    colors.Resize( numberOfGlyphs );
 
     mImpl->AddGlyphs( view,
                       positions,
                       glyphs,
+                      colors,
                       depth );
 
-    /* In the case where AddGlyphs does not create a renderable Actor for example when glyphs are all whitespace create a new Actor.  */
-    /* This renderable actor is used to position the text, other "decorations" can rely on there always being an Actor regardless of it is whitespace or regular text*/
+    /* In the case where AddGlyphs does not create a renderable Actor for example when glyphs are all whitespace create a new Actor. */
+    /* This renderable actor is used to position the text, other "decorations" can rely on there always being an Actor regardless of it is whitespace or regular text*/
     if ( !mImpl->mActor )
     {
       mImpl->mActor = Actor::New();
index 466991b..a7c7135 100644 (file)
@@ -15,7 +15,7 @@
  *
  */
 
-// CLASS HEADER
+// FILE HEADER
 #include <dali-toolkit/internal/text/segmentation.h>
 
 // EXTERNAL INCLUDES
index ccd64db..bc85e95 100644 (file)
@@ -25,6 +25,7 @@
 // INTERNAL INCLUDES
 #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/multi-language-support.h>
 #include <dali-toolkit/internal/text/segmentation.h>
 #include <dali-toolkit/internal/text/shaper.h>
@@ -132,7 +133,8 @@ EventData::EventData( DecoratorPtr decorator )
   mUpdateRightSelectionPosition( false ),
   mScrollAfterUpdatePosition( false ),
   mScrollAfterDelete( false ),
-  mAllTextSelected( false )
+  mAllTextSelected( false ),
+  mUpdateInputStyle( false )
 {
   mImfManager = ImfManager::Get();
 }
@@ -287,6 +289,20 @@ bool Controller::Impl::ProcessInputEvents()
     }
   }
 
+  if( mEventData->mUpdateInputStyle )
+  {
+    // Set the default style first.
+    RetrieveDefaultInputStyle( mEventData->mInputStyle );
+
+    // Get the character index from the cursor index.
+    const CharacterIndex styleIndex = ( mEventData->mPrimaryCursorPosition > 0u ) ? mEventData->mPrimaryCursorPosition - 1u : 0u;
+
+    // Retrieve the style from the style runs stored in the logical model.
+    mLogicalModel->RetrieveStyle( styleIndex, mEventData->mInputStyle );
+
+    mEventData->mUpdateInputStyle = false;
+  }
+
   mEventData->mEventQueue.clear();
 
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "<--Controller::ProcessInputEvents\n" );
@@ -481,6 +497,30 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
   }
 }
 
+bool Controller::Impl::UpdateModelStyle( OperationsMask operationsRequired )
+{
+  bool updated = false;
+
+  if( COLOR & operationsRequired )
+  {
+    // Set the color runs in glyphs.
+    SetColorSegmentationInfo( mLogicalModel->mColorRuns,
+                              mVisualModel->mCharactersToGlyph,
+                              mVisualModel->mGlyphsPerCharacter,
+                              mVisualModel->mColorRuns );
+
+    updated = true;
+  }
+
+  return updated;
+}
+
+void Controller::Impl::RetrieveDefaultInputStyle( InputStyle& inputStyle )
+{
+  // Set the default text's color.
+  inputStyle.textColor = mTextColor;
+}
+
 void Controller::Impl::GetDefaultFonts( Vector<FontRun>& fonts, Length numberOfCharacters )
 {
   if( mFontDefaults )
@@ -549,6 +589,7 @@ void Controller::Impl::OnCursorKeyEvent( const Event& event )
   }
 
   mEventData->mUpdateCursorPosition = true;
+  mEventData->mUpdateInputStyle = true;
   mEventData->mScrollAfterUpdatePosition = true;
 }
 
@@ -578,6 +619,7 @@ void Controller::Impl::OnTapEvent( const Event& event )
 
       mEventData->mUpdateCursorPosition = true;
       mEventData->mScrollAfterUpdatePosition = true;
+      mEventData->mUpdateInputStyle = true;
 
       // Notify the cursor position to the imf manager.
       if( mEventData->mImfManager )
@@ -709,6 +751,7 @@ void Controller::Impl::OnHandleEvent( const Event& event )
     if( Event::GRAB_HANDLE_EVENT == event.type )
     {
       mEventData->mUpdateCursorPosition = true;
+      mEventData->mUpdateInputStyle = true;
 
       if ( !IsClipboardEmpty() )
       {
@@ -795,6 +838,7 @@ void Controller::Impl::OnHandleEvent( const Event& event )
       mEventData->mUpdateCursorPosition = mEventData->mPrimaryCursorPosition != handlePosition;
       mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateCursorPosition;
       mEventData->mPrimaryCursorPosition = handlePosition;
+      mEventData->mUpdateInputStyle = mEventData->mUpdateCursorPosition;
     }
     else if( leftSelectionHandleEvent || rightSelectionHandleEvent )
     {
@@ -889,31 +933,36 @@ void Controller::Impl::OnSelectAllEvent()
   }
 }
 
-void Controller::Impl::RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival )
+void Controller::Impl::RetrieveSelection( std::string& selectedText, bool deleteAfterRetrieval )
 {
-  if( mEventData->mLeftSelectionPosition ==  mEventData->mRightSelectionPosition )
+  if( mEventData->mLeftSelectionPosition == mEventData->mRightSelectionPosition )
   {
     // Nothing to select if handles are in the same place.
-    selectedText="";
+    selectedText.clear();
     return;
   }
 
   const bool handlesCrossed = mEventData->mLeftSelectionPosition > mEventData->mRightSelectionPosition;
 
   //Get start and end position of selection
-  uint32_t startOfSelectedText = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
-  uint32_t lengthOfSelectedText =  ( handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition ) - startOfSelectedText;
+  const CharacterIndex startOfSelectedText = handlesCrossed ? mEventData->mRightSelectionPosition : mEventData->mLeftSelectionPosition;
+  const Length lengthOfSelectedText = ( handlesCrossed ? mEventData->mLeftSelectionPosition : mEventData->mRightSelectionPosition ) - startOfSelectedText;
 
   // Validate the start and end selection points
-  if(  ( startOfSelectedText + lengthOfSelectedText ) <=  mLogicalModel->mText.Count() )
+  if( ( startOfSelectedText + lengthOfSelectedText ) <= mLogicalModel->mText.Count() )
   {
     //Get text as a UTF8 string
     Vector<Character>& utf32Characters = mLogicalModel->mText;
 
     Utf32ToUtf8( &utf32Characters[startOfSelectedText], lengthOfSelectedText, selectedText );
 
-    if ( deleteAfterRetreival  ) // Only delete text if copied successfully
+    if( deleteAfterRetrieval ) // Only delete text if copied successfully
     {
+      // Set as input style the style of the first deleted character.
+      mLogicalModel->RetrieveStyle( startOfSelectedText, mEventData->mInputStyle );
+
+      mLogicalModel->UpdateTextStyleRuns( startOfSelectedText, -static_cast<int>( lengthOfSelectedText ) );
+
       // Delete text between handles
       Vector<Character>& currentText = mLogicalModel->mText;
 
@@ -963,11 +1012,11 @@ void Controller::Impl::SendSelectionToClipboard( bool deleteAfterSending )
   ChangeState( EventData::EDITING );
 }
 
-void Controller::Impl::GetTextFromClipboard( unsigned int itemIndex, std::string& retreivedString )
+void Controller::Impl::GetTextFromClipboard( unsigned int itemIndex, std::string& retrievedString )
 {
   if ( mClipboard )
   {
-    retreivedString =  mClipboard.GetItem( itemIndex );
+    retrievedString =  mClipboard.GetItem( itemIndex );
   }
 }
 
@@ -1534,7 +1583,7 @@ CharacterIndex Controller::Impl::GetClosestCursorIndex( float visualX,
       // Get the position of the first glyph.
       const Vector2& position = *( positionsBuffer + firstLogicalGlyphIndex );
 
-      // Whether the glyph can be split, like Latin ligatures fi, ff or Arabic ï»». 
+      // Whether the glyph can be split, like Latin ligatures fi, ff or Arabic ï»».
       const bool isInterglyphIndex = ( numberOfCharacters > numberOfGlyphs ) && HasLigatureMustBreak( script );
       const Length numberOfBlocks = isInterglyphIndex ? numberOfCharacters : 1u;
       const float glyphAdvance = glyphMetrics.advance / static_cast<float>( numberOfBlocks );
index 0f5149d..3ae0c7f 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/devel-api/text-abstraction/font-client.h>
 
 // INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/input-style.h>
 #include <dali-toolkit/internal/text/layouts/layout-engine.h>
 #include <dali-toolkit/internal/text/logical-model-impl.h>
 #include <dali-toolkit/internal/text/text-controller.h>
@@ -133,6 +134,8 @@ struct EventData
    */
   std::vector<Event> mEventQueue;              ///< The queue of touch events etc.
 
+  InputStyle         mInputStyle;              ///< The style to be set to the new inputed text.
+
   /**
    * 0,0 means that the top-left corner of the layout matches the top-left corner of the UI control.
    * Typically this will have a negative value with scrolling occurs.
@@ -162,7 +165,8 @@ struct EventData
   bool mUpdateRightSelectionPosition    : 1;   ///< True if the visual position of the right selection handle must be recalculated.
   bool mScrollAfterUpdatePosition       : 1;   ///< Whether to scroll after the cursor position is updated.
   bool mScrollAfterDelete               : 1;   ///< Whether to scroll after delete characters.
-  bool mAllTextSelected                 : 1;   ///< True if the selection handles are selecting all the text
+  bool mAllTextSelected                 : 1;   ///< True if the selection handles are selecting all the text.
+  bool mUpdateInputStyle                : 1;   ///< Whether to update the input style after moving the cursor.
 };
 
 struct ModifyEvent
@@ -182,8 +186,8 @@ struct FontDefaults
   FontDefaults()
   : mFontDescription(),
     mFontStyle(),
-    mDefaultPointSize(0.0f),
-    mFontId(0u)
+    mDefaultPointSize( 0.f ),
+    mFontId( 0u )
   {
     // Initially use the default platform font
     TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
@@ -194,7 +198,7 @@ struct FontDefaults
   {
     if( !mFontId )
     {
-      Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
+      const PointSize26Dot6 pointSize = static_cast<PointSize26Dot6>( mDefaultPointSize * 64.f );
       mFontId = fontClient.GetFontId( mFontDescription, pointSize );
     }
 
@@ -224,9 +228,10 @@ struct Controller::Impl
     mTextColor( Color::BLACK ),
     mAlignmentOffset(),
     mOperationsPending( NO_OPERATION ),
-    mMaximumNumberOfCharacters( 50 ),
+    mMaximumNumberOfCharacters( 50u ),
     mRecalculateNaturalSize( true ),
-    mUserDefinedFontFamily( false )
+    mUserDefinedFontFamily( false ),
+    mMarkupProcessorEnabled( false )
   {
     mLogicalModel = LogicalModel::New();
     mVisualModel  = VisualModel::New();
@@ -264,12 +269,12 @@ struct Controller::Impl
     if( ModifyEvent::TEXT_REPLACED == type)
     {
       // Cancel previously queued inserts etc.
-      mModifyEvents.clear();
+      mModifyEvents.Clear();
     }
 
     ModifyEvent event;
     event.type = type;
-    mModifyEvents.push_back( event );
+    mModifyEvents.PushBack( event );
 
     // The event will be processed during relayout
     RequestRelayout();
@@ -354,9 +359,35 @@ struct Controller::Impl
     return !result; // // If NumberOfItems greater than 0, return false
   }
 
+  /**
+   * @brief Updates the logical and visual models.
+   *
+   * When text or style changes the model is set with some operations pending.
+   * When i.e. the text's size or a relayout is required this method is called
+   * with a given @p operationsRequired parameter. The operations required are
+   * matched with the operations pending to perform the minimum number of operations.
+   *
+   * @param[in] operationsRequired The operations required.
+   */
   void UpdateModel( OperationsMask operationsRequired );
 
   /**
+   * @brief Updates the style runs in the visual model when the text's styles changes.
+   *
+   * @param[in] operationsRequired The operations required.
+   *
+   * @return @e true if the model has been modified.
+   */
+  bool UpdateModelStyle( OperationsMask operationsRequired );
+
+  /**
+   * @brief Retreieves the default style.
+   *
+   * @param[out] inputStyle The default style.
+   */
+  void RetrieveDefaultInputStyle( InputStyle& inputStyle );
+
+  /**
    * @brief Retrieve the default fonts.
    *
    * @param[out] fonts The default font family, style and point sizes.
@@ -383,7 +414,7 @@ struct Controller::Impl
 
   void OnSelectAllEvent();
 
-  void RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival );
+  void RetrieveSelection( std::string& selectedText, bool deleteAfterRetrieval );
 
   void ShowClipboard();
 
@@ -393,7 +424,7 @@ struct Controller::Impl
 
   void SendSelectionToClipboard( bool deleteAfterSending );
 
-  void GetTextFromClipboard( unsigned int itemIndex, std::string& retreivedString );
+  void GetTextFromClipboard( unsigned int itemIndex, std::string& retrievedString );
 
   void RepositionSelectionHandles();
   void RepositionSelectionHandles( float visualX, float visualY );
@@ -504,7 +535,7 @@ struct Controller::Impl
   View mView;                              ///< The view interface to the rendering back-end.
   MetricsPtr mMetrics;                     ///< A wrapper around FontClient used to get metrics & potentially down-scaled Emoji metrics.
   LayoutEngine mLayoutEngine;              ///< The layout engine.
-  std::vector<ModifyEvent> mModifyEvents;  ///< Temporary stores the text set until the next relayout.
+  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.
   OperationsMask mOperationsPending;       ///< Operations pending to be done to layout the text.
@@ -512,7 +543,7 @@ struct Controller::Impl
 
   bool mRecalculateNaturalSize:1;          ///< Whether the natural size needs to be recalculated.
   bool mUserDefinedFontFamily:1;           ///< Whether the Font family was set by the user instead of being left as sytem default.
-
+  bool mMarkupProcessorEnabled:1;          ///< Whether the mark-up procesor is enabled.
 };
 
 } // namespace Text
index 592bc12..e273f01 100644 (file)
@@ -28,6 +28,7 @@
 #include <dali-toolkit/internal/text/bidirectional-support.h>
 #include <dali-toolkit/internal/text/character-set-conversion.h>
 #include <dali-toolkit/internal/text/layouts/layout-parameters.h>
+#include <dali-toolkit/internal/text/markup-processor.h>
 #include <dali-toolkit/internal/text/text-controller-impl.h>
 
 namespace
@@ -73,6 +74,16 @@ void Controller::EnableTextInput( DecoratorPtr decorator )
   }
 }
 
+void Controller::SetMarkupProcessorEnabled( bool enable )
+{
+  mImpl->mMarkupProcessorEnabled = enable;
+}
+
+bool Controller::IsMarkupProcessorEnabled() const
+{
+  return mImpl->mMarkupProcessorEnabled;
+}
+
 void Controller::SetText( const std::string& text )
 {
   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText\n" );
@@ -80,9 +91,12 @@ void Controller::SetText( const std::string& text )
   // Reset keyboard as text changed
   mImpl->ResetImfManager();
 
-  // Remove the previously set text
+  // Remove the previously set text and style.
   ResetText();
 
+  // Remove the style.
+  ClearStyleData();
+
   CharacterIndex lastCursorIndex = 0u;
 
   if( mImpl->mEventData )
@@ -99,20 +113,37 @@ void Controller::SetText( const std::string& text )
 
   if( !text.empty() )
   {
+    MarkupProcessData markupProcessData( mImpl->mLogicalModel->mColorRuns );
+
+    Length textSize = 0u;
+    const uint8_t* utf8 = NULL;
+    if( mImpl->mMarkupProcessorEnabled )
+    {
+      ProcessMarkupString( text, markupProcessData );
+      textSize = markupProcessData.markupProcessedText.size();
+
+      // This is a bit horrible but std::string returns a (signed) char*
+      utf8 = reinterpret_cast<const uint8_t*>( markupProcessData.markupProcessedText.c_str() );
+    }
+    else
+    {
+      textSize = text.size();
+
+      // This is a bit horrible but std::string returns a (signed) char*
+      utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+    }
+
     //  Convert text into UTF-32
     Vector<Character>& utf32Characters = mImpl->mLogicalModel->mText;
-    utf32Characters.Resize( text.size() );
-
-    // This is a bit horrible but std::string returns a (signed) char*
-    const uint8_t* utf8 = reinterpret_cast<const uint8_t*>( text.c_str() );
+    utf32Characters.Resize( textSize );
 
     // Transform a text array encoded in utf8 into an array encoded in utf32.
     // It returns the actual number of characters.
-    Length characterCount = Utf8ToUtf32( utf8, text.size(), utf32Characters.Begin() );
+    Length characterCount = Utf8ToUtf32( utf8, textSize, utf32Characters.Begin() );
     utf32Characters.Resize( characterCount );
 
-    DALI_ASSERT_DEBUG( text.size() >= characterCount && "Invalid UTF32 conversion length" );
-    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Controller::SetText %p UTF8 size %d, UTF32 size %d\n", this, text.size(), mImpl->mLogicalModel->mText.Count() );
+    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() );
 
     // To reset the cursor position
     lastCursorIndex = characterCount;
@@ -461,6 +492,20 @@ bool Controller::RemoveText( int cursorOffset, int numberOfChars )
 
     if( ( cursorIndex + numberOfChars ) <= currentText.Count() )
     {
+      // Update the input style and remove the text's style before removing the text.
+      if( mImpl->mEventData )
+      {
+        // Set first the default input style.
+        mImpl->RetrieveDefaultInputStyle( mImpl->mEventData->mInputStyle );
+
+        // Update the input style.
+        mImpl->mLogicalModel->RetrieveStyle( cursorIndex, mImpl->mEventData->mInputStyle );
+
+        // Remove the text's style before removing the text.
+        mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, -numberOfChars );
+      }
+
+      // Remove the characters.
       Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
       Vector<Character>::Iterator last  = first + numberOfChars;
 
@@ -561,6 +606,48 @@ float Controller::GetUnderlineHeight() const
   return mImpl->mVisualModel->GetUnderlineHeight();
 }
 
+void Controller::SetInputColor( const Vector4& color )
+{
+  if( mImpl->mEventData )
+  {
+    mImpl->mEventData->mInputStyle.textColor = color;
+
+    if( EventData::SELECTING == mImpl->mEventData->mState )
+    {
+      const bool handlesCrossed = mImpl->mEventData->mLeftSelectionPosition > mImpl->mEventData->mRightSelectionPosition;
+
+      // Get start and end position of selection
+      const CharacterIndex startOfSelectedText = handlesCrossed ? mImpl->mEventData->mRightSelectionPosition : mImpl->mEventData->mLeftSelectionPosition;
+      const Length lengthOfSelectedText = ( handlesCrossed ? mImpl->mEventData->mLeftSelectionPosition : mImpl->mEventData->mRightSelectionPosition ) - startOfSelectedText;
+
+      // Add the color run.
+      const VectorBase::SizeType numberOfRuns = mImpl->mLogicalModel->mColorRuns.Count();
+      mImpl->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
+
+      ColorRun& colorRun = *( mImpl->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
+      colorRun.color = color;
+      colorRun.characterRun.characterIndex = startOfSelectedText;
+      colorRun.characterRun.numberOfCharacters = lengthOfSelectedText;
+
+      // Request to relayout.
+      mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending | COLOR );
+      mImpl->RequestRelayout();
+    }
+  }
+}
+
+const Vector4& Controller::GetInputColor() const
+{
+  if( mImpl->mEventData )
+  {
+    return mImpl->mEventData->mInputStyle.textColor;
+  }
+
+  // Return the default text's color if there is no EventData.
+  return mImpl->mTextColor;
+
+}
+
 void Controller::SetEnableCursorBlink( bool enable )
 {
   DALI_ASSERT_DEBUG( NULL != mImpl->mEventData && "TextInput disabled" );
@@ -731,7 +818,7 @@ bool Controller::Relayout( const Size& size )
   {
     DALI_LOG_INFO( gLogFilter, Debug::Verbose, "new size (previous size %f,%f)\n", mImpl->mVisualModel->mControlSize.width, mImpl->mVisualModel->mControlSize.height );
 
-    // Operations that need to be done if the size changes.
+    // Layout operations that need to be done if the size changes.
     mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
                                                              LAYOUT                    |
                                                              ALIGN                     |
@@ -741,14 +828,28 @@ bool Controller::Relayout( const Size& size )
     mImpl->mVisualModel->mControlSize = size;
   }
 
-  // Make sure the model is up-to-date before layouting
+  // Whether there are modify events.
+  const bool isModifyEventsEmpty = 0u == mImpl->mModifyEvents.Count();
+
+  // Make sure the model is up-to-date before layouting.
   ProcessModifyEvents();
   mImpl->UpdateModel( mImpl->mOperationsPending );
 
+  // Style operations that need to be done if the text is modified.
+  if( !isModifyEventsEmpty )
+  {
+    mImpl->mOperationsPending = static_cast<OperationsMask>( mImpl->mOperationsPending |
+                                                             COLOR );
+  }
+
+  // Apply the style runs if text is modified.
+  bool updated = mImpl->UpdateModelStyle( mImpl->mOperationsPending );
+
+  // Layout the text.
   Size layoutSize;
-  bool updated = DoRelayout( mImpl->mVisualModel->mControlSize,
-                             mImpl->mOperationsPending,
-                             layoutSize );
+  updated = DoRelayout( mImpl->mVisualModel->mControlSize,
+                        mImpl->mOperationsPending,
+                        layoutSize ) || updated;
 
   // Do not re-do any operation until something changes.
   mImpl->mOperationsPending = NO_OPERATION;
@@ -784,22 +885,33 @@ bool Controller::Relayout( const Size& size )
 
 void Controller::ProcessModifyEvents()
 {
-  std::vector<ModifyEvent>& events = mImpl->mModifyEvents;
+  Vector<ModifyEvent>& events = mImpl->mModifyEvents;
+
+  if( 0u == events.Count() )
+  {
+    // Nothing to do.
+    return;
+  }
 
-  for( unsigned int i=0; i<events.size(); ++i )
+  for( Vector<ModifyEvent>::ConstIterator it = events.Begin(),
+         endIt = events.End();
+       it != endIt;
+       ++it )
   {
-    if( ModifyEvent::TEXT_REPLACED == events[i].type )
+    const ModifyEvent& event = *it;
+
+    if( ModifyEvent::TEXT_REPLACED == event.type )
     {
       // A (single) replace event should come first, otherwise we wasted time processing NOOP events
-      DALI_ASSERT_DEBUG( 0 == i && "Unexpected TEXT_REPLACED event" );
+      DALI_ASSERT_DEBUG( it == events.Begin() && "Unexpected TEXT_REPLACED event" );
 
       TextReplacedEvent();
     }
-    else if( ModifyEvent::TEXT_INSERTED == events[i].type )
+    else if( ModifyEvent::TEXT_INSERTED == event.type )
     {
       TextInsertedEvent();
     }
-    else if( ModifyEvent::TEXT_DELETED == events[i].type )
+    else if( ModifyEvent::TEXT_DELETED == event.type )
     {
       // Placeholder-text cannot be deleted
       if( !mImpl->IsShowingPlaceholderText() )
@@ -809,15 +921,14 @@ void Controller::ProcessModifyEvents()
     }
   }
 
-  if( mImpl->mEventData &&
-      0 != events.size() )
+  if( mImpl->mEventData )
   {
     // When the text is being modified, delay cursor blinking
     mImpl->mEventData->mDecorator->DelayCursorBlink();
   }
 
   // Discard temporary text
-  events.clear();
+  events.Clear();
 }
 
 void Controller::ResetText()
@@ -1432,9 +1543,39 @@ void Controller::InsertText( const std::string& text, Controller::InsertType typ
     Length maxSizeOfNewText = std::min ( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
     maxLengthReached = ( characterCount > maxSizeOfNewText );
 
-    // Insert at current cursor position
+    // The cursor position.
     CharacterIndex& cursorIndex = mImpl->mEventData->mPrimaryCursorPosition;
 
+    // Update the text's style.
+    if( mImpl->mEventData )
+    {
+      // Updates the text style runs.
+      mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, maxSizeOfNewText );
+
+      // Get the character index from the cursor index.
+      const CharacterIndex styleIndex = ( cursorIndex > 0u ) ? cursorIndex - 1u : 0u;
+
+      // Retrieve the text's style for the given index.
+      InputStyle style;
+      mImpl->mLogicalModel->RetrieveStyle( styleIndex, style );
+
+      // Whether to add a new text color run.
+      const bool addColorRun = style.textColor != mImpl->mEventData->mInputStyle.textColor;
+
+      // Add style runs.
+      if( addColorRun )
+      {
+        const VectorBase::SizeType numberOfRuns = mImpl->mLogicalModel->mColorRuns.Count();
+        mImpl->mLogicalModel->mColorRuns.Resize( numberOfRuns + 1u );
+
+        ColorRun& colorRun = *( mImpl->mLogicalModel->mColorRuns.Begin() + numberOfRuns );
+        colorRun.color = mImpl->mEventData->mInputStyle.textColor;
+        colorRun.characterRun.characterIndex = cursorIndex;
+        colorRun.characterRun.numberOfCharacters = maxSizeOfNewText;
+      }
+    }
+
+    // Insert at current cursor position.
     Vector<Character>& modifyText = mImpl->mLogicalModel->mText;
 
     if( cursorIndex < numberOfCharactersInModel )
@@ -2041,6 +2182,7 @@ void Controller::ClearModelData()
   mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
   mImpl->mVisualModel->mGlyphPositions.Clear();
   mImpl->mVisualModel->mLines.Clear();
+  mImpl->mVisualModel->mColorRuns.Clear();
   mImpl->mVisualModel->ClearCaches();
 }
 
@@ -2058,6 +2200,11 @@ void Controller::ClearFontData()
   mImpl->mVisualModel->ClearCaches();
 }
 
+void Controller::ClearStyleData()
+{
+  mImpl->mLogicalModel->mColorRuns.Clear();
+}
+
 Controller::Controller( ControlInterface& controlInterface )
 : mImpl( NULL )
 {
index 5a80e35..058719e 100644 (file)
@@ -85,6 +85,7 @@ public:
     UPDATE_ACTUAL_SIZE = 0x0200,
     REORDER            = 0x0400,
     ALIGN              = 0x0800,
+    COLOR              = 0x1000,
     ALL_OPERATIONS     = 0xFFFF
   };
 
@@ -114,6 +115,24 @@ public:
   void EnableTextInput( DecoratorPtr decorator );
 
   /**
+   * @brief Enables/disables the mark-up processor.
+   *
+   * By default is disabled.
+   *
+   * @param[in] enable Whether to enable the mark-up processor.
+   */
+  void SetMarkupProcessorEnabled( bool enable );
+
+  /**
+   * @brief Retrieves whether the mark-up processor is enabled.
+   *
+   * By default is disabled.
+   *
+   * @return @e true if the mark-up processor is enabled, otherwise returns @e false.
+   */
+  bool IsMarkupProcessorEnabled() const;
+
+  /**
    * @brief Replaces any text previously set.
    *
    * @note This will be converted into UTF-32 when stored in the text model.
@@ -365,6 +384,20 @@ public:
   float GetUnderlineHeight() const;
 
   /**
+   * @brief Sets the input text's color.
+   *
+   * @param[in] color The input text's color.
+   */
+  void SetInputColor( const Vector4& color );
+
+  /**
+   * @brief Retrieves the input text's color.
+   *
+   * @return The input text's color.
+   */
+  const Vector4& GetInputColor() const;
+
+  /**
    * @brief Called to enable/disable cursor blink.
    *
    * @note Only editable controls should calls this.
@@ -662,6 +695,11 @@ private:
   void ClearFontData();
 
   /**
+   * @brief Helper to clear text's style data.
+   */
+  void ClearStyleData();
+
+  /**
    * @brief Private constructor.
    */
   Controller( ControlInterface& controlInterface );
diff --git a/dali-toolkit/internal/text/text-style-run-container.h b/dali-toolkit/internal/text/text-style-run-container.h
new file mode 100644 (file)
index 0000000..e35ccea
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
+#define __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief Updates the number of characters and the character index of the text's style runs.
+ *
+ * If the @p numberOfCharacters is a negative value, it means the number of characters that are removed starting from the @p index.
+ *
+ * It deletes runs if all their characters are removed.
+ *
+ * @param[in] index Index to the first character updated.
+ * @param[in] numberOfCharacters The number of characters to be updated.
+ * @param[in] totalNumberOfCharacters Total number of characters of the text.
+ * @param[in,out] runs The text's style runs.
+ * @param[out] removedRuns The text's style removed runs.
+ */
+template< typename T >
+void UpdateCharacterRuns( CharacterIndex index,
+                          int numberOfCharacters,
+                          Length totalNumberOfCharacters,
+                          Vector<T>& runs,
+                          Vector<T>& removedRuns )
+{
+  if( 0 > numberOfCharacters )
+  {
+    // Remove characters.
+    const Length numberOfRemovedCharacters = -numberOfCharacters;
+
+    if( ( 0u == index ) && ( numberOfRemovedCharacters == totalNumberOfCharacters ) )
+    {
+      // Set the removed runs.
+      removedRuns = runs;
+
+      // All characters are removed.
+      runs.Clear();
+
+      // Nothing else to do.
+      return;
+    }
+
+    const VectorBase::SizeType size = runs.Count();
+    // Temporary vector used to remove runs.
+    Vector<T> tempRuns;
+    // Reserve some space for the temporary vector.
+    tempRuns.Reserve( size );
+    removedRuns.Reserve( size );
+
+    // Whether any run has to be removed.
+    bool runsRemoved = false;
+
+    // Index to the last character added/removed.
+    const CharacterIndex lastIndex = index + numberOfRemovedCharacters - 1u;
+
+    // Update the style runs
+    for( typename Vector<T>::Iterator it = runs.Begin(),
+           endIt = runs.End();
+         it != endIt;
+         ++it )
+    {
+      T& run = *it;
+
+      const CharacterIndex lastRunIndex = run.characterRun.characterIndex + run.characterRun.numberOfCharacters - 1u;
+
+      if( lastRunIndex < index )
+      {
+        // The style run is not affected by the removed text.
+        tempRuns.PushBack( run );
+        continue;
+      }
+
+      if( ( index <= run.characterRun.characterIndex ) &&
+          ( lastIndex >= lastRunIndex ) )
+      {
+        // Add the removed run into the vector.
+        removedRuns.PushBack( run );
+
+        // All the characters are removed.
+        runsRemoved = true;
+      }
+      else
+      {
+        if( lastIndex < run.characterRun.characterIndex )
+        {
+          // Just move the character index.
+          run.characterRun.characterIndex -= numberOfRemovedCharacters;
+        }
+        else
+        {
+          if( run.characterRun.characterIndex < index )
+          {
+            // Remove characters starting from a character within the run.
+            run.characterRun.numberOfCharacters -= std::min( numberOfRemovedCharacters, 1u + lastRunIndex - index );
+          }
+          else
+          {
+            // Remove characters starting from a character located before the first index of the run.
+            run.characterRun.numberOfCharacters -= 1u + lastIndex - run.characterRun.characterIndex;
+            run.characterRun.characterIndex = index;
+          }
+        }
+
+        tempRuns.PushBack( run );
+      }
+    }
+
+    // Copy the temporary vector if there are runs removed.
+    if( runsRemoved )
+    {
+      runs = tempRuns;
+    }
+  }
+  else
+  {
+    // Add characters.
+
+    // Update the style runs
+    for( typename Vector<T>::Iterator it = runs.Begin(),
+           endIt = runs.End();
+         it != endIt;
+         ++it )
+    {
+      T& run = *it;
+
+      // Update the number of characters of the style run.
+
+      if( ( 0u == index ) && ( 0u == run.characterRun.characterIndex ) )
+      {
+        run.characterRun.numberOfCharacters += numberOfCharacters;
+      }
+      else if( index <= run.characterRun.characterIndex )
+      {
+        run.characterRun.characterIndex += numberOfCharacters;
+      }
+      else if( index <= run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+      {
+        run.characterRun.numberOfCharacters += numberOfCharacters;
+      }
+    }
+  }
+}
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
index 56439d2..409f9d7 100644 (file)
@@ -78,7 +78,8 @@ public:
    * @note The returned number of glyphs may be less than @p numberOfGlyphs if a line has ellipsis.
    *
    * @param[out] glyphs Pointer to a buffer where the glyphs are copied.
-   * @param[out] glyphPositions Pointer to a buffer where the glyph positions are copied.
+   * @param[out] glyphPositions Pointer to a buffer where the glyph's positions are copied.
+   * @param[out] colors Pointer to a buffer where the glyph's colors are copied.
    * @param[in] glyphIndex Index to the first glyph.
    * @param[in] numberOfGlyphs Number of glyphs to be copied.
    *
@@ -86,6 +87,7 @@ public:
    */
   virtual Length GetGlyphs( GlyphInfo* glyphs,
                             Vector2* glyphPositions,
+                            Vector4* glyphColors,
                             GlyphIndex glyphIndex,
                             Length numberOfGlyphs ) const = 0;
 
index 8d10b2a..2921700 100644 (file)
@@ -84,6 +84,7 @@ Length View::GetNumberOfGlyphs() const
 
 Length View::GetGlyphs( GlyphInfo* glyphs,
                         Vector2* glyphPositions,
+                        Vector4* glyphColors,
                         GlyphIndex glyphIndex,
                         Length numberOfGlyphs ) const
 {
@@ -121,6 +122,30 @@ Length View::GetGlyphs( GlyphInfo* glyphs,
                                                 glyphIndex,
                                                 numberOfLaidOutGlyphs );
 
+        // Set the colors.
+        const GlyphIndex lastLaidOutGlyphIndex = glyphIndex + numberOfLaidOutGlyphs;
+
+        for( Vector<ColorGlyphRun>::ConstIterator it = mImpl->mVisualModel->mColorRuns.Begin(),
+               endIt = mImpl->mVisualModel->mColorRuns.End();
+             it != endIt;
+             ++it )
+        {
+          const ColorGlyphRun& colorGlyphRun = *it;
+          const GlyphIndex lastGlyphIndex = colorGlyphRun.glyphRun.glyphIndex + colorGlyphRun.glyphRun.numberOfGlyphs;
+
+          if( ( colorGlyphRun.glyphRun.glyphIndex < lastLaidOutGlyphIndex ) &&
+              ( glyphIndex < lastGlyphIndex ) )
+          {
+            for( GlyphIndex index = glyphIndex < colorGlyphRun.glyphRun.glyphIndex ? colorGlyphRun.glyphRun.glyphIndex : glyphIndex,
+                   endIndex = lastLaidOutGlyphIndex < lastGlyphIndex ? lastLaidOutGlyphIndex : lastGlyphIndex;
+                 index < endIndex;
+                 ++index )
+            {
+              *( glyphColors + index - glyphIndex ) = colorGlyphRun.color;
+            }
+          }
+        }
+
         // Get the lines for the given range of glyphs.
         // The lines contain the alignment offset which needs to be added to the glyph's position.
         LineIndex firstLine = 0u;
index 058ca9c..899474d 100644 (file)
@@ -70,6 +70,7 @@ public:
    */
   virtual Length GetGlyphs( GlyphInfo* glyphs,
                             Vector2* glyphPositions,
+                            Vector4* glyphColors,
                             GlyphIndex glyphIndex,
                             Length numberOfGlyphs ) const;
 
index 0717582..ca579e1 100644 (file)
@@ -27,6 +27,7 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/line-run.h>
+#include <dali-toolkit/internal/text/color-run.h>
 
 namespace Dali
 {
@@ -88,19 +89,6 @@ public:
                   GlyphIndex glyphIndex,
                   Length numberOfGlyphs ) const;
 
-  // Character <--> Glyph conversion
-
-  /**
-   * @brief Retrieves for each character the number of glyphs the character is shaped.
-   *
-   * @param[out] glyphsPerCharacter Pointer to a buffer where the number of glyphs for each character are copied.
-   * @param[in] characterIndex Index to the first character.
-   * @param[in] numberOfCharacters The number of characters.
-   */
-  void GetGlyphsPerCharacterMap( Length* glyphsPerCharacter,
-                                 CharacterIndex characterIndex,
-                                 Length numberOfCharacters ) const;
-
   // Position interface
 
   /**
@@ -314,6 +302,7 @@ public:
   Vector<Vector2>        mGlyphPositions;       ///< For each glyph, the position.
   Vector<LineRun>        mLines;                ///< The laid out lines.
   Vector<GlyphRun>       mUnderlineRuns;        ///< Runs of glyphs that are underlined.
+  Vector<ColorGlyphRun>  mColorRuns;            ///< Runs of glyphs with the same color.
 
   Vector2                mControlSize;           ///< The size of the UI control the decorator is adding it's decorations to.
   Vector4                mTextColor;            ///< The text color
index 649946c..b41b630 100644 (file)
@@ -40,7 +40,6 @@
 #include <dali-toolkit/devel-api/styling/style-manager.h>
 #include <dali-toolkit/internal/styling/style-manager-impl.h>
 #include <dali-toolkit/internal/controls/renderers/color/color-renderer.h>
-#include <dali-toolkit/internal/controls/renderers/image/image-renderer.h>
 
 namespace Dali
 {
@@ -165,6 +164,7 @@ TypeAction registerAction( typeRegistration, ACTION_ACCESSIBILITY_ACTIVATED, &Do
 DALI_TYPE_REGISTRATION_END()
 
 const char * const BACKGROUND_COLOR_NAME("color");
+const char * const COLOR_RENDERER_COLOR_NAME("blendColor");
 
 } // unnamed namespace
 
@@ -399,42 +399,28 @@ const std::string& Control::GetStyleName() const
   return mImpl->mStyleName;
 }
 
-void Control::UpdateBackgroundState()
-{
-  // Set the depth of the background renderer after creating/modifying it.
-  // We do this regardless of whether or not it is on stage as the index
-  // is relative and still valid if this control is re-parented.
-  if( mImpl->mBackgroundRenderer )
-  {
-    mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX );
-
-    Actor self( Self() );
-    if( self.OnStage() )
-    {
-      mImpl->mBackgroundRenderer.SetOnStage( self );
-    }
-  }
-}
-
 void Control::SetBackgroundColor( const Vector4& color )
 {
   Actor self( Self() );
   Toolkit::RendererFactory factory = Toolkit::RendererFactory::Get();
-
-  if( mImpl->mBackgroundRenderer )
-  {
-    factory.ResetRenderer( mImpl->mBackgroundRenderer, self, color );
-  }
-  else
-  {
-    mImpl->mBackgroundRenderer = factory.GetControlRenderer( color );
-  }
-
-  UpdateBackgroundState();
+  factory.ResetRenderer( mImpl->mBackgroundRenderer, self, color );
+  mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX );
 }
 
 Vector4 Control::GetBackgroundColor() const
 {
+  if( mImpl->mBackgroundRenderer && ( &typeid( GetImplementation(mImpl->mBackgroundRenderer) ) == &typeid( ColorRenderer ) ) )
+  {
+     Property::Map map;
+     mImpl->mBackgroundRenderer.CreatePropertyMap( map );
+     const Property::Value* colorValue = map.Find( COLOR_RENDERER_COLOR_NAME );
+     Vector4 color;
+     if( colorValue && colorValue->Get(color))
+     {
+       return color;
+     }
+  }
+
   return Color::TRANSPARENT;
 }
 
@@ -450,28 +436,21 @@ void Control::SetBackground(const Property::Map& map)
 
   Actor self( Self() );
   mImpl->mBackgroundRenderer.RemoveAndReset( self );
-
   Toolkit::RendererFactory factory = Toolkit::RendererFactory::Get();
   mImpl->mBackgroundRenderer = factory.GetControlRenderer( map );
-
-  UpdateBackgroundState();
+  if( mImpl->mBackgroundRenderer  && self.OnStage() ) // Request control renderer with a property map might return an empty handle
+  {
+    mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX );
+    mImpl->mBackgroundRenderer.SetOnStage( self );
+  }
 }
 
 void Control::SetBackgroundImage( Image image )
 {
   Actor self( Self() );
   Toolkit::RendererFactory factory = Toolkit::RendererFactory::Get();
-
-  if(  mImpl->mBackgroundRenderer  )
-  {
-    factory.ResetRenderer( mImpl->mBackgroundRenderer, self, image );
-  }
-  else
-  {
-    mImpl->mBackgroundRenderer = factory.GetControlRenderer( image );
-  }
-
-  UpdateBackgroundState();
+  factory.ResetRenderer( mImpl->mBackgroundRenderer, self, image );
+  mImpl->mBackgroundRenderer.SetDepthIndex( BACKGROUND_DEPTH_INDEX );
 }
 
 void Control::ClearBackground()
index c6b3b5e..aa86d6a 100644 (file)
@@ -268,15 +268,6 @@ public:
    */
   DALI_INTERNAL bool EmitKeyEventSignal( const KeyEvent& event );
 
-private:
-
-  /**
-   * Sets up the background image/color based on the current state.
-   * This will set the depth index (always), and add to stage if the control is on stage.
-   *
-   */
-  void UpdateBackgroundState();
-
 protected: // For derived classes to call
 
   /**
index 9afebab..6d6ca11 100644 (file)
@@ -261,6 +261,8 @@ public:
   /**
    * @brief Sets the background color of the control.
    *
+   * @note if SetBackgroundImage is called later, this background color is removed.
+   *
    * @param[in] color The required background color of the control
    *
    * @note The background color fully blends with the actor color.
index 10f05a9..7ffdaca 100644 (file)
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/images/frame-buffer-image.h>
 #include <dali/public-api/render-tasks/render-task.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/control.h>
index 6408c19..3333289 100644 (file)
@@ -62,7 +62,7 @@ ImageView ImageView::New( Image image )
 {
   ImageView imageView = Internal::ImageView::New();
   imageView.SetImage( image );
-  return ImageView( imageView );
+  return imageView;
 }
 
 ImageView ImageView::New( const std::string& url )
index f4642cf..7332e92 100644 (file)
@@ -79,6 +79,7 @@ public:
       VERTICAL_ALIGNMENT,                       ///< name "verticalAlignment",                   The line vertical alignment,                                              type STRING,  values   "TOP",   "CENTER",   "BOTTOM"
       TEXT_COLOR,                               ///< name "textColor",                           The text color,                                                           type VECTOR4
       PLACEHOLDER_TEXT_COLOR,                   ///< name "placeholderTextColor",                The placeholder-text color,                                               type VECTOR4
+      INPUT_COLOR,                              ///< name "inputColor",                          The color of the new input text,                                          type VECTOR4
       SHADOW_OFFSET,                            ///< name "shadowOffset",                        The drop shadow offset 0 indicates no shadow,                             type VECTOR2
       SHADOW_COLOR,                             ///< name "shadowColor",                         The color of a drop shadow,                                               type VECTOR4
       PRIMARY_CURSOR_COLOR,                     ///< name "primaryCursorColor",                  The color to apply to the primary cursor,                                 type VECTOR4
index 9576434..0a8be16 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 = 14;
+const unsigned int TOOLKIT_MICRO_VERSION = 15;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index b820c7b..5c97457 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    The OpenGLES Canvas Core Library Toolkit
-Version:    1.1.14
+Version:    1.1.15
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0, BSD-2.0, MIT
index 9f051fb..98b35a4 100644 (file)
@@ -124,7 +124,7 @@ function OnPressed( actor, touchEvent )
 }
   
 // connect to touch events
-myActor.connect( "touched", onPressed );
+myActor.on( "touched", onPressed );
 
 ```
 
@@ -143,7 +143,7 @@ hoverEvent = {
 }
 ```
       // connect to touch events
-      myActor.connect( "hovered", onHover);
+      myActor.on( "hovered", onHover);
 
 #### Mouse wheel event
 
@@ -161,7 +161,7 @@ mouseWheelEvent = {
 }
   
 // connect to touch events
-myActor.connect( "mouseWheelEvent", onMouseWheel );
+myActor.on( "mouseWheelEvent", onMouseWheel );
 ```
 #### Key events
 
index 9d4dd48..54ba7c3 100644 (file)
@@ -35,7 +35,7 @@ function finished( animation )
   log("Animation finished \n");
 }
   
-anim.connect("finished", finished );
+anim.on("finished", finished );
   
 anim.play();
 ```
index 821b5dd..fbdf726 100644 (file)
@@ -18,7 +18,7 @@ The application is required to help the manager when moving focus.
 Connect to the pre-focus-change call back as follows:
 ```
 // listen for pre-focus change events
-dali.keyboardFocusManager.connect("keyboardPreFocusChange", this.preFocusChanged);
+dali.keyboardFocusManager.on("keyboardPreFocusChange", this.preFocusChanged);
   
 // example call back handler
   
@@ -39,7 +39,7 @@ myApp.preFocusChanged = function( currentFocusedActor, proposedActorToFocus, dir
   }
 }
   
-dali.keyboardFocusManager.connect("keyboardPreFocusChange", myCallback)
+dali.keyboardFocusManager.on("keyboardPreFocusChange", myCallback)
 ```
 
 KeyboardFocusManager makes the best guess for which actor to focus towards the given direction, but applications might want to change that.
@@ -58,7 +58,7 @@ myCallback( originalFocusedActor, currentFocusedActor)
 {
 }
   
-dali.keyboardFocusManager.connect("keyboardFocusChange", myCallback)
+dali.keyboardFocusManager.on("keyboardFocusChange", myCallback)
 ```
 
 @class KeyboardFocusManager
index 1e82183..55291e0 100644 (file)
@@ -20,7 +20,7 @@ dali.stage.add(actor);
 panGestureDetector.attach(actor);
 
 // Connect the detected signal
-panGestureDetector.connect("panDetected", onPan);
+panGestureDetector.on("panDetected", onPan);
 
 onPan = function(actor, panGesture)
 {
index e14ad0f..fb982a0 100644 (file)
@@ -28,7 +28,7 @@ function imageLoaded( image )
   
 var image = new dali.ResourceImage( {url: "my_image.png"} );
   
-image.connect("imageLoadingFinished", finished );
+image.on("imageLoadingFinished", finished );
   
 // Create a material and add the image as texture to be used by the material.
 var material = new dali.Material();
index c8b4cf3..512b661 100644 (file)
@@ -48,7 +48,7 @@ daliApp.myCallback = function (keyEvent)
   }
 }
 
-dali.stage.connect("keyEvent", daliApp.myCallback);
+dali.stage.on("keyEvent", daliApp.myCallback);
 ```
 
 The key event object has the following properties
index d04eec3..336ed23 100644 (file)
@@ -232,9 +232,9 @@ const ActorFunctions ActorFunctionTable[]=
     { "Raise",              LayerApi::Raise,                    LAYER_API  },
     { "Lower",              LayerApi::Lower,                    LAYER_API  },
     { "RaiseAbove",         LayerApi::RaiseAbove,               LAYER_API  },
-    { "RaiseBelow",         LayerApi::LowerBelow,               LAYER_API  },
+    { "LowerBelow",         LayerApi::LowerBelow,               LAYER_API  },
     { "RaiseToTop",         LayerApi::RaiseToTop,               LAYER_API  },
-    { "LowerToBottom",      LayerApi::ToBottom,                 LAYER_API  },
+    { "LowerToBottom",      LayerApi::LowerToBottom,            LAYER_API  },
     { "MoveAbove",          LayerApi::MoveAbove,                LAYER_API  },
     { "MoveBelow",          LayerApi::MoveBelow,                LAYER_API  },
     // ignore SetClipping, use layer.clippingEnable
index 734efef..da6e18f 100644 (file)
@@ -184,7 +184,7 @@ void LayerApi::RaiseToTop( const v8::FunctionCallbackInfo<v8::Value>& args )
  * @for Layer
  * @method lowerToBottom
  */
-void LayerApi::ToBottom( const v8::FunctionCallbackInfo<v8::Value>& args )
+void LayerApi::LowerToBottom( const v8::FunctionCallbackInfo<v8::Value>& args )
 {
   v8::Isolate* isolate = args.GetIsolate();
   v8::HandleScope handleScope( isolate );
index 9667452..adb50d6 100644 (file)
@@ -44,7 +44,7 @@ namespace LayerApi
   void RaiseAbove( const v8::FunctionCallbackInfo< v8::Value >& args );
   void LowerBelow( const v8::FunctionCallbackInfo< v8::Value >& args );
   void RaiseToTop( const v8::FunctionCallbackInfo< v8::Value >& args );
-  void ToBottom( const v8::FunctionCallbackInfo< v8::Value >& args );
+  void LowerToBottom( const v8::FunctionCallbackInfo< v8::Value >& args );
   void MoveBelow( const v8::FunctionCallbackInfo< v8::Value >& args );
   void MoveAbove( const v8::FunctionCallbackInfo< v8::Value >& args );
   void SetDepthTestDisabled( const v8::FunctionCallbackInfo< v8::Value >& args );
index 3510523..34a97e4 100644 (file)
@@ -34,12 +34,12 @@ namespace ObjectTemplateHelper
 
 void AddSignalConnectAndDisconnect( v8::Isolate* isolate,  v8::Local<v8::ObjectTemplate>& objTemplate )
 {
-  objTemplate->Set( v8::String::NewFromUtf8( isolate, "connect"),
+  objTemplate->Set( v8::String::NewFromUtf8( isolate, "on"),
                      v8::FunctionTemplate::New( isolate, SignalManager::SignalConnect) );
 
 
 
-  objTemplate->Set( v8::String::NewFromUtf8( isolate, "disconnect"),
+  objTemplate->Set( v8::String::NewFromUtf8( isolate, "off"),
                      v8::FunctionTemplate::New( isolate, SignalManager::SignalDisconnect) );
 }