.Add( ImageVisual::Property::WRAP_MODE_U, WrapMode::REPEAT )
.Add( ImageVisual::Property::WRAP_MODE_V, WrapMode::DEFAULT )
.Add( DevelVisual::Property::CORNER_RADIUS, 22.2f )
- .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE ));
+ .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::ABSOLUTE )
+ .Add( DevelVisual::Property::BORDERLINE_WIDTH, 33.3f )
+ .Add( DevelVisual::Property::BORDERLINE_COLOR, Color::RED )
+ .Add( DevelVisual::Property::BORDERLINE_OFFSET, 0.3f ));
Property::Map resultMap;
animatedImageVisual.CreatePropertyMap( resultMap );
DALI_TEST_CHECK( value );
DALI_TEST_CHECK( value->Get<int>() == Visual::Transform::Policy::ABSOLUTE );
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 33.3f, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), Color::RED, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 0.3f, TEST_LOCATION );
+
// request AnimatedImageVisual with an URL
Visual::Base animatedImageVisual2 = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() );
resultMap.Clear();
.Add( "wrapModeU", WrapMode::REPEAT )
.Add( "wrapModeV", WrapMode::DEFAULT )
.Add( "cornerRadius", Vector4(50.0f, 25.0f, 12.5f, 33.0f) )
- .Add( "cornerRadiusPolicy", Visual::Transform::Policy::RELATIVE ));
+ .Add( "cornerRadiusPolicy", Visual::Transform::Policy::RELATIVE )
+ .Add( "borderlineWidth", 20.0f )
+ .Add( "borderlineColor", Vector4() )
+ .Add( "borderlineOffset", -1.0f));
Property::Map resultMap;
animatedImageVisual.CreatePropertyMap( resultMap );
DALI_TEST_CHECK( value );
DALI_TEST_CHECK( value->Get<int>() == Visual::Transform::Policy::RELATIVE );
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 20.0f, TEST_LOCATION );
+
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), Vector4::ZERO, TEST_LOCATION );
+
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), -1.0f, TEST_LOCATION );
+
END_TEST;
}
DALI_TEST_CHECK( value );
DALI_TEST_CHECK( value->Get<int>() == Visual::Transform::Policy::ABSOLUTE );
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 0.0f, TEST_LOCATION );
+
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), Color::BLACK, TEST_LOCATION );
+
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 0.0f, TEST_LOCATION );
+
END_TEST;
}
.Add( ImageVisual::Property::URL, TEST_GIF_FILE_NAME )
.Add( ImageVisual::Property::BATCH_SIZE, 1 )
.Add( ImageVisual::Property::CACHE_SIZE, 1 )
- .Add( ImageVisual::Property::SYNCHRONOUS_LOADING, false ));
+ .Add( ImageVisual::Property::SYNCHRONOUS_LOADING, false )
+ .Add( DevelVisual::Property::BORDERLINE_WIDTH, 0.4f ));
Property::Map resultMap;
animatedImageVisual.CreatePropertyMap( resultMap );
DALI_TEST_CHECK( value );
DALI_TEST_EQUALS( value->Get<int>(), 4, TEST_LOCATION );
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 0.4f, TEST_LOCATION );
+
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), Vector4(0.0f, 0.0f, 0.0f, 1.0f), TEST_LOCATION );
+
+ value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), 0.0f, TEST_LOCATION );
+
END_TEST;
}
.Add( ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME )
.Add( DevelImageVisual::Property::LOOP_COUNT, 3 )
.Add( DevelImageVisual::Property::PLAY_RANGE, playRange )
- .Add( DevelVisual::Property::CORNER_RADIUS, 50.0f );
+ .Add( DevelVisual::Property::CORNER_RADIUS, 50.0f )
+ .Add( DevelVisual::Property::BORDERLINE_WIDTH, 20.0f );
Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
DALI_TEST_CHECK( visual );
int startFrame = 1, endFrame = 3;
float cornerRadius = 22.0f;
+ float borderlineWidth = 2.0f;
+ Vector4 borderlineColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f);
+ float borderlineOffset = 0.1f;
Property::Array playRange;
playRange.PushBack( startFrame );
playRange.PushBack( endFrame );
.Add( "stopBehavior", DevelImageVisual::StopBehavior::FIRST_FRAME )
.Add( "loopingMode", DevelImageVisual::LoopingMode::AUTO_REVERSE )
.Add( "redrawInScalingDown", false )
- .Add( "cornerRadius", cornerRadius );
+ .Add( "cornerRadius", cornerRadius )
+ .Add( "borderlineWidth", borderlineWidth )
+ .Add( "borderlineColor", borderlineColor )
+ .Add( "borderlineOffset", borderlineOffset );
Visual::Base visual = VisualFactory::Get().CreateVisual( propertyMap );
DALI_TEST_CHECK( visual );
DALI_TEST_CHECK( value );
DALI_TEST_CHECK( value->Get< int >() == Visual::Transform::Policy::ABSOLUTE );
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get< float >(), borderlineWidth, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get< Vector4 >(), borderlineColor, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get< float >(), borderlineOffset, TEST_LOCATION );
+
actor.Unparent( );
DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
int startFrame = 1, endFrame = 3;
Vector4 cornerRadius(50.0f, 22.0f, 0.0f, 3.0f);
+ float borderlineWidth = 2.3f;
+ Vector4 borderlineColor = Vector4(0.3f, 0.3f, 1.0f, 1.0f);
+ float borderlineOffset = 0.3f;
Property::Array playRange;
playRange.PushBack( startFrame );
playRange.PushBack( endFrame );
.Add( DevelImageVisual::Property::LOOP_COUNT, 3 )
.Add( DevelImageVisual::Property::PLAY_RANGE, playRange )
.Add( DevelVisual::Property::CORNER_RADIUS, cornerRadius )
- .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::RELATIVE);
+ .Add( DevelVisual::Property::CORNER_RADIUS_POLICY, Visual::Transform::Policy::RELATIVE)
+ .Add( DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth )
+ .Add( DevelVisual::Property::BORDERLINE_COLOR, borderlineColor )
+ .Add( DevelVisual::Property::BORDERLINE_OFFSET, borderlineOffset );
// request AnimatedVectorImageVisual with a property map
VisualFactory factory = VisualFactory::Get();
DALI_TEST_CHECK( value );
DALI_TEST_CHECK( value->Get< int >() == Visual::Transform::Policy::RELATIVE );
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get< float >(), borderlineWidth, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get< Vector4 >(), borderlineColor, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get< float >(), borderlineOffset, TEST_LOCATION );
+
// request AnimatedVectorImageVisual with an URL
Visual::Base visual2 = factory.CreateVisual( TEST_VECTOR_IMAGE_FILE_NAME, ImageDimensions() );
}
END_TEST;
-}
\ No newline at end of file
+}
propertyMap.Insert(Visual::Property::MIX_COLOR, Color::BLUE);
propertyMap.Insert( DevelVisual::Property::CORNER_RADIUS, 10.0f );
propertyMap.Insert( DevelVisual::Property::CORNER_RADIUS_POLICY, Toolkit::Visual::Transform::Policy::RELATIVE );
+ propertyMap.Insert( DevelVisual::Property::BORDERLINE_WIDTH, 20.0f );
+ propertyMap.Insert( DevelVisual::Property::BORDERLINE_COLOR, Color::RED );
+ propertyMap.Insert( DevelVisual::Property::BORDERLINE_OFFSET, -1.0f );
propertyMap.Insert( DevelColorVisual::Property::BLUR_RADIUS, 20.0f );
Visual::Base colorVisual = factory.CreateVisual( propertyMap );
DALI_TEST_CHECK( cornerRadiusPolicyValue );
DALI_TEST_CHECK( cornerRadiusPolicyValue->Get< int >() == Toolkit::Visual::Transform::Policy::RELATIVE );
+ Property::Value* borderlineWidthValue = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT );
+ DALI_TEST_CHECK( borderlineWidthValue );
+ DALI_TEST_CHECK( borderlineWidthValue->Get< float >() == 20.0f );
+
+ Property::Value* borderlineColorValue = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 );
+ DALI_TEST_CHECK( borderlineColorValue );
+ DALI_TEST_CHECK( borderlineColorValue->Get< Vector4 >() == Color::RED );
+
+ Property::Value* borderlineOffsetValue = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT );
+ DALI_TEST_CHECK( borderlineOffsetValue );
+ DALI_TEST_CHECK( borderlineOffsetValue->Get< float >() == -1.0f );
+
Property::Value* blurRadiusValue = resultMap.Find( DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT );
DALI_TEST_CHECK( blurRadiusValue );
DALI_TEST_CHECK( blurRadiusValue->Get< float >() == 20.0f );
DALI_TEST_CHECK( colorValue );
DALI_TEST_CHECK( colorValue->Get<Vector4>() == Color::CYAN );
- colorValue = resultMap.Find( BorderVisual::Property::SIZE, Property::FLOAT );
+ sizeValue = resultMap.Find( BorderVisual::Property::SIZE, Property::FLOAT );
+ DALI_TEST_CHECK( sizeValue );
+ DALI_TEST_CHECK( sizeValue->Get<float>() == 10.f );
+
+ // Get default value of borderline values here
+
+ sizeValue = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT );
+ DALI_TEST_CHECK( sizeValue );
+ DALI_TEST_CHECK( sizeValue->Get<float>() == 0.0f );
+
+ colorValue = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 );
DALI_TEST_CHECK( colorValue );
- DALI_TEST_CHECK( colorValue->Get<float>() == 10.f );
+ DALI_TEST_CHECK( colorValue->Get<Vector4>() == Color::BLACK );
+ sizeValue = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT );
+ DALI_TEST_CHECK( sizeValue );
+ DALI_TEST_CHECK( sizeValue->Get<float>() == 0.0f );
END_TEST;
}
stopColors.PushBack( Color::GREEN );
propertyMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
+ float borderlineWidth = 4.0f;
+ Vector4 cornerRadius(7.0f, 10.0f, 13.0f, 16.0f);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
+ propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, cornerRadius);
+
Visual::Base gradientVisual = factory.CreateVisual(propertyMap);
Property::Map resultMap;
DALI_TEST_CHECK( value );
DALI_TEST_EQUALS( value->Get<Vector2>(), end , Math::MACHINE_EPSILON_100, TEST_LOCATION );
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), borderlineWidth , Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4 );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), cornerRadius , Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
value = resultMap.Find( GradientVisual::Property::STOP_OFFSET, Property::ARRAY );
DALI_TEST_CHECK( value );
Property::Array* offsetArray = value->GetArray();
stopColors.PushBack( Color::GREEN );
propertyMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
+ float borderlineWidth = 8.0f;
+ Vector4 cornerRadius(1.0f, 2.0f, 4.0f, 8.0f);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, borderlineWidth);
+ propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, cornerRadius);
+
Visual::Base gradientVisual = factory.CreateVisual(propertyMap);
DALI_TEST_CHECK( gradientVisual );
DALI_TEST_CHECK( value );
DALI_TEST_EQUALS( value->Get<float>(), radius , Math::MACHINE_EPSILON_100, TEST_LOCATION );
+ value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<float>(), borderlineWidth , Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+ value = resultMap.Find( DevelVisual::Property::CORNER_RADIUS, Property::VECTOR4 );
+ DALI_TEST_CHECK( value );
+ DALI_TEST_EQUALS( value->Get<Vector4>(), cornerRadius , Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
value = resultMap.Find( GradientVisual::Property::STOP_OFFSET, Property::ARRAY );
DALI_TEST_CHECK( value );
Property::Array* offsetArray = value->GetArray();
END_TEST;
}
+int UtcDaliVisualBorderline(void)
+{
+#ifdef OLD_GRAPHICS_TEST
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualBorderline" );
+
+ static std::vector<UniformData> customUniforms =
+ {
+ UniformData("cornerRadius", Property::Type::VECTOR4),
+ UniformData("cornerRadiusPolicy", Property::Type::FLOAT),
+ UniformData("borderlineWidth", Property::Type::FLOAT),
+ UniformData("borderlineColor", Property::Type::VECTOR4),
+ UniformData("borderlineOffset", Property::Type::FLOAT),
+ };
+
+ TestGraphicsController& graphics = application.GetGraphicsController();
+ graphics.AddCustomUniforms(customUniforms);
+
+ // image visual
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ float cornerRadius = 5.0f;
+ float borderlineWidth = 30.0f;
+ Vector4 borderlineColor(1.0f, 0.0f, 0.0f, 1.0f);
+ float borderlineOffset = 1.0f;
+
+ properties[Visual::Property::TYPE] = Visual::IMAGE;
+ properties[ImageVisual::Property::URL] = TEST_IMAGE_FILE_NAME;
+ properties[DevelVisual::Property::CORNER_RADIUS] = cornerRadius;
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth;
+ properties[DevelVisual::Property::BORDERLINE_COLOR] = borderlineColor;
+ properties[DevelVisual::Property::BORDERLINE_OFFSET] = borderlineOffset;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", Vector4(cornerRadius, cornerRadius, cornerRadius, cornerRadius) ), true, TEST_LOCATION );
+ // Default corner radius policy is absolute.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::ABSOLUTE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION );
+ }
+
+ // color visual 1
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ Vector4 cornerRadius(23.0f, 2.0f, 3.0f, 2.3f);
+ float borderlineWidth = 30.0f;
+ Vector4 borderlineColor(0.5f, 0.4f, 0.3f, 0.2f);
+ float borderlineOffset = -0.4f;
+
+ properties[Visual::Property::TYPE] = Visual::COLOR;
+ properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE;
+ properties["cornerRadius"] = cornerRadius;
+ properties["borderlineWidth"] = borderlineWidth;
+ properties["borderlineColor"] = borderlineColor;
+ properties["borderlineOffset"] = borderlineOffset;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", cornerRadius ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION );
+ }
+
+ // color visual 2, default color, default offset
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ float borderlineWidth = 30.0f;
+
+ properties[Visual::Property::TYPE] = Visual::COLOR;
+ properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE;
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ // Default borderline color is BLACK.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", Color::BLACK ), true, TEST_LOCATION );
+ // Default borderline offset is 0.0f.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", 0.0f ), true, TEST_LOCATION );
+ }
+
+ // color visual 3, offset not [-1.0 ~ 1.0], but uniform value is same anyway
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ float borderlineWidth = 30.0f;
+ Vector4 borderlineColor(0.5f, 0.4f, 0.3f, 0.2f);
+ float borderlineOffset = 37.4f;
+
+ properties[Visual::Property::TYPE] = Visual::COLOR;
+ properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE;
+ properties["borderlineWidth"] = borderlineWidth;
+ properties["borderlineColor"] = borderlineColor;
+ properties["borderlineOffset"] = borderlineOffset;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION );
+ // NOTE : borderlineOffset will clamp in fragment shader. not visual itself
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION );
+ }
+
+ // gradient visual
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ float borderlineWidth = 30.0f;
+ float cornerRadius = 70.0f;
+
+ properties[Visual::Property::TYPE] = Visual::GRADIENT;
+ properties[ColorVisual::Property::MIX_COLOR] = Color::BLUE;
+ properties[DevelVisual::Property::CORNER_RADIUS] = cornerRadius;
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth;
+ properties[GradientVisual::Property::START_POSITION] = Vector2( 0.5f, 0.5f );
+ properties[GradientVisual::Property::END_POSITION] = Vector2( -0.5f, -0.5f );
+ properties[GradientVisual::Property::UNITS] = GradientVisual::Units::USER_SPACE;
+
+ Property::Array stopOffsets;
+ stopOffsets.PushBack( 0.0f );
+ stopOffsets.PushBack( 0.6f );
+ stopOffsets.PushBack( 1.0f );
+ properties[GradientVisual::Property::STOP_OFFSET] = stopOffsets;
+
+ Property::Array stopColors;
+ stopColors.PushBack( Color::RED );
+ stopColors.PushBack( Color::YELLOW );
+ stopColors.PushBack( Color::GREEN );
+ properties[GradientVisual::Property::STOP_COLOR] = stopColors;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", Vector4(cornerRadius, cornerRadius, cornerRadius, cornerRadius) ), true, TEST_LOCATION );
+ // Default corner radius policy is absolute.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::ABSOLUTE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ // Default borderline color is BLACK.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", Color::BLACK ), true, TEST_LOCATION );
+ // Default borderline offset is 0.0f.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", 0.0f ), true, TEST_LOCATION );
+ }
+
+ // animated image visual
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ float borderlineWidth = 24.0f;
+ float borderlineOffset = -1.0f;
+
+ properties[Visual::Property::TYPE] = Visual::ANIMATED_IMAGE;
+ properties[ImageVisual::Property::URL] = TEST_GIF_FILE_NAME;
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth + 10.0f; // Dummy Input
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth;
+ properties["borderlineOffset"] = borderlineOffset;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ // Default borderline color is BLACK.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", Color::BLACK ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION );
+ }
+
+ // vector image visual
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ Vector4 cornerRadius(54.0f, 43.0f, 32.0f, 21.0f);
+ float borderlineWidth = 27.0f;
+ Vector4 borderlineColor(0.5f, 0.5f, 0.5f, 0.0f);
+
+ properties[Visual::Property::TYPE] = Visual::SVG;
+ properties[ImageVisual::Property::URL] = TEST_SVG_FILE_NAME;
+ properties[DevelVisual::Property::CORNER_RADIUS] = cornerRadius;
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth;
+ properties[DevelVisual::Property::BORDERLINE_COLOR] = borderlineColor;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", cornerRadius ), true, TEST_LOCATION );
+ // Default corner radius policy is absolute.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::ABSOLUTE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION );
+ // Default borderline offset is 0.0.
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", 0.0f ), true, TEST_LOCATION );
+ }
+
+ // animated vector image visual
+ {
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map properties;
+ Vector4 cornerRadius(1.3f, 0.0f, 0.4f, 0.2f);
+ float borderlineWidth = 13.0f;
+ Vector4 borderlineColor(0.3f, 0.3f, 0.3f, 1.0f);
+ float borderlineOffset = 13.0f;
+
+ properties[Visual::Property::TYPE] = DevelVisual::ANIMATED_VECTOR_IMAGE;
+ properties[ImageVisual::Property::URL] = TEST_VECTOR_IMAGE_FILE_NAME;
+ properties["cornerRadius"] = cornerRadius;
+ properties[DevelVisual::Property::CORNER_RADIUS_POLICY] = Toolkit::Visual::Transform::Policy::RELATIVE;
+ properties[DevelVisual::Property::BORDERLINE_WIDTH] = borderlineWidth;
+ properties["borderlineColor"] = borderlineColor;
+ properties[DevelVisual::Property::BORDERLINE_OFFSET] = borderlineOffset;
+
+ Visual::Base visual = factory.CreateVisual( properties );
+
+ // trigger creation through setting on stage
+ DummyControl dummy = DummyControl::New( true );
+ Impl::DummyControl& dummyImpl = static_cast< Impl::DummyControl& >( dummy.GetImplementation() );
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummy.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ dummy.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+ application.GetScene().Add( dummy );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "cornerRadius", cornerRadius ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "cornerRadiusPolicy", Toolkit::Visual::Transform::Policy::RELATIVE ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineWidth", borderlineWidth ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< Vector4 >( "borderlineColor", borderlineColor ), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( application.GetGlAbstraction().CheckUniformValue< float >( "borderlineOffset", borderlineOffset ), true, TEST_LOCATION );
+ }
+#else
+ tet_result(TET_PASS);
+#endif
+
+ END_TEST;
+}
+
+
int UtcDaliColorVisualBlurRadius(void)
{
ToolkitTestApplication application;
UniformData("size", Property::Type::VECTOR2),
UniformData("cornerRadius", Property::Type::VECTOR4),
UniformData("blurRadius", Property::Type::FLOAT),
+ UniformData("borderlineWidth", Property::Type::FLOAT),
+ UniformData("borderlineColor", Property::Type::VECTOR4),
+ UniformData("borderlineOffset", Property::Type::FLOAT),
};
TestGraphicsController& graphics = application.GetGraphicsController();
propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, Vector4(10.0f, 0.0f, 2.0f, 4.0f));
propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS_POLICY, Toolkit::Visual::Transform::Policy::RELATIVE);
propertyMap.Insert(DevelColorVisual::Property::BLUR_RADIUS, 20.0f);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 20.0f);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_COLOR, Color::RED);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_OFFSET, 1.0f);
Visual::Base colorVisual = factory.CreateVisual(propertyMap);
DummyControl dummyControl = DummyControl::New(true);
float targetOpacity = 0.5f;
Vector4 targetCornerRadius(0.0f, 0.0f, 0.0f, 0.0f);
float targetBlurRadius = 10.0f;
+ float targetBorderlineWidth = 25.0f;
+ Vector4 targetBorderlineColor(1.0f, 1.0f, 1.0f, 1.0f);
+ float targetBorderlineOffset = -1.0f;
Animation animation = Animation::New(1.0f);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR), targetColor);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Transform::Property::SIZE), targetSize);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), targetCornerRadius);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelColorVisual::Property::BLUR_RADIUS), targetBlurRadius);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), targetBorderlineWidth);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_COLOR), targetBorderlineColor);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_OFFSET), targetBorderlineOffset);
animation.Play();
application.SendNotification();
DALI_TEST_CHECK(blurRadiusValue);
DALI_TEST_EQUALS(blurRadiusValue->Get< float >(), targetBlurRadius, TEST_LOCATION);
+ Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineWidthValue);
+ DALI_TEST_EQUALS(borderlineWidthValue->Get< float >(), targetBorderlineWidth, TEST_LOCATION);
+
+ Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(borderlineColorValue);
+ DALI_TEST_EQUALS(borderlineColorValue->Get< Vector4 >(), targetBorderlineColor, TEST_LOCATION);
+
+ Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineOffsetValue);
+ DALI_TEST_EQUALS(borderlineOffsetValue->Get< float >(), targetBorderlineOffset, TEST_LOCATION);
+
// Test uniform values
DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector3>("mixColor", targetColor), true, TEST_LOCATION);
DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector2>("offset", targetOffset), true, TEST_LOCATION);
DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector2>("size", targetSize), true, TEST_LOCATION);
DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector4>("cornerRadius", targetCornerRadius), true, TEST_LOCATION);
DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("blurRadius", targetBlurRadius), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("borderlineWidth", targetBorderlineWidth), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector4>("borderlineColor", targetBorderlineColor), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("borderlineOffset", targetBorderlineOffset), true, TEST_LOCATION);
// Test not-supported property
Property property1 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::PREMULTIPLIED_ALPHA);
UniformData("offset", Property::Type::VECTOR2),
UniformData("size", Property::Type::VECTOR2),
UniformData("cornerRadius", Property::Type::VECTOR4),
+ UniformData("borderlineWidth", Property::Type::FLOAT),
+ UniformData("borderlineCOlor", Property::Type::VECTOR4),
+ UniformData("borderlineOffset", Property::Type::FLOAT),
UniformData("blurRadius", Property::Type::FLOAT),
};
Vector2 targetSize(1.1f, 1.1f);
float targetOpacity = 0.5f;
Vector4 targetCornerRadius(20.0f, 0.0f, 20.0f, 0.0f);
+ float targetBorderlineWidth = 77.7f;
+ Vector4 targetBorderlineColor(0.4f, 0.2f, 0.3f, 0.9f);
+ float targetBorderlineOffset = 1.0f;
float targetBlurRadius = 10.0f;
// Should work when the properties are not set before
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "offset"), targetOffset);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "size"), targetSize);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "cornerRadius"), targetCornerRadius);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "borderlineWidth"), targetBorderlineWidth);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "borderlineColor"), targetBorderlineColor);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "borderlineOffset"), targetBorderlineOffset);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "blurRadius"), targetBlurRadius);
animation.Play();
DALI_TEST_CHECK(cornerRadiusValue);
DALI_TEST_EQUALS(cornerRadiusValue->Get< Vector4 >(), targetCornerRadius, TEST_LOCATION);
+ Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineWidthValue);
+ DALI_TEST_EQUALS(borderlineWidthValue->Get< float >(), targetBorderlineWidth, TEST_LOCATION);
+
+ Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(borderlineColorValue);
+ DALI_TEST_EQUALS(borderlineColorValue->Get< Vector4 >(), targetBorderlineColor, TEST_LOCATION);
+
+ Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineOffsetValue);
+ DALI_TEST_EQUALS(borderlineOffsetValue->Get< float >(), targetBorderlineOffset, TEST_LOCATION);
+
Property::Value* blurRadiusValue = resultMap.Find(DevelColorVisual::Property::BLUR_RADIUS, Property::FLOAT);
DALI_TEST_CHECK(blurRadiusValue);
DALI_TEST_EQUALS(blurRadiusValue->Get< float >(), targetBlurRadius, TEST_LOCATION);
{
#ifdef OLD_GRAPHICS_TEST
ToolkitTestApplication application;
- tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, ImageVisual" );
+ tet_infoline( "UtcDaliVisualGetVisualProperty03: Test animatable property, ImageVisual" );
static std::vector<UniformData> customUniforms =
{
UniformData("cornerRadius", Property::Type::VECTOR4),
+ UniformData("borderlineWidth", Property::Type::FLOAT),
+ UniformData("borderlineColor", Property::Type::VECTOR4),
+ UniformData("borderlineOffset", Property::Type::FLOAT),
};
TestGraphicsController& graphics = application.GetGraphicsController();
Property::Map propertyMap;
propertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE);
propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+ //We must set some value because application cannot notify shader changed
+ propertyMap.Insert(DevelVisual::Property::CORNER_RADIUS, 1.0f);
+ propertyMap.Insert(DevelVisual::Property::BORDERLINE_WIDTH, 1.0f);
+
Visual::Base imageVisual = factory.CreateVisual(propertyMap);
DummyControl dummyControl = DummyControl::New(true);
float targetOpacity = 0.5f;
Vector4 targetCornerRadius(20.0f, 20.0f, 0.0f, 0.0f);
+ float targetBorderlineWidth = 10.0f;
+ Vector4 targetBorderlineColor(1.0f, 0.0f, 1.0f, 0.5f);
+ float targetBorderlineOffset = -1.5f;
Animation animation = Animation::New(1.0f);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::OPACITY), targetOpacity);
animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::CORNER_RADIUS), targetCornerRadius);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_WIDTH), targetBorderlineWidth);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_COLOR), targetBorderlineColor);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelVisual::Property::BORDERLINE_OFFSET), targetBorderlineOffset);
animation.Play();
application.SendNotification();
DALI_TEST_CHECK(cornerRadiusValue);
DALI_TEST_EQUALS(cornerRadiusValue->Get< Vector4 >(), targetCornerRadius, TEST_LOCATION);
+ Property::Value* borderlineWidthValue = resultMap.Find(DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineWidthValue);
+ DALI_TEST_EQUALS(borderlineWidthValue->Get< float >(), targetBorderlineWidth, TEST_LOCATION);
+
+ Property::Value* borderlineColorValue = resultMap.Find(DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(borderlineColorValue);
+ DALI_TEST_EQUALS(borderlineColorValue->Get< Vector4 >(), targetBorderlineColor, TEST_LOCATION);
+
+ Property::Value* borderlineOffsetValue = resultMap.Find(DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT);
+ DALI_TEST_CHECK(borderlineOffsetValue);
+ DALI_TEST_EQUALS(borderlineOffsetValue->Get< float >(), targetBorderlineOffset, TEST_LOCATION);
+
// Test uniform value
DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector4>("cornerRadius", targetCornerRadius), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("borderlineWidth", targetBorderlineWidth), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector4>("borderlineColor", targetBorderlineColor), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("borderlineOffset", targetBorderlineOffset), true, TEST_LOCATION);
#else
tet_result(TET_PASS);
#endif
* If it it RELATIVE, the corner radius value is relative to the smaller of the visual width and visual height.
*/
CORNER_RADIUS_POLICY = OPACITY + 3,
+
+ /**
+ * @brief The width for the borderline of the visual
+ * @details Name "borderlineWidth", type Property::FLOAT, animatable
+ * @note Optional. Default value is 0.0f.
+ */
+ BORDERLINE_WIDTH = OPACITY + 4,
+
+ /**
+ * @brief The color for the borderline of the visual
+ * @details Name "borderlineColor", type Property::VECTOR4, animatable
+ * @note Default value is Color::BLACK
+ */
+ BORDERLINE_COLOR = OPACITY + 5,
+
+ /**
+ * @brief The offset from the visual borderline (recommend [-1.0f to 1.0f]).
+ * @details Name "borderlineOffset", type Property::FLOAT, animatable
+ * @note Default value is 0.0f.
+ * @note This value will be clipped by [-1.0f to 1.0f].
+ */
+ BORDERLINE_OFFSET = OPACITY + 6,
};
} // namespace Property
+++ /dev/null
-INPUT mediump vec2 vPosition;
-INPUT mediump vec2 vRectSize;
-INPUT mediump vec2 vOptRectSize;
-INPUT mediump vec4 vCornerRadius;
-
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-uniform mediump float blurRadius;
-
-void main()
-{
- OUT_COLOR = vec4(mixColor, 1.0) * uColor;
- if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
- {
- return;
- }
-
- mediump float radius =
- mix(
- mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
- mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
- sign(vPosition.y) * 0.5 + 0.5
- );
-
- mediump vec2 v = abs(vPosition) - vRectSize + radius;
- mediump float cy = radius + blurRadius;
- mediump float cr = radius + blurRadius;
-
- cy = min(cy, min(vRectSize.x, vRectSize.y) - radius);
- v = vec2(min(v.x, v.y), max(v.x, v.y));
- v = v + cy;
-
- mediump float blur = 1.0;
- mediump float potential = 0.0;
- mediump float alias = min(radius, 1.0);
- mediump float potentialMin = cy + radius - blurRadius - alias;
- mediump float potentialMax = cy + radius + blurRadius + alias;
-
- // move center of circles for reduce defact
- mediump float cyDiff = min(cy, 0.2 * blurRadius);
- cy -= cyDiff;
- cr += cyDiff;
-
- mediump float diffFromBaseline = cy * v.y - (cy + cr) * v.x;
-
- if(diffFromBaseline > 0.0)
- {
- // out of calculation bound.
- potential = v.y;
-
- // for anti-alias when blurRaidus = 0.0
- mediump float heuristicBaselineScale = max(1.0 , cr * (cr + cy));
- mediump float potentialDiff = min(alias, diffFromBaseline / heuristicBaselineScale);
- potentialMin += potentialDiff;
- potentialMax -= potentialDiff;
- }
- else
- {
- // get some circle centered (x, x) and radius (r = cr / cy * x)
- // s.t. point v is on that circle
- // highest point of that circle is (x, x + r) and potential is x + r
-
- // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2
-
- mediump float A = (cr * cr - 2.0 * cy * cy);
- mediump float B = cy * (v.x + v.y);
- mediump float V = dot(v,v);
- mediump float D = B * B + A * V;
- potential = V * (cr + cy) / (sqrt(D) + B);
- }
-
- blur = 1.0 - smoothstep(potentialMin, potentialMax, potential);
- OUT_COLOR.a *= blur;
-}
+++ /dev/null
-INPUT mediump vec2 aPosition;
-OUTPUT mediump vec2 vPosition;
-OUTPUT mediump vec2 vRectSize;
-OUTPUT mediump vec2 vOptRectSize;
-OUTPUT mediump vec4 vCornerRadius;
-
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec2 extraSize;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-uniform mediump float blurRadius;
-uniform mediump vec4 cornerRadius;
-uniform mediump float cornerRadiusPolicy;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
- mediump float minSize = min( visualSize.x, visualSize.y );
- vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy );
- vCornerRadius = min( vCornerRadius, minSize * 0.5 );
- vRectSize = visualSize / 2.0;
- // optimize fragment shader
- mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
- vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0 - blurRadius;
-
- vPosition = aPosition * (visualSize + 2.0 * blurRadius);
- return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
-}
-
-void main()
-{
- gl_Position = uMvpMatrix * ComputeVertexPosition();
-}
+++ /dev/null
-INPUT mediump vec2 vPosition;
-INPUT mediump vec2 vRectSize;
-INPUT mediump vec2 vOptRectSize;
-INPUT mediump vec4 vCornerRadius;
-
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-
-void main()
-{
- OUT_COLOR = vec4(mixColor, 1.0) * uColor;
- if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
- {
- return;
- }
- mediump float radius =
- mix(
- mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
- mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
- sign(vPosition.y) * 0.5 + 0.5
- );
-
- mediump vec2 diff = abs(vPosition) - vRectSize + radius;
- mediump float dist = length(max(diff, vec2(0.0))) - radius;
- if(dist > 1.0)
- {
- OUT_COLOR.a = 0.0;
- }
- else if(dist > -1.0)
- {
- if(min(diff.x, diff.y) < 0.0)
- {
- dist += min(diff.x, diff.y) / max(radius, 1.0);
- }
- OUT_COLOR.a *= 1.0 - smoothstep(-1.0, 1.0, dist);
- }
-}
+++ /dev/null
-INPUT mediump vec2 aPosition;
-OUTPUT mediump vec2 vPosition;
-OUTPUT mediump vec2 vRectSize;
-OUTPUT mediump vec2 vOptRectSize;
-OUTPUT mediump vec4 vCornerRadius;
-
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec2 extraSize;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-uniform mediump vec4 cornerRadius;
-uniform mediump float cornerRadiusPolicy;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
- mediump float minSize = min( visualSize.x, visualSize.y );
- vCornerRadius = mix( cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
- vCornerRadius = min( vCornerRadius, minSize * 0.5 );
- vRectSize = visualSize / 2.0;
- // optimize fragment shader
- mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
- vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0;
- vPosition = aPosition* visualSize;
- return vec4( vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
-}
-
-void main()
-{
- gl_Position = uMvpMatrix * ComputeVertexPosition();
-}
+#ifndef IS_REQUIRED_ROUNDED_CORNER
+#define IS_REQUIRED_ROUNDED_CORNER 0
+#endif
+#ifndef IS_REQUIRED_BORDERLINE
+#define IS_REQUIRED_BORDERLINE 0
+#endif
+#ifndef IS_REQUIRED_BLUR
+#define IS_REQUIRED_BLUR 0
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+INPUT mediump vec2 vPosition;
+INPUT mediump vec2 vRectSize;
+INPUT mediump vec2 vOptRectSize;
+#if IS_REQUIRED_ROUNDED_CORNER
+INPUT mediump vec4 vCornerRadius;
+#endif
+#endif
+
uniform lowp vec4 uColor;
uniform lowp vec3 mixColor;
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+uniform mediump float borderlineWidth;
+uniform mediump float borderlineOffset;
+uniform lowp vec4 borderlineColor;
+#endif
+#if IS_REQUIRED_BLUR
+uniform mediump float blurRadius;
+#endif
+
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+// Global values both rounded corner and borderline use
+
+// radius of rounded corner on this quadrant
+mediump float gRadius = 0.0;
+
+// fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual
+mediump vec2 gFragmentPosition = vec2(0.0, 0.0);
+// center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition).
+mediump float gCenterPosition = 0.0;
+// relative coordinate of gFragmentPosition from gCenterPosition.
+mediump vec2 gDiff = vec2(0.0, 0.0);
+// potential value what our algorithm use.
+mediump float gPotential = 0.0;
+
+// threshold of potential
+mediump float gPotentialRange = 0.0;
+mediump float gMaxOutlinePotential = 0.0;
+mediump float gMinOutlinePotential = 0.0;
+mediump float gMaxInlinePotential = 0.0;
+mediump float gMinInlinePotential = 0.0;
+
+void calculateCornerRadius()
+{
+#if IS_REQUIRED_ROUNDED_CORNER
+ gRadius =
+ mix(
+ mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
+ mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
+ sign(vPosition.y) * 0.5 + 0.5
+ );
+#endif
+}
+
+void calculatePosition()
+{
+ gFragmentPosition = abs(vPosition) - vRectSize;
+ gCenterPosition = -gRadius;
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+ gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
+#endif
+ gDiff = gFragmentPosition - gCenterPosition;
+}
+
+void calculatePotential()
+{
+ gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y));
+}
+
+void setupMinMaxPotential()
+{
+ gPotentialRange = 1.0;
+
+ gMaxOutlinePotential = gRadius + gPotentialRange;
+ gMinOutlinePotential = gRadius - gPotentialRange;
+
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+ gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
+ gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
+#else
+ gMaxInlinePotential = gMaxOutlinePotential;
+ gMinInlinePotential = gMinOutlinePotential;
+#endif
+
+ // reduce defect near edge of rounded corner.
+ gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
+ gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
+}
+
+void PreprocessPotential()
+{
+ calculateCornerRadius();
+ calculatePosition();
+ calculatePotential();
+
+ setupMinMaxPotential();
+}
+#endif
+
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
+{
+ mediump float potential = gPotential;
+
+ // default opacity of borderline is 0.0
+ mediump float borderlineOpacity = 0.0;
+
+ // calculate borderline opacity by potential
+ if(potential > gMinInlinePotential)
+ {
+ // potential is inside borderline range.
+ borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+ }
+
+ //calculate inside of borderline when outilneColor.a < 1.0
+ if(borderlineColor.a < 1.0)
+ {
+ mediump float tCornerRadius = -gCenterPosition;
+ mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
+ mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
+ if(potential > MaxTexturelinePotential)
+ {
+ // potential is out of texture range. use borderline color instead of texture
+ textureColor = vec4(borderlineColor.xyz, 0.0);
+ }
+ else if(potential > MinTexturelinePotential)
+ {
+ // potential is in texture range
+ textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ }
+ borderlineOpacity *= borderlineColor.a;
+ }
+ return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
+}
+#endif
+
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_ROUNDED_CORNER
+mediump float calculateCornerOpacity()
+{
+ mediump float potential = gPotential;
+
+ // default opacity is 1.0
+ mediump float opacity = 1.0;
+
+ // calculate borderline opacity by potential
+ if(potential > gMaxOutlinePotential)
+ {
+ // potential is out of borderline range
+ opacity = 0.0;
+ }
+ else if(potential > gMinOutlinePotential)
+ {
+ opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential);
+ }
+ return opacity;
+}
+#endif
+
+#if IS_REQUIRED_BLUR
+mediump float calculateBlurOpacity()
+{
+// Don't use borderline!
+ mediump vec2 v = gDiff;
+ mediump float cy = gRadius + blurRadius;
+ mediump float cr = gRadius + blurRadius;
+
+#if IS_REQUIRED_ROUNDED_CORNER
+ // This routine make perfect circle. If corner radius is not exist, we don't consider prefect circle.
+ cy = min(cy, min(vRectSize.x, vRectSize.y) - gRadius);
+#endif
+ v = vec2(min(v.x, v.y), max(v.x, v.y));
+ v = v + cy;
+
+ mediump float potential = 0.0;
+ mediump float alias = min(gRadius, 1.0);
+ mediump float potentialMin = cy + gRadius - blurRadius - alias;
+ mediump float potentialMax = cy + gRadius + blurRadius + alias;
+
+ // move center of circles for reduce defact
+ mediump float cyDiff = min(cy, 0.2 * blurRadius);
+ cy -= cyDiff;
+ cr += cyDiff;
+
+ mediump float diffFromBaseline = cy * v.y - (cy + cr) * v.x;
+
+ if(diffFromBaseline > 0.0)
+ {
+ // out of calculation bound.
+ potential = v.y;
+
+ // for anti-alias when blurRaidus = 0.0
+ mediump float heuristicBaselineScale = max(1.0 , cr * (cr + cy));
+ mediump float potentialDiff = min(alias, diffFromBaseline / heuristicBaselineScale);
+ potentialMin += potentialDiff;
+ potentialMax -= potentialDiff;
+ }
+ else
+ {
+ // get some circle centered (x, x) and radius (r = cr / cy * x)
+ // s.t. point v is on that circle
+ // highest point of that circle is (x, x + r) and potential is x + r
+
+ // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2
+#if IS_REQUIRED_ROUNDED_CORNER
+ // NOTE : lowspec HW cannot calculate here. need to reduce numeric error
+ mediump float A = (cr * cr - 2.0 * cy * cy);
+ mediump float B = cy * (v.x + v.y);
+ mediump float V = dot(v,v);
+ mediump float D = B * B + A * V;
+ potential = V * (cr + cy) / (sqrt(D) + B);
+#else
+ // We can simplify this value cause cy = 0.8 * blurRadius, cr = 1.2 * blurRadius
+ // potential = 5.0*(sqrt(4.0*(v.x+v.y)^2 + dot(v,v)) - 2.0*(v.x+v.y));
+ // = 10.0*(v.x+v.y) * (sqrt(1.0 + (length(v) / (2.0*(v.x+v.y)))^2) - 1.0);
+ // = 10.0*(v.x+v.y) * (sqrt(1.25 - x + x^2) - 1.0);
+ // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^4)) (Taylor series)
+ // ~= -1.0557281 * (v.x + v.y) + 2.236068 * length(v) - ~~~ (here, x <= 0.5 * (1.0 - sqrt(0.5)) < 0.1464467)
+ // Note : This simplify need cause we should use it on lowspec HW.
+ mediump float x = 0.5 * (1.0 - length(v) / (v.x + v.y));
+ potential = -1.0557281 * (v.x + v.y) + 2.236068 * length(v) + 10.0 * (v.x + v.y) * (0.35777088 - 0.14310 * x) * x * x;
+#endif
+ }
+
+ return 1.0 - smoothstep(potentialMin, potentialMax, potential);
+}
+#endif
void main()
{
- OUT_COLOR = vec4(mixColor, 1.0) * uColor;
-}
\ No newline at end of file
+ lowp vec4 targetColor = vec4(mixColor, 1.0) * uColor;
+
+#if IS_REQUIRED_BLUR || IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+ // skip most potential calculate for performance
+ if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
+ {
+ OUT_COLOR = targetColor;
+ return;
+ }
+ PreprocessPotential();
+#endif
+
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+ targetColor = convertBorderlineColor(targetColor);
+#endif
+ OUT_COLOR = targetColor;
+
+#if IS_REQUIRED_BLUR
+ mediump float opacity = calculateBlurOpacity();
+ OUT_COLOR.a *= opacity;
+#elif IS_REQUIRED_ROUNDED_CORNER
+ mediump float opacity = calculateCornerOpacity();
+ OUT_COLOR.a *= opacity;
+#endif
+}
+#ifndef IS_REQUIRED_ROUNDED_CORNER
+#define IS_REQUIRED_ROUNDED_CORNER 0
+#endif
+#ifndef IS_REQUIRED_BORDERLINE
+#define IS_REQUIRED_BORDERLINE 0
+#endif
+#ifndef IS_REQUIRED_BLUR
+#define IS_REQUIRED_BLUR 0
+#endif
+
INPUT mediump vec2 aPosition;
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+OUTPUT mediump vec2 vPosition;
+OUTPUT mediump vec2 vRectSize;
+OUTPUT mediump vec2 vOptRectSize;
+#if IS_REQUIRED_ROUNDED_CORNER
+OUTPUT mediump vec4 vCornerRadius;
+#endif
+#endif
uniform highp mat4 uMvpMatrix;
uniform highp vec3 uSize;
uniform mediump vec4 offsetSizeMode;
uniform mediump vec2 origin;
uniform mediump vec2 anchorPoint;
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+uniform mediump float borderlineWidth;
+uniform mediump float borderlineOffset;
+#endif
+#if IS_REQUIRED_BLUR
+uniform mediump float blurRadius;
+#endif
+#if IS_REQUIRED_ROUNDED_CORNER
+uniform mediump vec4 cornerRadius;
+uniform mediump float cornerRadiusPolicy;
+#endif
uniform mediump vec2 extraSize;
vec4 ComputeVertexPosition()
{
vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
- return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+ vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR
+ vRectSize = visualSize * 0.5;
+ vOptRectSize = vRectSize;
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER
+#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE
+ mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth;
+#else
+ mediump float minSize = min(visualSize.x, visualSize.y);
+#endif
+ vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
+ vCornerRadius = min(vCornerRadius, minSize * 0.5);
+ // Optimize fragment shader. 0.2929 ~= 1.0 - sqrt(0.5)
+ mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
+ vOptRectSize -= 0.2929 * maxRadius + 1.0;
+#endif
+
+#if IS_REQUIRED_BLUR
+ vPosition = aPosition * (visualSize + 2.0 * blurRadius);
+ vOptRectSize -= blurRadius + 1.0;
+#elif IS_REQUIRED_BORDERLINE
+ vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0))* borderlineWidth);
+ vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
+#elif IS_REQUIRED_ROUNDED_CORNER
+ vPosition = aPosition * visualSize;
+#else
+ mediump vec2 vPosition = aPosition * visualSize;
+#endif
+ return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
}
void main()
{
gl_Position = uMvpMatrix * ComputeVertexPosition();
-}
\ No newline at end of file
+}
+++ /dev/null
-attribute mediump vec2 aPosition;
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-uniform mediump mat3 uAlignmentMatrix;
-varying mediump vec2 vTexCoord;
-varying mediump vec2 vPosition;
-varying mediump vec2 vRectSize;
-varying mediump vec2 vOptRectSize;
-varying mediump vec4 vCornerRadius;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-uniform mediump vec4 cornerRadius;
-uniform mediump float cornerRadiusPolicy;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw);
- vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
- mediump float minSize = min(visualSize.x, visualSize.y);
- vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
- vCornerRadius = min(vCornerRadius, minSize * 0.5);
- vRectSize = visualSize * 0.5;
- // Optimize fragment shader
- mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
- vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0;
- vPosition = aPosition * visualSize;
- return vec4((aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0);
-}
-
-void main()
-{
- mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
- vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
-
- gl_Position = uMvpMatrix * ComputeVertexPosition();
-}
+++ /dev/null
-attribute mediump vec2 aPosition;
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-uniform mediump mat3 uAlignmentMatrix;
-varying mediump vec2 vTexCoord;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
- return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
-}
-
-void main()
-{
- mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
- vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
-
- gl_Position = uMvpMatrix * ComputeVertexPosition();
-}
\ No newline at end of file
+++ /dev/null
-uniform sampler2D sTexture; // sampler1D?
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-varying mediump vec2 vTexCoord;
-varying mediump vec2 vPosition;
-varying mediump vec2 vRectSize;
-varying mediump vec2 vOptRectSize;
-varying mediump vec4 vCornerRadius;
-
-void main()
-{
- gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor, 1.0) * uColor;
- if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
- {
- return;
- }
- mediump float radius =
- mix(
- mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
- mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
- sign(vPosition.y) * 0.5 + 0.5
- );
-
- mediump vec2 diff = abs(vPosition) - vRectSize + radius;
- mediump float dist = length(max(diff, vec2(0.0))) - radius;
- if(dist > 1.0)
- {
- gl_FragColor = vec4(0.0);
- }
- else if(dist > -1.0)
- {
- if(min(diff.x, diff.y) < 0.0)
- {
- dist += min(diff.x, diff.y) / max(radius, 1.0);
- }
- gl_FragColor *= 1.0 - smoothstep(-1.0, 1.0, dist);
- }
-}
+++ /dev/null
-uniform sampler2D sTexture; // sampler1D?
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-varying mediump vec2 vTexCoord;
-
-void main()
-{
- gl_FragColor = texture2D( sTexture, vec2( vTexCoord.y, 0.5 ) ) * vec4(mixColor, 1.0) * uColor;
-}
+++ /dev/null
-uniform sampler2D sTexture; // sampler1D?
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-varying mediump vec2 vTexCoord;
-varying mediump vec2 vPosition;
-varying mediump vec2 vRectSize;
-varying mediump vec2 vOptRectSize;
-varying mediump vec4 vCornerRadius;
-
-void main()
-{
- gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor, 1.0) * uColor;
- if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
- {
- return;
- }
- mediump float radius =
- mix(
- mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
- mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
- sign(vPosition.y) * 0.5 + 0.5
- );
-
- mediump vec2 diff = abs(vPosition) - vRectSize + radius;
- mediump float dist = length(max(diff, vec2(0.0))) - radius;
- if(dist > 1.0)
- {
- gl_FragColor = vec4(0.0);
- }
- else if(dist > -1.0)
- {
- if(min(diff.x, diff.y) < 0.0)
- {
- dist += min(diff.x, diff.y) / max(radius, 1.0);
- }
- gl_FragColor *= 1.0 - smoothstep(-1.0, 1.0, dist);
- }
-}
+++ /dev/null
-uniform sampler2D sTexture; // sampler1D?
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-varying mediump vec2 vTexCoord;
-
-void main()
-{
- gl_FragColor = texture2D( sTexture, vec2( length(vTexCoord), 0.5 ) ) * vec4(mixColor, 1.0) * uColor;
-}
--- /dev/null
+#ifndef IS_REQUIRED_ROUNDED_CORNER
+#define IS_REQUIRED_ROUNDED_CORNER 0
+#endif
+#ifndef IS_REQUIRED_BORDERLINE
+#define IS_REQUIRED_BORDERLINE 0
+#endif
+#ifndef RADIAL
+#define RADIAL 0
+#endif
+
+INPUT mediump vec2 vTexCoord;
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+INPUT mediump vec2 vPosition;
+INPUT mediump vec2 vRectSize;
+INPUT mediump vec2 vOptRectSize;
+#if IS_REQUIRED_ROUNDED_CORNER
+INPUT mediump vec4 vCornerRadius;
+#endif
+#endif
+
+uniform sampler2D sTexture; // sampler1D?
+uniform lowp vec4 uColor;
+uniform lowp vec3 mixColor;
+#if IS_REQUIRED_BORDERLINE
+uniform mediump float borderlineWidth;
+uniform mediump float borderlineOffset;
+uniform lowp vec4 borderlineColor;
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+// Global values both rounded corner and borderline use
+
+// radius of rounded corner on this quadrant
+mediump float gRadius = 0.0;
+
+// fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual
+mediump vec2 gFragmentPosition = vec2(0.0, 0.0);
+// center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition).
+mediump float gCenterPosition = 0.0;
+// relative coordinate of gFragmentPosition from gCenterPosition.
+mediump vec2 gDiff = vec2(0.0, 0.0);
+// potential value what our algorithm use.
+mediump float gPotential = 0.0;
+
+// threshold of potential
+mediump float gPotentialRange = 0.0;
+mediump float gMaxOutlinePotential = 0.0;
+mediump float gMinOutlinePotential = 0.0;
+mediump float gMaxInlinePotential = 0.0;
+mediump float gMinInlinePotential = 0.0;
+
+void calculateCornerRadius()
+{
+#if IS_REQUIRED_ROUNDED_CORNER
+ gRadius =
+ mix(
+ mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
+ mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
+ sign(vPosition.y) * 0.5 + 0.5
+ );
+#endif
+}
+
+void calculatePosition()
+{
+ gFragmentPosition = abs(vPosition) - vRectSize;
+ gCenterPosition = -gRadius;
+#if IS_REQUIRED_BORDERLINE
+ gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
+#endif
+ gDiff = gFragmentPosition - gCenterPosition;
+}
+
+void calculatePotential()
+{
+ gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y));
+}
+
+void setupMinMaxPotential()
+{
+ gPotentialRange = 1.0;
+
+ gMaxOutlinePotential = gRadius + gPotentialRange;
+ gMinOutlinePotential = gRadius - gPotentialRange;
+
+#if IS_REQUIRED_BORDERLINE
+ gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
+ gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
+#else
+ gMaxInlinePotential = gMaxOutlinePotential;
+ gMinInlinePotential = gMinOutlinePotential;
+#endif
+
+ // reduce defect near edge of rounded corner.
+ gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
+ gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
+}
+
+void PreprocessPotential()
+{
+ calculateCornerRadius();
+ calculatePosition();
+ calculatePotential();
+
+ setupMinMaxPotential();
+}
+#endif
+
+
+#if IS_REQUIRED_BORDERLINE
+lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
+{
+ mediump float potential = gPotential;
+
+ // default opacity of borderline is 0.0
+ mediump float borderlineOpacity = 0.0;
+
+ // calculate borderline opacity by potential
+ if(potential > gMinInlinePotential)
+ {
+ // potential is inside borderline range.
+ borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+ }
+
+ //calculate inside of borderline when outilneColor.a < 1.0
+ if(borderlineColor.a < 1.0)
+ {
+ mediump float tCornerRadius = -gCenterPosition;
+ mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
+ mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
+ if(potential > MaxTexturelinePotential)
+ {
+ // potential is out of texture range. use borderline color instead of texture
+ textureColor = vec4(borderlineColor.xyz, 0.0);
+ }
+ else if(potential > MinTexturelinePotential)
+ {
+ // potential is in texture range
+ textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ }
+ borderlineOpacity *= borderlineColor.a;
+ }
+ return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
+}
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER
+mediump float calculateCornerOpacity()
+{
+ mediump float potential = gPotential;
+
+ // default opacity is 1.0
+ mediump float opacity = 1.0;
+
+ // calculate borderline opacity by potential
+ if(potential > gMaxOutlinePotential)
+ {
+ // potential is out of borderline range
+ opacity = 0.0;
+ }
+ else if(potential > gMinOutlinePotential)
+ {
+ opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential);
+ }
+ return opacity;
+}
+#endif
+
+void main()
+{
+#if RADIAL
+ lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0) * uColor;
+#else
+ lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0) * uColor;
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+ // skip most potential calculate for performance
+ if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
+ {
+ OUT_COLOR = textureColor;
+ return;
+ }
+ PreprocessPotential();
+#endif
+
+#if IS_REQUIRED_BORDERLINE
+ textureColor = convertBorderlineColor(textureColor);
+#endif
+ OUT_COLOR = textureColor;
+
+#if IS_REQUIRED_ROUNDED_CORNER
+ mediump float opacity = calculateCornerOpacity();
+ OUT_COLOR *= opacity;
+#endif
+}
--- /dev/null
+#ifndef IS_REQUIRED_ROUNDED_CORNER
+#define IS_REQUIRED_ROUNDED_CORNER 0
+#endif
+#ifndef IS_REQUIRED_BORDERLINE
+#define IS_REQUIRED_BORDERLINE 0
+#endif
+#ifndef USER_SPACE
+#define USER_SPACE 0
+#endif
+
+INPUT mediump vec2 aPosition;
+OUTPUT mediump vec2 vTexCoord;
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+OUTPUT mediump vec2 vPosition;
+OUTPUT mediump vec2 vRectSize;
+OUTPUT mediump vec2 vOptRectSize;
+#if IS_REQUIRED_ROUNDED_CORNER
+OUTPUT mediump vec4 vCornerRadius;
+#endif
+#endif
+
+uniform highp mat4 uMvpMatrix;
+uniform highp vec3 uSize;
+uniform mediump mat3 uAlignmentMatrix;
+
+//Visual size and offset
+uniform mediump vec2 offset;
+uniform highp vec2 size;
+uniform mediump vec4 offsetSizeMode;
+uniform mediump vec2 origin;
+uniform mediump vec2 anchorPoint;
+#if IS_REQUIRED_BORDERLINE
+uniform mediump float borderlineWidth;
+uniform mediump float borderlineOffset;
+#endif
+#if IS_REQUIRED_ROUNDED_CORNER
+uniform mediump vec4 cornerRadius;
+uniform mediump float cornerRadiusPolicy;
+#endif
+
+vec4 ComputeVertexPosition()
+{
+ vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
+ vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+ vRectSize = visualSize * 0.5;
+ vOptRectSize = vRectSize;
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER
+#if IS_REQUIRED_BORDERLINE
+ mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth;
+#else
+ mediump float minSize = min(visualSize.x, visualSize.y);
+#endif
+ vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
+ vCornerRadius = min(vCornerRadius, minSize * 0.5);
+ // Optimize fragment shader. 0.2929 ~= 1.0 - sqrt(0.5)
+ mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
+ vOptRectSize -= 0.2929 * maxRadius + 1.0;
+#endif
+
+#if IS_REQUIRED_BORDERLINE
+ vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
+ vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
+#elif IS_REQUIRED_ROUNDED_CORNER
+ vPosition = aPosition * visualSize;
+#else
+ mediump vec2 vPosition = aPosition * visualSize;
+#endif
+
+ return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
+}
+
+void main()
+{
+ mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
+ gl_Position = uMvpMatrix * ComputeVertexPosition();
+#if USER_SPACE
+ vertexPosition.xyz *= uSize;
+#endif
+ vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
+}
+++ /dev/null
-attribute mediump vec2 aPosition;
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-uniform mediump mat3 uAlignmentMatrix;
-varying mediump vec2 vTexCoord;
-varying mediump vec2 vPosition;
-varying mediump vec2 vRectSize;
-varying mediump vec2 vOptRectSize;
-varying mediump vec4 vCornerRadius;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-uniform mediump vec4 cornerRadius;
-uniform mediump float cornerRadiusPolicy;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw);
- vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
- mediump float minSize = min(visualSize.x, visualSize.y);
- vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
- vCornerRadius = min(vCornerRadius, minSize * 0.5);
- vRectSize = visualSize * 0.5;
- // Optimze fragment shader
- mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
- vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0;
- vCornerRadius = max(vCornerRadius, 1.0);
- vPosition = aPosition * visualSize;
- return vec4((aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0);
-}
-
-void main()
-{
- mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
- vertexPosition.xyz *= uSize;
- gl_Position = uMvpMatrix * ComputeVertexPosition();
-
- vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
-}
+++ /dev/null
-attribute mediump vec2 aPosition;
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-uniform mediump mat3 uAlignmentMatrix;
-varying mediump vec2 vTexCoord;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
- return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
-}
-
-void main()
-{
- mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
- vertexPosition.xyz *= uSize;
- gl_Position = uMvpMatrix * ComputeVertexPosition();
-
- vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
-}
+++ /dev/null
-INPUT mediump vec2 vTexCoord;
-
-uniform sampler2D sTexture;
-uniform mediump vec4 uAtlasRect;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-uniform lowp float preMultipliedAlpha;
-
-void main()
-{
- mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );
- OUT_COLOR = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );
-}
\ No newline at end of file
+++ /dev/null
-INPUT mediump vec2 vTexCoord;
-
-uniform sampler2D sTexture;
-uniform mediump vec4 uAtlasRect;
-
-// WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
-uniform lowp vec2 wrapMode;
-
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-uniform lowp float preMultipliedAlpha;
-mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )
-
-{
- mediump float coord;
- if( wrap > 1.5 )\n // REFLECT
- coord = 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0);
- else \n// warp == 0 or 1
- coord = mix(coordinate, fract( coordinate ), wrap);
- return clamp( mix(range.x, range.y, coord), range.x, range.y );
-}
-
-void main()
-{
- mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
- wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );
- OUT_COLOR = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );
-}
\ No newline at end of file
+++ /dev/null
-INPUT mediump vec2 vTexCoord;
-
-uniform sampler2D sTexture;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-uniform lowp float preMultipliedAlpha;
-
-void main()
-{
- OUT_COLOR = TEXTURE( sTexture, vTexCoord ) * uColor * vec4( mixColor, 1.0 );
-}
+++ /dev/null
-INPUT mediump vec2 vTexCoord;
-INPUT mediump vec2 vPosition;
-INPUT mediump vec2 vRectSize;
-INPUT mediump vec2 vOptRectSize;
-INPUT mediump vec4 vCornerRadius;
-
-uniform sampler2D sTexture;
-uniform lowp vec4 uColor;
-uniform lowp vec3 mixColor;
-uniform lowp float preMultipliedAlpha;
-
-void main()
-{
- if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
- {
- OUT_COLOR = TEXTURE(sTexture, vTexCoord) * uColor * vec4(mixColor, 1.0);
- return;
- }
- mediump float radius =
- mix(
- mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
- mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
- sign(vPosition.y) * 0.5 + 0.5
- );
-
- mediump vec2 diff = abs(vPosition) - vRectSize + radius;
- mediump float dist = length(max(diff, vec2(0.0))) - radius;
- mediump float opacity = 1.0;
- if(dist > 1.0)
- {
- opacity = 0.0;
- }
- else if(dist > -1.0)
- {
- if(min(diff.x, diff.y) < 0.0)
- {
- dist += min(diff.x, diff.y) / max(radius, 1.0);
- }
- opacity = 1.0 - smoothstep(-1.0, 1.0, dist);
- }
-
- OUT_COLOR = TEXTURE(sTexture, vTexCoord) * uColor * vec4(mixColor, 1.0);
- OUT_COLOR.a *= opacity;
- OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha);
-}
+++ /dev/null
-INPUT mediump vec2 aPosition;
-OUTPUT mediump vec2 vTexCoord;
-OUTPUT mediump vec2 vPosition;
-OUTPUT mediump vec2 vRectSize;
-OUTPUT mediump vec2 vOptRectSize;
-OUTPUT mediump vec4 vCornerRadius;
-
-uniform highp mat4 uMvpMatrix;
-uniform highp vec3 uSize;
-uniform mediump vec4 pixelArea;
-
-//Visual size and offset
-uniform mediump vec2 offset;
-uniform highp vec2 size;
-uniform mediump vec4 offsetSizeMode;
-uniform mediump vec2 origin;
-uniform mediump vec2 anchorPoint;
-uniform mediump vec4 cornerRadius;
-uniform mediump float cornerRadiusPolicy;
-uniform mediump vec2 extraSize;
-
-vec4 ComputeVertexPosition()
-{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw) + extraSize;
- vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
- mediump float minSize = min(visualSize.x, visualSize.y);
- vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
- vCornerRadius = min(vCornerRadius, minSize * 0.5);
- vRectSize = visualSize * 0.5;
- // Optimize fragment shader
- mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
- vOptRectSize = vRectSize - 0.2929 * maxRadius - 1.0;
- vPosition = aPosition* visualSize;
- return vec4(vPosition + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0);
-}
-
-void main()
-{
- gl_Position = uMvpMatrix * ComputeVertexPosition();
- vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5));
-}
--- /dev/null
+#ifndef IS_REQUIRED_ROUNDED_CORNER
+#define IS_REQUIRED_ROUNDED_CORNER 0
+#endif
+#ifndef IS_REQUIRED_BORDERLINE
+#define IS_REQUIRED_BORDERLINE 0
+#endif
+#ifndef ATLAS_DEFAULT_WARP
+#define ATLAS_DEFAULT_WARP 0
+#endif
+#ifndef ATLAS_CUSTOM_WARP
+#define ATLAS_CUSTOM_WARP 0
+#endif
+
+INPUT mediump vec2 vTexCoord;
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+INPUT mediump vec2 vPosition;
+INPUT mediump vec2 vRectSize;
+INPUT mediump vec2 vOptRectSize;
+#if IS_REQUIRED_ROUNDED_CORNER
+INPUT mediump vec4 vCornerRadius;
+#endif
+#endif
+
+uniform sampler2D sTexture;
+#if ATLAS_DEFAULT_WARP
+uniform mediump vec4 uAtlasRect;
+#elif ATLAS_CUSTOM_WARP
+// WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
+uniform lowp vec2 wrapMode;
+#endif
+
+uniform lowp vec4 uColor;
+uniform lowp vec3 mixColor;
+uniform lowp float preMultipliedAlpha;
+#if IS_REQUIRED_BORDERLINE
+uniform mediump float borderlineWidth;
+uniform mediump float borderlineOffset;
+uniform lowp vec4 borderlineColor;
+#endif
+
+#if ATLAS_CUSTOM_WARP
+mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )
+{
+ mediump float coord;
+ if( wrap > 1.5 ) /* REFLECT */
+ coord = 1.0 - abs(fract(coordinate*0.5)*2.0 - 1.0);
+ else /* warp is 0 or 1 */
+ coord = mix(coordinate, fract(coordinate), wrap);
+ return clamp(mix(range.x, range.y, coord), range.x, range.y);
+}
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+// Global values both rounded corner and borderline use
+
+// radius of rounded corner on this quadrant
+mediump float gRadius = 0.0;
+
+// fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual
+mediump vec2 gFragmentPosition = vec2(0.0, 0.0);
+// center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition).
+mediump float gCenterPosition = 0.0;
+// relative coordinate of gFragmentPosition from gCenterPosition.
+mediump vec2 gDiff = vec2(0.0, 0.0);
+// potential value what our algorithm use.
+mediump float gPotential = 0.0;
+
+// threshold of potential
+mediump float gPotentialRange = 0.0;
+mediump float gMaxOutlinePotential = 0.0;
+mediump float gMinOutlinePotential = 0.0;
+mediump float gMaxInlinePotential = 0.0;
+mediump float gMinInlinePotential = 0.0;
+
+void calculateCornerRadius()
+{
+#if IS_REQUIRED_ROUNDED_CORNER
+ gRadius =
+ mix(
+ mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
+ mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
+ sign(vPosition.y) * 0.5 + 0.5
+ );
+#endif
+}
+
+void calculatePosition()
+{
+ gFragmentPosition = abs(vPosition) - vRectSize;
+ gCenterPosition = -gRadius;
+#if IS_REQUIRED_BORDERLINE
+ gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
+#endif
+ gDiff = gFragmentPosition - gCenterPosition;
+}
+
+void calculatePotential()
+{
+ gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y));
+}
+
+void setupMinMaxPotential()
+{
+ gPotentialRange = 1.0;
+
+ gMaxOutlinePotential = gRadius + gPotentialRange;
+ gMinOutlinePotential = gRadius - gPotentialRange;
+
+#if IS_REQUIRED_BORDERLINE
+ gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
+ gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
+#else
+ gMaxInlinePotential = gMaxOutlinePotential;
+ gMinInlinePotential = gMinOutlinePotential;
+#endif
+
+ // reduce defect near edge of rounded corner.
+ gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
+ gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
+}
+
+void PreprocessPotential()
+{
+ calculateCornerRadius();
+ calculatePosition();
+ calculatePotential();
+
+ setupMinMaxPotential();
+}
+#endif
+
+#if IS_REQUIRED_BORDERLINE
+lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
+{
+ mediump float potential = gPotential;
+
+ // default opacity of borderline is 0.0
+ mediump float borderlineOpacity = 0.0;
+
+ // calculate borderline opacity by potential
+ if(potential > gMinInlinePotential)
+ {
+ // potential is inside borderline range.
+ borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
+ }
+
+ //calculate inside of borderline when outilneColor.a < 1.0
+ if(borderlineColor.a < 1.0)
+ {
+ mediump float tCornerRadius = -gCenterPosition;
+ mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
+ mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
+ if(potential > MaxTexturelinePotential)
+ {
+ // potential is out of texture range. use borderline color instead of texture
+ textureColor = vec4(borderlineColor.xyz, 0.0);
+ }
+ else if(potential > MinTexturelinePotential)
+ {
+ // potential is in texture range
+ textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ }
+ borderlineOpacity *= borderlineColor.a;
+ }
+ return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity);
+}
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER
+mediump float calculateCornerOpacity()
+{
+ mediump float potential = gPotential;
+
+ // default opacity is 1.0
+ mediump float opacity = 1.0;
+
+ // calculate borderline opacity by potential
+ if(potential > gMaxOutlinePotential)
+ {
+ // potential is out of borderline range
+ opacity = 0.0;
+ }
+ else if(potential > gMinOutlinePotential)
+ {
+ opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential);
+ }
+ return opacity;
+}
+#endif
+
+void main()
+{
+#if ATLAS_DEFAULT_WARP
+ mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );
+#elif ATLAS_CUSTOM_WARP
+ mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
+ wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );
+#else
+ mediump vec2 texCoord = vTexCoord;
+#endif
+
+ lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * uColor * vec4( mixColor, 1.0 );
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+ // skip most potential calculate for performance
+ if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
+ {
+ OUT_COLOR = textureColor;
+ return;
+ }
+ PreprocessPotential();
+#endif
+
+#if IS_REQUIRED_BORDERLINE
+ textureColor = convertBorderlineColor(textureColor);
+#endif
+ OUT_COLOR = textureColor;
+
+#if IS_REQUIRED_ROUNDED_CORNER
+ mediump float opacity = calculateCornerOpacity();
+ OUT_COLOR.a *= opacity;
+ OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha);
+#endif
+}
+#ifndef IS_REQUIRED_ROUNDED_CORNER
+#define IS_REQUIRED_ROUNDED_CORNER 0
+#endif
+#ifndef IS_REQUIRED_BORDERLINE
+#define IS_REQUIRED_BORDERLINE 0
+#endif
+
INPUT mediump vec2 aPosition;
OUTPUT mediump vec2 vTexCoord;
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+OUTPUT mediump vec2 vPosition;
+OUTPUT mediump vec2 vRectSize;
+OUTPUT mediump vec2 vOptRectSize;
+#if IS_REQUIRED_ROUNDED_CORNER
+OUTPUT mediump vec4 vCornerRadius;
+#endif
+#endif
uniform highp mat4 uMvpMatrix;
uniform highp vec3 uSize;
uniform mediump vec4 offsetSizeMode;
uniform mediump vec2 origin;
uniform mediump vec2 anchorPoint;
+#if IS_REQUIRED_BORDERLINE
+uniform mediump float borderlineWidth;
+uniform mediump float borderlineOffset;
+#endif
+#if IS_REQUIRED_ROUNDED_CORNER
+uniform mediump vec4 cornerRadius;
+uniform mediump float cornerRadiusPolicy;
+#endif
uniform mediump vec2 extraSize;
vec4 ComputeVertexPosition()
{
- vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw ) + extraSize;
- vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);
- return vec4( (aPosition + anchorPoint)*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );
+ vec2 visualSize = mix(uSize.xy * size, size, offsetSizeMode.zw) + extraSize;
+ vec2 visualOffset = mix(offset, offset/uSize.xy, offsetSizeMode.xy);
+
+#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
+ vRectSize = visualSize * 0.5;
+ vOptRectSize = vRectSize;
+#endif
+
+#if IS_REQUIRED_ROUNDED_CORNER
+#if IS_REQUIRED_BORDERLINE
+ mediump float minSize = min(visualSize.x, visualSize.y) + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth;
+#else
+ mediump float minSize = min(visualSize.x, visualSize.y);
+#endif
+ vCornerRadius = mix(cornerRadius * minSize, cornerRadius, cornerRadiusPolicy);
+ vCornerRadius = min(vCornerRadius, minSize * 0.5);
+ // Optimize fragment shader. 0.2929 ~= 1.0 - sqrt(0.5)
+ mediump float maxRadius = max(max(vCornerRadius.x, vCornerRadius.y), max(vCornerRadius.z, vCornerRadius.w));
+ vOptRectSize -= 0.2929 * maxRadius + 1.0;
+#endif
+
+#if IS_REQUIRED_BORDERLINE
+ vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
+ vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
+#elif IS_REQUIRED_ROUNDED_CORNER
+ vPosition = aPosition * visualSize;
+#else
+ mediump vec2 vPosition = aPosition * visualSize;
+#endif
+
+ vTexCoord = pixelArea.xy + pixelArea.zw * (vPosition.xy / max(vec2(1.0), visualSize) + vec2(0.5));
+ return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
}
void main()
{
gl_Position = uMvpMatrix * ComputeVertexPosition();
- vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );
-}
\ No newline at end of file
+}
{
bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE;
bool atlasing = false;
- Shader shader = mImageVisualShaderFactory.GetShader(mFactoryCache, atlasing, defaultWrapMode, IsRoundedCornerRequired());
+ Shader shader = mImageVisualShaderFactory.GetShader(
+ mFactoryCache,
+ atlasing ? TextureAtlas::ENABLED : TextureAtlas::DISABLED,
+ defaultWrapMode ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY,
+ IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED,
+ IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED
+ );
Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
}
else
{
- shader = mImageVisualShaderFactory.GetShader(mFactoryCache, false, true, IsRoundedCornerRequired());
+ shader = mImageVisualShaderFactory.GetShader(
+ mFactoryCache,
+ TextureAtlas::DISABLED,
+ DefaultTextureWrapMode::APPLY,
+ IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED,
+ IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED
+ );
}
Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
{
namespace Internal
{
+namespace
+{
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[6] =
+{
+ VisualFactoryCache::COLOR_SHADER,
+ VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER,
+ VisualFactoryCache::COLOR_SHADER_BORDERLINE,
+ VisualFactoryCache::COLOR_SHADER_ROUNDED_BORDERLINE,
+ VisualFactoryCache::COLOR_SHADER_BLUR_EDGE,
+ VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE,
+};
+
+// enum of required list when we select shader
+enum ColorVisualRequireFlag
+{
+ DEFAULT = 0,
+ ROUNDED_CORNER = 1 << 0,
+ BORDERLINE = 1 << 1,
+ BLUR = 1 << 2,
+};
+} // unnamed namespace
ColorVisualPtr ColorVisual::New(VisualFactoryCache& factoryCache, const Property::Map& properties)
{
ColorVisualPtr colorVisualPtr(new ColorVisual(factoryCache));
Shader ColorVisual::GetShader()
{
Shader shader;
- if(!EqualsZero(mBlurRadius) || mNeedBlurRadius)
+ VisualFactoryCache::ShaderType shaderType;
+
+ bool roundedCorner = IsRoundedCornerRequired();
+ bool borderline = IsBorderlineRequired();
+ bool blur = !EqualsZero(mBlurRadius) || mNeedBlurRadius;
+ int shaderTypeFlag = ColorVisualRequireFlag::DEFAULT;
+
+ if(roundedCorner)
{
- shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER_BLUR_EDGE);
- if(!shader)
- {
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_BLUR_EDGE_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_BLUR_EDGE_SHADER_FRAG.data());
- mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER_BLUR_EDGE, shader);
- }
+ shaderTypeFlag |= ColorVisualRequireFlag::ROUNDED_CORNER;
}
- else if(!IsRoundedCornerRequired())
+ if(blur)
{
- shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER);
- if(!shader)
- {
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_SHADER_FRAG.data());
- mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER, shader);
- }
+ // If we use blur, just ignore borderline
+ borderline = false;
+ shaderTypeFlag |= ColorVisualRequireFlag::BLUR;
}
- else
+ if(borderline)
+ {
+ shaderTypeFlag |= ColorVisualRequireFlag::BORDERLINE;
+ }
+
+ shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+ shader = mFactoryCache.GetShader(shaderType);
+ if(!shader)
{
- shader = mFactoryCache.GetShader(VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER);
- if(!shader)
+ std::string vertexShaderPrefixList;
+ std::string fragmentShaderPrefixList;
+ if(roundedCorner)
+ {
+ vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+ }
+ if(blur)
+ {
+ vertexShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_BLUR 1\n";
+ }
+ if(borderline)
{
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_COLOR_VISUAL_ROUNDED_CORNER_SHADER_VERT.data(), Dali::Shader::GetFragmentShaderPrefix() + SHADER_COLOR_VISUAL_ROUNDED_CORNER_SHADER_FRAG.data());
- mFactoryCache.SaveShader(VisualFactoryCache::COLOR_SHADER_ROUNDED_CORNER, shader);
+ vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
}
+ shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_VERT.data(),
+ Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_COLOR_VISUAL_SHADER_FRAG.data());
+ mFactoryCache.SaveShader(shaderType, shader);
}
return shader;
#include <typeinfo>
// INTERNAL INCLUDES
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-bounding-box-rounded-corner-shader-vert.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-bounding-box-shader-vert.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-linear-rounded-corner-shader-frag.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-linear-shader-frag.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-radial-rounded-corner-shader-frag.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-radial-shader-frag.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-user-space-rounded-corner-shader-vert.h>
-#include <dali-toolkit/internal/graphics/generated/gradient-visual-user-space-shader-vert.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-toolkit/internal/visuals/gradient/linear-gradient.h>
#include <dali-toolkit/internal/visuals/gradient/radial-gradient.h>
#include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
const unsigned int DEFAULT_OFFSET_MINIMUM = 0.0f;
const unsigned int DEFAULT_OFFSET_MAXIMUM = 1.0f;
-VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[][4] =
- {
- {VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE,
- VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX,
- VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER,
- VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER},
- {VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE,
- VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
- VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER,
- VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER}};
-
-const std::string_view VERTEX_SHADER[] =
- {
- // vertex shader for gradient units as OBJECT_BOUNDING_BOX
- SHADER_GRADIENT_VISUAL_BOUNDING_BOX_SHADER_VERT,
-
- // vertex shader for gradient units as USER_SPACE
- SHADER_GRADIENT_VISUAL_USER_SPACE_SHADER_VERT,
-
- // vertex shader for gradient units as OBJECT_BOUNDING_BOX with corner radius
- SHADER_GRADIENT_VISUAL_BOUNDING_BOX_ROUNDED_CORNER_SHADER_VERT,
-
- // vertex shader for gradient units as USER_SPACE with corner radius
- SHADER_GRADIENT_VISUAL_USER_SPACE_ROUNDED_CORNER_SHADER_VERT};
-
-const std::string_view FRAGMENT_SHADER[] =
- {
- // fragment shader for linear gradient
- SHADER_GRADIENT_VISUAL_LINEAR_SHADER_FRAG,
-
- // fragment shader for radial gradient
- SHADER_GRADIENT_VISUAL_RADIAL_SHADER_FRAG,
-
- // fragment shader for linear gradient with corner radius
- SHADER_GRADIENT_VISUAL_LINEAR_ROUNDED_CORNER_SHADER_FRAG,
-
- // fragment shader for radial gradient with corner radius
- SHADER_GRADIENT_VISUAL_RADIAL_ROUNDED_CORNER_SHADER_FRAG};
+VisualFactoryCache::ShaderType SHADER_TYPE_TABLE[16] =
+{
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_BORDERLINE,
+ VisualFactoryCache::GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_BORDERLINE,
+};
+
+// enum of required list when we select shader
+enum GradientVisualRequireFlag
+{
+ DEFAULT = 0,
+ ROUNDED_CORNER = 1 << 0,
+ BORDERLINE = 1 << 1,
+ USER_SPACE = 1 << 2,
+ RADIAL = 1 << 3,
+};
Dali::WrapMode::Type GetWrapMode(Toolkit::GradientVisual::SpreadMethod::Type spread)
{
Scripting::GetEnumerationProperty(*unitsValue, UNITS_TABLE, UNITS_TABLE_COUNT, gradientUnits);
}
- mGradientType = LINEAR;
+ mGradientType = Type::LINEAR;
if(propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME))
{
- mGradientType = RADIAL;
+ mGradientType = Type::RADIAL;
}
if(NewGradient(mGradientType, propertyMap))
bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propertyMap)
{
- if(gradientType == LINEAR)
+ if(gradientType == Type::LINEAR)
{
Property::Value* startPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::START_POSITION, START_POSITION_NAME);
Property::Value* endPositionValue = propertyMap.Find(Toolkit::GradientVisual::Property::END_POSITION, END_POSITION_NAME);
return false;
}
}
- else // type==RADIAL
+ else // type==Type::RADIAL
{
Property::Value* centerValue = propertyMap.Find(Toolkit::GradientVisual::Property::CENTER, CENTER_NAME);
Property::Value* radiusValue = propertyMap.Find(Toolkit::GradientVisual::Property::RADIUS, RADIUS_NAME);
Shader GradientVisual::GetShader()
{
- Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits();
- int roundedCorner = IsRoundedCornerRequired() ? 1 : 0;
- VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[mGradientType][gradientUnits + roundedCorner * 2];
- Shader shader = mFactoryCache.GetShader(shaderType);
+ bool userspaceUnit = (mGradient->GetGradientUnits() == Toolkit::GradientVisual::Units::USER_SPACE);
+ bool roundedCorner = IsRoundedCornerRequired();
+ bool borderline = IsBorderlineRequired();
+ bool radialGradient = (mGradientType == Type::RADIAL);
+
+ int shaderTypeFlag = GradientVisualRequireFlag::DEFAULT;
+ if(roundedCorner)
+ {
+ shaderTypeFlag |= GradientVisualRequireFlag::ROUNDED_CORNER;
+ }
+ if(borderline)
+ {
+ shaderTypeFlag |= GradientVisualRequireFlag::BORDERLINE;
+ }
+ if(userspaceUnit)
+ {
+ shaderTypeFlag |= GradientVisualRequireFlag::USER_SPACE;
+ }
+ if(radialGradient)
+ {
+ shaderTypeFlag |= GradientVisualRequireFlag::RADIAL;
+ }
+
+ VisualFactoryCache::ShaderType shaderType = SHADER_TYPE_TABLE[shaderTypeFlag];
+ Shader shader = mFactoryCache.GetShader(shaderType);
if(!shader)
{
- shader = Shader::New(VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[mGradientType + roundedCorner * 2]);
+ std::string vertexShaderPrefixList;
+ std::string fragmentShaderPrefixList;
+
+ if(roundedCorner)
+ {
+ vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+ }
+ if(borderline)
+ {
+ vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+ }
+ if(radialGradient)
+ {
+ fragmentShaderPrefixList += "#define RADIAL 1\n";
+ }
+ if(userspaceUnit)
+ {
+ vertexShaderPrefixList += "#define USER_SPACE 1\n";
+ }
+
+ shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_VERT.data(),
+ Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_GRADIENT_VISUAL_SHADER_FRAG.data());
mFactoryCache.SaveShader(shaderType, shader);
}
{
}
-Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping, bool roundedCorner)
+Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, TextureAtlas atlasing, DefaultTextureWrapMode defaultTextureWrapping, RoundedCorner roundedCorner, Borderline borderline)
{
Shader shader;
- if(atlasing)
+ VisualFactoryCache::ShaderType shaderType = VisualFactoryCache::IMAGE_SHADER;
+ if(atlasing == TextureAtlas::ENABLED)
{
- if(defaultTextureWrapping)
+ if(defaultTextureWrapping == DefaultTextureWrapMode::APPLY)
{
- shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP);
- if(!shader)
+ shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP;
+ }
+ else
+ {
+ shaderType = VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP;
+ }
+ }
+ else
+ {
+ if(roundedCorner == RoundedCorner::ENABLED)
+ {
+ if(borderline == Borderline::ENABLED)
{
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
- Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ATLAS_CLAMP_SHADER_FRAG.data());
- shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
- factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader);
+ shaderType = VisualFactoryCache::IMAGE_SHADER_ROUNDED_BORDERLINE;
+ }
+ else
+ {
+ shaderType = VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER;
}
}
else
{
- shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP);
- if(!shader)
+ if(borderline == Borderline::ENABLED)
{
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
- Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ATLAS_VARIOUS_WRAP_SHADER_FRAG.data());
- shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
- factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader);
+ shaderType = VisualFactoryCache::IMAGE_SHADER_BORDERLINE;
}
}
}
- else
+
+ shader = factoryCache.GetShader(shaderType);
+ if(!shader)
{
- if(roundedCorner)
+ std::string vertexShaderPrefixList;
+ std::string fragmentShaderPrefixList;
+ if(atlasing == TextureAtlas::ENABLED)
{
- shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER);
- if(!shader)
+ if(defaultTextureWrapping == DefaultTextureWrapMode::APPLY)
+ {
+ fragmentShaderPrefixList += "#define ATLAS_DEFAULT_WARP 1\n";
+ }
+ else
{
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_ROUNDED_CORNER_SHADER_VERT.data(),
- Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_ROUNDED_CORNER_SHADER_FRAG.data());
- shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
- factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER_ROUNDED_CORNER, shader);
+ fragmentShaderPrefixList += "#define ATLAS_CUSTOM_WARP 1\n";
}
}
else
{
- shader = factoryCache.GetShader(VisualFactoryCache::IMAGE_SHADER);
- if(!shader)
+ if(roundedCorner == RoundedCorner::ENABLED)
+ {
+ vertexShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_ROUNDED_CORNER 1\n";
+ }
+ if(borderline == Borderline::ENABLED)
{
- shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
- Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG.data());
- shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
- factoryCache.SaveShader(VisualFactoryCache::IMAGE_SHADER, shader);
+ vertexShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
+ fragmentShaderPrefixList += "#define IS_REQUIRED_BORDERLINE 1\n";
}
}
+
+ shader = Shader::New(Dali::Shader::GetVertexShaderPrefix() + vertexShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_VERT.data(),
+ Dali::Shader::GetFragmentShaderPrefix() + fragmentShaderPrefixList + SHADER_IMAGE_VISUAL_SHADER_FRAG.data());
+ shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT);
+ factoryCache.SaveShader(shaderType, shader);
}
return shader;
{
if(gFragmentShaderNoAtlas.empty())
{
- gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_NO_ATLAS_SHADER_FRAG.data();
+ gFragmentShaderNoAtlas = Dali::Shader::GetFragmentShaderPrefix() + SHADER_IMAGE_VISUAL_SHADER_FRAG.data();
}
return gFragmentShaderNoAtlas;
}
namespace Internal
{
/**
+ * @brief Whether use texture with atlas, or not
+ */
+enum class TextureAtlas
+{
+ DISABLED = 0, ///< Image visual use ATLAS
+ ENABLED ///< Image visual doesn't use ATLAS
+};
+
+/**
+ * @brief Whether apply to texture wraping in default, or not
+ */
+enum class DefaultTextureWrapMode
+{
+ DO_NOT_APPLY = 0, ///< Image visual doesn't apply to wraping texture in default
+ APPLY ///< Image visual apply to wraping texture in default
+};
+
+/**
+ * @brief Whether use rounded corner, or not
+ */
+enum class RoundedCorner
+{
+ DISABLED = 0, ///< Image visual doesn't use rounded corner
+ ENABLED ///< Image visual use rounded corner
+};
+
+/**
+ * @brief Whether use borderline, or not
+ */
+enum class Borderline
+{
+ DISABLED = 0, ///< Image visual doesn't use borderline
+ ENABLED ///< Image visual use borderline
+};
+
+/**
* ImageVisualShaderFactory is an object that provides and shares shaders between image visuals
*/
class ImageVisualShaderFactory
{
public:
+
/**
* @brief Constructor
*/
* @param[in] atlasing Whether texture atlasing is applied.
* @param[in] defaultTextureWrapping Whether the default texture wrap mode is applied.
* @param[in] roundedCorner Whether the rounded corder is applied.
+ * @param[in] borderline Whether the borderline of visual is applied.
*/
- Shader GetShader(VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping, bool roundedCorner);
+ Shader GetShader(VisualFactoryCache& factoryCache, TextureAtlas atlasing, DefaultTextureWrapMode defaultTextureWrapping, RoundedCorner roundedCorner, Borderline borderline);
/**
* Request the default vertex shader source.
// Create and cache the standard shader
shader = mImageVisualShaderFactory.GetShader(
mFactoryCache,
- mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
- mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE,
- IsRoundedCornerRequired());
+ mImpl->mFlags & Impl::IS_ATLASING_APPLIED ? TextureAtlas::ENABLED : TextureAtlas::DISABLED,
+ mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE ? DefaultTextureWrapMode::APPLY : DefaultTextureWrapMode::DO_NOT_APPLY,
+ IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED,
+ IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED
+ );
}
else if(mImpl->mCustomShader)
{
{
// Get basic geometry and shader
Geometry geometry = mFactoryCache.GetGeometry(VisualFactoryCache::QUAD_GEOMETRY);
- Shader shader = mImageVisualShaderFactory.GetShader(mFactoryCache, false, true, false);
+ Shader shader = mImageVisualShaderFactory.GetShader(
+ mFactoryCache,
+ TextureAtlas::DISABLED,
+ DefaultTextureWrapMode::APPLY,
+ RoundedCorner::DISABLED,
+ Borderline::DISABLED
+ );
mImpl->mRenderer = Renderer::New(geometry, shader);
Shader shader;
if(!mImpl->mCustomShader)
{
- shader = mImageVisualShaderFactory.GetShader(mFactoryCache, mAttemptAtlasing, true, IsRoundedCornerRequired());
+ shader = mImageVisualShaderFactory.GetShader(
+ mFactoryCache,
+ mAttemptAtlasing ? TextureAtlas::ENABLED : TextureAtlas::DISABLED,
+ DefaultTextureWrapMode::APPLY,
+ IsRoundedCornerRequired() ? RoundedCorner::ENABLED : RoundedCorner::DISABLED,
+ IsBorderlineRequired() ? Borderline::ENABLED : Borderline::DISABLED
+ );
}
else
{
mTransform(),
mMixColor(Color::WHITE),
mControlSize(Vector2::ZERO),
+ mBorderlineWidth(0.0f),
+ mBorderlineColor(Color::BLACK),
+ mBorderlineOffset(0.0f),
mCornerRadius(Vector4::ZERO),
mCornerRadiusPolicy(1.0f),
mDepthIndex(0.0f),
mMixColorIndex(Property::INVALID_INDEX),
+ mBorderlineWidthIndex(Property::INVALID_INDEX),
+ mBorderlineColorIndex(Property::INVALID_INDEX),
+ mBorderlineOffsetIndex(Property::INVALID_INDEX),
mCornerRadiusIndex(Property::INVALID_INDEX),
mFittingMode(fittingMode),
mFlags(0),
mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
mType(type),
- mNeedCornerRadius(false)
+ mNeedCornerRadius(false),
+ mNeedBorderline(false)
{
}
Transform mTransform;
Vector4 mMixColor;
Size mControlSize;
+ float mBorderlineWidth;
+ Vector4 mBorderlineColor;
+ float mBorderlineOffset;
Vector4 mCornerRadius;
float mCornerRadiusPolicy;
int mDepthIndex;
Property::Index mMixColorIndex;
+ Property::Index mBorderlineWidthIndex;
+ Property::Index mBorderlineColorIndex;
+ Property::Index mBorderlineOffsetIndex;
Property::Index mCornerRadiusIndex;
FittingMode mFittingMode; //< How the contents should fit the view
int mFlags;
Toolkit::Visual::ResourceStatus mResourceStatus;
const Toolkit::Visual::Type mType;
bool mNeedCornerRadius;
+ bool mNeedBorderline;
};
} // namespace Visual
mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
}
+ if(IsBorderlineRequired())
+ {
+ mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
+ mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
+ mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
+
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+ }
}
}
{
matchKey = Property::Key(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE);
}
+ else if(matchKey == BORDERLINE_WIDTH)
+ {
+ matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH);
+ }
+ else if(matchKey == BORDERLINE_COLOR)
+ {
+ matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_COLOR);
+ }
+ else if(matchKey == BORDERLINE_OFFSET)
+ {
+ matchKey = Property::Key(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET);
+ }
else if(matchKey == CORNER_RADIUS)
{
matchKey = Property::Key(Toolkit::DevelVisual::Property::CORNER_RADIUS);
value, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT, mImpl->mFittingMode);
break;
}
+ case Toolkit::DevelVisual::Property::BORDERLINE_WIDTH:
+ {
+ float width;
+ if(value.Get(width))
+ {
+ mImpl->mBorderlineWidth = width;
+ }
+ break;
+ }
+ case Toolkit::DevelVisual::Property::BORDERLINE_COLOR:
+ {
+ Vector4 color;
+ if(value.Get(color))
+ {
+ mImpl->mBorderlineColor = color;
+ }
+ break;
+ }
+ case Toolkit::DevelVisual::Property::BORDERLINE_OFFSET:
+ {
+ float offset;
+ if(value.Get(offset))
+ {
+ mImpl->mBorderlineOffset = offset;
+ }
+ break;
+ }
case Toolkit::DevelVisual::Property::CORNER_RADIUS:
{
if(value.GetType() == Property::VECTOR4)
{
mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mCornerRadiusIndex);
}
+ if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineWidthIndex);
+ }
+ if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mBorderlineColor = mImpl->mRenderer.GetProperty<Vector4>(mImpl->mBorderlineColorIndex);
+ }
+ if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mBorderlineOffset = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineOffsetIndex);
+ }
}
DoCreatePropertyMap(map);
mImpl->mFittingMode, VISUAL_FITTING_MODE_TABLE, VISUAL_FITTING_MODE_TABLE_COUNT);
map.Insert(Toolkit::DevelVisual::Property::VISUAL_FITTING_MODE, fittingModeString);
+ map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
+ map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_COLOR, mImpl->mBorderlineColor);
+ map.Insert(Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
+
map.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS, mImpl->mCornerRadius);
map.Insert(Toolkit::DevelVisual::Property::CORNER_RADIUS_POLICY, static_cast<int>(mImpl->mCornerRadiusPolicy));
}
return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius;
}
+bool Visual::Base::IsBorderlineRequired() const
+{
+ if(mImpl->mRenderer && mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
+ {
+ // Update values from Renderer
+ mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(mImpl->mBorderlineWidthIndex);
+ }
+ return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline;
+}
+
void Visual::Base::OnDoAction(const Property::Index actionId, const Property::Value& attributes)
{
// May be overriden by derived class
Property::Index index = GetPropertyIndex(key);
if(index == Property::INVALID_INDEX)
{
- if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::CORNER_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == CORNER_RADIUS))
+ if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_WIDTH) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_WIDTH) ||
+ (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_COLOR) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_COLOR) ||
+ (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_OFFSET) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_OFFSET))
+ {
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+
+ // Register borderline properties
+ mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth);
+ mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor);
+ mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset);
+ mImpl->mNeedBorderline = true;
+
+ index = mImpl->mRenderer.GetPropertyIndex(key);
+
+ // Change shader
+ UpdateShader();
+ }
+ else if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::CORNER_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == CORNER_RADIUS))
{
// Register CORNER_RADIUS property
mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
*/
bool IsRoundedCornerRequired() const;
+ /**
+ * @brief Query whether the borderline of the visual requires to be rendered.
+ *
+ * @return Returns true if the outline is required, false otherwise.
+ */
+ bool IsBorderlineRequired() const;
+
private:
/**
* Register the mix color uniform on the Renderer and store the property index.
{
COLOR_SHADER,
COLOR_SHADER_ROUNDED_CORNER,
+ COLOR_SHADER_BORDERLINE,
+ COLOR_SHADER_ROUNDED_BORDERLINE,
COLOR_SHADER_BLUR_EDGE,
+ COLOR_SHADER_ROUNDED_CORNER_BLUR_EDGE,
BORDER_SHADER,
BORDER_SHADER_ANTI_ALIASING,
- GRADIENT_SHADER_LINEAR_USER_SPACE,
GRADIENT_SHADER_LINEAR_BOUNDING_BOX,
- GRADIENT_SHADER_RADIAL_USER_SPACE,
- GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
- GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER,
GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_CORNER,
- GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER,
+ GRADIENT_SHADER_LINEAR_BOUNDING_BOX_BORDERLINE,
+ GRADIENT_SHADER_LINEAR_BOUNDING_BOX_ROUNDED_BORDERLINE,
+ GRADIENT_SHADER_LINEAR_USER_SPACE,
+ GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_CORNER,
+ GRADIENT_SHADER_LINEAR_USER_SPACE_BORDERLINE,
+ GRADIENT_SHADER_LINEAR_USER_SPACE_ROUNDED_BORDERLINE,
+ GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_CORNER,
+ GRADIENT_SHADER_RADIAL_BOUNDING_BOX_BORDERLINE,
+ GRADIENT_SHADER_RADIAL_BOUNDING_BOX_ROUNDED_BORDERLINE,
+ GRADIENT_SHADER_RADIAL_USER_SPACE,
+ GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_CORNER,
+ GRADIENT_SHADER_RADIAL_USER_SPACE_BORDERLINE,
+ GRADIENT_SHADER_RADIAL_USER_SPACE_ROUNDED_BORDERLINE,
IMAGE_SHADER,
IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
IMAGE_SHADER_ROUNDED_CORNER,
+ IMAGE_SHADER_BORDERLINE,
+ IMAGE_SHADER_ROUNDED_BORDERLINE,
NINE_PATCH_SHADER,
NINE_PATCH_MASK_SHADER,
TEXT_SHADER_MULTI_COLOR_TEXT,
// Fitting mode
const char* const VISUAL_FITTING_MODE("visualFittingMode");
+// Border line
+const char* const BORDERLINE_WIDTH("borderlineWidth");
+const char* const BORDERLINE_COLOR("borderlineColor");
+const char* const BORDERLINE_OFFSET("borderlineOffset");
+
// Corner radius
const char* const CORNER_RADIUS("cornerRadius");
const char* const CORNER_RADIUS_POLICY("cornerRadiusPolicy");
// Fitting mode
extern const char* const VISUAL_FITTING_MODE;
+// Border line
+extern const char* const BORDERLINE_WIDTH;
+extern const char* const BORDERLINE_COLOR;
+extern const char* const BORDERLINE_OFFSET;
+
// Corner radius
extern const char* const CORNER_RADIUS;
extern const char* const CORNER_RADIUS_POLICY;