From: Eunki, Hong Date: Mon, 22 Feb 2021 09:37:36 +0000 (+0900) Subject: Add borderline property for visual + Integrate some shaders in one X-Git-Tag: dali_2.0.30~4^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=0547e874c936c6837e6e4511a7715cf555b0fb68 Add borderline property for visual + Integrate some shaders in one Add borderline properies for visual - BORDERLINE_WIDTH "borderlineWidth" (float, default = 0.0) : Width of the borderline - BORDERLINE_COLOR "borderlineColor" (Vector4, default = Color::BLACK) : Color of the borderline - BORDERLINE_OFFSET "borderlineOffset" (float, default = 0.0) : Relative position offset from 'Real' borderline of visual. == 0.0f then half is inside, and half is outside of visual. == -1.0f then all borderline will be rendered inside of visual. == 1.0f then all borderline will be rendered outside of visual. These three properties are animatable Also, I integrate image / color / gradient visual shaders in one file. Cause If I add above feature, the shader files need so many. Change-Id: Ieeea3c1fd4703c5f446018ceffb46a7b715b36f1 Signed-off-by: Eunki, Hong --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp index 6d74b7c..56d67f4 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedImageVisual.cpp @@ -77,7 +77,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap01(void) .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 ); @@ -98,6 +101,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap01(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get() == Visual::Transform::Policy::ABSOLUTE ); + value = resultMap.Find( DevelVisual::Property::BORDERLINE_WIDTH, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 33.3f, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Color::RED, TEST_LOCATION ); + + value = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.3f, TEST_LOCATION ); + // request AnimatedImageVisual with an URL Visual::Base animatedImageVisual2 = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); resultMap.Clear(); @@ -137,7 +152,10 @@ int UtcDaliAnimatedImageVisualGetPropertyMap02(void) .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 ); @@ -180,6 +198,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap02(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get() == Visual::Transform::Policy::RELATIVE ); + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 20.0f, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Vector4::ZERO, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), -1.0f, TEST_LOCATION ); + END_TEST; } @@ -248,6 +278,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap03(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get() == Visual::Transform::Policy::ABSOLUTE ); + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.0f, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), Color::BLACK, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_OFFSET, "borderlineOffset" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.0f, TEST_LOCATION ); + END_TEST; } @@ -264,7 +306,8 @@ int UtcDaliAnimatedImageVisualGetPropertyMap04(void) .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 ); @@ -290,6 +333,18 @@ int UtcDaliAnimatedImageVisualGetPropertyMap04(void) DALI_TEST_CHECK( value ); DALI_TEST_EQUALS( value->Get(), 4, TEST_LOCATION ); + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_WIDTH, "borderlineWidth" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 0.4f, TEST_LOCATION ); + + value = resultMap.Find( Toolkit::DevelVisual::Property::BORDERLINE_COLOR, "borderlineColor" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( value->Get(), 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(), 0.0f, TEST_LOCATION ); + END_TEST; } diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index 83c6a09..6159e71 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -145,7 +145,8 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual03(void) .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 ); @@ -177,6 +178,9 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void) 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 ); @@ -189,7 +193,10 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void) .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 ); @@ -253,6 +260,18 @@ int UtcDaliVisualFactoryGetAnimatedVectorImageVisual04(void) 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 ); @@ -266,6 +285,9 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) 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 ); @@ -276,7 +298,10 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) .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(); @@ -344,6 +369,18 @@ int UtcDaliAnimatedVectorImageVisualGetPropertyMap01(void) 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() ); @@ -1774,4 +1811,4 @@ int UtcDaliAnimatedVectorImageVisualPlaybackRiveFile(void) } END_TEST; -} \ No newline at end of file +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index a0f5334..5864554 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -502,6 +502,9 @@ int UtcDaliVisualGetPropertyMap1(void) 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 ); @@ -524,6 +527,18 @@ int UtcDaliVisualGetPropertyMap1(void) 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 ); @@ -599,10 +614,23 @@ int UtcDaliVisualGetPropertyMap2(void) DALI_TEST_CHECK( colorValue ); DALI_TEST_CHECK( colorValue->Get() == 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() == 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() == 0.0f ); + + colorValue = resultMap.Find( DevelVisual::Property::BORDERLINE_COLOR, Property::VECTOR4 ); DALI_TEST_CHECK( colorValue ); - DALI_TEST_CHECK( colorValue->Get() == 10.f ); + DALI_TEST_CHECK( colorValue->Get() == Color::BLACK ); + sizeValue = resultMap.Find( DevelVisual::Property::BORDERLINE_OFFSET, Property::FLOAT ); + DALI_TEST_CHECK( sizeValue ); + DALI_TEST_CHECK( sizeValue->Get() == 0.0f ); END_TEST; } @@ -655,6 +683,11 @@ int UtcDaliVisualGetPropertyMap3(void) 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; @@ -681,6 +714,14 @@ int UtcDaliVisualGetPropertyMap3(void) DALI_TEST_CHECK( value ); DALI_TEST_EQUALS( value->Get(), 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(), 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(), 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(); @@ -722,6 +763,11 @@ int UtcDaliVisualGetPropertyMap4(void) 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 ); @@ -749,6 +795,14 @@ int UtcDaliVisualGetPropertyMap4(void) DALI_TEST_CHECK( value ); DALI_TEST_EQUALS( value->Get(), 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(), 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(), 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(); @@ -3910,6 +3964,361 @@ int UtcDaliVisualRoundedCorner(void) END_TEST; } +int UtcDaliVisualBorderline(void) +{ +#ifdef OLD_GRAPHICS_TEST + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualBorderline" ); + + static std::vector 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; @@ -4101,6 +4510,9 @@ int UtcDaliVisualGetVisualProperty01(void) 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(); @@ -4113,6 +4525,9 @@ int UtcDaliVisualGetVisualProperty01(void) 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); @@ -4130,6 +4545,9 @@ int UtcDaliVisualGetVisualProperty01(void) 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); @@ -4138,6 +4556,9 @@ int UtcDaliVisualGetVisualProperty01(void) 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(); @@ -4172,12 +4593,27 @@ int UtcDaliVisualGetVisualProperty01(void) 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("mixColor", targetColor), true, TEST_LOCATION); DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("offset", targetOffset), true, TEST_LOCATION); DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("size", targetSize), true, TEST_LOCATION); DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("cornerRadius", targetCornerRadius), true, TEST_LOCATION); DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("blurRadius", targetBlurRadius), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineWidth", targetBorderlineWidth), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineColor", targetBorderlineColor), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineOffset", targetBorderlineOffset), true, TEST_LOCATION); // Test not-supported property Property property1 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::PREMULTIPLIED_ALPHA); @@ -4203,6 +4639,9 @@ int UtcDaliVisualGetVisualProperty02(void) 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), }; @@ -4228,6 +4667,9 @@ int UtcDaliVisualGetVisualProperty02(void) 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 @@ -4237,6 +4679,9 @@ int UtcDaliVisualGetVisualProperty02(void) 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(); @@ -4268,6 +4713,18 @@ int UtcDaliVisualGetVisualProperty02(void) 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); @@ -4288,11 +4745,14 @@ int UtcDaliVisualGetVisualProperty03(void) { #ifdef OLD_GRAPHICS_TEST ToolkitTestApplication application; - tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, ImageVisual" ); + tet_infoline( "UtcDaliVisualGetVisualProperty03: Test animatable property, ImageVisual" ); static std::vector 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(); @@ -4302,6 +4762,10 @@ int UtcDaliVisualGetVisualProperty03(void) 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); @@ -4318,10 +4782,16 @@ int UtcDaliVisualGetVisualProperty03(void) 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(); @@ -4340,8 +4810,23 @@ int UtcDaliVisualGetVisualProperty03(void) 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("cornerRadius", targetCornerRadius), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineWidth", targetBorderlineWidth), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineColor", targetBorderlineColor), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue("borderlineOffset", targetBorderlineOffset), true, TEST_LOCATION); #else tet_result(TET_PASS); #endif diff --git a/dali-toolkit/devel-api/visuals/visual-properties-devel.h b/dali-toolkit/devel-api/visuals/visual-properties-devel.h index 1098b7d..ddb02d5 100644 --- a/dali-toolkit/devel-api/visuals/visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/visual-properties-devel.h @@ -94,6 +94,28 @@ enum Type * 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 diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.frag deleted file mode 100644 index a3bb80a..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.frag +++ /dev/null @@ -1,74 +0,0 @@ -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; -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.vert b/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.vert deleted file mode 100644 index 5306aef..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-blur-edge-shader.vert +++ /dev/null @@ -1,40 +0,0 @@ -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(); -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.frag deleted file mode 100644 index 811dc1d..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.frag +++ /dev/null @@ -1,37 +0,0 @@ -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); - } -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.vert deleted file mode 100644 index 0a6a257..0000000 --- a/dali-toolkit/internal/graphics/shaders/color-visual-rounded-corner-shader.vert +++ /dev/null @@ -1,38 +0,0 @@ -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(); -} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag index fef045b..bf93629 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag @@ -1,7 +1,265 @@ +#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 +} diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert index 993d9d4..2798185 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.vert @@ -1,4 +1,22 @@ +#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; @@ -9,16 +27,57 @@ uniform highp vec2 size; 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 +} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-rounded-corner-shader.vert deleted file mode 100644 index bd08a63..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-rounded-corner-shader.vert +++ /dev/null @@ -1,41 +0,0 @@ -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(); -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-shader.vert deleted file mode 100644 index 018e260..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-bounding-box-shader.vert +++ /dev/null @@ -1,27 +0,0 @@ -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 diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-rounded-corner-shader.frag deleted file mode 100644 index 1b29ae0..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-rounded-corner-shader.frag +++ /dev/null @@ -1,38 +0,0 @@ -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); - } -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-shader.frag deleted file mode 100644 index 1ec04b2..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-linear-shader.frag +++ /dev/null @@ -1,9 +0,0 @@ -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; -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-rounded-corner-shader.frag deleted file mode 100644 index 68df0c5..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-rounded-corner-shader.frag +++ /dev/null @@ -1,38 +0,0 @@ -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); - } -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-shader.frag deleted file mode 100644 index 8d37383..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-radial-shader.frag +++ /dev/null @@ -1,9 +0,0 @@ -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; -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag new file mode 100644 index 0000000..305ff92 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag @@ -0,0 +1,196 @@ +#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 +} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert new file mode 100644 index 0000000..f9e80fe --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.vert @@ -0,0 +1,84 @@ +#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; +} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-rounded-corner-shader.vert deleted file mode 100644 index 23ded26..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-rounded-corner-shader.vert +++ /dev/null @@ -1,43 +0,0 @@ -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; -} diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-shader.vert b/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-shader.vert deleted file mode 100644 index ca1eab6..0000000 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-user-space-shader.vert +++ /dev/null @@ -1,28 +0,0 @@ -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; -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-clamp-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-atlas-clamp-shader.frag deleted file mode 100644 index 0d87f9d..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-clamp-shader.frag +++ /dev/null @@ -1,13 +0,0 @@ -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 diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-various-wrap-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-atlas-various-wrap-shader.frag deleted file mode 100644 index eeb8a0c..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-atlas-various-wrap-shader.frag +++ /dev/null @@ -1,28 +0,0 @@ -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 diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-no-atlas-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-no-atlas-shader.frag deleted file mode 100644 index ffc960c..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-no-atlas-shader.frag +++ /dev/null @@ -1,11 +0,0 @@ -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 ); -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.frag deleted file mode 100644 index 6eacb93..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.frag +++ /dev/null @@ -1,45 +0,0 @@ -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); -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.vert b/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.vert deleted file mode 100644 index c35b1b6..0000000 --- a/dali-toolkit/internal/graphics/shaders/image-visual-rounded-corner-shader.vert +++ /dev/null @@ -1,41 +0,0 @@ -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)); -} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag new file mode 100644 index 0000000..e83d463 --- /dev/null +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag @@ -0,0 +1,224 @@ +#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 +} diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert b/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert index fe0c35c..21d4084 100644 --- a/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.vert @@ -1,5 +1,20 @@ +#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; @@ -11,17 +26,53 @@ 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 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 +} diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp index c9623a6..30a0dfe 100644 --- a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -539,7 +539,13 @@ void AnimatedImageVisual::OnInitialize() { 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); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index c6604ad..edd7b1b 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -295,7 +295,13 @@ void AnimatedVectorImageVisual::OnInitialize(void) } 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); diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index cf6abd3..8f748cf 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -39,6 +39,27 @@ namespace Toolkit { 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)); @@ -192,32 +213,52 @@ void ColorVisual::OnInitialize() 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; diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index b122359..896b095 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -28,14 +28,7 @@ #include // INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include #include @@ -71,44 +64,35 @@ const char* const UNIFORM_ALIGNMENT_MATRIX_NAME("uAlignmentMatrix"); 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) { @@ -162,10 +146,10 @@ void GradientVisual::DoSetProperties(const Property::Map& propertyMap) 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)) @@ -283,7 +267,7 @@ void GradientVisual::OnInitialize() 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); @@ -299,7 +283,7 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert 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); @@ -363,13 +347,57 @@ bool GradientVisual::NewGradient(Type gradientType, const Property::Map& propert 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); } diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp index f8f7e5e..7f2cac7 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp @@ -50,58 +50,77 @@ ImageVisualShaderFactory::~ImageVisualShaderFactory() { } -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; @@ -121,7 +140,7 @@ std::string_view ImageVisualShaderFactory::GetFragmentShaderSource() { 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; } diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.h b/dali-toolkit/internal/visuals/image-visual-shader-factory.h index 8ed50a6..604b49b 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.h +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.h @@ -30,11 +30,48 @@ namespace Toolkit 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 */ @@ -51,8 +88,9 @@ public: * @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. diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 1c5f5e7..bbbab23 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -978,9 +978,11 @@ Shader ImageVisual::GetShader() // 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) { diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index bb8571d..bbee1d4 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -376,7 +376,13 @@ void NPatchVisual::OnInitialize() { // 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); diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index dc148a2..b6f9520 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -87,7 +87,13 @@ void SvgVisual::OnInitialize() 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 { diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp index 2d42f93..53b5246 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.cpp @@ -119,16 +119,23 @@ Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Typ 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) { } diff --git a/dali-toolkit/internal/visuals/visual-base-data-impl.h b/dali-toolkit/internal/visuals/visual-base-data-impl.h index acb6805..52e0d98 100644 --- a/dali-toolkit/internal/visuals/visual-base-data-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-data-impl.h @@ -123,16 +123,23 @@ struct Base::Impl 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 diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 528bc14..49b3120 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -89,6 +89,14 @@ void Visual::Base::Initialize() 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); + } } } @@ -142,6 +150,18 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) { 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); @@ -217,6 +237,33 @@ void Visual::Base::SetProperties(const Property::Map& propertyMap) 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) @@ -388,6 +435,18 @@ void Visual::Base::CreatePropertyMap(Property::Map& map) const { mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); } + if(mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX) + { + mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty(mImpl->mBorderlineWidthIndex); + } + if(mImpl->mBorderlineColorIndex != Property::INVALID_INDEX) + { + mImpl->mBorderlineColor = mImpl->mRenderer.GetProperty(mImpl->mBorderlineColorIndex); + } + if(mImpl->mBorderlineOffsetIndex != Property::INVALID_INDEX) + { + mImpl->mBorderlineOffset = mImpl->mRenderer.GetProperty(mImpl->mBorderlineOffsetIndex); + } } DoCreatePropertyMap(map); @@ -413,6 +472,10 @@ void Visual::Base::CreatePropertyMap(Property::Map& map) const 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(mImpl->mCornerRadiusPolicy)); } @@ -470,6 +533,16 @@ bool Visual::Base::IsRoundedCornerRequired() const 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(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 @@ -824,7 +897,24 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key) 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); diff --git a/dali-toolkit/internal/visuals/visual-base-impl.h b/dali-toolkit/internal/visuals/visual-base-impl.h index c958992..8800ad8 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.h +++ b/dali-toolkit/internal/visuals/visual-base-impl.h @@ -389,6 +389,13 @@ protected: */ 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. diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index 418b10e..6e8f37d 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -57,21 +57,34 @@ public: { 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, diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 9c9ca4b..53bcd1c 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -75,6 +75,11 @@ const char* const OPACITY("opacity"); // 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"); diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 966e51f..470ded9 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -59,6 +59,11 @@ extern const char* const OPACITY; // 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;