From: Xiangyin Ma Date: Wed, 7 Dec 2016 15:49:35 +0000 (+0000) Subject: AnimatedImageVisual X-Git-Tag: dali_1.2.20~18^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=11d6d49bd9837159b95a27199c48dd7a39b8ccee AnimatedImageVisual Change-Id: I6d00000865b02fbdd1f47880e68b3b554da61d1c --- diff --git a/automated-tests/resources/anim.gif b/automated-tests/resources/anim.gif new file mode 100644 index 0000000..f66f076 Binary files /dev/null and b/automated-tests/resources/anim.gif differ diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualFactoryResolveUrl.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualFactoryResolveUrl.cpp index f859b74..8235355 100644 --- a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualFactoryResolveUrl.cpp +++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualFactoryResolveUrl.cpp @@ -30,8 +30,6 @@ int UtcDaliResolveUrlRegularImage(void) DALI_TEST_EQUALS( UrlType::REGULAR_IMAGE, ResolveUrlType("foobar.jpeg"), TEST_LOCATION ); - DALI_TEST_EQUALS( UrlType::REGULAR_IMAGE, ResolveUrlType("foobar.gif"), TEST_LOCATION ); - DALI_TEST_EQUALS( UrlType::REGULAR_IMAGE, ResolveUrlType("foobar.PNG"), TEST_LOCATION ); DALI_TEST_EQUALS( UrlType::REGULAR_IMAGE, ResolveUrlType("foobar.Png123"), TEST_LOCATION ); @@ -78,8 +76,6 @@ int UtcDaliResolveUrlNPatch(void) { tet_infoline( "UtcDaliResolveUrl N_PATCH" ); - DALI_TEST_EQUALS( UrlType::N_PATCH, ResolveUrlType("foobar.9.gif"), TEST_LOCATION ); - DALI_TEST_EQUALS( UrlType::N_PATCH, ResolveUrlType("foobar.#.png"), TEST_LOCATION ); DALI_TEST_EQUALS( UrlType::N_PATCH, ResolveUrlType("foobar.9.9.bmp"), TEST_LOCATION ); @@ -94,3 +90,26 @@ int UtcDaliResolveUrlNPatch(void) END_TEST; } + +int UtcDaliResolveUrlGif(void) +{ + tet_infoline( "UtcDaliResolveUrl GIF" ); + + DALI_TEST_EQUALS( UrlType::GIF, ResolveUrlType("foobar.gif"), TEST_LOCATION ); + + DALI_TEST_EQUALS( UrlType::GIF, ResolveUrlType("foobar.gif.gif"), TEST_LOCATION ); + + DALI_TEST_EQUALS( UrlType::GIF, ResolveUrlType("foobar.giF"), TEST_LOCATION ); + + DALI_TEST_EQUALS( UrlType::GIF, ResolveUrlType("foobar.GIF"), TEST_LOCATION ); + + DALI_TEST_EQUALS( UrlType::GIF, ResolveUrlType(".GiF"), TEST_LOCATION ); + + // GIFs aren't N-patch + DALI_TEST_EQUALS( UrlType::GIF, ResolveUrlType("foobar.9.gif"), TEST_LOCATION ); + + DALI_TEST_EQUALS( UrlType::REGULAR_IMAGE, ResolveUrlType("gif.png"), TEST_LOCATION ); + DALI_TEST_EQUALS( UrlType::REGULAR_IMAGE, ResolveUrlType("gif.gif1"), TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index fae713a..4885bc2 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -38,6 +38,7 @@ namespace const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; const char* TEST_NPATCH_FILE_NAME = "gallery_image_01.9.jpg"; const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg"; +const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif"; const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj"; const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl"; const char* TEST_RESOURCE_LOCATION = TEST_RESOURCE_DIR "/"; @@ -292,6 +293,14 @@ int UtcDaliVisualSize(void) const float height = textVisual.GetHeightForWidth( 40.f ); DALI_TEST_EQUALS( height, 40.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + //AnimatedImageVisual + Visual::Base animatedImageVisual = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); + animatedImageVisual.SetTransformAndSize(DefaultTransform(), controlSize ); + animatedImageVisual.GetNaturalSize(naturalSize); + // TEST_GIF_FILE: anim.gif + // resolution: 50*50, frame count: 4, frame delay: 0.2 second for each frame + DALI_TEST_EQUALS( naturalSize, Vector2(50.f, 50.f), TEST_LOCATION ); + END_TEST; } @@ -990,6 +999,45 @@ int UtcDaliVisualGetPropertyMap10(void) END_TEST; } +int UtcDaliVisualGetPropertyMap11(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualGetPropertyMap7: AnimatedImageVisual" ); + + // request SvgVisual with a property map + VisualFactory factory = VisualFactory::Get(); + Property::Map propertyMap; + Visual::Base svgVisual = factory.CreateVisual( Property::Map() + .Add( Visual::Property::TYPE, Visual::IMAGE ) + .Add( ImageVisual::Property::URL, TEST_GIF_FILE_NAME ) ); + + Property::Map resultMap; + svgVisual.CreatePropertyMap( resultMap ); + // check the property values from the returned map from a visual + Property::Value* value = resultMap.Find( Visual::Property::TYPE, Property::INTEGER ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == Visual::IMAGE ); + + value = resultMap.Find( ImageVisual::Property::URL, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == TEST_GIF_FILE_NAME ); + + // request SvgVisual with an URL + Visual::Base svgVisual2 = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); + resultMap.Clear(); + svgVisual2.CreatePropertyMap( resultMap ); + // check the property values from the returned map from a visual + value = resultMap.Find( Visual::Property::TYPE, Property::INTEGER ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == Visual::IMAGE ); + + value = resultMap.Find( ImageVisual::Property::URL, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == TEST_GIF_FILE_NAME ); + + END_TEST; +} + int UtcDaliVisualGetPropertyMapBatchImageVisualNoAtlas(void) { ToolkitTestApplication application; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp index b186ea4..0e9c014 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,9 @@ const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl"; const char* TEST_SIMPLE_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube-Points-Only.obj"; const char* TEST_SIMPLE_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal-Simple.mtl"; +// resolution: 50*50, frame count: 4, frame delay: 0.2 second for each frame +const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif"; + // resolution: 34*34, pixel format: RGBA8888 static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png"; // resolution: 600*600, pixel format: RGB888 @@ -2051,3 +2055,82 @@ int UtcDaliVisualFactoryGetBatchImageVisual3(void) END_TEST; } + +int UtcDaliVisualFactoryGetAnimatedImageVisual(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliVisualFactoryGetAnimatedImageVisual: Request animated image visual with a gif url" ); + + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( TEST_GIF_FILE_NAME, ImageDimensions() ); + DALI_TEST_CHECK( visual ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + DummyControl actor = DummyControl::New(); + DummyControlImpl& dummyImpl = static_cast(actor.GetImplementation()); + dummyImpl.RegisterVisual( Control::CONTROL_PROPERTY_END_INDEX + 1, visual ); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + // renderer is added to actor + DALI_TEST_CHECK( actor.GetRendererCount() == 1u ); + + // test the uniforms which used to handle the atlas rect + // the four frames should be located inside atlas as follows: atlas size 100*100 + // ------------- + // | | | + // | 0 | 1 | + // ------------- + // | | | + // | 2 | 3 | + // ------------- + + Renderer renderer = actor.GetRendererAt( 0u ); + DALI_TEST_CHECK( renderer ); + + Property::Value atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); + // take into consideration the half pixel correction + DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(0.5f, 0.5f, 49.5f, 49.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + + // waiting for the resource uploading + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION ); + + // Force the timer used by the animatedImageVisual to tick, + Dali::Timer timer = Timer::New( 0 ); + timer.MockEmitSignal(); + application.SendNotification(); + application.Render(); + atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); + // take into consideration the half pixel correction + DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(50.5f, 0.5f, 99.5f, 49.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + + // Force the timer used by the animatedImageVisual to tick, + timer.MockEmitSignal(); + application.SendNotification(); + application.Render(); + atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); + // take into consideration the half pixel correction + DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(0.5f, 50.5f, 49.5f, 99.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + + // Force the timer used by the animatedImageVisual to tick, + timer.MockEmitSignal(); + application.SendNotification(); + application.Render(); + atlasRectValue = renderer.GetProperty( renderer.GetPropertyIndex( "uAtlasRect" ) ); + // take into consideration the half pixel correction + DALI_TEST_EQUALS( atlasRectValue.Get(), Vector4(50.5f, 50.5f, 99.5f, 99.5f)/100.f, Math::MACHINE_EPSILON_100, TEST_LOCATION ); + + // Test SetOffStage(). + actor.Unparent(); + DALI_TEST_CHECK( actor.GetRendererCount() == 0u ); + + END_TEST; +} diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 7fa3af7..a4f49d9 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -17,6 +17,7 @@ toolkit_src_files = \ $(toolkit_src_dir)/visuals/visual-factory-cache.cpp \ $(toolkit_src_dir)/visuals/visual-factory-impl.cpp \ $(toolkit_src_dir)/visuals/visual-string-constants.cpp \ + $(toolkit_src_dir)/visuals/animated-image/animated-image-visual.cpp \ $(toolkit_src_dir)/visuals/border/border-visual.cpp \ $(toolkit_src_dir)/visuals/color/color-visual.cpp \ $(toolkit_src_dir)/visuals/gradient/gradient.cpp \ diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp new file mode 100644 index 0000000..5a3a154 --- /dev/null +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2016 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 "animated-image-visual.h" + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl, const Property::Map& properties ) +{ + AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); + visual->mImageUrl = imageUrl; + visual->SetProperties( properties ); + + return visual; +} + +AnimatedImageVisualPtr AnimatedImageVisual::New( VisualFactoryCache& factoryCache, const std::string& imageUrl ) +{ + AnimatedImageVisual* visual = new AnimatedImageVisual( factoryCache ); + visual->mImageUrl = imageUrl; + + return visual; +} + +AnimatedImageVisual::AnimatedImageVisual( VisualFactoryCache& factoryCache ) +: Visual::Base( factoryCache ), + mFrameDelayTimer(), + mImageUrl(), + mImageSize(), + mCurrentFrameIndex( 0 ) +{} + +AnimatedImageVisual::~AnimatedImageVisual() +{ +} + +void AnimatedImageVisual::GetNaturalSize( Vector2& naturalSize ) +{ + if( mImageSize.GetWidth() == 0 && mImageSize.GetHeight() == 0) + { + mImageSize = Dali::GetGifImageSize( mImageUrl ); + } + + naturalSize.width = mImageSize.GetWidth(); + naturalSize.height = mImageSize.GetHeight(); +} + +void AnimatedImageVisual::DoCreatePropertyMap( Property::Map& map ) const +{ + map.Clear(); + map.Insert( Toolkit::DevelVisual::Property::TYPE, Toolkit::Visual::IMAGE ); + if( !mImageUrl.empty() ) + { + map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl ); + } +} + +void AnimatedImageVisual::DoSetProperties( const Property::Map& propertyMap ) +{ + // url already passed in from constructor +} + +void AnimatedImageVisual::DoSetOnStage( Actor& actor ) +{ + Texture texture = PrepareAnimatedImage(); + if( texture ) // if the image loading is successful + { + Shader shader = ImageVisual::GetImageShader( mFactoryCache, true, true ); + Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); + TextureSet textureSet = TextureSet::New(); + mImpl->mRenderer = Renderer::New( geometry, shader ); + mImpl->mRenderer.SetTextures( textureSet ); + textureSet.SetTexture( 0u, PrepareAnimatedImage() ); + mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[0] ); + + // Register transform properties + mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + + mCurrentFrameIndex = 0; + if( mFrameDelayContainer.Count() > 1 ) + { + mFrameDelayTimer = Timer::New( mFrameDelayContainer[0] ); + mFrameDelayTimer.TickSignal().Connect( this, &AnimatedImageVisual::DisplayNextFrame ); + mFrameDelayTimer.Start(); + } + + actor.AddRenderer( mImpl->mRenderer ); + } +} + +void AnimatedImageVisual::DoSetOffStage( Actor& actor ) +{ + if( !mImpl->mRenderer ) + { + return; + } + + if( mFrameDelayTimer ) + { + mFrameDelayTimer.Stop(); + mFrameDelayTimer.Reset(); + } + + mTextureRectContainer.Clear(); + mFrameDelayContainer.Clear(); + + actor.RemoveRenderer( mImpl->mRenderer ); + mImpl->mRenderer.Reset(); +} + +void AnimatedImageVisual::OnSetTransform() +{ + if( mImpl->mRenderer ) + { + mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); + } +} + +Texture AnimatedImageVisual::PrepareAnimatedImage() +{ + // load from image file + std::vector pixelDataList; + if( Dali::LoadAnimatedGifFromFile( mImageUrl.c_str() , pixelDataList, mFrameDelayContainer ) ) + { + mImageSize.SetWidth( pixelDataList[0].GetWidth() ); + mImageSize.SetHeight( pixelDataList[0].GetHeight() ); + + return Toolkit::ImageAtlas::PackToAtlas( pixelDataList, mTextureRectContainer ); + } + + return Texture(); +} + +bool AnimatedImageVisual::DisplayNextFrame() +{ + mCurrentFrameIndex = (mCurrentFrameIndex+1) % mFrameDelayContainer.Count(); + mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, mTextureRectContainer[mCurrentFrameIndex] ); + if( mFrameDelayTimer.GetInterval() != mFrameDelayContainer[mCurrentFrameIndex] ) + { + mFrameDelayTimer.SetInterval( mFrameDelayContainer[mCurrentFrameIndex] ); + } + + return true; +} + + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h new file mode 100644 index 0000000..15dff43 --- /dev/null +++ b/dali-toolkit/internal/visuals/animated-image/animated-image-visual.h @@ -0,0 +1,156 @@ +#ifndef DALI_TOOLKIT_INTERNAL_ANIMATED_IMAGE_VISUAL_H +#define DALI_TOOLKIT_INTERNAL_ANIMATED_IMAGE_VISUAL_H + +/* + * Copyright (c) 2016 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 +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +class AnimatedImageVisual; +typedef IntrusivePtr< AnimatedImageVisual > AnimatedImageVisualPtr; + +/** + * The visual which renders an animated image + * + * The following property is essential + * + * | %Property Name | Type | + * |--------------------------|------------------| + * | url | STRING | + * + */ + +class AnimatedImageVisual : public Visual::Base, public ConnectionTracker +{ + +public: + + /** + * @brief Create the animated image Visual using the image URL. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] imageUrl The URL to svg resource to use + * @param[in] properties A Property::Map containing settings for this visual + * @return A smart-pointer to the newly allocated visual. + */ + static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, const std::string& imageUrl, const Property::Map& properties ); + + /** + * @brief Create the animated image visual using the image URL. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + * @param[in] imageUrl The URL to animated image resource to use + */ + static AnimatedImageVisualPtr New( VisualFactoryCache& factoryCache, const std::string& imageUrl ); + +public: // from Visual + + /** + * @copydoc Visual::Base::GetNaturalSize + */ + virtual void GetNaturalSize( Vector2& naturalSize ); + + /** + * @copydoc Visual::Base::CreatePropertyMap + */ + virtual void DoCreatePropertyMap( Property::Map& map ) const; + +protected: + + /** + * @brief Constructor. + * + * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object + */ + AnimatedImageVisual( VisualFactoryCache& factoryCache ); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~AnimatedImageVisual(); + + /** + * @copydoc Visual::Base::DoSetProperties + */ + virtual void DoSetProperties( const Property::Map& propertyMap ); + + /** + * @copydoc Visual::Base::DoSetOnStage + */ + virtual void DoSetOnStage( Actor& actor ); + + /** + * @copydoc Visual::Base::DoSetOffStage + */ + virtual void DoSetOffStage( Actor& actor ); + + /** + * @copydoc Visual::Base::OnSetTransform + */ + virtual void OnSetTransform(); + +private: + + /** + * Load the animated image and pack the frames into atlas. + * @return That atlas texture. + */ + Texture PrepareAnimatedImage(); + + /** + * Display the next frame. It is called when the mFrameDelayTimes ticks. + */ + bool DisplayNextFrame(); + + // Undefined + AnimatedImageVisual( const AnimatedImageVisual& animatedImageVisual ); + + // Undefined + AnimatedImageVisual& operator=( const AnimatedImageVisual& animatedImageVisual ); + +private: + + Timer mFrameDelayTimer; + Dali::Vector mTextureRectContainer; + Dali::Vector mFrameDelayContainer; + std::string mImageUrl; + ImageDimensions mImageSize; + uint32_t mCurrentFrameIndex; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali +#endif /* DALI_TOOLKIT_INTERNAL_ANIMATED_IMAGE_VISUAL_H */ diff --git a/dali-toolkit/internal/visuals/color/color-visual.cpp b/dali-toolkit/internal/visuals/color/color-visual.cpp index 08dfd20..5bc3c6e 100644 --- a/dali-toolkit/internal/visuals/color/color-visual.cpp +++ b/dali-toolkit/internal/visuals/color/color-visual.cpp @@ -131,11 +131,6 @@ void ColorVisual::OnSetTransform() void ColorVisual::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - if( !geometry ) - { - geometry = VisualFactoryCache::CreateQuadGeometry(); - mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); - } Shader shader = mFactoryCache.GetShader( VisualFactoryCache::COLOR_SHADER ); if( !shader ) diff --git a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp index 80c899f..7826984 100644 --- a/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp +++ b/dali-toolkit/internal/visuals/gradient/gradient-visual.cpp @@ -322,11 +322,6 @@ void GradientVisual::DoCreatePropertyMap( Property::Map& map ) const void GradientVisual::InitializeRenderer() { Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - if( !geometry ) - { - geometry = VisualFactoryCache::CreateQuadGeometry(); - mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); - } Toolkit::GradientVisual::Units::Type gradientUnits = mGradient->GetGradientUnits(); VisualFactoryCache::ShaderType shaderType = GetShaderType( mGradientType, gradientUnits ); diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index 69a1094..b61c23b 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -185,11 +185,6 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS if( gridSize == ImageDimensions( 1, 1 ) ) { geometry = factoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - if( !geometry ) - { - geometry = VisualFactoryCache::CreateQuadGeometry(); - factoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); - } } else { diff --git a/dali-toolkit/internal/visuals/svg/svg-visual.cpp b/dali-toolkit/internal/visuals/svg/svg-visual.cpp index 5dbb80f..955b84c 100644 --- a/dali-toolkit/internal/visuals/svg/svg-visual.cpp +++ b/dali-toolkit/internal/visuals/svg/svg-visual.cpp @@ -100,11 +100,6 @@ void SvgVisual::DoSetOnStage( Actor& actor ) { Shader shader = ImageVisual::GetImageShader( mFactoryCache, true, true ); Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - if( !geometry ) - { - geometry = mFactoryCache.CreateQuadGeometry(); - mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY, geometry ); - } TextureSet textureSet = TextureSet::New(); mImpl->mRenderer = Renderer::New( geometry, shader ); mImpl->mRenderer.SetTextures( textureSet ); diff --git a/dali-toolkit/internal/visuals/text/text-visual.cpp b/dali-toolkit/internal/visuals/text/text-visual.cpp index 2e7fa6d..4145bf7 100644 --- a/dali-toolkit/internal/visuals/text/text-visual.cpp +++ b/dali-toolkit/internal/visuals/text/text-visual.cpp @@ -269,11 +269,6 @@ void TextVisual::DoSetOnStage( Actor& actor ) mControl = actor; Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY ); - if( !geometry ) - { - geometry = VisualFactoryCache::CreateQuadGeometry(); - mFactoryCache.SaveGeometry( VisualFactoryCache::QUAD_GEOMETRY , geometry ); - } Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP ); mFactoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader ); diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.cpp b/dali-toolkit/internal/visuals/visual-factory-cache.cpp index bf6814d..05e32ff 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-cache.cpp @@ -52,6 +52,11 @@ VisualFactoryCache::~VisualFactoryCache() Geometry VisualFactoryCache::GetGeometry( GeometryType type ) { + if( !mGeometry[type] && type == QUAD_GEOMETRY ) + { + mGeometry[type] = CreateQuadGeometry(); + } + return mGeometry[type]; } diff --git a/dali-toolkit/internal/visuals/visual-factory-impl.cpp b/dali-toolkit/internal/visuals/visual-factory-impl.cpp index 92cc53c..239f5c4 100644 --- a/dali-toolkit/internal/visuals/visual-factory-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-factory-impl.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,10 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property { visualPtr = SvgVisual::New( *( mFactoryCache.Get() ), imageUrl, propertyMap ); } + else if( UrlType::GIF == type ) + { + visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), imageUrl, propertyMap ); + } else // Regular image { bool batchingEnabled( false ); @@ -259,6 +264,10 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, Image { visualPtr = SvgVisual::New( *( mFactoryCache.Get() ), url ); } + else if( UrlType::GIF == type ) + { + visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), url ); + } else // Regular image { visualPtr = ImageVisual::New( *( mFactoryCache.Get() ), url, size ); diff --git a/dali-toolkit/internal/visuals/visual-factory-resolve-url.h b/dali-toolkit/internal/visuals/visual-factory-resolve-url.h index 1d3ffe3..2c1c45b 100644 --- a/dali-toolkit/internal/visuals/visual-factory-resolve-url.h +++ b/dali-toolkit/internal/visuals/visual-factory-resolve-url.h @@ -37,7 +37,8 @@ namespace UrlType { REGULAR_IMAGE, N_PATCH, - SVG + SVG, + GIF }; } @@ -55,7 +56,9 @@ inline UrlType::Type ResolveUrlType( const std::string& url ) // parsing from the end for better chance of early outs enum { SUFFIX, HASH, HASH_DOT } state = SUFFIX; char SVG[ 4 ] = { 'g', 'v', 's', '.' }; + char GIF[ 4 ] = { 'f', 'i', 'g', '.' }; unsigned int svgScore = 0; + unsigned int gifScore = 0; int index = count; while( --index >= 0 ) { @@ -69,6 +72,14 @@ inline UrlType::Type ResolveUrlType( const std::string& url ) return UrlType::SVG; } } + if( ( offsetFromEnd < sizeof(GIF) )&&( tolower( currentChar ) == GIF[ offsetFromEnd ] ) ) + { + // early out if GIF + if( ++gifScore == sizeof(GIF) ) + { + return UrlType::GIF; + } + } switch( state ) { case SUFFIX: diff --git a/docs/content/images/visuals/animated-image-visual.gif b/docs/content/images/visuals/animated-image-visual.gif new file mode 100644 index 0000000..ddc3312 Binary files /dev/null and b/docs/content/images/visuals/animated-image-visual.gif differ diff --git a/docs/content/shared-javascript-and-cpp-documentation/visuals.md b/docs/content/shared-javascript-and-cpp-documentation/visuals.md index 457d8e1..eaaaed5 100644 --- a/docs/content/shared-javascript-and-cpp-documentation/visuals.md +++ b/docs/content/shared-javascript-and-cpp-documentation/visuals.md @@ -30,7 +30,7 @@ Visuals have a **transform** field in the property map to allow layouting within | Dali::Toolkit::Visual::Transform::Property::OFFSET | offset | VECTOR2 | No | The offset of the visual. | | Dali::Toolkit::Visual::Transform::Property::SIZE | size | VECTOR2 | No | The size of the visual. | | Dali::Toolkit::Visual::Transform::Property::OFFSET_SIZE_MODE | offsetSizeMode | VECTOR4 | No | Whether the size or offset components are Relative or Absolute [More info](@ref offset-size-mode)| -| Dali::Toolkit::Visual::Transform::Property::ORIGIN | origin | INTEGER or STRING | No | The origin of the visual within the control's area. [More info](@ref align-type)] | +| Dali::Toolkit::Visual::Transform::Property::ORIGIN | origin | INTEGER or STRING | No | The origin of the visual within the control's area. [More info](@ref align-type) | | Dali::Toolkit::Visual::Transform::Property::ANCHOR_POINT | anchorPoint | INTEGER or STRING | No | The anchor point of the visual. [More info](@ref align-type)| @@ -282,6 +282,7 @@ Depending on the extension of the image, a different visual is provided to rende + [Normal (Quad)](@ref image-visual) + [N-Patch](@ref n-patch-visual) + [SVG](@ref svg-visual) + + [Animated Image]( @ref animated-image-visual ) ___________________________ @@ -440,6 +441,45 @@ control.background = url : "path-to-image.svg" }; ~~~ + +___________________________________________________________________________________________________ + +## Animated Image Visual {#animated-image-visual} + +Renders an animated image into the visual's quad geometry. Currently, only the GIF format is supported. + +![ ](../assets/img/visuals/animated-image-visual.gif) +![ ](animated-image-visual.gif) + +#### Properties Supported + +**VisualType:** Dali::Toolkit::Visual::IMAGE, "IMAGE" + +| Property | String | Type | Required | Description | +|-------------------------------------------|--------|:-------:|:--------:|----------------------------------| +| Dali::Toolkit::ImageVisual::Property::URL | url | STRING | Yes | The URL of the animated image. | + +#### Usage + +~~~{.cpp} +// C++ +Dali::Toolkit::Control control = Dali::Toolkit::Control::New(); + +control.SetProperty( Control::Property::BACKGROUND, + Property::Map().Add( Visual::Property::TYPE, Dali::Toolkit::Visual::IMAGE ) + .Add( Dali::Toolkit::ImageVisual::Property::URL, "path-to-image.gif" ) ); +~~~ + +~~~{.js} +// JavaScript +var control = new dali.Control( "Control" ); + +control.background = +{ + visualType : "IMAGE", + url : "path-to-image.gif" +}; +~~~ ___________________________________________________________________________________________________ ## Border Visual {#border-visual}