return Dali::Geometry::New();
}
-static void* NPatchBuildInternal(const Devel::PixelBuffer& pixelBuffer, Toolkit::Internal::NPatchLoader::Data* data )
+static void* NPatchBuildInternal(const Devel::PixelBuffer& pixelBuffer, Toolkit::Internal::NPatchData* data )
{
gCallStack.emplace_back( "BuildNPatch" );
fprintf(stderr, "AddOn::NPatchBuild()\n");
}
+int UtcDaliAnimatedImageVisualStopBehavior02(void)
+{
+ ToolkitTestApplication application;
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+
+ Property::Array urls;
+ CopyUrlsIntoArray( urls );
+
+ {
+ Property::Map propertyMap;
+ propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE );
+ propertyMap.Insert( ImageVisual::Property::URL, Property::Value(urls) );
+ propertyMap.Insert( DevelImageVisual::Property::STOP_BEHAVIOR, DevelImageVisual::StopBehavior::LAST_FRAME);
+ propertyMap.Insert( ImageVisual::Property::BATCH_SIZE, 2);
+ propertyMap.Insert( ImageVisual::Property::CACHE_SIZE, 2);
+ propertyMap.Insert( ImageVisual::Property::FRAME_DELAY, 20);
+
+ VisualFactory factory = VisualFactory::Get();
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+
+ // Expect that a batch of 4 textures has been requested. These will be serially loaded
+ // below.
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ dummyControl.SetResizePolicy( ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS );
+ application.GetScene().Add( dummyControl );
+
+ tet_infoline( "Ready the visual after the visual is on stage" );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetLastGenTextureId(), 2, TEST_LOCATION );
+
+ Test::EmitGlobalTimerSignal();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 2, TEST_LOCATION );
+
+ DevelControl::DoAction( dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedImageVisual::Action::STOP, Property::Map() );
+
+ tet_infoline( "Ready the visual after the visual is on stage" );
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render(20);
+
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 2, TEST_LOCATION );
+
+ dummyControl.Unparent();
+ }
+ tet_infoline("Test that removing the visual from stage deletes all textures");
+ application.SendNotification();
+ application.Render(16);
+ DALI_TEST_EQUALS( gl.GetNumGeneratedTextures(), 0, TEST_LOCATION );
+
+ END_TEST;
+}
+
+
int UtcDaliAnimatedImageVisualAnimatedImage01(void)
{
ToolkitTestApplication application;
END_TEST;
}
+
+int UtcDaliVisualGetVisualProperty01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, Visual::Base, ColorVisual" );
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+ 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(DevelColorVisual::Property::BLUR_RADIUS, 20.0f);
+ Visual::Base colorVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, colorVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 targetColor(1.0f, 1.0f, 1.0f);
+ float targetOpacity = 0.5f;
+ float targetCornerRadius = 20.0f;
+ float targetBlurRadius = 10.0f;
+
+ Animation animation = Animation::New(1.0f);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR), targetColor);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::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, DevelColorVisual::Property::BLUR_RADIUS), targetBlurRadius);
+ animation.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(1001u); // End of animation
+
+ Property::Map resultMap;
+ colorVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* colorValue = resultMap.Find(ColorVisual::Property::MIX_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(colorValue);
+ DALI_TEST_EQUALS(colorValue->Get<Vector4>(), Vector4(targetColor.r, targetColor.g, targetColor.b, targetOpacity), TEST_LOCATION);
+
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, 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);
+
+ // Test uniform values
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector3>("mixColor", targetColor), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("cornerRadius", targetCornerRadius), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("blurRadius", targetBlurRadius), true, TEST_LOCATION);
+
+ // Test not-supported property
+ Property property1 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::PREMULTIPLIED_ALPHA);
+ DALI_TEST_CHECK(!property1.object);
+ DALI_TEST_CHECK(property1.propertyIndex == Property::INVALID_INDEX);
+
+ // Test not-supported property
+ Property property2 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, DevelColorVisual::Property::RENDER_IF_TRANSPARENT);
+ DALI_TEST_CHECK(!property2.object);
+ DALI_TEST_CHECK(property2.propertyIndex == Property::INVALID_INDEX);
+
+ // Test unregistered visual
+ Property property3 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL2, Visual::Property::MIX_COLOR);
+ DALI_TEST_CHECK(!property3.object);
+ DALI_TEST_CHECK(property3.propertyIndex == Property::INVALID_INDEX);
+
+ // Test after the control is unparented
+ dummyControl.Unparent();
+
+ Property property4 = DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, Visual::Property::MIX_COLOR);
+ DALI_TEST_CHECK(!property4.object);
+ DALI_TEST_CHECK(property4.propertyIndex == Property::INVALID_INDEX);
+
+ END_TEST;
+}
+
+int UtcDaliVisualGetVisualProperty02(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualGetVisualProperty02: Test animatable property" );
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::COLOR);
+ Visual::Base colorVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, colorVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ Vector3 targetColor(1.0f, 1.0f, 1.0f);
+ float targetOpacity = 0.5f;
+ float targetCornerRadius = 20.0f;
+ float targetBlurRadius = 10.0f;
+
+ // Should work when the properties are not set before
+ Animation animation = Animation::New(1.0f);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "mixColor"), targetColor);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "opacity"), targetOpacity);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "cornerRadius"), targetCornerRadius);
+ animation.AnimateTo(DevelControl::GetVisualProperty(dummyControl, DummyControl::Property::TEST_VISUAL, "blurRadius"), targetBlurRadius);
+ animation.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(1001u); // End of animation
+
+ Property::Map resultMap;
+ colorVisual.CreatePropertyMap(resultMap);
+
+ // Test property values: they should be updated
+ Property::Value* colorValue = resultMap.Find(ColorVisual::Property::MIX_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(colorValue);
+ DALI_TEST_EQUALS(colorValue->Get<Vector4>(), Vector4(targetColor.r, targetColor.g, targetColor.b, targetOpacity), TEST_LOCATION);
+
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, 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);
+
+ // Test uniform values
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<Vector3>("mixColor", targetColor), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("cornerRadius", targetCornerRadius), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("blurRadius", targetBlurRadius), true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliVisualGetVisualProperty03(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, ImageVisual" );
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::IMAGE);
+ propertyMap.Insert(ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME);
+ Visual::Base imageVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, imageVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ // Wait for image loading
+ DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION);
+
+ application.SendNotification();
+ application.Render();
+
+ float targetOpacity = 0.5f;
+ float targetCornerRadius = 20.0f;
+
+ 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.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(1001u); // End of animation
+
+ Property::Map resultMap;
+ imageVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* colorValue = resultMap.Find(Visual::Property::MIX_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(colorValue);
+ DALI_TEST_EQUALS(colorValue->Get<Vector4>(), Vector4(1.0f, 1.0f, 1.0f, targetOpacity), TEST_LOCATION);
+
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, TEST_LOCATION);
+
+ // Test uniform value
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("cornerRadius", targetCornerRadius), true, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliVisualGetVisualProperty04(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualGetVisualProperty01: Test animatable property, GradientVisual" );
+
+ Vector2 start(-1.f, -1.f);
+ Vector2 end(1.f, 1.f);
+ Property::Array stopColors;
+ stopColors.PushBack( Color::RED );
+ stopColors.PushBack( Color::GREEN );
+
+ VisualFactory factory = VisualFactory::Get();
+ Property::Map propertyMap;
+ propertyMap.Insert(Visual::Property::TYPE, Visual::GRADIENT);
+ propertyMap.Insert(GradientVisual::Property::START_POSITION, start);
+ propertyMap.Insert(GradientVisual::Property::END_POSITION, end);
+ propertyMap.Insert(GradientVisual::Property::STOP_OFFSET, Vector2(0.f, 1.f));
+ propertyMap.Insert(GradientVisual::Property::SPREAD_METHOD, GradientVisual::SpreadMethod::REPEAT);
+ propertyMap.Insert(GradientVisual::Property::STOP_COLOR, stopColors);
+ Visual::Base gradientVisual = factory.CreateVisual(propertyMap);
+
+ DummyControl dummyControl = DummyControl::New(true);
+ Impl::DummyControl& dummyImpl = static_cast<Impl::DummyControl&>(dummyControl.GetImplementation());
+ dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, gradientVisual);
+ dummyControl[Actor::Property::SIZE] = Vector2(200.f, 200.f);
+ application.GetScene().Add(dummyControl);
+
+ application.SendNotification();
+ application.Render();
+
+ float targetOpacity = 0.5f;
+ float targetCornerRadius = 20.0f;
+
+ 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.Play();
+
+ application.SendNotification();
+ application.Render();
+ application.Render(1001u); // End of animation
+
+ Property::Map resultMap;
+ gradientVisual.CreatePropertyMap( resultMap );
+
+ // Test property values: they should be updated
+ Property::Value* colorValue = resultMap.Find(Visual::Property::MIX_COLOR, Property::VECTOR4);
+ DALI_TEST_CHECK(colorValue);
+ DALI_TEST_EQUALS(colorValue->Get<Vector4>(), Vector4(1.0f, 1.0f, 1.0f, targetOpacity), TEST_LOCATION);
+
+ Property::Value* cornerRadiusValue = resultMap.Find(DevelVisual::Property::CORNER_RADIUS, Property::FLOAT);
+ DALI_TEST_CHECK(cornerRadiusValue);
+ DALI_TEST_EQUALS(cornerRadiusValue->Get< float >(), targetCornerRadius, TEST_LOCATION);
+
+ // Test uniform value
+ DALI_TEST_EQUALS(application.GetGlAbstraction().CheckUniformValue<float>("cornerRadius", targetCornerRadius), true, TEST_LOCATION);
+
+ END_TEST;
+}
DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
- application.GetScene().Remove( actor );
- DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
-
Vector2 naturalSize( 0.0f, 0.0f );
visual.GetNaturalSize( naturalSize );
DALI_TEST_EQUALS( naturalSize, Vector2( imageSize.GetWidth() - 2.0f, imageSize.GetHeight() - 2.0f ), TEST_LOCATION );
END_TEST;
}
+int UtcDaliVisualFactoryGetNPatchVisual8(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual8: Add 9-patch visual on stage, instantly remove it and add new 9-patch visual with same propertyMap" );
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ // Get actual size of test image
+ ImageDimensions imageSize = Dali::GetClosestImageSize( TEST_9_PATCH_FILE_NAME );
+
+ Property::Map propertyMap;
+ propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::N_PATCH );
+ propertyMap.Insert( ImageVisual::Property::URL, TEST_9_PATCH_FILE_NAME );
+ propertyMap.Insert( ImageVisual::Property::SYNCHRONOUS_LOADING, false );
+ {
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+ DALI_TEST_CHECK( visual );
+
+ Vector2 naturalSize( 0.0f, 0.0f );
+ visual.GetNaturalSize( naturalSize );
+ DALI_TEST_EQUALS( naturalSize, Vector2( imageSize.GetWidth(), imageSize.GetHeight() ), TEST_LOCATION );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ DummyControl actor = DummyControl::New(true);
+
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+ application.GetScene().Add( actor );
+ actor.Unparent();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ visual = factory.CreateVisual( propertyMap );
+ DALI_TEST_CHECK( visual );
+
+ visual.GetNaturalSize( naturalSize );
+ DALI_TEST_EQUALS( naturalSize, Vector2( imageSize.GetWidth(), imageSize.GetHeight() ), TEST_LOCATION );
+
+ actor = DummyControl::New(true);
+
+ DummyControlImpl& dummyImpl2 = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl2.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+ application.GetScene().Add( actor );
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger(1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ Renderer renderer = actor.GetRendererAt( 0 );
+ auto textures = renderer.GetTextures();
+
+ DALI_TEST_EQUALS( textures.GetTextureCount(), 1, TEST_LOCATION );
+ }
+
+ END_TEST;
+}
+
int UtcDaliNPatchVisualAuxiliaryImage01(void)
{
ToolkitTestApplication application;
Renderer renderer2 = imageView2.GetRendererAt( 0 );
auto textureSet2 = renderer2.GetTextures();
- DALI_TEST_EQUALS( textureSet1 == textureSet2, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( textureSet1 != textureSet2, true, TEST_LOCATION );
END_TEST;
}
return c;
}
-size_t TreeNode::Count(const std::string& childName) const
+size_t TreeNode::Count(std::string_view childName) const
{
const TreeNode* c = GetChild(childName);
if(c)
}
}
-const TreeNode* TreeNode::GetChild(const std::string& childName) const
+const TreeNode* TreeNode::GetChild(std::string_view childName) const
{
const TreeNode* p = mFirstChild;
while(p)
{
- if(p->mName && (std::string(p->mName) == childName))
+ if(p->mName && (std::string_view(p->mName) == childName))
{
return p;
}
return NULL;
}
-const TreeNode* TreeNode::GetChildIgnoreCase(const std::string& childName) const
+const TreeNode* TreeNode::GetChildIgnoreCase(std::string_view childName) const
{
const TreeNode* p = mFirstChild;
while(p)
return NULL;
}
-const TreeNode* TreeNode::Find(const std::string& childName) const
+const TreeNode* TreeNode::Find(std::string_view childName) const
{
- if(mName && std::string(mName) == childName)
+ if(mName && std::string_view(mName) == childName)
{
return this;
}
* @param childName The name of the child to find
* @return the number of children in the found child
*/
- size_t Count(const std::string& childName) const;
+ size_t Count(std::string_view childName) const;
/*
* Get the nodes name
* @param name The name of the child.
* @return The child if found, else NULL
*/
- const TreeNode* GetChild(const std::string& name) const;
+ const TreeNode* GetChild(std::string_view name) const;
/*
* Gets a child of the node (using case insensitive matching)
* @param name The name of the child in lower case
* @return The child if found, else NULL
*/
- const TreeNode* GetChildIgnoreCase(const std::string& name) const;
+ const TreeNode* GetChildIgnoreCase(std::string_view name) const;
/*
* Recursively search for a child of the node
* @param name The name of the child
* @return The child if found, else NULL
*/
- const TreeNode* Find(const std::string& name) const;
+ const TreeNode* Find(std::string_view name) const;
private:
friend class Internal::TreeNodeManipulator;
return controlDataImpl.VisualEventSignal();
}
+Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
+{
+ Internal::Control& internalControl = Toolkit::Internal::GetImplementation(control);
+ Internal::Control::Impl& controlDataImpl = Internal::Control::Impl::Get(internalControl);
+ return controlDataImpl.GetVisualProperty(index, visualPropertyKey);
+}
+
static Toolkit::Internal::Control::Impl *GetControlImplementationIfAny( Dali::Actor actor)
{
Dali::Toolkit::Control c = Toolkit::Control::DownCast( actor );
DALI_TOOLKIT_API VisualEventSignalType& VisualEventSignal(Control control);
/**
+ * @brief Retrieve the property object associated with the given property index and the visual property key.
+ *
+ * @param[in] control The control
+ * @param[in] index The Property index of the visual.
+ * @param[in] visualPropertyKey The key of the visual's property.
+ * @return The Property object
+ * @pre The control should be added to the Scene.
+ * @pre The returned object is valid for as long as the control is on the Scene.
+ */
+DALI_TOOLKIT_API Dali::Property GetVisualProperty(Control control, Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
+
+/**
* @brief The signal is emmited as a succession of "activate" signal send by accessibility client.
* @return The signal to connect to
*/
/**
* @brief The blur radius of the visual.
- * @details Name "blurRadius", type Property::FLOAT.
+ * @details Name "blurRadius", type Property::FLOAT, animatable.
* If the value is 0, the edge is sharp. Otherwise, the larger the value, the more the edge is blurred.
* @note Optional.
* @note The default is 0.
/**
* @brief The radius for the rounded corners of the visual
- * @details Name "cornerRadius", type Property::FLOAT.
+ * @details Name "cornerRadius", type Property::FLOAT, animatable
* @note Optional.
*/
CORNER_RADIUS = OPACITY + 2,
} // switch
} // DoWrite
-
-const TreeNode* FindIt(const std::string& childName, const TreeNode* node)
+const TreeNode* FindIt(std::string_view childName, const TreeNode* node)
{
DALI_ASSERT_DEBUG(node);
* @param tree The tree to search
* @return the TreeNode if found, else NULL
*/
-const TreeNode* FindIt(const std::string& childName, const TreeNode* tree);
+const TreeNode* FindIt(std::string_view childName, const TreeNode* tree);
/*
* Copy string to a buffer
}
}
-Toolkit::Visual::Type GetVisualTypeFromMap( const Property::Map& map )
+/**
+ * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
+ */
+bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
{
- Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE );
- Toolkit::Visual::Type type = Toolkit::Visual::IMAGE;
- if( typeValue )
+ for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
{
- Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type );
+ if ( (*iter)->index == targetIndex )
+ {
+ return true;
+ }
}
- return type;
+ return false;
}
/**
* Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
*/
-bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
+bool FindVisual( std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
{
for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
{
- if ( (*iter)->index == targetIndex )
+ Toolkit::Visual::Base visual = (*iter)->visual;
+ if( visual && visual.GetName() == visualName )
{
return true;
}
return visualHandle;
}
+Toolkit::Visual::Base GetVisualByIndex(
+ const RegisteredVisualContainer& visuals,
+ Property::Index index)
+{
+ Toolkit::Visual::Base visualHandle;
+
+ RegisteredVisualContainer::Iterator iter;
+ for(iter = visuals.Begin(); iter != visuals.End(); iter++)
+ {
+ if((*iter)->index == index)
+ {
+ visualHandle = (*iter)->visual;
+ break;
+ }
+ }
+ return visualHandle;
+}
+
/**
* Move visual from source to destination container
*/
const std::string& visualName = (*iter).key;
const Property::Map& toMap = (*iter).entry;
- // is it a candidate for re-creation?
- bool recreate = false;
-
- Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName );
- if( visual )
+ Actor self = mControlImpl.Self();
+ RegisteredVisualContainer::Iterator registeredVisualsiter;
+ // Check if visual (visualName) is already registered, this is the current visual.
+ if(FindVisual(visualName, mVisuals, registeredVisualsiter))
{
- Property::Map fromMap;
- visual.CreatePropertyMap( fromMap );
-
- Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
- Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
-
- if( fromType != toType )
+ Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
+ if(visual)
{
- recreate = true;
- }
- else
- {
- if( fromType == Toolkit::Visual::IMAGE || fromType == Toolkit::Visual::N_PATCH
- || fromType == Toolkit::Visual::SVG || fromType == Toolkit::Visual::ANIMATED_IMAGE )
- {
- Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
- Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
+ // No longer required to know if the replaced visual's resources are ready
+ StopObservingVisual(visual);
- if( fromUrl && toUrl )
+ // If control staged then visuals will be swapped once ready
+ if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ {
+ // Check if visual is currently in the process of being replaced ( is in removal container )
+ RegisteredVisualContainer::Iterator visualQueuedForRemoval;
+ if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
{
- std::string fromUrlString;
- std::string toUrlString;
- fromUrl->Get(fromUrlString);
- toUrl->Get(toUrlString);
-
- if( fromUrlString != toUrlString )
- {
- recreate = true;
- }
+ // Visual with same visual name is already in removal container so current visual pending
+ // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
+ Toolkit::GetImplementation(visual).SetOffScene(self);
+ (*registeredVisualsiter)->visual.Reset();
+ mVisuals.Erase(registeredVisualsiter);
+ }
+ else
+ {
+ // current visual not already in removal container so add now.
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
+ MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
}
}
+ else
+ {
+ // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
+ (*registeredVisualsiter)->visual.Reset();
+ mVisuals.Erase(registeredVisualsiter);
+ }
}
- const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
- if( recreate || instancedMap )
- {
- RemoveVisual( mVisuals, visualName );
- Style::ApplyVisual( handle, visualName, toMap, instancedMap );
- }
- else
- {
- // @todo check to see if we can apply toMap without recreating the visual
- // e.g. by setting only animatable properties
- // For now, recreate all visuals, but merge in instance data.
- RemoveVisual( mVisuals, visualName );
- Style::ApplyVisual( handle, visualName, toMap, instancedMap );
- }
+ const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
+ Style::ApplyVisual(handle, visualName, toMap, instancedMap);
}
}
}
mControlImpl.RelayoutRequest();
}
+Dali::Property Control::Impl::GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey)
+{
+ Toolkit::Visual::Base visual = GetVisualByIndex(mVisuals, index);
+ if(visual)
+ {
+ Internal::Visual::Base& visualImpl = Toolkit::GetImplementation(visual);
+ return visualImpl.GetPropertyObject(visualPropertyKey);
+ }
+
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
+}
+
void Control::Impl::EmitResourceReadySignal()
{
if(!mIsEmittingResourceReadySignal)
*/
void ClearShadow();
+ /**
+ * @copydoc DevelControl::GetVisualProperty()
+ */
+ Dali::Property GetVisualProperty(Dali::Property::Index index, Dali::Property::Key visualPropertyKey);
+
private:
/**
${toolkit_src_dir}/visuals/image-atlas-manager.cpp
${toolkit_src_dir}/visuals/image/image-visual.cpp
${toolkit_src_dir}/visuals/mesh/mesh-visual.cpp
+ ${toolkit_src_dir}/visuals/npatch-data.cpp
${toolkit_src_dir}/visuals/npatch-loader.cpp
${toolkit_src_dir}/visuals/npatch/npatch-visual.cpp
${toolkit_src_dir}/visuals/primitive/primitive-visual.cpp
mPixelArea( FULL_TEXTURE_RECT ),
mImageUrl(),
mAnimatedImageLoading(),
- mCurrentFrameIndex( 0 ),
+ mFrameIndexForJumpTo( 0 ),
mImageUrls( NULL ),
mImageCache( NULL ),
mCacheSize( 2 ),
else
{
mIsJumpTo = true;
- mCurrentFrameIndex = frameNumber;
+ mFrameIndexForJumpTo = frameNumber;
if( IsOnScene() )
{
DisplayNextFrame();
actor.RemoveRenderer( mImpl->mRenderer );
mImpl->mRenderer.Reset();
mPlacementActor.Reset();
+ mStartFirstFrame = false;
}
void AnimatedImageVisual::OnSetTransform()
{
mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea );
}
-
- mCurrentFrameIndex = 0;
}
void AnimatedImageVisual::LoadFirstBatch()
if(mImpl->mRenderer)
{
mImpl->mRenderer.SetTextures( textureSet );
- }
- Actor actor = mPlacementActor.GetHandle();
- if( actor )
- {
- actor.AddRenderer( mImpl->mRenderer );
- mPlacementActor.Reset();
- }
- mCurrentFrameIndex = 0;
+ Actor actor = mPlacementActor.GetHandle();
+ if( actor )
+ {
+ actor.AddRenderer( mImpl->mRenderer );
+ mPlacementActor.Reset();
+ }
+ }
if( mFrameCount > 1 )
{
- int frameDelay = mFrameDelay; // from URL array
- if( mAnimatedImageLoading && mImageCache )
+ int frameDelay = mImageCache->GetFrameInterval( 0 );
+ if( frameDelay == 0u )
{
- frameDelay = mImageCache->GetFrameInterval( 0 );
+ frameDelay = mFrameDelay; // from URL array
}
mFrameDelayTimer = Timer::New( frameDelay );
mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame );
{
textureSet = mImageCache->FirstFrame();
}
+
if( textureSet )
{
SetImageSize( textureSet );
}
- else
- {
- DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n" );
- ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
- }
return textureSet;
}
void AnimatedImageVisual::FrameReady( TextureSet textureSet )
{
- SetImageSize( textureSet );
-
- if( mStartFirstFrame )
+ if(textureSet)
{
- StartFirstFrame( textureSet );
+ SetImageSize(textureSet);
+
+ if(mStartFirstFrame)
+ {
+ StartFirstFrame(textureSet);
+ }
+ else
+ {
+ if(mImpl->mRenderer)
+ {
+ mImpl->mRenderer.SetTextures(textureSet);
+ }
+ }
}
else
{
- if( mImpl->mRenderer )
- {
- mImpl->mRenderer.SetTextures( textureSet );
- }
+ DALI_LOG_INFO( gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n" );
+ ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
}
}
bool AnimatedImageVisual::DisplayNextFrame()
{
- if( mIsJumpTo )
- {
- mIsJumpTo = false;
- }
- else if( mActionStatus == DevelAnimatedImageVisual::Action::PAUSE )
- {
- return false;
- }
- else if( mActionStatus == DevelAnimatedImageVisual::Action::STOP )
+ bool continueTimer = false;
+
+ if(mImageCache)
{
- mCurrentLoopIndex = 0;
- if( mStopBehavior == DevelImageVisual::StopBehavior::FIRST_FRAME )
+ bool nextFrame = false;
+ uint32_t frameIndex = mImageCache->GetCurrentFrameIndex();
+
+ if( mIsJumpTo )
{
- mCurrentFrameIndex = 0;
+ mIsJumpTo = false;
+ frameIndex = mFrameIndexForJumpTo;
}
- else if( mStopBehavior == DevelImageVisual::StopBehavior::LAST_FRAME )
+ else if( mActionStatus == DevelAnimatedImageVisual::Action::PAUSE )
{
- mCurrentFrameIndex = mFrameCount - 1;
+ return false;
}
- else
+ else if( mActionStatus == DevelAnimatedImageVisual::Action::STOP )
{
- return false; // Do not draw already rendered scene twice.
- }
- }
- else
- {
- if( mFrameCount > 1 )
- {
- // Wrap the frame index
- bool finished = false;
- ++mCurrentFrameIndex;
- if( mCurrentFrameIndex >= mFrameCount )
+ frameIndex = 0;
+ if( mStopBehavior == DevelImageVisual::StopBehavior::FIRST_FRAME )
{
- ++mCurrentLoopIndex;
- finished = true;
+ frameIndex = 0;
}
-
- if( mLoopCount < 0 || mCurrentLoopIndex < mLoopCount)
+ else if( mStopBehavior == DevelImageVisual::StopBehavior::LAST_FRAME )
{
- if( finished )
- {
- mCurrentFrameIndex = 0; // Back to the first frame
- }
+ frameIndex = mFrameCount - 1;
}
else
{
- // This will stop timer
- mActionStatus = DevelAnimatedImageVisual::Action::STOP;
- return DisplayNextFrame();
+ return false; // Do not draw already rendered scene twice.
}
}
- // TODO : newly added one.
- if( mAnimatedImageLoading && mImageCache )
+ else
{
- unsigned int delay = mImageCache->GetFrameInterval( mCurrentFrameIndex );
- if( mFrameDelayTimer.GetInterval() != delay )
+ if( mFrameCount > 1 )
{
- mFrameDelayTimer.SetInterval( delay );
+ nextFrame = true;
+ frameIndex++;
+ if( frameIndex >= mFrameCount )
+ {
+ frameIndex %= mFrameCount;
+ ++mCurrentLoopIndex;
+ }
+
+ if(mLoopCount >= 0 && mCurrentLoopIndex >= mLoopCount)
+ {
+ // This will stop timer
+ mActionStatus = DevelAnimatedImageVisual::Action::STOP;
+ return DisplayNextFrame();
+ }
+ }
+
+ unsigned int delay = mImageCache->GetFrameInterval( frameIndex );
+ if( delay > 0u )
+ {
+ if( mFrameDelayTimer.GetInterval() != delay )
+ {
+ mFrameDelayTimer.SetInterval( delay );
+ }
}
}
- }
- DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, mCurrentFrameIndex);
+ DALI_LOG_INFO( gAnimImgLogFilter,Debug::Concise,"AnimatedImageVisual::DisplayNextFrame(this:%p) CurrentFrameIndex:%d\n", this, frameIndex);
+
+ TextureSet textureSet;
+ if(nextFrame)
+ {
+ textureSet = mImageCache->NextFrame();
+ }
+ else
+ {
+ textureSet = mImageCache->Frame( frameIndex );
+ }
- TextureSet textureSet;
- if( mImageCache )
- {
- textureSet = mImageCache->Frame( mCurrentFrameIndex );
if( textureSet )
{
SetImageSize( textureSet );
- mImpl->mRenderer.SetTextures( textureSet );
+ if( mImpl->mRenderer )
+ {
+ mImpl->mRenderer.SetTextures( textureSet );
+ }
}
+
+ continueTimer = ( mActionStatus == DevelAnimatedImageVisual::Action::PLAY ) ? true : false;
}
- return ( mActionStatus == DevelAnimatedImageVisual::Action::PLAY ) ? true : false;
+ return continueTimer;
}
Vector4 mPixelArea;
VisualUrl mImageUrl;
Dali::AnimatedImageLoading mAnimatedImageLoading; // Only needed for animated image
- uint32_t mCurrentFrameIndex; // Frame index into textureRects
+ uint32_t mFrameIndexForJumpTo; // Frame index into textureRects
// Variables for Multi-Image player
ImageCache::UrlList* mImageUrls;
return textureSet;
}
-uint32_t FixedImageCache::GetFrameInterval( uint32_t frameIndex )
+TextureSet FixedImageCache::NextFrame()
+{
+ TextureSet textureSet = Frame((mFront + 1) % mImageUrls.size());
+
+ return textureSet;
+}
+
+uint32_t FixedImageCache::GetFrameInterval( uint32_t frameIndex ) const
{
return 0u;
}
+int32_t FixedImageCache::GetCurrentFrameIndex() const
+{
+ return static_cast<int32_t>(mFront);
+}
+
bool FixedImageCache::IsFrontReady() const
{
return ( mReadyFlags.size() > 0 && mReadyFlags[mFront] == true );
TextureSet FirstFrame() override;
/**
+ * Get the next frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet NextFrame() override;
+
+ /**
* Get the interval of Nth frame.
*/
- uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+ uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+ /**
+ * Get the current rendered frame index.
+ * If there isn't any loaded frame, returns -1.
+ */
+ int32_t GetCurrentFrameIndex() const override;
private:
/**
virtual TextureSet FirstFrame() = 0;
/**
+ * Get the next frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ virtual TextureSet NextFrame() = 0;
+
+ /**
* Get the Nth frame. If it's not ready, this will trigger the
* sending of FrameReady() when the image becomes ready.
*/
/**
* Get the interval of Nth frame.
*/
- virtual uint32_t GetFrameInterval( uint32_t frameIndex ) = 0;
+ virtual uint32_t GetFrameInterval( uint32_t frameIndex ) const = 0;
+
+ /**
+ * Get the current rendered frame index.
+ * If there isn't any loaded frame, returns -1.
+ */
+ virtual int32_t GetCurrentFrameIndex() const = 0;
private:
mAnimatedImageLoading( animatedImageLoading ),
mFrameCount( frameCount ),
mFrameIndex( 0 ),
+ mCacheSize( cacheSize ),
mQueue( cacheSize ),
mIsSynchronousLoading( isSynchronousLoading ),
mOnLoading( false )
// If the frame of frameIndex was already loaded, load batch from the last frame of queue
if( !mQueue.IsEmpty() )
{
- mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
+ if(!mLoadWaitingQueue.empty())
+ {
+ mFrameIndex = ( mLoadWaitingQueue.back() + 1 ) % mFrameCount;
+ }
+ else
+ {
+ mFrameIndex = ( mQueue.Back().mFrameNumber + 1 ) % mFrameCount;
+ }
}
else
{
+ mOnLoading = false;
// If the request is for the first frame or a jumped frame(JUMP_TO) remove current waiting queue.
mLoadWaitingQueue.clear();
// If the queue is empty, and the frame of frameIndex is not loaded synchronously. load batch from the frame of frameIndex
return Frame( 0u );
}
-uint32_t RollingAnimatedImageCache::GetFrameInterval( uint32_t frameIndex )
+TextureSet RollingAnimatedImageCache::NextFrame()
+{
+ TextureSet textureSet;
+ if(!mQueue.IsEmpty())
+ {
+ uint32_t frameIndex = mQueue.Front().mFrameNumber;
+ if(IsFrontReady())
+ {
+ frameIndex = (frameIndex + 1) % mFrameCount;
+ }
+ textureSet = Frame(frameIndex);
+ }
+ else
+ {
+ DALI_LOG_ERROR("Cache is empty.");
+ }
+
+ return textureSet;
+}
+
+uint32_t RollingAnimatedImageCache::GetFrameInterval( uint32_t frameIndex ) const
{
return mAnimatedImageLoading.GetFrameInterval( frameIndex );
}
+int32_t RollingAnimatedImageCache::GetCurrentFrameIndex() const
+{
+ if(mQueue.IsEmpty())
+ {
+ return -1;
+ }
+ return mQueue.Front().mFrameNumber;
+}
+
bool RollingAnimatedImageCache::IsFrontReady() const
{
return ( !mQueue.IsEmpty() && mQueue.Front().mReady );
void RollingAnimatedImageCache::RequestFrameLoading( uint32_t frameIndex )
{
+ ImageFrame imageFrame;
+ imageFrame.mFrameNumber = frameIndex;
+ imageFrame.mReady = false;
+
+ mQueue.PushBack(imageFrame);
+
mRequestingLoad = true;
bool synchronousLoading = false;
// removed, and another frame is loaded
bool frontFrameReady = IsFrontReady();
- for( unsigned int i=0; i< mBatchSize && !mQueue.IsFull(); ++i )
+ for( unsigned int i=0; i< mBatchSize && mQueue.Count() + mLoadWaitingQueue.size() < static_cast<uint32_t>(mCacheSize) && !mQueue.IsFull(); ++i )
{
- ImageFrame imageFrame;
- imageFrame.mFrameNumber = mFrameIndex;
- imageFrame.mReady = false;
-
- mQueue.PushBack( imageFrame );
-
if( !mOnLoading )
{
mOnLoading = true;
TextureSet FirstFrame() override;
/**
+ * Get the next frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet NextFrame() override;
+
+ /**
* Get the interval of Nth frame.
*/
- uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+ uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+ /**
+ * Get the current rendered frame index.
+ * If there isn't any loaded frame, returns -1.
+ */
+ int32_t GetCurrentFrameIndex() const override;
private:
/**
Dali::AnimatedImageLoading mAnimatedImageLoading;
uint32_t mFrameCount;
int mFrameIndex;
+ int mCacheSize;
std::vector<UrlStore> mImageUrls;
std::vector<int32_t> mIntervals;
std::vector<uint32_t> mLoadWaitingQueue;
return Frame( 0u );
}
-uint32_t RollingImageCache::GetFrameInterval( uint32_t frameIndex )
+TextureSet RollingImageCache::NextFrame()
+{
+ TextureSet textureSet;
+ if(!mQueue.IsEmpty())
+ {
+ uint32_t frameIndex = mQueue.Front().mUrlIndex;
+ if(IsFrontReady())
+ {
+ frameIndex = (frameIndex + 1) % mImageUrls.size();
+ }
+ textureSet = Frame(frameIndex);
+ }
+ else
+ {
+ DALI_LOG_ERROR("Cache is empty.");
+ }
+
+ return textureSet;
+}
+
+uint32_t RollingImageCache::GetFrameInterval( uint32_t frameIndex ) const
{
return 0u;
}
+int32_t RollingImageCache::GetCurrentFrameIndex() const
+{
+ if(mQueue.IsEmpty())
+ {
+ return -1;
+ }
+ return mQueue.Front().mUrlIndex;
+}
+
bool RollingImageCache::IsFrontReady() const
{
return ( !mQueue.IsEmpty() && mQueue.Front().mReady );
TextureSet FirstFrame() override;
/**
+ * Get the next frame. If it's not ready, this will trigger the
+ * sending of FrameReady() when the image becomes ready.
+ */
+ TextureSet NextFrame() override;
+
+ /**
* Get the interval of Nth frame.
*/
- uint32_t GetFrameInterval( uint32_t frameIndex ) override;
+ uint32_t GetFrameInterval( uint32_t frameIndex ) const override;
+
+ /**
+ * Get the current rendered frame index.
+ * If there isn't any loaded frame, returns -1.
+ */
+ int32_t GetCurrentFrameIndex() const override;
private:
/**
return colorVisualPtr;
}
-ColorVisual::ColorVisual( VisualFactoryCache& factoryCache )
-: Visual::Base( factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR ),
- mBlurRadius( 0.0f ),
- mRenderIfTransparent( false )
+ColorVisual::ColorVisual(VisualFactoryCache& factoryCache)
+: Visual::Base(factoryCache, Visual::FittingMode::FILL, Toolkit::Visual::COLOR),
+ mBlurRadius(0.0f),
+ mBlurRadiusIndex(Property::INVALID_INDEX),
+ mRenderIfTransparent(false),
+ mNeedBlurRadius(false)
{
}
ResourceReady( Toolkit::Visual::ResourceStatus::READY );
}
+void ColorVisual::DoSetOffScene(Actor& actor)
+{
+ if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX)
+ {
+ // Update values from Renderer
+ mBlurRadius = mImpl->mRenderer.GetProperty<float>(mBlurRadiusIndex);
+ }
+
+ actor.RemoveRenderer(mImpl->mRenderer);
+ mImpl->mRenderer.Reset();
+ mBlurRadiusIndex = Property::INVALID_INDEX;
+}
+
void ColorVisual::DoCreatePropertyMap( Property::Map& map ) const
{
map.Clear();
map.Insert( Toolkit::Visual::Property::TYPE, Toolkit::Visual::COLOR );
map.Insert( Toolkit::ColorVisual::Property::MIX_COLOR, mImpl->mMixColor );
map.Insert( Toolkit::DevelColorVisual::Property::RENDER_IF_TRANSPARENT, mRenderIfTransparent );
- map.Insert( Toolkit::DevelColorVisual::Property::BLUR_RADIUS, mBlurRadius );
+
+ if(mImpl->mRenderer && mBlurRadiusIndex != Property::INVALID_INDEX)
+ {
+ // Update values from Renderer
+ float blurRadius = mImpl->mRenderer.GetProperty<float>(mBlurRadiusIndex);
+ map.Insert(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, blurRadius);
+ }
+ else
+ {
+ map.Insert(Toolkit::DevelColorVisual::Property::BLUR_RADIUS, mBlurRadius);
+ }
}
void ColorVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
// Do nothing
}
-
void ColorVisual::OnSetTransform()
{
if( mImpl->mRenderer )
}
}
+void ColorVisual::UpdateShader()
+{
+ if(mImpl->mRenderer)
+ {
+ Shader shader = GetShader();
+ mImpl->mRenderer.SetShader(shader);
+ }
+}
+
void ColorVisual::InitializeRenderer()
{
Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
+ Shader shader = GetShader();
+
+ mImpl->mRenderer = Renderer::New(geometry, shader);
+
+ // ColorVisual has it's own index key for mix color - use this instead
+ // of using the new base index to avoid changing existing applications
+ // String keys will get to this property.
+ mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty(Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR, Vector3(mImpl->mMixColor));
+
+ if(!EqualsZero(mBlurRadius))
+ {
+ mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+ }
+
+ // Register transform properties
+ mImpl->mTransform.RegisterUniforms(mImpl->mRenderer, Direction::LEFT_TO_RIGHT);
+}
+
+Shader ColorVisual::GetShader()
+{
Shader shader;
- if( !EqualsZero( mBlurRadius ) )
+ if(!EqualsZero(mBlurRadius) || mNeedBlurRadius)
{
shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER_BLUR_EDGE );
if( !shader )
}
}
- mImpl->mRenderer = Renderer::New( geometry, shader );
-
- // ColorVisual has it's own index key for mix color - use this instead
- // of using the new base index to avoid changing existing applications
- // String keys will get to this property.
- mImpl->mMixColorIndex = mImpl->mRenderer.RegisterProperty( Toolkit::ColorVisual::Property::MIX_COLOR, MIX_COLOR, Vector3(mImpl->mMixColor) );
+ return shader;
+}
- mImpl->mRenderer.RegisterProperty( BLUR_RADIUS_NAME, mBlurRadius );
+Dali::Property ColorVisual::OnGetPropertyObject(Dali::Property::Key key)
+{
+ if(!mImpl->mRenderer)
+ {
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
+ }
- if( !EqualsZero( mBlurRadius ) )
+ if((key.type == Property::Key::INDEX && key.indexKey == DevelColorVisual::Property::BLUR_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == BLUR_RADIUS_NAME))
{
- mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
+ mBlurRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelColorVisual::Property::BLUR_RADIUS, BLUR_RADIUS_NAME, mBlurRadius);
+
+ mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON);
+
+ mNeedBlurRadius = true;
+
+ // Change shader
+ UpdateShader();
+
+ return Dali::Property(mImpl->mRenderer, mBlurRadiusIndex);
}
- // Register transform properties
- mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
}
} // namespace Internal
void DoSetOnScene( Actor& actor ) override;
/**
+ * @copydoc Visual::Base::DoSetOffScene
+ */
+ void DoSetOffScene(Actor& actor) override;
+
+ /**
* @copydoc Visual::Base::OnSetTransform
*/
void OnSetTransform() override;
*/
void OnDoAction( const Property::Index actionId, const Property::Value& attributes ) override;
+ /**
+ * @copydoc Visual::Base::UpdateShader
+ */
+ void UpdateShader() override;
+
+ /**
+ * @copydoc Visual::Base::OnGetPropertyObject
+ */
+ Dali::Property OnGetPropertyObject(Dali::Property::Key key) override;
+
private:
/**
* @brief Initialize the renderer with the geometry and shader from the cache, if not available, create and save to the cache for sharing.
*/
void InitializeRenderer();
+ /**
+ * @brief Get a shader for the current properties.
+ * @return The shader for the current properties.
+ */
+ Shader GetShader();
+
private:
// Undefined
ColorVisual& operator=( const ColorVisual& colorRenderer );
private:
-
- float mBlurRadius; ///< The blur radius
- bool mRenderIfTransparent; ///< Whether we should render even if the mix-color is transparent.
+ float mBlurRadius; ///< The blur radius
+ Property::Index mBlurRadiusIndex; ///< The blur radius property index
+ bool mRenderIfTransparent; ///< Whether we should render even if the mix-color is transparent.
+ bool mNeedBlurRadius; ///< Whether we need the blur radius in shader.
};
} // namespace Internal
ResourceReady( Toolkit::Visual::ResourceStatus::READY );
}
+void GradientVisual::UpdateShader()
+{
+ if(mImpl->mRenderer)
+ {
+ Shader shader = GetShader();
+ mImpl->mRenderer.SetShader(shader);
+ }
+}
+
void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const
{
map.Clear();
void GradientVisual::InitializeRenderer()
{
Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
-
- 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 );
- if( !shader )
- {
- shader = Shader::New( VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[ mGradientType + roundedCorner * 2 ] );
- mFactoryCache.SaveShader( shaderType, shader );
- }
+ Shader shader = GetShader();
//Set up the texture set
TextureSet textureSet = TextureSet::New();
return true;
}
+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);
+ if(!shader)
+ {
+ shader = Shader::New(VERTEX_SHADER[gradientUnits + roundedCorner * 2], FRAGMENT_SHADER[mGradientType + roundedCorner * 2]);
+ mFactoryCache.SaveShader(shaderType, shader);
+ }
+
+ return shader;
+}
+
void GradientVisual::GetStopOffsets(const Property::Value* value, Vector<float>& stopOffsets)
{
*/
void DoSetOnScene( Actor& actor ) override;
+ /**
+ * @copydoc Visual::Base::UpdateShader
+ */
+ void UpdateShader() override;
+
private:
/**
bool NewGradient(Type gradientType, const Property::Map& propertyMap);
/**
+ * @brief Get a shader for the current properties.
+ * @return The shader for the current properties.
+ */
+ Shader GetShader();
+
+ /**
* Get the stop-offsets from the property.
* The valid property type are ARRAY, VECTOR2, VECTOR3, VECTOR4.
*
void ImageVisual::CreateRenderer( TextureSet& textureSet )
{
Geometry geometry;
- Shader shader;
// Get the geometry
if( mImpl->mCustomShader )
}
}
- std::string vertexShader;
- bool usesWholeTexture = true;
- if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty())
- {
- vertexShader = mImpl->mCustomShader->mVertexShader;
- usesWholeTexture = false; // Impossible to tell.
- }
- else
- {
- vertexShader = mImageVisualShaderFactory.GetVertexShaderSource().data();
- }
-
- std::string fragmentShader;
- if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty())
- {
- fragmentShader = mImpl->mCustomShader->mFragmentShader;
- }
- else
- {
- fragmentShader = mImageVisualShaderFactory.GetFragmentShaderSource().data();
- }
-
- // If the texture is native, we may need to change prefix and sampler in
- // the fragment shader
- bool modifiedFragmentShader = false;
- if(mTextures && DevelTexture::IsNative(mTextures.GetTexture(0)))
- {
- Texture nativeTexture = mTextures.GetTexture(0);
- modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShader);
- }
-
- const bool useStandardShader = !mImpl->mCustomShader && !modifiedFragmentShader;
- if(useStandardShader)
- {
- // 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() );
- }
- else if(mImpl->mCustomShader)
- {
- shader = Shader::New(vertexShader, fragmentShader, mImpl->mCustomShader->mHints);
- }
- else
- {
- shader = Shader::New(vertexShader, fragmentShader);
- }
-
- if(usesWholeTexture)
- {
- shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
- }
-
- // Set pixel align off as default.
- // ToDo: Pixel align causes issues such as rattling image animation.
- // We should trun it off until issues are resolved
- shader.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF );
+ Shader shader = GetShader();
// Create the renderer
mImpl->mRenderer = Renderer::New( geometry, shader );
mImpl->mResourceStatus == Toolkit::Visual::ResourceStatus::FAILED );
}
+void ImageVisual::UpdateShader()
+{
+ if(mImpl->mRenderer)
+ {
+ Shader shader = GetShader();
+ mImpl->mRenderer.SetShader(shader);
+ }
+}
+
// From existing atlas manager
void ImageVisual::UploadCompleted()
{
}
}
+Shader ImageVisual::GetShader()
+{
+ Shader shader;
+
+ std::string_view vertexShaderView;
+ bool usesWholeTexture = true;
+ if(mImpl->mCustomShader && !mImpl->mCustomShader->mVertexShader.empty())
+ {
+ vertexShaderView = mImpl->mCustomShader->mVertexShader;
+ usesWholeTexture = false; // Impossible to tell.
+ }
+ else
+ {
+ vertexShaderView = mImageVisualShaderFactory.GetVertexShaderSource();
+ }
+
+ std::string_view fragmentShaderView;
+ if(mImpl->mCustomShader && !mImpl->mCustomShader->mFragmentShader.empty())
+ {
+ fragmentShaderView = mImpl->mCustomShader->mFragmentShader;
+ }
+ else
+ {
+ fragmentShaderView = mImageVisualShaderFactory.GetFragmentShaderSource();
+ }
+
+ // If the texture is native, we may need to change prefix and sampler in
+ // the fragment shader
+ bool modifiedFragmentShader = false;
+ std::string fragmentShaderString;
+ if(mTextures && DevelTexture::IsNative(mTextures.GetTexture(0)))
+ {
+ Texture nativeTexture = mTextures.GetTexture(0);
+ fragmentShaderString = std::string(fragmentShaderView);
+ modifiedFragmentShader = DevelTexture::ApplyNativeFragmentShader(nativeTexture, fragmentShaderString);
+ fragmentShaderView = fragmentShaderString;
+ }
+
+ const bool useStandardShader = !mImpl->mCustomShader && !modifiedFragmentShader;
+ if(useStandardShader)
+ {
+ // 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() );
+ }
+ else if(mImpl->mCustomShader)
+ {
+ shader = Shader::New(vertexShaderView, fragmentShaderView, mImpl->mCustomShader->mHints);
+ }
+ else
+ {
+ shader = Shader::New(vertexShaderView, fragmentShaderView);
+ }
+
+ if(usesWholeTexture)
+ {
+ shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
+ }
+
+ // Set pixel align off as default.
+ // ToDo: Pixel align causes issues such as rattling image animation.
+ // We should trun it off until issues are resolved
+ shader.RegisterProperty( PIXEL_ALIGNED_UNIFORM_NAME, PIXEL_ALIGN_OFF );
+
+ return shader;
+}
+
} // namespace Internal
} // namespace Toolkit
*/
bool IsResourceReady() const override;
+ /**
+ * @copydoc Visual::Base::UpdateShader
+ */
+ void UpdateShader() override;
+
public:
/**
*/
void DoSetProperty( Property::Index index, const Property::Value& value );
+ /**
+ * @brief Get a shader for the current properties.
+ * @return The shader for the current properties.
+ */
+ Shader GetShader();
+
private:
Vector4 mPixelArea;
--- /dev/null
+ /*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/npatch-data.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/visuals/rendering-addon.h>
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+NPatchData::NPatchData()
+: mId(INVALID_NPATCH_DATA_ID),
+ mUrl(),
+ mTextureSet(),
+ mHash(0),
+ mCroppedWidth(0),
+ mCroppedHeight(0),
+ mBorder(0, 0, 0, 0),
+ mLoadingState(LoadingState::LOADING),
+ mPreMultiplyOnLoad(false),
+ mRenderingMap{nullptr}
+{
+}
+
+NPatchData::~NPatchData()
+{
+ // If there is an opacity map, it has to be destroyed using addon call
+ if( mRenderingMap )
+ {
+ RenderingAddOn::Get().DestroyNPatch( mRenderingMap );
+ }
+}
+
+void NPatchData::SetId(const NPatchDataId id)
+{
+ mId = id;
+}
+
+NPatchData::NPatchDataId NPatchData::GetId() const
+{
+ return mId;
+}
+
+void NPatchData::AddObserver(TextureUploadObserver* textureObserver)
+{
+ mObserverList.PushBack( textureObserver );
+}
+
+void NPatchData::RemoveObserver(TextureUploadObserver* textureObserver)
+{
+ for(uint32_t index = 0; index < mObserverList.Count(); ++index )
+ {
+ if(textureObserver == mObserverList[index])
+ {
+ mObserverList.Erase( mObserverList.begin() + index );
+ break;
+ }
+ }
+}
+
+uint32_t NPatchData::GetObserverCount() const
+{
+ return mObserverList.Count();
+}
+
+void NPatchData::SetUrl(const std::string url)
+{
+ mUrl = url;
+}
+
+std::string NPatchData::GetUrl() const
+{
+ return mUrl;
+}
+
+void NPatchData::SetTextures(const TextureSet textureSet)
+{
+ mTextureSet = textureSet;
+}
+
+TextureSet NPatchData::GetTextures() const
+{
+ return mTextureSet;
+}
+
+void NPatchData::SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX)
+{
+ mStretchPixelsX = stretchPixelsX;
+}
+
+void NPatchData::SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY)
+{
+ mStretchPixelsY = stretchPixelsY;
+}
+
+NPatchUtility::StretchRanges NPatchData::GetStretchPixelsX() const
+{
+ return mStretchPixelsX;
+}
+
+NPatchUtility::StretchRanges NPatchData::GetStretchPixelsY() const
+{
+ return mStretchPixelsY;
+}
+
+void NPatchData::SetHash(std::size_t hash)
+{
+ mHash = hash;
+}
+
+std::size_t NPatchData::GetHash() const
+{
+ return mHash;
+}
+
+void NPatchData::SetCroppedWidth(uint32_t croppedWidth)
+{
+ mCroppedWidth = croppedWidth;
+}
+
+void NPatchData::SetCroppedHeight(uint32_t croppedHeight)
+{
+ mCroppedHeight = croppedHeight;
+}
+
+uint32_t NPatchData::GetCroppedWidth() const
+{
+ return mCroppedWidth;
+}
+
+uint32_t NPatchData::GetCroppedHeight() const
+{
+ return mCroppedHeight;
+}
+
+void NPatchData::SetBorder(const Rect<int> border)
+{
+ mBorder = border;
+}
+
+Rect<int> NPatchData::GetBorder() const
+{
+ return mBorder;
+}
+
+void NPatchData::SetPreMultiplyOnLoad(bool preMultiplyOnLoad)
+{
+ mPreMultiplyOnLoad = preMultiplyOnLoad;
+}
+
+bool NPatchData::IsPreMultiplied() const
+{
+ return mPreMultiplyOnLoad;
+}
+
+void NPatchData::SetLoadingState(const LoadingState loadingState)
+{
+ mLoadingState = loadingState;
+}
+
+NPatchData::LoadingState NPatchData::GetLoadingState() const
+{
+ return mLoadingState;
+}
+
+void* NPatchData::GetRenderingMap() const
+{
+ return mRenderingMap;
+}
+
+void NPatchData::SetLoadedNPatchData( Devel::PixelBuffer& pixelBuffer, bool preMultiplied )
+{
+ if( mBorder == Rect< int >( 0, 0, 0, 0 ) )
+ {
+ NPatchUtility::ParseBorders( pixelBuffer, mStretchPixelsX, mStretchPixelsY );
+
+ // Crop the image
+ pixelBuffer.Crop( 1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2 );
+ }
+ else
+ {
+ mStretchPixelsX.PushBack( Uint16Pair( mBorder.left, ( (pixelBuffer.GetWidth() >= static_cast< unsigned int >( mBorder.right )) ? pixelBuffer.GetWidth() - mBorder.right : 0 ) ) );
+ mStretchPixelsY.PushBack( Uint16Pair( mBorder.top, ( (pixelBuffer.GetHeight() >= static_cast< unsigned int >( mBorder.bottom )) ? pixelBuffer.GetHeight() - mBorder.bottom : 0 ) ) );
+ }
+
+ mCroppedWidth = pixelBuffer.GetWidth();
+ mCroppedHeight = pixelBuffer.GetHeight();
+
+ // Create opacity map
+ mRenderingMap = RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().BuildNPatch(pixelBuffer, this) : nullptr;
+
+ PixelData pixels = Devel::PixelBuffer::Convert( pixelBuffer ); // takes ownership of buffer
+
+ Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
+ texture.Upload( pixels );
+
+ mTextureSet = TextureSet::New();
+ mTextureSet.SetTexture( 0u, texture );
+
+ mPreMultiplyOnLoad = preMultiplied;
+
+ mLoadingState = LoadingState::LOAD_COMPLETE;
+}
+
+void NPatchData::LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied )
+{
+ if(loadSuccess)
+ {
+ SetLoadedNPatchData( pixelBuffer, preMultiplied );
+ }
+ else
+ {
+ mLoadingState = LoadingState::LOAD_FAILED;
+ }
+
+ for(uint32_t index = 0; index < mObserverList.Count(); ++index)
+ {
+ TextureUploadObserver* observer = mObserverList[index];
+ observer->UploadComplete(loadSuccess, TextureManager::INVALID_TEXTURE_ID, mTextureSet, false, Vector4(), preMultiplied);
+ }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_NPATCH_DATA_H
+#define DALI_TOOLKIT_NPATCH_DATA_H
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <dali/public-api/rendering/texture-set.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class NPatchData : public Dali::Toolkit::TextureUploadObserver
+{
+public:
+ typedef int32_t NPatchDataId; ///< The NPatchDataId type. This is used as a handle to refer to a particular Npatch Data.
+ static const int INVALID_NPATCH_DATA_ID = -1; ///< Used to represent a null TextureId or error
+
+ /**
+ * @brief Loading State of the NPatch image.
+ */
+ enum class LoadingState
+ {
+ LOADING = 0, ///< NPatch is on loading.
+ LOAD_COMPLETE, ///< NPatch loading is completed successfully.
+ LOAD_FAILED ///< NPatch loading is failed.
+ };
+
+public:
+
+ /**
+ * Constructor
+ */
+ NPatchData();
+
+ /**
+ * Destructor, non-virtual as not a base class
+ */
+ ~NPatchData();
+
+public:
+
+ /**
+ * @brief Set cache data id.
+ *
+ * @param [in] id cache data id
+ */
+ void SetId(const NPatchDataId id);
+
+ /**
+ * @brief Retrieve cache data id
+ *
+ * @return cache data id.
+ */
+ NPatchDataId GetId() const;
+
+ /**
+ * @brief Add TextureUploadObserver that uses the image of this cache data.
+ *
+ * @param [in] textureObserver the TextureUploadObserver that uses the image of this cache data.
+ */
+ void AddObserver(TextureUploadObserver* textureObserver);
+
+ /**
+ * @brief Remove TextureUploadObserver.
+ *
+ * @param [in] textureObserver the TextureUploadObserver that will be removed in this cache data.
+ */
+ void RemoveObserver(TextureUploadObserver* textureObserver);
+
+ /**
+ * @brief Retrieve the number of observer.
+ *
+ * @return Return the number of observer.
+ */
+ uint32_t GetObserverCount() const;
+
+ /**
+ * @brief Set NPatch image url.
+ *
+ * @param [in] url NPatch image url
+ */
+ void SetUrl(const std::string url);
+
+ /**
+ * @brief Retrieve the image url.
+ *
+ * @return Return the image url.
+ */
+ std::string GetUrl() const;
+
+ /**
+ * @brief Set texture set on the cache data
+ *
+ * @param [in] textureSet loaded texture set
+ */
+ void SetTextures(const TextureSet textureSet);
+
+ /**
+ * @brief Retrieve loaded texture set.
+ *
+ * @return Return loaded texture set.
+ */
+ TextureSet GetTextures() const;
+
+ /**
+ * @brief Set X directional stretchPixels
+ *
+ * @param [in] stretchPixelsX stretchPixels for X direction
+ */
+ void SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX);
+
+ /**
+ * @brief Set Y directional stretchPixels
+ *
+ * @param [in] stretchPixelsY stretchPixels for Y direction
+ */
+ void SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY);
+
+ /**
+ * @brief Retrieve stretchPixels for X direction.
+ *
+ * @return Return stretchPixels for X direction.
+ */
+ NPatchUtility::StretchRanges GetStretchPixelsX() const;
+
+ /**
+ * @brief Retrieve stretchPixels for Y direction.
+ *
+ * @return Return stretchPixels for Y direction.
+ */
+ NPatchUtility::StretchRanges GetStretchPixelsY() const;
+
+ /**
+ * @brief Set cache data hash.
+ *
+ * @param [in] hash cache hash
+ */
+ void SetHash(std::size_t hash);
+
+ /**
+ * @brief Retrieve hash value of the cache.
+ *
+ * @return Return hash value of the cache.
+ */
+ std::size_t GetHash() const;
+
+ /**
+ * @brief Set croppedWidth of NPatch
+ *
+ * @param [in] croppedWidth croppedWidth of NPatch
+ */
+ void SetCroppedWidth(uint32_t croppedWidth);
+
+ /**
+ * @brief Set croppedHeight of NPatch
+ *
+ * @param [in] croppedHeight croppedHeight of NPatch
+ */
+ void SetCroppedHeight(uint32_t croppedHeight);
+
+ /**
+ * @brief Retrieve croppedWidth of NPatch.
+ *
+ * @return Return croppedWidth of NPatch.
+ */
+ uint32_t GetCroppedWidth() const;
+
+ /**
+ * @brief Retrieve croppedHeight of NPatch.
+ *
+ * @return Return croppedHeight of NPatch.
+ */
+ uint32_t GetCroppedHeight() const;
+
+ /**
+ * @brief Set border of NPatch.
+ *
+ * @param [in] border border of NPatch
+ */
+ void SetBorder(const Rect<int> border);
+
+ /**
+ * @brief Retrieve border of NPatch.
+ *
+ * @return Return border of NPatch.
+ */
+ Rect<int> GetBorder() const;
+
+ /**
+ * @brief Set whether the loaded image is premultiplied or not
+ *
+ * @param [in] preMultiplyOnLoad whether the loaded image is premultiplied or not
+ */
+ void SetPreMultiplyOnLoad(bool preMultiplyOnLoad);
+
+ /**
+ * @brief Retrieve whether the loaded image is premultiplied or not.
+ *
+ * @return Return true if the image is premultiplied alpha.
+ */
+ bool IsPreMultiplied() const;
+
+ /**
+ * @brief Set current loading state.
+ *
+ * @param [in] loadingState current loading state
+ */
+ void SetLoadingState(const LoadingState loadingState);
+
+ /**
+ * @brief Retrieve current loading state.
+ *
+ * @return Return current loading state.
+ */
+ LoadingState GetLoadingState() const;
+
+
+ /**
+ * @brief Retrieve NPatch rendering data.
+ *
+ * @return Return NPatch rendering data.
+ */
+ void* GetRenderingMap() const;
+
+ /**
+ * @brief Set loaded pixel buffer for the cache data.
+ *
+ * @param [in] pixelBuffer loaded pixel buffer.
+ * @param [in] preMultiplied whether the loaded image is premultiplied or not
+ */
+ void SetLoadedNPatchData( Devel::PixelBuffer& pixelBuffer, bool preMultiplied );
+
+private:
+
+ /**
+ * @copydoc TextureUploadObserver::UploadCompleted
+ *
+ * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
+ * This callback is the place to add the renderer as it would be called once the loading is finished.
+ */
+ void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override {}
+
+ /**
+ * @copydoc TextureUploadObserver::LoadComplete
+ *
+ * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
+ * This callback is the place to add the renderer as it would be called once the loading is finished.
+ */
+ void LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied ) override;
+
+
+private:
+
+ using ObserverListType = Dali::Vector<TextureUploadObserver*>;
+
+ NPatchDataId mId;
+ ObserverListType mObserverList; ///< Container used to store all observer clients of this Texture
+ std::string mUrl; ///< Url of the N-Patch
+ TextureSet mTextureSet; ///< Texture containing the cropped image
+ NPatchUtility::StretchRanges mStretchPixelsX; ///< X stretch pixels
+ NPatchUtility::StretchRanges mStretchPixelsY; ///< Y stretch pixels
+ std::size_t mHash; ///< Hash code for the Url
+ uint32_t mCroppedWidth; ///< Width of the cropped middle part of N-patch
+ uint32_t mCroppedHeight; ///< Height of the cropped middle part of N-patch
+ Rect<int> mBorder; ///< The size of the border
+ LoadingState mLoadingState; ///< True if the data loading is completed
+ bool mPreMultiplyOnLoad; ///< Whether to multiply alpha into color channels on load
+ void* mRenderingMap; ///< NPatch rendering data
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_NPATCH_DATA_H
namespace Internal
{
-namespace NPatchBuffer
+namespace
{
-void SetLoadedNPatchData( NPatchLoader::Data* data, Devel::PixelBuffer& pixelBuffer )
-{
- if( data->border == Rect< int >( 0, 0, 0, 0 ) )
- {
- NPatchUtility::ParseBorders( pixelBuffer, data->stretchPixelsX, data->stretchPixelsY );
-
- // Crop the image
- pixelBuffer.Crop( 1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2 );
- }
- else
- {
- data->stretchPixelsX.PushBack( Uint16Pair( data->border.left, ( (pixelBuffer.GetWidth() >= static_cast< unsigned int >( data->border.right )) ? pixelBuffer.GetWidth() - data->border.right : 0 ) ) );
- data->stretchPixelsY.PushBack( Uint16Pair( data->border.top, ( (pixelBuffer.GetHeight() >= static_cast< unsigned int >( data->border.bottom )) ? pixelBuffer.GetHeight() - data->border.bottom : 0 ) ) );
- }
-
- data->croppedWidth = pixelBuffer.GetWidth();
- data->croppedHeight = pixelBuffer.GetHeight();
-
- // Create opacity map
- data->renderingMap = RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().BuildNPatch(pixelBuffer, data ) : nullptr;
-
- PixelData pixels = Devel::PixelBuffer::Convert( pixelBuffer ); // takes ownership of buffer
-
- Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
- texture.Upload( pixels );
+constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
+constexpr auto UNINITIALIZED_ID = int32_t{0}; ///< uninitialised id, use to initialize ids
- data->textureSet = TextureSet::New();
- data->textureSet.SetTexture( 0u, texture );
+} // Anonymous namespace
- data->loadCompleted = true;
-}
-
-} // namespace NPatchBuffer
-
-NPatchLoader::Data::~Data()
+NPatchLoader::NPatchLoader()
+: mCurrentNPatchDataId(0)
{
- // If there is an opacity map, it has to be destroyed using addon call
- if( renderingMap )
- {
- RenderingAddOn::Get().DestroyNPatch( renderingMap );
- }
}
-NPatchLoader::NPatchLoader()
+NPatchLoader::~NPatchLoader()
{
}
-NPatchLoader::~NPatchLoader()
+NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
{
+ return mCurrentNPatchDataId++;
}
std::size_t NPatchLoader::Load( TextureManager& textureManager, TextureUploadObserver* textureObserver, const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad, bool synchronousLoading )
{
std::size_t hash = CalculateHash( url );
- OwnerContainer< Data* >::SizeType index = UNINITIALIZED_ID;
- const OwnerContainer< Data* >::SizeType count = mCache.Count();
- int cachedIndex = -1;
- Data* data;
+ OwnerContainer< NPatchData* >::SizeType index = UNINITIALIZED_ID;
+ const OwnerContainer< NPatchData* >::SizeType count = mCache.Count();
for( ; index < count; ++index )
{
- if( mCache[ index ]->hash == hash )
+ if( mCache[ index ]->GetHash() == hash )
{
// hash match, check url as well in case of hash collision
- if( mCache[ index ]->url == url )
+ if(mCache[ index ]->GetUrl() == url)
{
// Use cached data
- if( mCache[ index ]->border == border )
+ if( mCache[ index ]->GetBorder() == border )
{
- if( mCache[ index ]->loadCompleted )
+ if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOADING )
{
- return index + 1u; // valid indices are from 1 onwards
+ mCache[ index ]->AddObserver( textureObserver );
}
- mCache[ index ]->observerList.PushBack( textureObserver );
- data = mCache[ index ];
- return index + 1u; // valid indices are from 1 onwards
+ return mCache[ index ]->GetId(); // valid indices are from 1 onwards
}
else
{
- if( mCache[ index ]->loadCompleted )
+ if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
// Same url but border is different - use the existing texture
- Data* data = new Data();
- data->hash = hash;
- data->url = url;
- data->croppedWidth = mCache[ index ]->croppedWidth;
- data->croppedHeight = mCache[ index ]->croppedHeight;
+ NPatchData* newData = new NPatchData();
+ newData->SetId(GenerateUniqueNPatchDataId());
+ newData->SetHash(hash);
+ newData->SetUrl(url);
+ newData->SetCroppedWidth(mCache[ index ]->GetCroppedWidth());
+ newData->SetCroppedHeight(mCache[ index ]->GetCroppedHeight());
- data->textureSet = mCache[ index ]->textureSet;
+ newData->SetTextures(mCache[ index ]->GetTextures());
NPatchUtility::StretchRanges stretchRangesX;
- stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) );
+ stretchRangesX.PushBack( Uint16Pair( border.left, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.right )) ? newData->GetCroppedHeight() - border.right : 0 ) ) );
NPatchUtility::StretchRanges stretchRangesY;
- stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) );
+ stretchRangesY.PushBack( Uint16Pair( border.top, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.bottom )) ? newData->GetCroppedHeight() - border.bottom : 0 ) ) );
+
+ newData->SetStretchPixelsX(stretchRangesX);
+ newData->SetStretchPixelsY(stretchRangesY);
+ newData->SetBorder(border);
- data->stretchPixelsX = stretchRangesX;
- data->stretchPixelsY = stretchRangesY;
- data->border = border;
+ newData->SetPreMultiplyOnLoad(mCache[ index ]->IsPreMultiplied());
- data->loadCompleted = mCache[ index ]->loadCompleted;
+ newData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
+ newData->AddObserver( textureObserver );
- mCache.PushBack( data );
+ mCache.PushBack( newData );
- return mCache.Count(); // valid ids start from 1u
+ return newData->GetId(); // valid ids start from 1u
}
}
}
}
}
- if( cachedIndex == -1 )
- {
- data = new Data();
- data->loadCompleted = false;
- data->hash = hash;
- data->url = url;
- data->border = border;
-
- mCache.PushBack( data );
-
- cachedIndex = mCache.Count();
- }
+ // If this is new image loading, make new cache data
+ NPatchData* data;
+ data = new NPatchData();
+ data->SetId(GenerateUniqueNPatchDataId());
+ data->SetHash(hash);
+ data->SetUrl(url);
+ data->SetBorder(border);
+ data->SetPreMultiplyOnLoad(preMultiplyOnLoad);
+ data->AddObserver(textureObserver);
+ mCache.PushBack(data);
auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
: TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer( url, Dali::ImageDimensions(), FittingMode::DEFAULT,
SamplingMode::BOX_THEN_LINEAR, synchronousLoading,
- textureObserver, true, preMultiplyOnLoading );
+ data, true, preMultiplyOnLoading );
if( pixelBuffer )
{
- NPatchBuffer::SetLoadedNPatchData( data, pixelBuffer );
preMultiplyOnLoad = ( preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ) ? true : false;
+ data->SetLoadedNPatchData( pixelBuffer, preMultiplyOnLoad );
}
- return cachedIndex;
+ return data->GetId();
}
-void NPatchLoader::SetNPatchData( bool loadSuccess, std::size_t id, Devel::PixelBuffer& pixelBuffer, const Internal::VisualUrl& url, bool preMultiplied )
+int32_t NPatchLoader::GetCacheIndexFromId( const NPatchData::NPatchDataId id )
{
- Data* data;
- data = mCache[ id - 1u ];
+ const unsigned int size = mCache.Count();
- // To prevent recursion.
- // data->loadCompleted will be set true in the NPatchBuffer::SetLoadedNPatchData when the first observer called this method.
- if( data->loadCompleted )
+ for( unsigned int i = 0; i < size; ++i )
{
- return;
+ if( mCache[i]->GetId() == id )
+ {
+ return i;
+ }
}
- NPatchBuffer::SetLoadedNPatchData( data, pixelBuffer );
+ return INVALID_CACHE_INDEX;
+}
- while( data->observerList.Count() )
+bool NPatchLoader::GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data )
+{
+ int32_t cacheIndex = GetCacheIndexFromId(id);
+ if( cacheIndex != INVALID_CACHE_INDEX )
{
- TextureUploadObserver* observer = data->observerList[0];
- observer->LoadComplete( loadSuccess, Devel::PixelBuffer(), url, preMultiplied );
- data->observerList.Erase( data->observerList.begin() );
+ data = mCache[cacheIndex];
+ return true;
}
+ data = nullptr;
+ return false;
}
-bool NPatchLoader::GetNPatchData( std::size_t id, const Data*& data )
+void NPatchLoader::Remove( std::size_t id, TextureUploadObserver* textureObserver )
{
- if( ( id > UNINITIALIZED_ID )&&( id <= mCache.Count() ) )
+ int32_t cacheIndex = GetCacheIndexFromId(id);
+ if( cacheIndex == INVALID_CACHE_INDEX )
{
- data = mCache[ id - 1u ]; // id's start from 1u
- return true;
+ return;
+ }
+
+ NPatchData* data;
+ data = mCache[cacheIndex];
+
+ data->RemoveObserver(textureObserver);
+
+ if(data->GetObserverCount() == 0)
+ {
+ mCache.Erase( mCache.Begin() + cacheIndex );
}
- data = NULL;
- return false;
}
} // namespace Internal
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/npatch-data.h>
#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
{
public:
- enum
- {
- UNINITIALIZED_ID = 0 ///< uninitialised id, use to initialize ids
- };
-
- struct Data
- {
- Data()
- : url(),
- textureSet(),
- hash( 0 ),
- croppedWidth( 0 ),
- croppedHeight( 0 ),
- border( 0, 0, 0, 0 ),
- loadCompleted( false ),
- renderingMap{ nullptr }
- {}
-
- ~Data();
-
- using ObserverListType = Dali::Vector< TextureUploadObserver* >;
-
- ObserverListType observerList; ///< Container used to store all observer clients of this Texture
- std::string url; ///< Url of the N-Patch
- TextureSet textureSet; ///< Texture containing the cropped image
- NPatchUtility::StretchRanges stretchPixelsX; ///< X stretch pixels
- NPatchUtility::StretchRanges stretchPixelsY; ///< Y stretch pixels
- std::size_t hash; ///< Hash code for the Url
- uint32_t croppedWidth; ///< Width of the cropped middle part of N-patch
- uint32_t croppedHeight; ///< Height of the cropped middle part of N-patch
- Rect< int > border; ///< The size of the border
- bool loadCompleted; ///< True if the data loading is completed
- void* renderingMap; ///< NPatch rendering data
- };
-
-public:
-
/**
* Constructor
*/
/**
* @brief Set loaded PixelBuffer and its information
*
- * @param [in] loadSuccess True if the texture load was successful (i.e. the resource is available). If false, then the resource failed to load.
* @param [in] id cache data id
* @param [in] pixelBuffer of loaded image
- * @param [in] url The url address of the loaded image.
* @param [in] preMultiplied True if the image had pre-multiplied alpha applied
*/
- void SetNPatchData( bool loadSuccess, std::size_t id, Devel::PixelBuffer& pixelBuffer, const Internal::VisualUrl& url, bool preMultiplied );
+ void SetNPatchData( std::size_t id, Devel::PixelBuffer& pixelBuffer, bool preMultiplied );
/**
* @brief Retrieve N patch data matching to an id
* @param [in] id of data
- * @param [out] data const pointer to the data
+ * @param [out] data const pointer to the NPatchData
* @return true if data matching to id was really found
*/
- bool GetNPatchData( std::size_t id, const Data*& data );
+ bool GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data );
+
+ /**
+ * @brief Remove a texture matching id.
+ * Erase the observer from the observer list of cache.
+ * If the observer list is empty, the textureSet will be reset.
+ *
+ * @param [in] id cache data id
+ * @param [in] textureObserver The NPatchVisual that requested loading.
+ */
+ void Remove( std::size_t id, TextureUploadObserver* textureObserver );
+
+private:
+
+ NPatchData::NPatchDataId GenerateUniqueNPatchDataId();
+
+ int32_t GetCacheIndexFromId( const NPatchData::NPatchDataId id );
protected:
private:
- OwnerContainer< Data* > mCache;
-
+ NPatchData::NPatchDataId mCurrentNPatchDataId;
+ OwnerContainer< NPatchData* > mCache;
};
} // name Internal
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
#include <dali-toolkit/public-api/visuals/visual-properties.h>
#include <dali-toolkit/internal/visuals/npatch-loader.h>
TextureManager& textureManager = mFactoryCache.GetTextureManager();
bool synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
- if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() )
+ if( mId == NPatchData::INVALID_NPATCH_DATA_ID && mImageUrl.IsLocalResource() )
{
bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
mId = mLoader.Load( textureManager, this, mImageUrl.GetUrl(), mBorder, preMultiplyOnLoad, synchronousLoading );
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ const NPatchData* data;
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
- EnablePreMultipliedAlpha( preMultiplyOnLoad );
+ EnablePreMultipliedAlpha( data->IsPreMultiplied() );
}
}
naturalSize.y = 0u;
// load now if not already loaded
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ const NPatchData* data;
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() != NPatchData::LoadingState::LOADING )
{
- naturalSize.x = data->croppedWidth;
- naturalSize.y = data->croppedHeight;
+ naturalSize.x = data->GetCroppedWidth();
+ naturalSize.y = data->GetCroppedHeight();
}
else
{
mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
}
}
+
+ Property::Value* releasePolicy = propertyMap.Find( Toolkit::ImageVisual::Property::RELEASE_POLICY, RELEASE_POLICY_NAME );
+ if( releasePolicy )
+ {
+ releasePolicy->Get( mReleasePolicy );
+ }
}
void NPatchVisual::DoSetOnScene( Actor& actor )
// load when first go on stage
LoadImages();
- const NPatchLoader::Data* data;
+ const NPatchData* data;
if( mLoader.GetNPatchData( mId, data ) )
{
Geometry geometry = CreateGeometry();
mImpl->mRenderer = Renderer::New( geometry, shader );
mPlacementActor = actor;
- if( data->loadCompleted )
+ if( data->GetLoadingState() != NPatchData::LoadingState::LOADING )
{
if( RenderingAddOn::Get().IsValid() )
{
- RenderingAddOn::Get().SubmitRenderTask( mImpl->mRenderer, data->renderingMap );
+ RenderingAddOn::Get().SubmitRenderTask( mImpl->mRenderer, data->GetRenderingMap() );
}
ApplyTextureAndUniforms();
void NPatchVisual::DoSetOffScene( Actor& actor )
{
+ if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
+ {
+ mLoader.Remove(mId, this);
+ mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
+ mId = NPatchData::INVALID_NPATCH_DATA_ID;
+ }
+
actor.RemoveRenderer( mImpl->mRenderer );
mImpl->mRenderer.Reset();
mPlacementActor.Reset();
map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl() );
map.Insert( Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly );
map.Insert( Toolkit::ImageVisual::Property::BORDER, mBorder );
+ map.Insert( Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy );
if( mAuxiliaryUrl.IsValid() )
{
mLoader( factoryCache.GetNPatchLoader() ),
mImageUrl(),
mAuxiliaryUrl(),
- mId( NPatchLoader::UNINITIALIZED_ID ),
+ mId(NPatchData::INVALID_NPATCH_DATA_ID),
mBorderOnly( false ),
mBorder(),
- mAuxiliaryImageAlpha( 0.0f )
+ mAuxiliaryImageAlpha( 0.0f ),
+ mReleasePolicy( Toolkit::ImageVisual::ReleasePolicy::DETACHED )
{
EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
NPatchVisual::~NPatchVisual()
{
+ if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && ( mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER ))
+ {
+ mLoader.Remove(mId, this);
+ mId = NPatchData::INVALID_NPATCH_DATA_ID;
+ }
}
Geometry NPatchVisual::CreateGeometry()
{
Geometry geometry;
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ const NPatchData* data;
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
- if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 )
+ if( data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1 )
{
if( DALI_UNLIKELY( mBorderOnly ) )
{
}
else
{
- if( data->renderingMap )
+ if( data->GetRenderingMap() )
{
uint32_t elementCount[2];
- geometry = RenderingAddOn::Get().CreateGeometryGrid(data->renderingMap, Uint16Pair(3, 3), elementCount );
+ geometry = RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), Uint16Pair(3, 3), elementCount );
if( mImpl->mRenderer )
{
- RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->renderingMap);
+ RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
}
}
else
}
}
}
- else if( data->stretchPixelsX.Size() > 0 || data->stretchPixelsY.Size() > 0)
+ else if( data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
{
- Uint16Pair gridSize( 2 * data->stretchPixelsX.Size() + 1, 2 * data->stretchPixelsY.Size() + 1 );
- if( !data->renderingMap )
+ Uint16Pair gridSize( 2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1 );
+ if( !data->GetRenderingMap() )
{
geometry = !mBorderOnly ? CreateGridGeometry( gridSize ) : CreateBorderGeometry( gridSize );
}
{
uint32_t elementCount[2];
geometry = !mBorderOnly ?
- RenderingAddOn::Get().CreateGeometryGrid(data->renderingMap, gridSize, elementCount ) : CreateBorderGeometry(gridSize );
+ RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), gridSize, elementCount ) : CreateBorderGeometry(gridSize );
if( mImpl->mRenderer )
{
- RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->renderingMap);
+ RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
}
}
}
Shader NPatchVisual::CreateShader()
{
Shader shader;
- const NPatchLoader::Data* data;
+ const NPatchData* data;
// 0 is either no data (load failed?) or no stretch regions on image
// for both cases we use the default shader
NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
// ask loader for the regions
if( mLoader.GetNPatchData( mId, data ) )
{
- xStretchCount = data->stretchPixelsX.Count();
- yStretchCount = data->stretchPixelsY.Count();
+ xStretchCount = data->GetStretchPixelsX().Count();
+ yStretchCount = data->GetStretchPixelsY().Count();
}
if( DALI_LIKELY( !mImpl->mCustomShader ) )
void NPatchVisual::ApplyTextureAndUniforms()
{
- const NPatchLoader::Data* data;
+ const NPatchData* data;
TextureSet textureSet;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
- textureSet = data->textureSet;
+ textureSet = data->GetTextures();
- if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 )
+ if( data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1 )
{
//special case for 9 patch
- Uint16Pair stretchX = data->stretchPixelsX[ 0 ];
- Uint16Pair stretchY = data->stretchPixelsY[ 0 ];
+ Uint16Pair stretchX = data->GetStretchPixelsX()[ 0 ];
+ Uint16Pair stretchY = data->GetStretchPixelsY()[ 0 ];
uint16_t stretchWidth = ( stretchX.GetY() >= stretchX.GetX() ) ? stretchX.GetY() - stretchX.GetX() : 0;
uint16_t stretchHeight = ( stretchY.GetY() >= stretchY.GetX() ) ? stretchY.GetY() - stretchY.GetX() : 0;
mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO );
mImpl->mRenderer.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) );
- mImpl->mRenderer.RegisterProperty( "uFixed[2]", Vector2( data->croppedWidth - stretchWidth, data->croppedHeight - stretchHeight ) );
+ mImpl->mRenderer.RegisterProperty( "uFixed[2]", Vector2( data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight ) );
mImpl->mRenderer.RegisterProperty( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) );
}
else
mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsX[0]", Vector2::ZERO );
mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsY[0]", Vector2::ZERO );
- RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsX", data->stretchPixelsX, data->croppedWidth );
- RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsY", data->stretchPixelsY, data->croppedHeight );
+ RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth() );
+ RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight() );
}
}
else
// If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the
// same size as the unstretched NPatch. This will give slightly higher quality results than just relying
// on GL interpolation alone.
- if( mAuxiliaryPixelBuffer.GetWidth() < data->croppedWidth &&
- mAuxiliaryPixelBuffer.GetHeight() < data->croppedHeight )
+ if( mAuxiliaryPixelBuffer.GetWidth() < data->GetCroppedWidth() &&
+ mAuxiliaryPixelBuffer.GetHeight() < data->GetCroppedHeight() )
{
- mAuxiliaryPixelBuffer.Resize( data->croppedWidth, data->croppedHeight );
+ mAuxiliaryPixelBuffer.Resize( data->GetCroppedWidth(), data->GetCroppedHeight() );
}
// Note, this resets mAuxiliaryPixelBuffer handle
void NPatchVisual::SetResource()
{
- const NPatchLoader::Data* data;
+ const NPatchData* data;
if( mImpl->mRenderer && mLoader.GetNPatchData( mId, data ) )
{
Geometry geometry = CreateGeometry();
}
}
+void NPatchVisual::UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied )
+{
+ EnablePreMultipliedAlpha( preMultiplied );
+ if(!loadSuccess)
+ {
+ // Image loaded and ready to display
+ ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
+ }
+
+ if( mAuxiliaryPixelBuffer || !mAuxiliaryUrl.IsValid() )
+ {
+ SetResource();
+ }
+}
+
void NPatchVisual::LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied )
{
- if( url.GetUrl() == mAuxiliaryUrl.GetUrl() )
+ if( loadSuccess && url.GetUrl() == mAuxiliaryUrl.GetUrl() )
{
mAuxiliaryPixelBuffer = pixelBuffer;
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
- {
- SetResource();
- }
+ SetResource();
}
else
{
- Devel::PixelBuffer loadedPixelBuffer;
- if( loadSuccess )
- {
- loadedPixelBuffer = pixelBuffer;
- EnablePreMultipliedAlpha( preMultiplied );
- }
- else
- {
- loadedPixelBuffer = LoadImageFromFile( mFactoryCache.GetTextureManager().GetBrokenImageUrl() );
- }
- mLoader.SetNPatchData( loadSuccess, mId, loadedPixelBuffer, url, preMultiplied );
-
- if( mAuxiliaryPixelBuffer || !mAuxiliaryUrl.IsValid() )
- {
- SetResource();
- }
+ // Image loaded and ready to display
+ ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
}
}
#include <dali/public-api/object/weak-handle.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
* To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
* This callback is the place to add the renderer as it would be called once the loading is finished.
*/
- void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override {}
+ void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override;
/**
* @copydoc TextureUploadObserver::LoadComplete
void LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied ) override;
private:
-
- WeakHandle<Actor> mPlacementActor; ///< Weakhandle to contain Actor during texture loading
- NPatchLoader& mLoader; ///< reference to N patch loader for fast access
- VisualUrl mImageUrl; ///< The url to the N patch to load
- VisualUrl mAuxiliaryUrl; ///< An auxiliary image that can be displayed on top of the N-Patch
- std::size_t mId; ///< id of the N patch (from loader/cache)
- Devel::PixelBuffer mAuxiliaryPixelBuffer; ///< pixel buffer of the auxiliary mask image
- bool mBorderOnly; ///< if only border is desired
- Rect<int> mBorder; ///< The size of the border
- float mAuxiliaryImageAlpha; ///< The alpha value for the auxiliary image only
+ WeakHandle<Actor> mPlacementActor; ///< Weakhandle to contain Actor during texture loading
+ NPatchLoader& mLoader; ///< reference to N patch loader for fast access
+ VisualUrl mImageUrl; ///< The url to the N patch to load
+ VisualUrl mAuxiliaryUrl; ///< An auxiliary image that can be displayed on top of the N-Patch
+ NPatchData::NPatchDataId mId; ///< id of the N patch (from loader/cache)
+ Devel::PixelBuffer mAuxiliaryPixelBuffer; ///< pixel buffer of the auxiliary mask image
+ bool mBorderOnly; ///< if only border is desired
+ Rect<int> mBorder; ///< The size of the border
+ float mAuxiliaryImageAlpha; ///< The alpha value for the auxiliary image only
+ Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy; ///< The release policy to determine when an image should no longer be cached.
};
} // namespace Internal
TextureHash textureHash = INITIAL_CACHE_NUMBER;
int cacheIndex = INVALID_CACHE_INDEX;
- if(storageType != StorageType::RETURN_PIXEL_BUFFER)
+ if(storageType != StorageType::RETURN_PIXEL_BUFFER && !isAnimatedImage)
{
- textureHash = GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, isAnimatedImage, frameIndex);
+ textureHash = GenerateHash(url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId);
// Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
- cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, preMultiplyOnLoad, isAnimatedImage, frameIndex);
+ cacheIndex = FindCachedTexture(textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas, maskTextureId, preMultiplyOnLoad);
}
TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
-
// Check if the requested Texture exists in the cache.
if( cacheIndex != INVALID_CACHE_INDEX )
{
}
else
{
- // @todo If the load was unsuccessful, upload the broken image.
textureInfo.loadState = LoadState::LOAD_FAILED;
CheckForWaitingTexture( textureInfo );
NotifyObservers( textureInfo, false );
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode,
const UseAtlas useAtlas,
- TextureId maskTextureId,
- bool isAnimationImage,
- uint32_t frameIndex )
+ TextureId maskTextureId)
{
std::string hashTarget( url );
const size_t urlLength = hashTarget.length();
}
}
- if( isAnimationImage )
- {
- auto textureIdIndex = hashTarget.length();
- hashTarget.resize( hashTarget.length() + sizeof( uint32_t ) );
- char* hashTargetPtr = &( hashTarget[ textureIdIndex ] );
-
- for( size_t byteIter = 0; byteIter < sizeof( uint32_t ); ++byteIter )
- {
- *hashTargetPtr++ = frameIndex & 0xff;
- frameIndex >>= 8u;
- }
- }
-
if( maskTextureId != INVALID_TEXTURE_ID )
{
auto textureIdIndex = hashTarget.length();
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
TextureId maskTextureId,
- TextureManager::MultiplyOnLoad preMultiplyOnLoad,
- bool isAnimatedImage,
- uint32_t frameIndex )
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad)
{
// Default to an invalid ID, in case we do not find a match.
int cacheIndex = INVALID_CACHE_INDEX;
( size == textureInfo.desiredSize ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
- samplingMode == textureInfo.samplingMode ) ) &&
- ( isAnimatedImage == ( ( textureInfo.animatedImageLoading ) ? true : false ) ) &&
- ( frameIndex == textureInfo.frameIndex ) )
+ samplingMode == textureInfo.samplingMode ) ) )
{
// 1. If preMultiplyOnLoad is MULTIPLY_ON_LOAD, then textureInfo.preMultiplyOnLoad should be true. The premultiplication result can be different.
// 2. If preMultiplyOnLoad is LOAD_WITHOUT_MULTIPLY, then textureInfo.preMultiplied should be false.
mBrokenImageUrl = brokenImageUrl;
}
-const std::string TextureManager::GetBrokenImageUrl()
-{
- return mBrokenImageUrl;
-}
-
Geometry TextureManager::GetRenderGeometry(TextureId textureId, uint32_t& frontElements, uint32_t& backElements )
{
return RenderingAddOn::Get().IsValid() ?
void SetBrokenImageUrl(const std::string& brokenImageUrl);
/**
- * @brief Get an image to be used when a visual has failed to correctly render
- * @return Returns The broken image url.
- */
- const std::string GetBrokenImageUrl();
-
- /**
* @brief Returns the geometry associated with texture.
* @param[in] textureId Id of the texture
* @param[out] frontElements number of front elements
* @param[in] samplingMode The SamplingMode to use
* @param[in] useAtlas True if atlased
* @param[in] maskTextureId The masking texture id (or INVALID_TEXTURE_ID)
- * @param[in] isAnimatedImage The boolean value to know whether the request is for animated image or not
- * @param[in] frameIndex The frame index of a frame to be loaded frame
* @return A hash of the provided data for caching.
*/
TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
- TextureId maskTextureId, bool isAnimatedImage, uint32_t frameIndex );
+ TextureId maskTextureId );
/**
* @brief Looks up a cached texture by its hash.
* @param[in] useAtlas True if atlased
* @param[in] maskTextureId Optional texture ID to use to mask this image
* @param[in] preMultiplyOnLoad if the image's color should be multiplied by it's alpha. Set to OFF if there is no alpha.
- * @param[in] isAnimatedImage The boolean value to know whether the request is for animated image or not
- * @param[in] frameIndex The frame index of a frame to be loaded frame
* @return A TextureId of a cached Texture if found. Or INVALID_TEXTURE_ID if not found.
*/
TextureManager::TextureId FindCachedTexture(
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
TextureId maskTextureId,
- MultiplyOnLoad preMultiplyOnLoad,
- bool isAnimatedImage,
- uint32_t frameIndex );
+ MultiplyOnLoad preMultiplyOnLoad);
private:
} // unnamed namespace
-Internal::Visual::Base::Impl::Impl( FittingMode fittingMode, Toolkit::Visual::Type type )
-: mCustomShader( NULL ),
- mEventObserver( NULL ),
+Internal::Visual::Base::Impl::Impl(FittingMode fittingMode, Toolkit::Visual::Type type)
+: mCustomShader(NULL),
+ mEventObserver(NULL),
mTransform(),
- mMixColor( Color::WHITE ),
- mControlSize( Vector2::ZERO ),
- mCornerRadius( 0.0f ),
- mCornerRadiusPolicy( 1.0f ),
- mDepthIndex( 0.0f ),
- mMixColorIndex( Property::INVALID_INDEX ),
- mCornerRadiusIndex( Property::INVALID_INDEX ),
- mFittingMode( fittingMode ),
- mFlags( 0 ),
- mResourceStatus( Toolkit::Visual::ResourceStatus::PREPARING ),
- mType( type )
+ mMixColor(Color::WHITE),
+ mControlSize(Vector2::ZERO),
+ mCornerRadius(0.0f),
+ mCornerRadiusPolicy(1.0f),
+ mDepthIndex(0.0f),
+ mMixColorIndex(Property::INVALID_INDEX),
+ mCornerRadiusIndex(Property::INVALID_INDEX),
+ mFittingMode(fittingMode),
+ mFlags(0),
+ mResourceStatus(Toolkit::Visual::ResourceStatus::PREPARING),
+ mType(type),
+ mNeedCornerRadius(false)
{
}
int mFlags;
Toolkit::Visual::ResourceStatus mResourceStatus;
const Toolkit::Visual::Type mType;
+ bool mNeedCornerRadius;
};
} // namespace Visual
if( IsRoundedCornerRequired() )
{
- mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty( CORNER_RADIUS, mImpl->mCornerRadius );
+ mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
mImpl->mRenderer.RegisterProperty( CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy );
mImpl->mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
{
if( IsOnScene() )
{
+ if(mImpl->mRenderer)
+ {
+ // Update values from Renderer
+ mImpl->mMixColor = mImpl->mRenderer.GetProperty<Vector3>(mImpl->mMixColorIndex);
+ mImpl->mMixColor.a = mImpl->mRenderer.GetProperty<float>(DevelRenderer::Property::OPACITY);
+ if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<float>(mImpl->mCornerRadiusIndex);
+ }
+ }
+
DoSetOffScene( actor );
mImpl->mMixColorIndex = Property::INVALID_INDEX;
mImpl->mCornerRadiusIndex = Property::INVALID_INDEX;
void Visual::Base::CreatePropertyMap( Property::Map& map ) const
{
- DoCreatePropertyMap( map );
+ if(mImpl->mRenderer)
+ {
+ // Update values from Renderer
+ mImpl->mMixColor = mImpl->mRenderer.GetProperty<Vector3>(mImpl->mMixColorIndex);
+ mImpl->mMixColor.a = mImpl->mRenderer.GetProperty<float>(DevelRenderer::Property::OPACITY);
+ if(mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
+ {
+ mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<float>(mImpl->mCornerRadiusIndex);
+ }
+ }
- if( mImpl->mCustomShader )
+ DoCreatePropertyMap(map);
+
+ if(mImpl->mCustomShader)
{
- mImpl->mCustomShader->CreatePropertyMap( map );
+ mImpl->mCustomShader->CreatePropertyMap(map);
}
Property::Map transform;
bool Visual::Base::IsRoundedCornerRequired() const
{
- return !EqualsZero( mImpl->mCornerRadius );
+ if(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
+ {
+ // Update values from Renderer
+ mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<float>(mImpl->mCornerRadiusIndex);
+ }
+ return !EqualsZero(mImpl->mCornerRadius) || mImpl->mNeedCornerRadius;
}
void Visual::Base::OnDoAction( const Property::Index actionId, const Property::Value& attributes )
}
}
-const Vector4& Visual::Base::GetMixColor() const
-{
- return mImpl->mMixColor;
-}
-
void Visual::Base::AddEventObserver( Visual::EventObserver& observer)
{
mImpl->mEventObserver = &observer;
}
#endif
- Property::Map map;
- DoCreatePropertyMap( map );
- Property::Value* valuePtr = map.Find( Toolkit::Visual::Property::TYPE );
- int visualType = -1;
- if( valuePtr )
- {
- valuePtr->Get( visualType );
- }
-
- if( animator.propertyKey == Toolkit::Visual::Property::MIX_COLOR ||
- animator.propertyKey == MIX_COLOR ||
- ( visualType == Toolkit::Visual::COLOR &&
- animator.propertyKey == ColorVisual::Property::MIX_COLOR ) ||
- ( visualType == Toolkit::Visual::PRIMITIVE &&
- animator.propertyKey == PrimitiveVisual::Property::MIX_COLOR ) )
+ if(animator.propertyKey == Toolkit::Visual::Property::MIX_COLOR ||
+ animator.propertyKey == MIX_COLOR ||
+ (mImpl->mType == Toolkit::Visual::COLOR &&
+ animator.propertyKey == ColorVisual::Property::MIX_COLOR) ||
+ (mImpl->mType == Toolkit::Visual::PRIMITIVE &&
+ animator.propertyKey == PrimitiveVisual::Property::MIX_COLOR))
{
AnimateMixColorProperty( transition, animator );
}
}
}
+Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key)
+{
+ if(!mImpl->mRenderer)
+ {
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
+ }
+
+ // Mix color or opacity cases
+ if(key.type == Property::Key::INDEX)
+ {
+ if(key.indexKey == Toolkit::Visual::Property::MIX_COLOR || (mImpl->mType == Toolkit::Visual::COLOR && key.indexKey == ColorVisual::Property::MIX_COLOR) || (mImpl->mType == Toolkit::Visual::PRIMITIVE && key.indexKey == PrimitiveVisual::Property::MIX_COLOR))
+ {
+ return Dali::Property(mImpl->mRenderer, mImpl->mMixColorIndex);
+ }
+ else if(key.indexKey == Toolkit::Visual::Property::OPACITY)
+ {
+ return Dali::Property(mImpl->mRenderer, DevelRenderer::Property::OPACITY);
+ }
+ }
+ else
+ {
+ if(key.stringKey == MIX_COLOR)
+ {
+ return Dali::Property(mImpl->mRenderer, mImpl->mMixColorIndex);
+ }
+ else if(key.stringKey == OPACITY)
+ {
+ return Dali::Property(mImpl->mRenderer, DevelRenderer::Property::OPACITY);
+ }
+ }
+
+ // Other cases
+ 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))
+ {
+ // Register CORNER_RADIUS property
+ mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius);
+ mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy);
+ index = mImpl->mCornerRadiusIndex;
+
+ mImpl->mNeedCornerRadius = true;
+
+ // Change shader
+ UpdateShader();
+ }
+ else
+ {
+ // We can't find the property in the base class.
+ // Request to child class
+ return OnGetPropertyObject(key);
+ }
+ }
+
+ return Dali::Property(mImpl->mRenderer, index);
+}
+
} // namespace Internal
} // namespace Toolkit
void SetMixColor( const Vector3& color );
/**
- * Gets the mix color of the visual.
- * @return The mix color
- */
- const Vector4& GetMixColor() const;
-
- /**
* Animate the property if it exists in the visual or renderer.
*
* If it's a visual property such as mix color or a transform property,
*/
Toolkit::Visual::Type GetType() const;
- protected:
+ /**
+ * @brief Retrieve the property object associated with the property key.
+ *
+ * @param[in] key The Property key of the visual.
+ * @return The Property object
+ */
+ Dali::Property GetPropertyObject(Dali::Property::Key key);
+protected:
/**
* @brief Constructor.
*
*/
virtual void OnDoAction( const Property::Index actionId, const Property::Value& attributes );
+ /**
+ * @brief Update the shader when some properties are changed.
+ */
+ virtual void UpdateShader()
+ {
+ }
+
+ /**
+ * @brief Called by GetPropertyObject() allowing sub classes to respond to the GetPropertyObject event
+ * @note The derived class is required to register the given property.
+ * @param[in] key The key of the visual's property.
+ * @return The Property object
+ */
+ virtual Dali::Property OnGetPropertyObject(Dali::Property::Key key)
+ {
+ Handle handle;
+ return Dali::Property(handle, Property::INVALID_INDEX);
+ }
+
protected:
/**
{
const unsigned int TOOLKIT_MAJOR_VERSION = 2;
const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 5;
+const unsigned int TOOLKIT_MICRO_VERSION = 6;
const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
/**
* @brief Mix color is a blend color for any visual.
- * @details Name "mixColor", type Property::VECTOR3 or Property::VECTOR4.
+ * @details Name "mixColor", type Property::VECTOR3 or Property::VECTOR4, animatable
* @SINCE_1_2.60
* @note Optional
+ * @note To animate an opacity, OPACITY property should be used.
*/
MIX_COLOR,
/**
* @brief Opacity is the alpha component of the mixColor, above.
- * @details Name "opacity", type Property::FLOAT.
+ * @details Name "opacity", type Property::FLOAT, animatable
* @SINCE_1_2.60
* @note Optional
*/
Name: dali2-toolkit
Summary: Dali 3D engine Toolkit
-Version: 2.0.5
+Version: 2.0.6
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT