" \"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"
" \"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"
" \"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"
" \"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"
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 );
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;
}
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;
}
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;
}
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 ) );
* 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
"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"
"\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(
"\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(
"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"
" }\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;
" 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"
"\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(
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(
"{\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"
"}\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
"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"
"\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,
"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;
"\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"
" 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(
"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"
#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>
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"
"{\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
, mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
, mImageIntensityPropertyIndex(Property::INVALID_INDEX)
, mImageSaturationPropertyIndex(Property::INVALID_INDEX)
+ , mActivated( false )
{
}
, mBloomSaturationPropertyIndex(Property::INVALID_INDEX)
, mImageIntensityPropertyIndex(Property::INVALID_INDEX)
, mImageSaturationPropertyIndex(Property::INVALID_INDEX)
+ , mActivated( false )
{
}
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
// 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 );
////////////////////////////////
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();
}
}
// 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);
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);
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();
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();
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 );
}
// make sure resources are allocated and start the render tasks processing
AllocateResources();
CreateRenderTasks();
+ mActivated = true;
}
void BloomView::Deactivate()
// stop render tasks processing
// Note: render target resources are automatically freed since we set the Image::Unused flag
RemoveRenderTasks();
+ mActivated = false;
}
/**
// 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();
// 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();
// 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();
// 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();
// 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();
}
#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
// 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
/////////////////////////////////////////////////////////////
// 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
Property::Index mImageIntensityPropertyIndex;
Property::Index mImageSaturationPropertyIndex;
+ bool mActivated:1;
+
private:
// Undefined copy constructor.
#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>
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";
, mLastSize(Vector2::ZERO)
, mChildrenRoot(Actor::New())
, mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
+ , mActivated( false )
{
SetBlurBellCurveWidth(GAUSSIAN_BLUR_VIEW_DEFAULT_BLUR_BELL_CURVE_WIDTH);
}
, mLastSize(Vector2::ZERO)
, mChildrenRoot(Actor::New())
, mBlurStrengthPropertyIndex(Property::INVALID_INDEX)
+ , mActivated( false )
{
SetBlurBellCurveWidth(blurBellCurveWidth);
}
//////////////////////////////////////////////////////
// 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);
// 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());
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);
//////////////////////////////////////////////////////
// Create camera for the renders corresponding to the (potentially downsampled) render targets' size
mRenderDownsampledCamera = CameraActor::New();
+ mRenderDownsampledCamera.SetInvertYAxis( true );
mRenderDownsampledCamera.SetParentOrigin(ParentOrigin::CENTER);
}
- // 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();
}
}
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 );
}
// 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);
mHorizBlurTask.SetInputEnabled( false );
mHorizBlurTask.SetClearEnabled( true );
mHorizBlurTask.SetClearColor( mBackgroundColor );
+ mHorizBlurTask.SetCameraActor(mRenderDownsampledCamera);
+ mHorizBlurTask.SetTargetFrameBuffer( mRenderTarget2 );
if( mRenderOnce && mBlurUserImage )
{
mHorizBlurTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
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);
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()
// make sure resources are allocated and start the render tasks processing
AllocateResources();
CreateRenderTasks();
+ mActivated = true;
}
void GaussianBlurView::ActivateOnce()
// 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)
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;
// 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
{
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
FrameBufferImage mUserOutputRenderTarget;
Dali::Toolkit::GaussianBlurView::GaussianBlurViewSignal mFinishedSignal; ///< Signal emitted when blur has completed.
+
+ bool mActivated:1;
private:
// Undefined copy constructor.
**/
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
{\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
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 );
\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
// 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
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
// 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 );
}
// 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();
{
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 );
+ }
}
}
}
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" );
}
}
}
return nextFocusableActor;
}
+
} // namespace Internal
} // namespace Toolkit
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&);
{
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() )
{
{
InitializeRenderer( mImageUrl );
}
- else if( mImage )
+ else
{
InitializeRenderer( mImage );
}
#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>
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.
*/
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 );
}
}
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()
{
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;
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 )
{
Stage::GetCurrent().Remove( mGaussianBlurView[i] );
mGaussianBlurView[i].Deactivate();
- mGaussianBlurView[i].Reset();
}
mResourcesCleared = true;
}
{
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 ) );
{
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 );
}
#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
{
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;
*/
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:
/**
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;
};
}
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 )
if( impl.mController->GetTextColor() != textColor )
{
impl.mController->SetTextColor( textColor );
+ impl.mController->SetInputColor( textColor );
impl.mRenderer.Reset();
}
}
}
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 )
}
break;
}
+ case Toolkit::TextField::Property::INPUT_COLOR:
+ {
+ if( impl.mController )
+ {
+ value = impl.mController->GetInputColor();
+ }
+ break;
+ }
case Toolkit::TextField::Property::SHADOW_OFFSET:
{
if ( impl.mController )
{
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 );
}
}
// 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>
// 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.
}
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 );
$(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 \
{
}
-bool KeyboardFocusManager::SetCurrentFocusActor(Actor actor)
+bool KeyboardFocusManager::SetCurrentFocusActor( Actor actor )
{
DALI_ASSERT_DEBUG( !mIsWaitingKeyboardFocusChangeCommit && "Calling this function in the PreFocusChangeSignal callback?" );
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()
{
// 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 );
};
} // 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;
{
/**
+ * @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.
--- /dev/null
+#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__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
--- /dev/null
+#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__
// 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
{
}
- ImageActor actor;
+ ImageView actor;
Actor grabArea;
- ImageActor markerActor;
+ ImageView markerActor;
Vector2 position;
Size size;
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 );
}
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
{
if( image )
{
- handle.markerActor = ImageActor::New( image );
+ handle.markerActor = ImageView::New( image );
handle.markerActor.SetColor( mHandleColor );
handle.actor.Add( handle.markerActor );
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
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
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;
// 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 );
}
}
--- /dev/null
+#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__
// 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
{
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()
{
}
// 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>
class LogicalModel;
typedef IntrusivePtr<LogicalModel> LogicalModelPtr;
+struct InputStyle;
/**
* @brief A logical text model contains layout independent information.
*/
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:
/**
Vector<Character> mText;
Vector<ScriptRun> mScriptRuns;
Vector<FontRun> mFontRuns;
+ Vector<ColorRun> mColorRuns;
Vector<LineBreakInfo> mLineBreakInfo;
Vector<WordBreakInfo> mWordBreakInfo;
Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
--- /dev/null
+#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__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
--- /dev/null
+#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__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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
--- /dev/null
+#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__
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 );
}
);
{
Vector2 mPosition; ///< Vertex posiiton
Vector2 mTexCoords; ///< Vertex texture co-ordinates
+ Vector4 mColor; ///< Vertex color
};
struct Mesh2D
struct MeshRecord
{
MeshRecord()
- : mColor( Color::BLACK ),
- mAtlasId( 0 )
+ : mAtlasId( 0u )
{
}
- Vector4 mColor;
uint32_t mAtlasId;
AtlasManager::Mesh2D mMesh;
FrameBufferImage mBuffer;
mRight( 0.0f ),
mUnderlinePosition( 0.0f ),
mUnderlineThickness( 0.0f ),
- mMeshRecordIndex( 0 )
+ mMeshRecordIndex( 0u )
{
}
mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2;
+ mQuadVertexFormat[ "aColor" ] = Property::VECTOR4;
mQuadIndexFormat[ "indices" ] = Property::INTEGER;
}
void AddGlyphs( Text::ViewInterface& view,
const Vector<Vector2>& positions,
const Vector<GlyphInfo>& glyphs,
+ const Vector<Vector4>& colors,
int depth )
{
AtlasManager::AtlasSlot slot;
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() );
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 )
{
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;
}
// 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 )
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
}
// 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;
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,
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;
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 ? "" : " ",
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*/ );
}
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;
}
void StitchTextMesh( std::vector< MeshRecord >& meshContainer,
AtlasManager::Mesh2D& newMesh,
Vector< Extent >& extents,
- const Vector4& color,
float baseLine,
bool underlineGlyph,
float underlinePosition,
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 );
MeshRecord meshRecord;
meshRecord.mAtlasId = slot.mAtlasId;
meshRecord.mMesh = newMesh;
- meshRecord.mColor = color;
meshContainer.push_back( meshRecord );
if( underlineGlyph )
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 );
}
}
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;
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 );
}
}
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();
*
*/
-// CLASS HEADER
+// FILE HEADER
#include <dali-toolkit/internal/text/segmentation.h>
// EXTERNAL INCLUDES
// 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>
mUpdateRightSelectionPosition( false ),
mScrollAfterUpdatePosition( false ),
mScrollAfterDelete( false ),
- mAllTextSelected( false )
+ mAllTextSelected( false ),
+ mUpdateInputStyle( false )
{
mImfManager = ImfManager::Get();
}
}
}
+ 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" );
}
}
+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 )
}
mEventData->mUpdateCursorPosition = true;
+ mEventData->mUpdateInputStyle = true;
mEventData->mScrollAfterUpdatePosition = true;
}
mEventData->mUpdateCursorPosition = true;
mEventData->mScrollAfterUpdatePosition = true;
+ mEventData->mUpdateInputStyle = true;
// Notify the cursor position to the imf manager.
if( mEventData->mImfManager )
if( Event::GRAB_HANDLE_EVENT == event.type )
{
mEventData->mUpdateCursorPosition = true;
+ mEventData->mUpdateInputStyle = true;
if ( !IsClipboardEmpty() )
{
mEventData->mUpdateCursorPosition = mEventData->mPrimaryCursorPosition != handlePosition;
mEventData->mScrollAfterUpdatePosition = mEventData->mUpdateCursorPosition;
mEventData->mPrimaryCursorPosition = handlePosition;
+ mEventData->mUpdateInputStyle = mEventData->mUpdateCursorPosition;
}
else if( leftSelectionHandleEvent || rightSelectionHandleEvent )
{
}
}
-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;
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 );
}
}
// 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 );
#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>
*/
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.
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
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();
{
if( !mFontId )
{
- Dali::TextAbstraction::PointSize26Dot6 pointSize = mDefaultPointSize*64;
+ const PointSize26Dot6 pointSize = static_cast<PointSize26Dot6>( mDefaultPointSize * 64.f );
mFontId = fontClient.GetFontId( mFontDescription, pointSize );
}
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();
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();
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.
void OnSelectAllEvent();
- void RetrieveSelection( std::string& selectedText, bool deleteAfterRetreival );
+ void RetrieveSelection( std::string& selectedText, bool deleteAfterRetrieval );
void ShowClipboard();
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 );
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.
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
#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
}
}
+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" );
// 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 )
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;
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;
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" );
{
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 |
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;
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() )
}
}
- 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()
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 )
mImpl->mVisualModel->mGlyphsPerCharacter.Clear();
mImpl->mVisualModel->mGlyphPositions.Clear();
mImpl->mVisualModel->mLines.Clear();
+ mImpl->mVisualModel->mColorRuns.Clear();
mImpl->mVisualModel->ClearCaches();
}
mImpl->mVisualModel->ClearCaches();
}
+void Controller::ClearStyleData()
+{
+ mImpl->mLogicalModel->mColorRuns.Clear();
+}
+
Controller::Controller( ControlInterface& controlInterface )
: mImpl( NULL )
{
UPDATE_ACTUAL_SIZE = 0x0200,
REORDER = 0x0400,
ALIGN = 0x0800,
+ COLOR = 0x1000,
ALL_OPERATIONS = 0xFFFF
};
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.
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.
void ClearFontData();
/**
+ * @brief Helper to clear text's style data.
+ */
+ void ClearStyleData();
+
+ /**
* @brief Private constructor.
*/
Controller( ControlInterface& controlInterface );
--- /dev/null
+#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__
* @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.
*
*/
virtual Length GetGlyphs( GlyphInfo* glyphs,
Vector2* glyphPositions,
+ Vector4* glyphColors,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const = 0;
Length View::GetGlyphs( GlyphInfo* glyphs,
Vector2* glyphPositions,
+ Vector4* glyphColors,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const
{
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;
*/
virtual Length GetGlyphs( GlyphInfo* glyphs,
Vector2* glyphPositions,
+ Vector4* glyphColors,
GlyphIndex glyphIndex,
Length numberOfGlyphs ) const;
// INTERNAL INCLUDES
#include <dali-toolkit/internal/text/line-run.h>
+#include <dali-toolkit/internal/text/color-run.h>
namespace Dali
{
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
/**
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
#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
{
DALI_TYPE_REGISTRATION_END()
const char * const BACKGROUND_COLOR_NAME("color");
+const char * const COLOR_RENDERER_COLOR_NAME("blendColor");
} // unnamed namespace
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;
}
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()
*/
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
/**
/**
* @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.
// 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>
{
ImageView imageView = Internal::ImageView::New();
imageView.SetImage( image );
- return ImageView( imageView );
+ return imageView;
}
ImageView ImageView::New( const std::string& url )
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
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
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
}
// connect to touch events
-myActor.connect( "touched", onPressed );
+myActor.on( "touched", onPressed );
```
}
```
// connect to touch events
- myActor.connect( "hovered", onHover);
+ myActor.on( "hovered", onHover);
#### Mouse wheel event
}
// connect to touch events
-myActor.connect( "mouseWheelEvent", onMouseWheel );
+myActor.on( "mouseWheelEvent", onMouseWheel );
```
#### Key events
log("Animation finished \n");
}
-anim.connect("finished", finished );
+anim.on("finished", finished );
anim.play();
```
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
}
}
-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.
{
}
-dali.keyboardFocusManager.connect("keyboardFocusChange", myCallback)
+dali.keyboardFocusManager.on("keyboardFocusChange", myCallback)
```
@class KeyboardFocusManager
panGestureDetector.attach(actor);
// Connect the detected signal
-panGestureDetector.connect("panDetected", onPan);
+panGestureDetector.on("panDetected", onPan);
onPan = function(actor, panGesture)
{
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();
}
}
-dali.stage.connect("keyEvent", daliApp.myCallback);
+dali.stage.on("keyEvent", daliApp.myCallback);
```
The key event object has the following properties
{ "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
* @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 );
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 );
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) );
}