Wrap Mode support for ImageVisual 09/82509/9
authorXiangyin Ma <x1.ma@samsung.com>
Wed, 3 Aug 2016 13:14:45 +0000 (14:14 +0100)
committerXiangyin Ma <x1.ma@samsung.com>
Wed, 10 Aug 2016 15:27:46 +0000 (16:27 +0100)
Change-Id: Ie21e985867a800438e066fc78c98d640bbd76977

15 files changed:
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/internal/visuals/image/batch-image-visual.cpp
dali-toolkit/internal/visuals/image/batch-image-visual.h
dali-toolkit/internal/visuals/image/image-visual.cpp
dali-toolkit/internal/visuals/image/image-visual.h
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.h
dali-toolkit/internal/visuals/visual-base-data-impl.h
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h
dali-toolkit/internal/visuals/visual-factory-impl.cpp
dali-toolkit/internal/visuals/visual-factory-impl.h
dali-toolkit/public-api/visuals/image-visual-properties.h

index ef9dab8..f3667bc 100644 (file)
@@ -512,6 +512,9 @@ int UtcDaliVisualGetPropertyMap5(void)
   propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT,   30 );
   propertyMap.Insert( ImageVisual::Property::FITTING_MODE,   FittingMode::FIT_HEIGHT );
   propertyMap.Insert( ImageVisual::Property::SAMPLING_MODE,   SamplingMode::BOX_THEN_NEAREST );
+  propertyMap.Insert( ImageVisual::Property::PIXEL_AREA, Vector4( 0.25f, 0.25f, 0.5f, 0.5f ) );
+  propertyMap.Insert( ImageVisual::Property::WRAP_MODE_U, WrapMode::REPEAT );
+  propertyMap.Insert( ImageVisual::Property::WRAP_MODE_V, WrapMode::MIRRORED_REPEAT );
   propertyMap.Insert( "synchronousLoading",   true );
 
   Visual::Base imageVisual = factory.CreateVisual(propertyMap);
@@ -545,6 +548,18 @@ int UtcDaliVisualGetPropertyMap5(void)
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get<int>() == 30 );
 
+  value = resultMap.Find( ImageVisual::Property::PIXEL_AREA, Property::VECTOR4 );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_EQUALS( value->Get<Vector4>(), Vector4( 0.25f, 0.25f, 0.5f, 0.5f ), Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+  value = resultMap.Find( ImageVisual::Property::WRAP_MODE_U, Property::INTEGER );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK(  value->Get<int>() == WrapMode::REPEAT);
+
+  value = resultMap.Find( ImageVisual::Property::WRAP_MODE_V, Property::INTEGER );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK(  value->Get<int>() == WrapMode::MIRRORED_REPEAT);
+
   value = resultMap.Find( "synchronousLoading",   Property::BOOLEAN );
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get<bool>() == true );
@@ -578,6 +593,18 @@ int UtcDaliVisualGetPropertyMap5(void)
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get<int>() == 200 );
 
+  value = resultMap.Find( ImageVisual::Property::PIXEL_AREA, Property::VECTOR4 );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_EQUALS( value->Get<Vector4>(), Vector4( 0.f, 0.f, 1.f, 1.f ), Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+  value = resultMap.Find( ImageVisual::Property::WRAP_MODE_U, Property::INTEGER );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK(  value->Get<int>() == WrapMode::DEFAULT);
+
+  value = resultMap.Find( ImageVisual::Property::WRAP_MODE_V, Property::INTEGER );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK(  value->Get<int>() == WrapMode::DEFAULT);
+
   value = resultMap.Find( "synchronousLoading",   Property::BOOLEAN );
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get<bool>() == false );
index 53eee06..79b2f69 100644 (file)
@@ -17,6 +17,7 @@
 #include <iostream>
 #include <stdlib.h>
 #include <dali-toolkit-test-suite-utils.h>
+#include <toolkit-bitmap-loader.h>
 #include <toolkit-event-thread-callback.h>
 #include <dali/public-api/rendering/renderer.h>
 #include <dali/public-api/rendering/texture-set.h>
@@ -33,13 +34,17 @@ typedef NinePatchImage::StretchRanges StretchRanges;
 
 const char* TEST_IMAGE_FILE_NAME =  "gallery_image_01.jpg";
 const char* TEST_NPATCH_FILE_NAME =  "gallery_image_01.9.png";
-
 const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg";
 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_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: 34*34, pixel format: RGBA8888
+static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
+// resolution: 600*600, pixel format: RGB888
+static const char* gImage_600_RGB = TEST_RESOURCE_DIR "/test-image-600.jpg";
+
 Integration::Bitmap* CreateBitmap( unsigned int imageWidth, unsigned int imageHeight, unsigned int initialColor, Pixel::Format pixelFormat )
 {
   Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
@@ -251,7 +256,7 @@ int UtcDaliVisualFactoryGet(void)
   VisualFactory newFactory = VisualFactory::Get();
   DALI_TEST_CHECK( newFactory );
 
-  // Check that renderer factory is a singleton
+  // Check that visual factory is a singleton
   DALI_TEST_CHECK(factory == newFactory);
 
   END_TEST;
@@ -572,7 +577,7 @@ int UtcDaliVisualFactoryDefaultOffsetsGradientVisual(void)
 int UtcDaliVisualFactoryGetImageVisual1(void)
 {
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliVisualFactoryGetImageVisual1: Request image renderer with a Property::Map" );
+  tet_infoline( "UtcDaliVisualFactoryGetImageVisual1: Request image visual with a Property::Map" );
 
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK( factory );
@@ -612,7 +617,7 @@ int UtcDaliVisualFactoryGetImageVisual1(void)
 int UtcDaliVisualFactoryGetImageVisual2(void)
 {
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliVisualFactoryGetImageVisual2: Request image renderer with an image handle" );
+  tet_infoline( "UtcDaliVisualFactoryGetImageVisual2: Request image visual with an image handle" );
 
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK( factory );
@@ -643,10 +648,170 @@ int UtcDaliVisualFactoryGetImageVisual2(void)
   END_TEST;
 }
 
+int UtcDaliVisualFactoryGetImageVisual3(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualFactoryGetImageVisual3: Request image visual with a Property::Map, test custom wrap mode and pixel area with atlasing" );
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK( factory );
+
+  // Test wrap mode with atlasing. Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+  const int width=34;
+  const int height=34;
+  const Vector4 pixelArea(-0.5f, -0.5f, 2.f, 2.f);
+
+  Property::Map propertyMap;
+  propertyMap.Insert( Visual::Property::TYPE,  Visual::IMAGE );
+  propertyMap.Insert( ImageVisual::Property::URL,  gImage_34_RGBA );
+  propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, width );
+  propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, height );
+  propertyMap.Insert( ImageVisual::Property::SYNCHRONOUS_LOADING, true );
+  propertyMap.Insert( ImageVisual::Property::PIXEL_AREA, pixelArea );
+  propertyMap.Insert( ImageVisual::Property::WRAP_MODE_U, WrapMode::MIRRORED_REPEAT );
+  propertyMap.Insert( ImageVisual::Property::WRAP_MODE_V, WrapMode::REPEAT );
+
+  Visual::Base visual = factory.CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  Actor actor = Actor::New();
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& texParameterTrace = gl.GetTexParameterTrace();
+  texParameterTrace.Enable( true );
+
+  actor.SetSize( 200.f, 200.f );
+  Stage::GetCurrent().Add( actor );
+  visual.SetOnStage( actor );
+
+  // loading started
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+  BitmapLoader loader = BitmapLoader::GetLatestCreated();
+  DALI_TEST_CHECK( loader );
+  loader.WaitForLoading();// waiting until the image to be loaded
+  DALI_TEST_CHECK( loader.IsLoaded() );
+
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+  DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
+
+  // WITH atlasing, the wrapping is handled manually in shader, so the following gl function should not be called
+  std::stringstream out;
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_S << ", " << GL_MIRRORED_REPEAT;
+  DALI_TEST_CHECK( !texParameterTrace.FindMethodAndParams("TexParameteri", out.str()) );
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_T << ", " << GL_REPEAT;
+  DALI_TEST_CHECK( !texParameterTrace.FindMethodAndParams("TexParameteri", out.str()) );
+
+  // test the uniforms which used to handle the wrap mode
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  Property::Value pixelAreaValue = renderer.GetProperty( renderer.GetPropertyIndex( "pixelArea" ) );
+  DALI_TEST_EQUALS( pixelAreaValue.Get<Vector4>(), pixelArea, TEST_LOCATION );
+  Vector4 pixelAreaUniform;
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "pixelArea", pixelAreaUniform ) );
+  DALI_TEST_EQUALS( pixelArea, pixelAreaUniform, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+  Property::Value wrapModeValue = renderer.GetProperty( renderer.GetPropertyIndex( "wrapMode" ) );
+  Vector2 wrapMode( WrapMode::MIRRORED_REPEAT-1, WrapMode::REPEAT-1 );
+  DALI_TEST_EQUALS( wrapModeValue.Get<Vector2>(), wrapMode, TEST_LOCATION );
+  Vector2 wrapModeUniform;
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector2>( "wrapMode", wrapModeUniform ) );
+  DALI_TEST_EQUALS( wrapMode, wrapModeUniform, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+  visual.SetOffStage( actor );
+  DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+  END_TEST;
+}
+
+int UtcDaliVisualFactoryGetImageVisual4(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "UtcDaliVisualFactoryGetImageVisual4: Request image visual with a Property::Map, test custom wrap mode and pixel area without atlasing" );
+
+  VisualFactory factory = VisualFactory::Get();
+  DALI_TEST_CHECK( factory );
+
+  // Test wrap mode without atlasing. Image with a size bigger than 512*512 will NOT be uploaded as a part of the atlas.
+  const int width=600;
+  const int height=600;
+  const Vector4 pixelArea(-0.5f, -0.5f, 2.f, 2.f);
+
+  Property::Map propertyMap;
+  propertyMap.Insert( Visual::Property::TYPE,  Visual::IMAGE );
+  propertyMap.Insert( ImageVisual::Property::URL,  gImage_600_RGB );
+  propertyMap.Insert( ImageVisual::Property::DESIRED_WIDTH, width );
+  propertyMap.Insert( ImageVisual::Property::DESIRED_HEIGHT, height );
+  propertyMap.Insert( ImageVisual::Property::SYNCHRONOUS_LOADING, true );
+  propertyMap.Insert( ImageVisual::Property::PIXEL_AREA, pixelArea );
+  propertyMap.Insert( ImageVisual::Property::WRAP_MODE_U, WrapMode::MIRRORED_REPEAT );
+  propertyMap.Insert( ImageVisual::Property::WRAP_MODE_V, WrapMode::REPEAT );
+
+  Visual::Base visual = factory.CreateVisual( propertyMap );
+  DALI_TEST_CHECK( visual );
+
+  Actor actor = Actor::New();
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = gl.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& texParameterTrace = gl.GetTexParameterTrace();
+  texParameterTrace.Enable( true );
+
+  actor.SetSize( 200.f, 200.f );
+  Stage::GetCurrent().Add( actor );
+  visual.SetOnStage( actor );
+
+  // loading started
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+  BitmapLoader loader = BitmapLoader::GetLatestCreated();
+  DALI_TEST_CHECK( loader );
+  loader.WaitForLoading();// waiting until the image to be loaded
+  DALI_TEST_CHECK( loader.IsLoaded() );
+
+  DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+  DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
+
+  // WITHOUT atlasing, the wrapping is handled by setting gl texture parameters
+  std::stringstream out;
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_S << ", " << GL_MIRRORED_REPEAT;
+  DALI_TEST_CHECK( texParameterTrace.FindMethodAndParams("TexParameteri", out.str()) );
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_T << ", " << GL_REPEAT;
+  DALI_TEST_CHECK( texParameterTrace.FindMethodAndParams("TexParameteri", out.str()) );
+
+  // test the uniforms which used to handle the wrap mode
+  Renderer renderer = actor.GetRendererAt( 0u );
+  DALI_TEST_CHECK( renderer );
+
+  Property::Value pixelAreaValue = renderer.GetProperty( renderer.GetPropertyIndex( "pixelArea" ) );
+  DALI_TEST_EQUALS( pixelAreaValue.Get<Vector4>(), pixelArea, TEST_LOCATION );
+  Vector4 pixelAreaUniform;
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "pixelArea", pixelAreaUniform ) );
+  DALI_TEST_EQUALS( pixelArea, pixelAreaUniform, Math::MACHINE_EPSILON_100, TEST_LOCATION );
+
+  Property::Index wrapModeIndex = renderer.GetPropertyIndex( "wrapMode" );
+  DALI_TEST_CHECK(wrapModeIndex == Property::INVALID_INDEX);
+
+  visual.SetOffStage( actor );
+  DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+  END_TEST;
+}
+
 int UtcDaliVisualFactoryGetNPatchVisual1(void)
 {
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual1: Request 9-patch renderer with a Property::Map" );
+  tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual1: Request 9-patch visual with a Property::Map" );
 
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK( factory );
@@ -705,7 +870,7 @@ int UtcDaliVisualFactoryGetNPatchVisual1(void)
 int UtcDaliVisualFactoryGetNPatchVisual2(void)
 {
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual2: Request n-patch renderer with a Property::Map" );
+  tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual2: Request n-patch visual with a Property::Map" );
 
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK( factory );
@@ -773,7 +938,7 @@ int UtcDaliVisualFactoryGetNPatchVisual2(void)
 int UtcDaliVisualFactoryGetNPatchVisual3(void)
 {
   ToolkitTestApplication application;
-  tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual3: Request 9-patch renderer with an image url" );
+  tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual3: Request 9-patch visual with an image url" );
 
   VisualFactory factory = VisualFactory::Get();
   DALI_TEST_CHECK( factory );
@@ -971,7 +1136,7 @@ int UtcDaliVisualFactoryGetSvgVisual(void)
   END_TEST;
 }
 
-//Creates a mesh renderer from the given propertyMap and tries to load it on stage in the given application.
+//Creates a mesh visual from the given propertyMap and tries to load it on stage in the given application.
 //This is expected to succeed, which will then pass the test.
 void MeshVisualLoadsCorrectlyTest( Property::Map& propertyMap, ToolkitTestApplication& application )
 {
@@ -1514,7 +1679,7 @@ int UtcDaliVisualFactoryGetPrimitiveVisual8(void)
   END_TEST;
 }
 
-//Test if primitive shape renderer handles the case of not being passed a specific shape to use.
+//Test if primitive shape visual handles the case of not being passed a specific shape to use.
 int UtcDaliVisualFactoryGetPrimitiveVisualN1(void)
 {
   //Set up test application first, so everything else can be handled.
index 12bfdad..5e24418 100644 (file)
@@ -88,9 +88,8 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
 
 } //unnamed namespace
 
-BatchImageVisual::BatchImageVisual( VisualFactoryCache& factoryCache, ImageAtlasManager& atlasManager )
+BatchImageVisual::BatchImageVisual( VisualFactoryCache& factoryCache )
   : Visual::Base( factoryCache ),
-    mAtlasManager( atlasManager ),
     mDesiredSize()
 {
 }
@@ -191,7 +190,7 @@ void BatchImageVisual::InitializeRenderer( const std::string& imageUrl )
   {
     if( !mImpl->mRenderer )
     {
-      TextureSet textureSet = mAtlasManager.Add(
+      TextureSet textureSet = mFactoryCache.GetAtlasManager()->Add(
             mAtlasRect,
             imageUrl,
             mDesiredSize );
@@ -281,7 +280,7 @@ void BatchImageVisual::CleanCache(const std::string& url)
   mImpl->mRenderer.Reset();
   if( mFactoryCache.CleanRendererCache( url ) )
   {
-    mAtlasManager.Remove( textureSet, mAtlasRect );
+    mFactoryCache.GetAtlasManager()->Remove( textureSet, mAtlasRect );
   }
 }
 
index 750e28f..71f85f9 100644 (file)
@@ -40,9 +40,8 @@ public:
    * @brief Constructor.
    *
    * @param[in] factoryCache The VisualFactoryCache object
-   * @param[in] atlasManager The atlasManager object
    */
-  BatchImageVisual( VisualFactoryCache& factoryCache, ImageAtlasManager& atlasManager );
+  BatchImageVisual( VisualFactoryCache& factoryCache );
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -110,7 +109,6 @@ private:
 
 private:
 
-  ImageAtlasManager&      mAtlasManager;
   Vector4                 mAtlasRect;
   std::string             mImageUrl;
   Dali::ImageDimensions   mDesiredSize;
index e430c7b..6d980f6 100644 (file)
@@ -57,6 +57,8 @@ const char * const IMAGE_FITTING_MODE( "fittingMode" );
 const char * const IMAGE_SAMPLING_MODE( "samplingMode" );
 const char * const IMAGE_DESIRED_WIDTH( "desiredWidth" );
 const char * const IMAGE_DESIRED_HEIGHT( "desiredHeight" );
+const char * const IMAGE_WRAP_MODE_U("wrapModeU");
+const char * const IMAGE_WRAP_MODE_V("wrapModeV");
 const char * const SYNCHRONOUS_LOADING( "synchronousLoading" );
 const char * const BATCHING_ENABLED( "batchingEnabled" );
 
@@ -80,7 +82,16 @@ DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, NO_FILTER )
 DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::SamplingMode, DONT_CARE )
 DALI_ENUM_TO_STRING_TABLE_END( SAMPLING_MODE )
 
+// wrap modes
+DALI_ENUM_TO_STRING_TABLE_BEGIN( WRAP_MODE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, DEFAULT )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, CLAMP_TO_EDGE )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, REPEAT )
+DALI_ENUM_TO_STRING_WITH_SCOPE( Dali::WrapMode, MIRRORED_REPEAT )
+DALI_ENUM_TO_STRING_TABLE_END( WRAP_MODE )
+
 const std::string PIXEL_AREA_UNIFORM_NAME = "pixelArea";
+const std::string WRAP_MODE_UNIFORM_NAME = "wrapMode";
 
 const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f);
 
@@ -90,7 +101,6 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
   attribute mediump vec2 aPosition;\n
   uniform mediump mat4 uMvpMatrix;\n
   uniform mediump vec3 uSize;\n
-  uniform mediump vec4 uAtlasRect;\n
   uniform mediump vec4 pixelArea;
   varying mediump vec2 vTexCoord;\n
   \n
@@ -100,12 +110,12 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
     vertexPosition.xyz *= uSize;\n
     vertexPosition = uMvpMatrix * vertexPosition;\n
     \n
-    vTexCoord = mix( uAtlasRect.xy, uAtlasRect.zw, pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) ) );\n
+    vTexCoord = pixelArea.xy+pixelArea.zw*(aPosition + vec2(0.5) );\n
     gl_Position = vertexPosition;\n
   }\n
 );
 
-const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+const char* FRAGMENT_SHADER_NO_ATLAS = DALI_COMPOSE_SHADER(
   varying mediump vec2 vTexCoord;\n
   uniform sampler2D sTexture;\n
   uniform lowp vec4 uColor;\n
@@ -116,6 +126,42 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
   }\n
 );
 
+const char* FRAGMENT_SHADER_ATLAS_CLAMP = DALI_COMPOSE_SHADER(
+    varying mediump vec2 vTexCoord;\n
+    uniform sampler2D sTexture;\n
+    uniform mediump vec4 uAtlasRect;\n
+    uniform lowp vec4 uColor;\n
+    \n
+    void main()\n
+    {\n
+      mediump vec2 texCoord = mix( uAtlasRect.xy, uAtlasRect.zw, clamp( vTexCoord, 0.0, 1.0 ) );\n
+      gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n
+    }\n
+);
+
+const char* FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP = DALI_COMPOSE_SHADER(
+    varying mediump vec2 vTexCoord;\n
+    uniform sampler2D sTexture;\n
+    uniform mediump vec4 uAtlasRect;\n
+    // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
+    uniform lowp vec2 wrapMode;\n
+    uniform lowp vec4 uColor;\n
+    \n
+    mediump float wrapCoordinate( mediump float coordinate, lowp float wrap )\n
+    {\n
+      if( abs(wrap-2.0) < 0.5 )\n // REFLECT
+        return 1.0-abs(fract(coordinate*0.5)*2.0 - 1.0);\n
+      else \n// warp == 0 or 1
+        return mix( clamp( coordinate, 0.0, 1.0 ), fract( coordinate ), wrap);\n
+    }\n
+    void main()\n
+    {\n
+      mediump vec2 texCoord = mix( uAtlasRect.xy, uAtlasRect.zw,
+                              vec2( wrapCoordinate( vTexCoord.x, wrapMode.x ), wrapCoordinate( vTexCoord.y, wrapMode.y ) ) );\n
+      gl_FragColor = texture2D( sTexture, texCoord ) * uColor;\n
+    }\n
+);
+
 Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridSize )
 {
   Geometry geometry;
@@ -139,12 +185,14 @@ Geometry CreateGeometry( VisualFactoryCache& factoryCache, ImageDimensions gridS
 
 } //unnamed namespace
 
-ImageVisual::ImageVisual( VisualFactoryCache& factoryCache, ImageAtlasManager& atlasManager )
+ImageVisual::ImageVisual( VisualFactoryCache& factoryCache )
 : Visual::Base( factoryCache ),
-  mAtlasManager( atlasManager ),
+  mPixelArea( FULL_TEXTURE_RECT ),
   mDesiredSize(),
   mFittingMode( FittingMode::DEFAULT ),
   mSamplingMode( SamplingMode::DEFAULT ),
+  mWrapModeU( WrapMode::DEFAULT ),
+  mWrapModeV( WrapMode::DEFAULT ),
   mNativeFragmentShaderCode( ),
   mNativeImageFlag( false )
 {
@@ -193,6 +241,24 @@ void ImageVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap )
       desiredHeightValue->Get( desiredHeight );
     }
 
+    Property::Value* pixelAreaValue = propertyMap.Find( Toolkit::ImageVisual::Property::PIXEL_AREA, PIXEL_AREA_UNIFORM_NAME );
+    if( pixelAreaValue )
+    {
+      pixelAreaValue->Get( mPixelArea );
+    }
+
+    Property::Value* wrapModeValueU = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_U, IMAGE_WRAP_MODE_U );
+    if( wrapModeValueU )
+    {
+      Scripting::GetEnumerationProperty( *wrapModeValueU, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, mWrapModeU );
+    }
+
+    Property::Value* wrapModeValueV = propertyMap.Find( Toolkit::ImageVisual::Property::WRAP_MODE_V, IMAGE_WRAP_MODE_V );
+    if( wrapModeValueV )
+    {
+      Scripting::GetEnumerationProperty( *wrapModeValueV, WRAP_MODE_TABLE, WRAP_MODE_TABLE_COUNT, mWrapModeV );
+    }
+
     mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
   }
 
@@ -245,11 +311,6 @@ void ImageVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap )
   }
 }
 
-void ImageVisual::SetSize( const Vector2& size )
-{
-  Visual::Base::SetSize( size );
-}
-
 void ImageVisual::GetNaturalSize( Vector2& naturalSize ) const
 {
   if(mImage)
@@ -275,15 +336,6 @@ void ImageVisual::GetNaturalSize( Vector2& naturalSize ) const
   naturalSize = Vector2::ZERO;
 }
 
-void ImageVisual::SetClipRect( const Rect<int>& clipRect )
-{
-  Visual::Base::SetClipRect( clipRect );
-}
-
-void ImageVisual::SetOffset( const Vector2& offset )
-{
-}
-
 Renderer ImageVisual::CreateRenderer() const
 {
   Geometry geometry;
@@ -300,23 +352,24 @@ Renderer ImageVisual::CreateRenderer() const
   {
     geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
 
-    shader = GetImageShader(mFactoryCache);
+    shader = GetImageShader( mFactoryCache,
+                             mImpl->mFlags & Impl::IS_ATLASING_APPLIED,
+                             mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE );
   }
   else
   {
     geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
     if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
     {
-      shader = GetImageShader(mFactoryCache);
+      shader = GetImageShader(mFactoryCache, false, true);
     }
     else
     {
       shader  = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
-                             mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER : mImpl->mCustomShader->mFragmentShader,
+                             mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER_NO_ATLAS : mImpl->mCustomShader->mFragmentShader,
                              mImpl->mCustomShader->mHints );
       if( mImpl->mCustomShader->mVertexShader.empty() )
       {
-        shader.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT );
         shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
       }
     }
@@ -337,7 +390,6 @@ Renderer ImageVisual::CreateNativeImageRenderer() const
     geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
 
     shader  = Shader::New( VERTEX_SHADER, mNativeFragmentShaderCode );
-    shader.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT );
     shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
   }
   else
@@ -348,7 +400,6 @@ Renderer ImageVisual::CreateNativeImageRenderer() const
                            mImpl->mCustomShader->mHints );
     if( mImpl->mCustomShader->mVertexShader.empty() )
     {
-      shader.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT );
       shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
     }
   }
@@ -356,7 +407,6 @@ Renderer ImageVisual::CreateNativeImageRenderer() const
   TextureSet textureSet = TextureSet::New();
   Renderer renderer = Renderer::New( geometry, shader );
   renderer.SetTextures( textureSet );
-
   return renderer;
 }
 
@@ -383,7 +433,7 @@ Image ImageVisual::LoadImage( const std::string& url, bool synchronousLoading )
     if( !mPixels )
     {
       // use broken image
-      return VisualFactory::GetBrokenVisualImage();
+      return VisualFactoryCache::GetBrokenVisualImage();
     }
     Atlas image = Atlas::New( mPixels.GetWidth(), mPixels.GetHeight(), mPixels.GetPixelFormat() );
     image.Upload( mPixels, 0, 0 );
@@ -407,13 +457,15 @@ TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::strin
     {
       // use broken image
       textureSet = TextureSet::New();
-      TextureSetImage( textureSet, 0u, VisualFactory::GetBrokenVisualImage() );
+      TextureSetImage( textureSet, 0u, VisualFactoryCache::GetBrokenVisualImage() );
     }
     else
     {
-      textureSet = mAtlasManager.Add(textureRect, mPixels );
+      textureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, mPixels );
+      mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
       if( !textureSet ) // big image, no atlasing
       {
+        mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
         Atlas image = Atlas::New( mPixels.GetWidth(), mPixels.GetHeight(), mPixels.GetPixelFormat() );
         image.Upload( mPixels, 0, 0 );
         textureSet = TextureSet::New();
@@ -423,9 +475,11 @@ TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::strin
   }
   else
   {
-    textureSet = mAtlasManager.Add(textureRect, url, mDesiredSize, mFittingMode, mSamplingMode );
+    textureSet = mFactoryCache.GetAtlasManager()->Add(textureRect, url, mDesiredSize, mFittingMode, mSamplingMode );
+    mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
     if( !textureSet ) // big image, no atlasing
     {
+      mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
       ResourceImage resourceImage = Dali::ResourceImage::New( url, mDesiredSize, mFittingMode, mSamplingMode );
       resourceImage.LoadingFinishedSignal().Connect( this, &ImageVisual::OnImageLoaded );
       textureSet = TextureSet::New();
@@ -433,6 +487,13 @@ TextureSet ImageVisual::CreateTextureSet( Vector4& textureRect, const std::strin
     }
   }
 
+  if( !(mImpl->mFlags & Impl::IS_ATLASING_APPLIED) )
+  {
+    Sampler sampler = Sampler::New();
+    sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
+    textureSet.SetSampler( 0u, sampler );
+  }
+
   return textureSet;
 }
 
@@ -450,28 +511,46 @@ void ImageVisual::InitializeRenderer( const std::string& imageUrl )
       ( strncasecmp( imageUrl.c_str(), HTTP_URL,  sizeof(HTTP_URL)  -1 ) != 0 ) && // ignore remote images
       ( strncasecmp( imageUrl.c_str(), HTTPS_URL, sizeof(HTTPS_URL) -1 ) != 0 ) )
   {
-    mImpl->mRenderer = mFactoryCache.GetRenderer( imageUrl );
-    if( !mImpl->mRenderer )
+    bool defaultWrapMode = mWrapModeU <= WrapMode::CLAMP_TO_EDGE && mWrapModeV <= WrapMode::CLAMP_TO_EDGE;
+    bool cacheable =  defaultWrapMode &&  mPixelArea == FULL_TEXTURE_RECT;
+
+    mImpl->mFlags &= ~Impl::IS_FROM_CACHE;
+    if( cacheable ) // fetch the renderer from cache if exist
+    {
+      mImpl->mRenderer = mFactoryCache.GetRenderer( imageUrl );
+      mImpl->mFlags |= Impl::IS_FROM_CACHE;
+    }
+
+    if( !mImpl->mRenderer ) // new renderer is needed
     {
       Vector4 atlasRect;
       TextureSet textureSet = CreateTextureSet(atlasRect, imageUrl, IsSynchronousResourceLoading() );
       Geometry geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
-      Shader shader( GetImageShader(mFactoryCache) );
+      Shader shader( GetImageShader(mFactoryCache, mImpl->mFlags & Impl::IS_ATLASING_APPLIED, defaultWrapMode) );
       mImpl->mRenderer = Renderer::New( geometry, shader );
       mImpl->mRenderer.SetTextures( textureSet );
-      if( atlasRect != FULL_TEXTURE_RECT )
+
+      if( mImpl->mFlags & Impl::IS_ATLASING_APPLIED ) // the texture is packed inside atlas
       {
         mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect );
+        if( !defaultWrapMode ) // custom wrap mode, renderer is not cached.
+        {
+          Vector2 wrapMode(mWrapModeU-WrapMode::CLAMP_TO_EDGE, mWrapModeV-WrapMode::CLAMP_TO_EDGE);
+          wrapMode.Clamp( Vector2::ZERO, Vector2( 2.f, 2.f ) );
+          mImpl->mRenderer.RegisterProperty( WRAP_MODE_UNIFORM_NAME, wrapMode );
+        }
       }
-      mFactoryCache.SaveRenderer( imageUrl, mImpl->mRenderer );
-    }
 
-    mImpl->mFlags |= Impl::IS_FROM_CACHE;
+      // save the renderer to cache only when default wrap mode and default pixel area is used
+      if( cacheable )
+      {
+        mFactoryCache.SaveRenderer( imageUrl, mImpl->mRenderer );
+      }
+    }
   }
   else
   {
     // for custom shader or remote image, renderer is not cached and atlas is not applied
-
     mImpl->mFlags &= ~Impl::IS_FROM_CACHE;
     mImpl->mRenderer = CreateRenderer();
     Image image = LoadImage( imageUrl, IsSynchronousResourceLoading() );
@@ -501,6 +580,11 @@ void ImageVisual::DoSetOnStage( Actor& actor )
   {
     InitializeRenderer( mImage );
   }
+
+  if( mPixelArea != FULL_TEXTURE_RECT )
+  {
+    mImpl->mRenderer.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, mPixelArea );
+  }
 }
 
 void ImageVisual::DoSetOffStage( Actor& actor )
@@ -546,18 +630,46 @@ void ImageVisual::DoCreatePropertyMap( Property::Map& map ) const
 
   map.Insert( Toolkit::ImageVisual::Property::FITTING_MODE, mFittingMode );
   map.Insert( Toolkit::ImageVisual::Property::SAMPLING_MODE, mSamplingMode );
+
+  map.Insert( Toolkit::ImageVisual::Property::PIXEL_AREA, mPixelArea );
+  map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_U, mWrapModeU );
+  map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV );
 }
 
-Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache )
+Shader ImageVisual::GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping )
 {
-  Shader shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
-  if( !shader )
+  Shader shader;
+  if( atlasing )
   {
-    shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
-    factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
-    shader.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, FULL_TEXTURE_RECT );
-    shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
+    if( defaultTextureWrapping )
+    {
+      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP );
+      if( !shader )
+      {
+        shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_CLAMP );
+        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_DEFAULT_WRAP, shader );
+      }
+    }
+    else
+    {
+      shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP );
+      if( !shader )
+      {
+        shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_ATLAS_VARIOUS_WRAP );
+        factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER_ATLAS_CUSTOM_WRAP, shader );
+      }
+    }
+  }
+  else
+  {
+    shader = factoryCache.GetShader( VisualFactoryCache::IMAGE_SHADER );
+    if( !shader )
+    {
+      shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER_NO_ATLAS );
+      factoryCache.SaveShader( VisualFactoryCache::IMAGE_SHADER, shader );
+    }
   }
+  shader.RegisterProperty( PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT );
   return shader;
 }
 
@@ -697,6 +809,9 @@ void ImageVisual::ApplyImageToSampler( const Image& image )
       mImpl->mRenderer.SetTextures( textureSet );
     }
     TextureSetImage( textureSet, 0u, image );
+    Sampler sampler = Sampler::New();
+    sampler.SetWrapMode(  mWrapModeU, mWrapModeV  );
+    textureSet.SetSampler( 0u, sampler );
   }
 }
 
@@ -704,7 +819,7 @@ void ImageVisual::OnImageLoaded( ResourceImage image )
 {
   if( image.GetLoadingState() == Dali::ResourceLoadingFailed )
   {
-    Image brokenImage = VisualFactory::GetBrokenVisualImage();
+    Image brokenImage = VisualFactoryCache::GetBrokenVisualImage();
     if( mImpl->mRenderer )
     {
       ApplyImageToSampler( brokenImage );
@@ -727,7 +842,7 @@ void ImageVisual::CleanCache(const std::string& url)
   mImpl->mRenderer.Reset();
   if( mFactoryCache.CleanRendererCache( url ) && index != Property::INVALID_INDEX )
   {
-    mAtlasManager.Remove( textureSet, atlasRect );
+    mFactoryCache.GetAtlasManager()->Remove( textureSet, atlasRect );
   }
 }
 
@@ -748,7 +863,7 @@ void ImageVisual::SetNativeFragmentShaderCode( Dali::NativeImage& nativeImage )
   }
   else
   {
-    mNativeFragmentShaderCode += FRAGMENT_SHADER;
+    mNativeFragmentShaderCode += FRAGMENT_SHADER_NO_ATLAS;
   }
 
   if( customSamplerTypename )
index baad92f..64b3f4b 100644 (file)
@@ -20,7 +20,6 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 
 // EXTERNAL INCLUDES
 #include <dali/public-api/images/image.h>
@@ -81,9 +80,8 @@ public:
    * @brief Constructor.
    *
    * @param[in] factoryCache The VisualFactoryCache object
-   * @param[in] atlasManager The atlasManager object
    */
-  ImageVisual( VisualFactoryCache& factoryCache, ImageAtlasManager& atlasManager );
+  ImageVisual( VisualFactoryCache& factoryCache );
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -93,26 +91,11 @@ public:
 public:  // from Visual
 
   /**
-   * @copydoc Visual::SetSize
-   */
-  virtual void SetSize( const Vector2& size );
-
-  /**
    * @copydoc Visual::GetNaturalSize
    */
   virtual void GetNaturalSize( Vector2& naturalSize ) const;
 
   /**
-   * @copydoc Visual::SetClipRect
-   */
-  virtual void SetClipRect( const Rect<int>& clipRect );
-
-  /**
-   * @copydoc Visual::SetOffset
-   */
-  virtual void SetOffset( const Vector2& offset );
-
-  /**
    * @copydoc Visual::CreatePropertyMap
    */
   virtual void DoCreatePropertyMap( Property::Map& map ) const;
@@ -138,8 +121,10 @@ public:
   /**
    * Get the standard image rendering shader.
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
+   * @param[in] atlasing Whether texture atlasing is applied.
+   * @param[in] defaultTextureWrapping Whether the default texture wrap mode is applied.
    */
-  static Shader GetImageShader( VisualFactoryCache& factoryCache );
+  static Shader GetImageShader( VisualFactoryCache& factoryCache, bool atlasing, bool defaultTextureWrapping );
 
   /**
    * @brief Sets the image of this visual to the resource at imageUrl
@@ -252,13 +237,15 @@ private:
 
 private:
   Image mImage;
-  ImageAtlasManager& mAtlasManager;
   PixelData mPixels;
+  Vector4 mPixelArea;
 
   std::string mImageUrl;
   Dali::ImageDimensions mDesiredSize;
   Dali::FittingMode::Type mFittingMode;
   Dali::SamplingMode::Type mSamplingMode;
+  Dali::WrapMode::Type mWrapModeU;
+  Dali::WrapMode::Type mWrapModeV;
 
   std::string mNativeFragmentShaderCode;
   bool mNativeImageFlag;
index fb13383..7ef3a6e 100644 (file)
@@ -522,7 +522,7 @@ void NPatchVisual::InitializeFromImage( NinePatchImage nPatch )
 
 void NPatchVisual::InitializeFromBrokenImage()
 {
-  mCroppedImage = VisualFactory::GetBrokenVisualImage();
+  mCroppedImage = VisualFactoryCache::GetBrokenVisualImage();
   mImageSize = ImageDimensions( mCroppedImage.GetWidth(), mCroppedImage.GetHeight() );
 
   mStretchPixelsX.Clear();
index f73df9f..4179d4d 100644 (file)
@@ -31,6 +31,7 @@
 #include <dali-toolkit/third-party/nanosvg/nanosvg.h>
 #include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 #include <dali-toolkit/internal/visuals/image/image-visual.h>
+#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
 #include <dali-toolkit/internal/visuals/visual-base-data-impl.h>
@@ -52,10 +53,9 @@ namespace Toolkit
 namespace Internal
 {
 
-SvgVisual::SvgVisual( VisualFactoryCache& factoryCache, ImageAtlasManager& atlasManager )
+SvgVisual::SvgVisual( VisualFactoryCache& factoryCache )
 : Visual::Base( factoryCache ),
   mAtlasRect( FULL_TEXTURE_RECT ),
-  mAtlasManager( atlasManager ),
   mParsedImage( NULL )
 {
   // the rasterized image is with pre-multiplied alpha format
@@ -94,7 +94,7 @@ void SvgVisual::DoInitialize( Actor& actor, const Property::Map& propertyMap )
 
 void SvgVisual::DoSetOnStage( Actor& actor )
 {
-  Shader shader = ImageVisual::GetImageShader( mFactoryCache );
+  Shader shader = ImageVisual::GetImageShader( mFactoryCache, true, true );
   Geometry geometry = mFactoryCache.GetGeometry( VisualFactoryCache::QUAD_GEOMETRY );
   if( !geometry )
   {
@@ -198,11 +198,11 @@ void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData )
     TextureSet currentTextureSet = mImpl->mRenderer.GetTextures();
     if( mAtlasRect != FULL_TEXTURE_RECT )
     {
-      mAtlasManager.Remove( currentTextureSet, mAtlasRect );
+      mFactoryCache.GetAtlasManager()->Remove( currentTextureSet, mAtlasRect );
     }
 
     Vector4 atlasRect;
-    TextureSet textureSet = mAtlasManager.Add(atlasRect, rasterizedPixelData );
+    TextureSet textureSet = mFactoryCache.GetAtlasManager()->Add(atlasRect, rasterizedPixelData );
     if( textureSet ) // atlasing
     {
       if( textureSet != currentTextureSet )
@@ -211,11 +211,13 @@ void SvgVisual::ApplyRasterizedImage( PixelData rasterizedPixelData )
       }
       mImpl->mRenderer.RegisterProperty( ATLAS_RECT_UNIFORM_NAME, atlasRect );
       mAtlasRect = atlasRect;
+      mImpl->mFlags |= Impl::IS_ATLASING_APPLIED;
     }
     else // no atlasing
     {
       Atlas texture = Atlas::New( rasterizedPixelData.GetWidth(), rasterizedPixelData.GetHeight() );
       texture.Upload( rasterizedPixelData, 0, 0 );
+      mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
 
       if( mAtlasRect == FULL_TEXTURE_RECT )
       {
index e4e97da..d841621 100644 (file)
@@ -20,7 +20,6 @@
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 
 struct NSVGimage;
 
@@ -52,7 +51,7 @@ public:
    *
    * @param[in] factoryCache A pointer pointing to the VisualFactoryCache object
    */
-  SvgVisual( VisualFactoryCache& factoryCache, ImageAtlasManager& atlasManager );
+  SvgVisual( VisualFactoryCache& factoryCache );
 
   /**
    * @brief A reference counted object may only be deleted by calling Unreference().
@@ -136,7 +135,6 @@ private:
 
 private:
   Vector4              mAtlasRect;
-  ImageAtlasManager&   mAtlasManager;
   std::string          mImageUrl;
   NSVGimage*           mParsedImage;
 
index 3ffdafb..fb8ae32 100644 (file)
@@ -43,8 +43,9 @@ struct Base::Impl
   {
     IS_ON_STAGE = 1,
     IS_FROM_CACHE = 1 << 1,
-    IS_PREMULTIPLIED_ALPHA = 1 << 2,
-    IS_SYNCHRONOUS_RESOURCE_LOADING = 1 << 3
+    IS_ATLASING_APPLIED = 1<<2,
+    IS_PREMULTIPLIED_ALPHA = 1 << 3,
+    IS_SYNCHRONOUS_RESOURCE_LOADING = 1 << 4
   };
 
   struct CustomShader
index 404f2ec..da86201 100644 (file)
 
 // EXTERNAL HEADER
 #include <dali/devel-api/common/hash.h>
+#include <dali/public-api/images/resource-image.h>
 
 // INTERNAL HEADER
 #include <dali-toolkit/internal/visuals/color/color-visual.h>
 #include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
+
+namespace
+{
+const char * const BROKEN_VISUAL_IMAGE_URL( DALI_IMAGE_DIR "broken.png");
+}
 
 namespace Dali
 {
@@ -179,6 +186,17 @@ Geometry VisualFactoryCache::CreateQuadGeometry()
   return geometry;
 }
 
+ImageAtlasManagerPtr VisualFactoryCache::GetAtlasManager()
+{
+  if( !mAtlasManager )
+  {
+    mAtlasManager = new ImageAtlasManager();
+    mAtlasManager->SetBrokenImage( BROKEN_VISUAL_IMAGE_URL );
+  }
+
+  return mAtlasManager;
+}
+
 SvgRasterizeThread* VisualFactoryCache::GetSVGRasterizationThread()
 {
   if( !mSvgRasterizeThread )
@@ -309,6 +327,11 @@ Geometry VisualFactoryCache::CreateBatchQuadGeometry( Vector4 texCoords )
   return geometry;
 }
 
+Image VisualFactoryCache::GetBrokenVisualImage()
+{
+  return ResourceImage::New( BROKEN_VISUAL_IMAGE_URL );
+}
+
 } // namespace Internal
 
 } // namespace Toolkit
index 2c2210a..6f67a66 100644 (file)
@@ -39,6 +39,9 @@ namespace Toolkit
 namespace Internal
 {
 
+class ImageAtlasManager;
+typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
+
 /**
  * Caches shaders and geometries. Owned by VisualFactory.
  */
@@ -60,6 +63,8 @@ public:
     GRADIENT_SHADER_RADIAL_BOUNDING_BOX,
     IMAGE_SHADER,
     BATCH_IMAGE_SHADER,
+    IMAGE_SHADER_ATLAS_DEFAULT_WRAP,
+    IMAGE_SHADER_ATLAS_CUSTOM_WRAP,
     NINE_PATCH_SHADER,
     SVG_SHADER,
     SHADER_TYPE_MAX = SVG_SHADER
@@ -130,6 +135,12 @@ public:
    */
   static Geometry CreateBatchQuadGeometry( Vector4 texCoords );
 
+  /**
+   * @brief Returns an image to be used when a visual has failed to correctly render
+   * @return The broken image handle.
+   */
+  static Image GetBrokenVisualImage();
+
 public:
 
   /**
@@ -170,6 +181,12 @@ public:
   Renderer GetDebugRenderer();
 
   /**
+   * Get the image atlas manager.
+   * @return A pointer pointing to the atlas manager
+   */
+  ImageAtlasManagerPtr GetAtlasManager();
+
+  /**
    * Get the SVG rasterization thread.
    * @return A pointer pointing to the SVG rasterization thread.
    */
@@ -230,6 +247,7 @@ private:
 
   Renderer mDebugRenderer;
 
+  ImageAtlasManagerPtr mAtlasManager;
   SvgRasterizeThread*  mSvgRasterizeThread;
 };
 
index df9cbb3..80f4420 100644 (file)
 #include <dali-toolkit/internal/visuals/primitive/primitive-visual.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
 #include <dali-toolkit/internal/visuals/image/batch-image-visual.h>
 
-namespace
-{
-const char * const BROKEN_VISUAL_IMAGE_URL( DALI_IMAGE_DIR "broken.png");
-}
-
 namespace Dali
 {
 
@@ -149,8 +143,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property
           batchingEnabledValue->Get( batchingEnabled );
           if( batchingEnabled )
           {
-            CreateAtlasManager();
-            visualPtr = new BatchImageVisual( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
+            visualPtr = new BatchImageVisual( *( mFactoryCache.Get() ) );
             break;
           }
         }
@@ -158,20 +151,16 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& property
         {
           visualPtr = new NPatchVisual( *( mFactoryCache.Get() ) );
         }
+        else if( SvgVisual::IsSvgUrl( imageUrl ) )
+        {
+          visualPtr = new SvgVisual( *( mFactoryCache.Get() ) );
+        }
         else
         {
-          CreateAtlasManager();
-
-          if( SvgVisual::IsSvgUrl( imageUrl ) )
-          {
-            visualPtr = new SvgVisual( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
-          }
-          else
-          {
-            visualPtr = new ImageVisual( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
-          }
+          visualPtr = new ImageVisual( *( mFactoryCache.Get() ) );
         }
       }
+
       break;
     }
 
@@ -230,8 +219,7 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const Image& image )
   }
   else
   {
-    CreateAtlasManager();
-    ImageVisual* visualPtr = new ImageVisual( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
+    ImageVisual* visualPtr = new ImageVisual( *( mFactoryCache.Get() ) );
     Actor actor;
     visualPtr->SetImage( actor, image );
 
@@ -260,15 +248,13 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, Image
   }
   else if( SvgVisual::IsSvgUrl( url ) )
   {
-    CreateAtlasManager();
-    SvgVisual* visualPtr = new SvgVisual( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
+    SvgVisual* visualPtr = new SvgVisual( *( mFactoryCache.Get() ) );
     visualPtr->SetImage( url, size );
     return Toolkit::Visual::Base( visualPtr );
   }
   else
   {
-    CreateAtlasManager();
-    ImageVisual* visualPtr = new ImageVisual( *( mFactoryCache.Get() ), *( mAtlasManager.Get() ) );
+    ImageVisual* visualPtr = new ImageVisual( *( mFactoryCache.Get() ));
     Actor actor;
     visualPtr->SetImage( actor, url, size );
 
@@ -276,21 +262,6 @@ Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, Image
   }
 }
 
-Image VisualFactory::GetBrokenVisualImage()
-{
-  return ResourceImage::New( BROKEN_VISUAL_IMAGE_URL );
-}
-
-void VisualFactory::CreateAtlasManager()
-{
-  if( !mAtlasManager )
-  {
-    Shader shader = ImageVisual::GetImageShader( *( mFactoryCache.Get() ) );
-    mAtlasManager = new ImageAtlasManager();
-    mAtlasManager->SetBrokenImage( BROKEN_VISUAL_IMAGE_URL );
-  }
-}
-
 } // namespace Internal
 
 } // namespace Toolkit
index f6e8d9c..484a688 100644 (file)
@@ -36,9 +36,6 @@ namespace Internal
 class VisualFactoryCache;
 typedef IntrusivePtr<VisualFactoryCache> VisualFactoryCachePtr;
 
-class ImageAtlasManager;
-typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
-
 /**
  * @copydoc Toolkit::VisualFactory
  */
@@ -68,11 +65,6 @@ public:
    */
   Toolkit::Visual::Base CreateVisual( const std::string& image, ImageDimensions size );
 
-public:
-  /**
-   * @brief Returns an image to be used when a visual has failed to correctly render
-   */
-  static Image GetBrokenVisualImage();
 
 protected:
 
@@ -84,11 +76,6 @@ protected:
 private:
 
   /**
-   * Prepare the atlas manager
-   */
-  void CreateAtlasManager();
-
-  /**
    * Undefined copy constructor.
    */
   VisualFactory(const VisualFactory&);
@@ -101,7 +88,6 @@ private:
 private:
 
   VisualFactoryCachePtr   mFactoryCache;
-  ImageAtlasManagerPtr    mAtlasManager;
   bool                    mDebugEnabled;
 };
 
index 7d46ac7..882f932 100644 (file)
@@ -103,9 +103,41 @@ enum
    * @brief This enables Image visuals to automatically be converted to Batch-Image visuals.
    * @details Name "batchingEnabled", type Property::BOOLEAN.
    * @SINCE_1_2.0
-   * @note Optional. For Image visuals only. Not to be used with NPatch or SVG images.
+   * @note Optional. If not specified, the default is false.
+   * @note For Image visuals only. Not to be used with NPatch or SVG images.
    */
   BATCHING_ENABLED,
+
+  /**
+   * @brief The image area to be displayed.
+   * @details Name "pixelArea", type Property::VECTOR4.
+   *          It is a rectangular area.
+   *          The first two elements indicate the top-left position of the area, and the last two elements are the area width and height respectively.
+   * @SINCE_1_2.1
+   * @note Optional. If not specified, the default value is [0.0, 0.0, 1.0, 1.0], i.e. the entire area of the image.
+   * @note For Normal Quad images only.
+   */
+  PIXEL_AREA,
+
+  /**
+   * @brief The wrap mode for u coordinate.
+   * @details Name "wrapModeU", type Dali::WrapMode::Type (Property::INTEGER) or Property::STRING
+   *          It decides how the texture should be sampled when the u coordinate exceeds the range of 0.0 to 1.0.
+   * @SINCE_1_2.1
+   * @note Optional. If not specified, the default is CLAMP.
+   * @note For Normal QUAD image only.
+   */
+  WRAP_MODE_U,
+
+  /**
+   * @brief The wrap mode for v coordinate.
+   * @details Name "wrapModeV", type Dali::WrapMode::Type (Property::INTEGER) or Property::STRING
+   *          it decides how the texture should be sampled when the v coordinate exceeds the range of 0.0 to 1.0.
+   * @SINCE_1_2.1
+   * @note Optional. If not specified, the default is CLAMP.
+   * @note For Normal QUAD image only.
+   */
+  WRAP_MODE_V,
 };
 
 } // namespace Property