Cache NPatch textures 69/94869/13
authorKimmo Hoikka <kimmo.hoikka@samsung.com>
Tue, 1 Nov 2016 15:16:35 +0000 (15:16 +0000)
committerKimmo Hoikka <kimmo.hoikka@samsung.com>
Fri, 4 Nov 2016 18:47:19 +0000 (18:47 +0000)
- introduce NPatchLoader, a simple cache to store loaded N patches, their textures and metadata
- refactor NPatchVisual to use NPatchLoader and removed some dead / inefficient code

GL stat improvements in dali-demo

Before (only relevant numbers presented)
-----------------------------------------
INFO: DALI: OpenGL ES statistics sampled over 60 frames) operations per frame:
INFO: DALI:   Bind textures : Mean 109.17  (Min:107.00, Max:113.00, StdDev: 1.33, Actual:6550)
INFO: DALI: OpenGL ES Object Count:
INFO: DALI:   Texture Count : 101  (Peak:101)

After
-----------------------------------------
INFO: DALI: OpenGL ES statistics sampled over 60 frames) operations per frame:
INFO: DALI:   Bind textures : Mean 14.83  (Min:14.00, Max:15.00, StdDev: 0.37, Actual:890)
INFO: DALI: OpenGL ES Object Count:
INFO: DALI:   Texture Count : 8  (Peak:8)

Change-Id: I4ce84e6c6578c30660106950b40dd3bc0c41efa1

23 files changed:
automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp
automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp
dali-toolkit/devel-api/visual-factory/visual-base.cpp
dali-toolkit/devel-api/visual-factory/visual-base.h
dali-toolkit/internal/file.list
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-loader.cpp [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch-loader.h [new file with mode: 0644]
dali-toolkit/internal/visuals/npatch/npatch-visual.cpp
dali-toolkit/internal/visuals/npatch/npatch-visual.h
dali-toolkit/internal/visuals/primitive/primitive-visual.cpp
dali-toolkit/internal/visuals/primitive/primitive-visual.h
dali-toolkit/internal/visuals/svg/svg-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.h
dali-toolkit/internal/visuals/text/text-visual.cpp
dali-toolkit/internal/visuals/text/text-visual.h
dali-toolkit/internal/visuals/visual-base-impl.cpp
dali-toolkit/internal/visuals/visual-base-impl.h
dali-toolkit/internal/visuals/visual-factory-cache.cpp
dali-toolkit/internal/visuals/visual-factory-cache.h

index 4959ed9..5f70749 100644 (file)
@@ -191,16 +191,7 @@ int UtcDaliVisualSize(void)
   imageVisual.GetNaturalSize(naturalSize);
   DALI_TEST_EQUALS( naturalSize, Vector2(100.f, 200.f), TEST_LOCATION );
 
-  // n patch visual
-  TestPlatformAbstraction& platform = application.GetPlatform();
-  Vector2 testSize(80.f, 160.f);
-  platform.SetClosestImageSize(testSize);
-  image = ResourceImage::New(TEST_NPATCH_FILE_NAME);
-  Visual::Base nPatchVisual = factory.CreateVisual( image );
-  nPatchVisual.SetSize( visualSize );
-  DALI_TEST_EQUALS( nPatchVisual.GetSize(), visualSize, TEST_LOCATION );
-  nPatchVisual.GetNaturalSize(naturalSize);
-  DALI_TEST_EQUALS( naturalSize, testSize, TEST_LOCATION );
+  // n patch visual is tested in the utc-Dali-VisualFactory.cpp
 
   // border visual
   float borderSize = 5.f;
@@ -250,6 +241,9 @@ int UtcDaliVisualSize(void)
   DALI_TEST_EQUALS( naturalSize, Vector2(100.f, 100.f), TEST_LOCATION ); // Natural size should still be 100, 100
 
   // Batch Image visual
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  Vector2 testSize(80.f, 160.f);
+  platform.SetClosestImageSize(testSize);
   propertyMap.Clear();
   propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE );
   propertyMap.Insert( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME );
@@ -707,10 +701,6 @@ int UtcDaliVisualGetPropertyMap5(void)
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get<bool>() == false );
 
-  // Test the properties. TODO: to be completed.
-  imageVisual.SetProperty( ImageVisual::Property::URL, TEST_IMAGE_FILE_NAME );
-  Property::Value imageValue = imageVisual.GetProperty( ImageVisual::Property::URL );
-
   END_TEST;
 }
 
@@ -742,9 +732,6 @@ int UtcDaliVisualGetPropertyMap6(void)
   DALI_TEST_CHECK( value );
   DALI_TEST_CHECK( value->Get<bool>() );
 
-  // Test the properties. TODO: to be completed.
-  nPatchVisual.SetProperty( ImageVisual::Property::URL, TEST_NPATCH_FILE_NAME );
-  Property::Value nPatchValue = nPatchVisual.GetProperty( ImageVisual::Property::URL );
 
   END_TEST;
 }
@@ -1596,4 +1583,37 @@ int UtcDaliVisualSetTransform7(void)
   END_TEST;
 }
 
+int UtcDaliNPatchVisualCustomShader(void)
+{
+  ToolkitTestApplication application;
+  tet_infoline( "NPatchVisual with custom shader" );
+
+  VisualFactory factory = VisualFactory::Get();
+  Property::Map properties;
+  Property::Map shader;
+  const std::string fragmentShader = "Foobar";
+  shader[Dali::Toolkit::Visual::Shader::Property::FRAGMENT_SHADER] = fragmentShader;
+  properties[Dali::Toolkit::Visual::Property::TYPE] = Dali::Toolkit::Visual::IMAGE;
+  properties[Dali::Toolkit::Visual::Property::SHADER]=shader;
+  properties[Dali::Toolkit::ImageVisual::Property::URL] = TEST_NPATCH_FILE_NAME;
+
+  Visual::Base visual = factory.CreateVisual( properties );
+  Actor dummy = Actor::New();
+  // trigger creation through setting on stage
+  visual.SetOnStage( dummy );
+
+  Renderer renderer = dummy.GetRendererAt( 0 );
+  Shader shader2 = renderer.GetShader();
+  Property::Value value = shader2.GetProperty( Shader::Property::PROGRAM );
+  Property::Map* map = value.GetMap();
+  DALI_TEST_CHECK( map );
+
+  Property::Value* fragment = map->Find( "fragment" ); // fragment key name from shader-impl.cpp
+  // *map["vertex"]; is default here so not verifying it
+
+  DALI_TEST_EQUALS( fragmentShader, fragment->Get<std::string>(), TEST_LOCATION );
+
+  END_TEST;
+}
+
 
index 3fe52b4..b6b42e3 100644 (file)
@@ -967,6 +967,15 @@ int UtcDaliVisualFactoryGetNPatchVisual3(void)
 
   DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
 
+
+  ResourceImage image = ResourceImage::New(TEST_NPATCH_FILE_NAME);
+  Visual::Base nPatchVisual = factory.CreateVisual( image );
+  Vector2 visualSize( 20.f, 30.f ), naturalSize(0,0);
+  nPatchVisual.SetSize( visualSize );
+  DALI_TEST_EQUALS( nPatchVisual.GetSize(), visualSize, TEST_LOCATION );
+  nPatchVisual.GetNaturalSize( naturalSize );
+  DALI_TEST_EQUALS( naturalSize, Vector2( ninePatchImageWidth-2, ninePatchImageHeight-2 ), TEST_LOCATION );
+
   END_TEST;
 }
 
index c40bc41..7a4821b 100644 (file)
@@ -76,7 +76,7 @@ float Visual::Base::GetHeightForWidth( float width ) const
   return GetImplementation( *this ).GetHeightForWidth( width );
 }
 
-void Visual::Base::GetNaturalSize(Vector2& naturalSize ) const
+void Visual::Base::GetNaturalSize(Vector2& naturalSize )
 {
   GetImplementation( *this ).GetNaturalSize( naturalSize );
 }
index 2cbb0b7..b590484 100644 (file)
@@ -121,7 +121,7 @@ public:
    *
    * @param[out] naturalSize The visual's natural size
    */
-  void GetNaturalSize( Vector2& naturalSize ) const;
+  void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @brief Set the depth index of this visual.
index 57b4dbf..902074b 100644 (file)
@@ -13,6 +13,7 @@ toolkit_src_files = \
    $(toolkit_src_dir)/visuals/visual-base-impl.cpp \
    $(toolkit_src_dir)/visuals/visual-base-data-impl.cpp \
    $(toolkit_src_dir)/visuals/image-atlas-manager.cpp \
+   $(toolkit_src_dir)/visuals/npatch-loader.cpp \
    $(toolkit_src_dir)/visuals/visual-factory-cache.cpp \
    $(toolkit_src_dir)/visuals/visual-factory-impl.cpp \
    $(toolkit_src_dir)/visuals/visual-string-constants.cpp \
index fe803b2..90d2b53 100644 (file)
@@ -132,7 +132,7 @@ void BatchImageVisual::SetSize( const Vector2& size )
   Visual::Base::SetSize( size );
 }
 
-void BatchImageVisual::GetNaturalSize( Vector2& naturalSize ) const
+void BatchImageVisual::GetNaturalSize( Vector2& naturalSize )
 {
   if( mDesiredSize.GetWidth() > 0 && mDesiredSize.GetHeight() > 0 )
   {
index d670c5d..85ef5b4 100644 (file)
@@ -57,7 +57,7 @@ public:  // from Visual
   /**
    * @copydoc Visual::Base::GetNaturalSize
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Visual::Base::CreatePropertyMap
index 742f068..d4d7e19 100644 (file)
@@ -332,7 +332,7 @@ void ImageVisual::DoSetProperties( const Property::Map& propertyMap )
   }
 }
 
-void ImageVisual::GetNaturalSize( Vector2& naturalSize ) const
+void ImageVisual::GetNaturalSize( Vector2& naturalSize )
 {
   if(mImage)
   {
index 7ad511f..de25d60 100644 (file)
@@ -109,7 +109,7 @@ public:  // from Visual
   /**
    * @copydoc Visual::Base::GetNaturalSize
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Visual::Base::CreatePropertyMap
diff --git a/dali-toolkit/internal/visuals/npatch-loader.cpp b/dali-toolkit/internal/visuals/npatch-loader.cpp
new file mode 100644 (file)
index 0000000..026450d
--- /dev/null
@@ -0,0 +1,97 @@
+ /*
+ * 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 <dali-toolkit/internal/visuals/npatch-loader.h>
+
+// EXTERNAL HEADER
+#include <dali/devel-api/common/hash.h>
+#include <dali/devel-api/images/texture-set-image.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+NPatchLoader::NPatchLoader()
+{
+}
+
+NPatchLoader::~NPatchLoader()
+{
+}
+
+std::size_t NPatchLoader::Load( const std::string& url )
+{
+  std::size_t hash = CalculateHash( url );
+  OwnerContainer< Data* >::SizeType index = UNINITIALIZED_ID;
+  const OwnerContainer< Data* >::SizeType count = mCache.Count();
+  for( ; index < count; ++index )
+  {
+    if( mCache[ index ]->hash == hash )
+    {
+      // hash match, check url as well in case of hash collision
+      if( mCache[ index ]->url == url )
+      {
+        return index+1u; // valid indices are from 1 onwards
+      }
+    }
+  }
+  // got to the end so no match, decode N patch and append new item to cache
+  NinePatchImage ninePatch = NinePatchImage::New( url );
+  if( ninePatch )
+  {
+    Data* data = new Data();
+    data->hash = hash;
+    data->url = url;
+    BufferImage croppedImage = ninePatch.CreateCroppedBufferImage();
+    if( croppedImage )
+    {
+      data->textureSet = TextureSet::New();
+      TextureSetImage( data->textureSet, 0u, croppedImage );
+      data->croppedWidth = croppedImage.GetWidth();
+      data->croppedHeight = croppedImage.GetHeight();
+      data->stretchPixelsX = ninePatch.GetStretchPixelsX();
+      data->stretchPixelsY = ninePatch.GetStretchPixelsY();
+      mCache.PushBack( data );
+
+      return mCache.Count(); // valid ids start from 1u
+    }
+  }
+  return 0u;
+}
+
+bool NPatchLoader::GetNPatchData( std::size_t id, const Data*& data )
+{
+  if( ( id > UNINITIALIZED_ID )&&( id <= mCache.Count() ) )
+  {
+    data = mCache[ id - 1u ]; // id's start from 1u
+    return true;
+  }
+  data = NULL;
+  return false;
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/dali-toolkit/internal/visuals/npatch-loader.h b/dali-toolkit/internal/visuals/npatch-loader.h
new file mode 100644 (file)
index 0000000..0d9a1c2
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_TOOLKIT_NPATCH_LOADER_H
+#define DALI_TOOLKIT_NPATCH_LOADER_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 <string>
+#include <dali/public-api/rendering/texture-set.h>
+#include <dali/devel-api/common/owner-container.h>
+#include <dali/devel-api/images/nine-patch-image.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/devel-api/image-loader/image-atlas.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+/**
+ * The manager for loading Npatch textures.
+ * It caches them internally for better performance; i.e. to avoid loading and
+ * parsing the files over and over.
+ *
+ * Cache is not cleaned during app lifecycle as N patches take considerably
+ * small space and there's not usually a lot of them. Usually N patches are specified in
+ * toolkit default style and there is 1-2 per control that are shared across the whole application.
+ */
+class NPatchLoader
+{
+public:
+
+  enum
+  {
+    UNINITIALIZED_ID = 0 ///< uninitialised id, use to initialize ids
+  };
+
+  struct Data
+  {
+    std::string url;                              ///< Url of the N-Patch
+    TextureSet textureSet;                        ///< Texture containing the cropped image
+    NinePatchImage::StretchRanges stretchPixelsX; ///< X stretch pixels
+    NinePatchImage::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
+  };
+
+public:
+
+  /**
+   * Constructor
+   */
+  NPatchLoader();
+
+  /**
+   * Destructor, non-virtual as not a base class
+   */
+  ~NPatchLoader();
+
+  /**
+   * @brief Retrieve a texture matching the n-patch url.
+   *
+   * @param [in] url to retrieve
+   * @return id of the texture.
+   */
+  std::size_t Load( const std::string& url );
+
+  /**
+   * @brief Retrieve N patch data matching to an id
+   * @param [in] id of data
+   * @param [out] data const pointer to the data
+   * @return true if data matching to id was really found
+   */
+  bool GetNPatchData( std::size_t id, const Data*& data );
+
+protected:
+
+  /**
+   * Undefined copy constructor.
+   */
+  NPatchLoader(const NPatchLoader&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  NPatchLoader& operator=(const NPatchLoader& rhs);
+
+private:
+
+  OwnerContainer< Data* > mCache;
+
+};
+
+} // name Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_NPATCH_LOADER_H
index a4cf8c0..60fdf58 100644 (file)
@@ -27,6 +27,7 @@
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/visuals/image-visual-properties.h>
 #include <dali-toolkit/devel-api/visual-factory/devel-visual-properties.h>
+#include <dali-toolkit/internal/visuals/npatch-loader.h>
 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
@@ -230,42 +231,38 @@ NPatchVisualPtr NPatchVisual::New( VisualFactoryCache& factoryCache, const std::
   NPatchVisual* nPatchVisual = new NPatchVisual( factoryCache );
   nPatchVisual->mImageUrl = imageUrl;
 
-  NinePatchImage image = NinePatchImage::New( imageUrl );
-  nPatchVisual->InitializeFromImage( image );
-
   return nPatchVisual;
 }
 
 NPatchVisualPtr NPatchVisual::New( VisualFactoryCache& factoryCache, NinePatchImage image )
 {
   NPatchVisual* nPatchVisual = new NPatchVisual( factoryCache );
-  nPatchVisual->mImage = image;
-
-  nPatchVisual->InitializeFromImage( image );
+  nPatchVisual->mImageUrl = image.GetUrl();
 
   return nPatchVisual;
 }
 
-NPatchVisual::NPatchVisual( VisualFactoryCache& factoryCache )
-: Visual::Base( factoryCache ),
-  mImage(),
-  mCroppedImage(),
-  mImageUrl(),
-  mStretchPixelsX(),
-  mStretchPixelsY(),
-  mImageSize(),
-  mBorderOnly( false )
-{
-}
-
-NPatchVisual::~NPatchVisual()
+void NPatchVisual::GetNaturalSize( Vector2& naturalSize )
 {
+  naturalSize.x = 0u;
+  naturalSize.y = 0u;
+  // load now if not already loaded
+  if( NPatchLoader::UNINITIALIZED_ID == mId )
+  {
+    mId = mLoader.Load( mImageUrl );
+  }
+  const NPatchLoader::Data* data;
+  if( mLoader.GetNPatchData( mId, data ) )
+  {
+    naturalSize.x = data->croppedWidth;
+    naturalSize.y = data->croppedHeight;
+  }
 }
 
 void NPatchVisual::DoSetProperties( const Property::Map& propertyMap )
 {
   // URL is already passed in via constructor
-  //Read the borderOnly property first since InitialiseFromImage relies on mBorderOnly to be properly set
+
   Property::Value* borderOnlyValue = propertyMap.Find( Toolkit::ImageVisual::Property::BORDER_ONLY, BORDER_ONLY );
   if( borderOnlyValue )
   {
@@ -273,77 +270,133 @@ void NPatchVisual::DoSetProperties( const Property::Map& propertyMap )
   }
 }
 
-void NPatchVisual::GetNaturalSize( Vector2& naturalSize ) const
+void NPatchVisual::DoSetOnStage( Actor& actor )
 {
-  if( mImage )
-  {
-    naturalSize.x = mImage.GetWidth();
-    naturalSize.y = mImage.GetHeight();
-  }
-  else if( !mImageUrl.empty() )
+  // load when first go on stage
+  if( NPatchLoader::UNINITIALIZED_ID == mId )
   {
-    ImageDimensions dimentions = ResourceImage::GetImageSize( mImageUrl );
-    naturalSize.x = dimentions.GetWidth();
-    naturalSize.y = dimentions.GetHeight();
+    mId = mLoader.Load( mImageUrl );
   }
-  else
+
+  Geometry geometry = CreateGeometry();
+  Shader shader = CreateShader();
+  mImpl->mRenderer = Renderer::New( geometry, shader );
+
+  ApplyTextureAndUniforms();
+
+  actor.AddRenderer( mImpl->mRenderer );
+}
+
+void NPatchVisual::DoSetOffStage( Actor& actor )
+{
+  actor.RemoveRenderer( mImpl->mRenderer );
+  mImpl->mRenderer.Reset();
+}
+
+void NPatchVisual::OnSetTransform()
+{
+  if( mImpl->mRenderer )
   {
-    naturalSize = Vector2::ZERO;
+    mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
   }
 }
 
+void NPatchVisual::DoCreatePropertyMap( Property::Map& map ) const
+{
+  map.Clear();
+  map.Insert( Toolkit::VisualProperty::TYPE, Toolkit::Visual::IMAGE );
+  map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl );
+  map.Insert( Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly );
+}
+
+void NPatchVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue )
+{
+  // TODO
+}
+
+Dali::Property::Value NPatchVisual::DoGetProperty( Dali::Property::Index index )
+{
+  // TODO
+  return Dali::Property::Value();
+}
+
+NPatchVisual::NPatchVisual( VisualFactoryCache& factoryCache )
+: Visual::Base( factoryCache ),
+  mLoader( factoryCache.GetNPatchLoader() ),
+  mImageUrl(),
+  mId( NPatchLoader::UNINITIALIZED_ID ),
+  mBorderOnly( false )
+{
+}
+
+NPatchVisual::~NPatchVisual()
+{
+}
+
 Geometry NPatchVisual::CreateGeometry()
 {
   Geometry geometry;
-  if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 )
+  const NPatchLoader::Data* data;
+  if( mLoader.GetNPatchData( mId, data ) )
   {
-    if( !mBorderOnly )
+    if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 )
     {
-      geometry = mFactoryCache.GetGeometry( VisualFactoryCache::NINE_PATCH_GEOMETRY );
-      if( !geometry )
+      if( DALI_UNLIKELY( mBorderOnly ) )
       {
-        geometry = CreateGeometry( Uint16Pair( 3, 3 ) );
-        mFactoryCache.SaveGeometry( VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry );
+        geometry = GetNinePatchGeometry( VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY );
       }
-    }
-    else
-    {
-      geometry = mFactoryCache.GetGeometry( VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY );
-      if( !geometry )
+      else
       {
-        geometry = CreateGeometryBorder( Uint16Pair( 3, 3 ) );
-        mFactoryCache.SaveGeometry( VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY, geometry );
+        geometry = GetNinePatchGeometry( VisualFactoryCache::NINE_PATCH_GEOMETRY );
       }
     }
+    else if( data->stretchPixelsX.Size() > 0 || data->stretchPixelsY.Size() > 0)
+    {
+      Uint16Pair gridSize( 2 * data->stretchPixelsX.Size() + 1,  2 * data->stretchPixelsY.Size() + 1 );
+      geometry = !mBorderOnly ? CreateGridGeometry( gridSize ) : CreateBorderGeometry( gridSize );
+    }
   }
-  else if( mStretchPixelsX.Size() > 0 || mStretchPixelsY.Size() > 0)
+  else
   {
-    Uint16Pair gridSize( 2 * mStretchPixelsX.Size() + 1,  2 * mStretchPixelsY.Size() + 1 );
-    geometry = !mBorderOnly ? CreateGeometry( gridSize ) : CreateGeometryBorder( gridSize );
+    // no N patch data so use default geometry
+    geometry = GetNinePatchGeometry( VisualFactoryCache::NINE_PATCH_GEOMETRY );
   }
-
   return geometry;
 }
 
 Shader NPatchVisual::CreateShader()
 {
   Shader shader;
-  if( !mImpl->mCustomShader )
+  const NPatchLoader::Data* data;
+  // 0 is either no data (load failed?) or no stretch regions on image
+  // for both cases we use the default shader
+  NinePatchImage::StretchRanges::SizeType xStretchCount = 0;
+  NinePatchImage::StretchRanges::SizeType yStretchCount = 0;
+
+  // ask loader for the regions
+  if( mLoader.GetNPatchData( mId, data ) )
+  {
+    xStretchCount = data->stretchPixelsX.Count();
+    yStretchCount = data->stretchPixelsY.Count();
+  }
+
+  if( DALI_LIKELY( !mImpl->mCustomShader ) )
   {
-    if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 )
+    if( DALI_LIKELY( ( xStretchCount == 1 && yStretchCount == 1 ) ||
+                     ( xStretchCount == 0 && yStretchCount == 0 ) ) )
     {
       shader = mFactoryCache.GetShader( VisualFactoryCache::NINE_PATCH_SHADER );
-      if( !shader )
+      if( DALI_UNLIKELY( !shader ) )
       {
         shader = Shader::New( VERTEX_SHADER_3X3, FRAGMENT_SHADER );
         mFactoryCache.SaveShader( VisualFactoryCache::NINE_PATCH_SHADER, shader );
       }
     }
-    else if( mStretchPixelsX.Size() > 0 || mStretchPixelsY.Size() > 0)
+    else if( xStretchCount > 0 || yStretchCount > 0)
     {
       std::stringstream vertexShader;
-      vertexShader << "#define FACTOR_SIZE_X " << mStretchPixelsX.Size() + 2 << "\n"
-                   << "#define FACTOR_SIZE_Y " << mStretchPixelsY.Size() + 2 << "\n"
+      vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
+                   << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
                    << VERTEX_SHADER;
 
       shader = Shader::New( vertexShader.str(), FRAGMENT_SHADER );
@@ -360,15 +413,16 @@ Shader NPatchVisual::CreateShader()
     }
     hints = mImpl->mCustomShader->mHints;
 
-    if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 )
+    if( ( xStretchCount == 1 && yStretchCount == 1 ) ||
+        ( xStretchCount == 0 && yStretchCount == 0 ) )
     {
       shader = Shader::New( VERTEX_SHADER_3X3, fragmentShader, hints );
     }
-    else if( mStretchPixelsX.Size() > 0 || mStretchPixelsY.Size() > 0)
+    else if( xStretchCount > 0 || yStretchCount > 0)
     {
       std::stringstream vertexShader;
-      vertexShader << "#define FACTOR_SIZE_X " << mStretchPixelsX.Size() + 2 << "\n"
-                   << "#define FACTOR_SIZE_Y " << mStretchPixelsY.Size() + 2 << "\n"
+      vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
+                   << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
                    << VERTEX_SHADER;
 
       shader = Shader::New( vertexShader.str(), fragmentShader, hints );
@@ -378,190 +432,72 @@ Shader NPatchVisual::CreateShader()
   return shader;
 }
 
-void NPatchVisual::InitializeRenderer()
-{
-  Geometry geometry = CreateGeometry();
-  Shader shader = CreateShader();
-
-  if( !geometry || !shader )
-  {
-    DALI_LOG_ERROR("The 9 patch image '%s' doesn't have any valid stretch borders and so is not a valid 9 patch image\n", mImageUrl.c_str() );
-    InitializeFromBrokenImage();
-  }
-
-  TextureSet textureSet = TextureSet::New();
-  mImpl->mRenderer = Renderer::New( geometry, shader );
-  mImpl->mRenderer.SetTextures( textureSet );
-
-  //Register transform properties
-  mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
-}
-
-
-void NPatchVisual::DoSetOnStage( Actor& actor )
+void NPatchVisual::ApplyTextureAndUniforms()
 {
-  if( !mCroppedImage )
+  const NPatchLoader::Data* data;
+  if( mLoader.GetNPatchData( mId, data ) )
   {
-    if( !mImageUrl.empty() )
+    TextureSet textures( data->textureSet );
+    mImpl->mRenderer.SetTextures( textures );
+    if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 )
     {
-      NinePatchImage nPatch = NinePatchImage::New( mImageUrl );
-      InitializeFromImage( nPatch );
-    }
-    else if( mImage )
-    {
-      InitializeFromImage( mImage );
-    }
-  }
-
-  //initialize the renderer after initializing from the image since we need to know the grid size from the image before creating the geometry
-  InitializeRenderer();
-
-  if( mCroppedImage )
-  {
-    ApplyImageToSampler();
-  }
-
-  actor.AddRenderer( mImpl->mRenderer );
-}
-
-void NPatchVisual::DoSetOffStage( Actor& actor )
-{
-  mCroppedImage.Reset();
-  actor.RemoveRenderer( mImpl->mRenderer );
-  mImpl->mRenderer.Reset();
-}
-
-void NPatchVisual::DoCreatePropertyMap( Property::Map& map ) const
-{
-  map.Clear();
-  map.Insert( Toolkit::VisualProperty::TYPE, Toolkit::Visual::IMAGE );
-  if( !mImageUrl.empty() )
-  {
-    map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl );
-  }
-  else if( mImage )
-  {
-    map.Insert( Toolkit::ImageVisual::Property::URL, mImage.GetUrl() );
-  }
-  map.Insert( Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly );
-}
-
-void NPatchVisual::DoSetProperty( Dali::Property::Index index, const Dali::Property::Value& propertyValue )
-{
-  // TODO
-}
-
-Dali::Property::Value NPatchVisual::DoGetProperty( Dali::Property::Index index )
-{
-  // TODO
-  return Dali::Property::Value();
-}
-
-void NPatchVisual::OnSetTransform()
-{
-  if( mImpl->mRenderer )
-  {
-    mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
-  }
-}
-
-
-void NPatchVisual::ChangeRenderer( bool oldBorderOnly, size_t oldGridX, size_t oldGridY )
-{
-  //check to see if the border style has changed
+      //special case for 9 patch
+      Uint16Pair stretchX = data->stretchPixelsX[ 0 ];
+      Uint16Pair stretchY = data->stretchPixelsY[ 0 ];
 
-  bool borderOnlyChanged = oldBorderOnly != mBorderOnly;
-  bool gridChanged = oldGridX != mStretchPixelsX.Size() || oldGridY != mStretchPixelsY.Size();
+      uint16_t stretchWidth = stretchX.GetY() - stretchX.GetX();
+      uint16_t stretchHeight = stretchY.GetY() - stretchY.GetX();
 
-  if( borderOnlyChanged || gridChanged )
-  {
-    Geometry geometry = CreateGeometry();
-    if( geometry )
-    {
-      mImpl->mRenderer.SetGeometry( geometry );
+      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( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) );
     }
     else
     {
-      InitializeFromBrokenImage();
-    }
-  }
+      mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsX[0]", Vector2::ZERO );
+      mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsY[0]", Vector2::ZERO );
 
-  if( gridChanged )
-  {
-    Shader shader = CreateShader();
-    TextureSet textureSet;
-    if( shader )
-    {
-      textureSet = mImpl->mRenderer.GetTextures();
-      if( !textureSet )
-      {
-        InitializeFromBrokenImage();
-      }
-      mImpl->mRenderer.SetShader( shader );
+      RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsX", data->stretchPixelsX, data->croppedWidth );
+      RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsY", data->stretchPixelsY, data->croppedHeight );
     }
   }
-}
-
-void NPatchVisual::InitializeFromImage( NinePatchImage nPatch )
-{
-  mCroppedImage = nPatch.CreateCroppedBufferImage();
-  if( !mCroppedImage )
+  else
   {
-    DALI_LOG_ERROR("'%s' specify a valid 9 patch image\n", mImageUrl.c_str() );
-    InitializeFromBrokenImage();
-    return;
+    DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.c_str() );
+    TextureSet textureSet = TextureSet::New();
+    mImpl->mRenderer.SetTextures( textureSet );
+    Image croppedImage = VisualFactoryCache::GetBrokenVisualImage();
+    TextureSetImage( textureSet, 0u, croppedImage );
+    mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO );
+    mImpl->mRenderer.RegisterProperty( "uFixed[1]", Vector2::ZERO );
+    mImpl->mRenderer.RegisterProperty( "uFixed[2]", Vector2::ZERO );
+    mImpl->mRenderer.RegisterProperty( "uStretchTotal", Vector2( croppedImage.GetWidth(), croppedImage.GetHeight() ) );
   }
 
-  mImageSize = ImageDimensions( mCroppedImage.GetWidth(), mCroppedImage.GetHeight() );
-
-  mStretchPixelsX = nPatch.GetStretchPixelsX();
-  mStretchPixelsY = nPatch.GetStretchPixelsY();
-}
-
-void NPatchVisual::InitializeFromBrokenImage()
-{
-  mCroppedImage = VisualFactoryCache::GetBrokenVisualImage();
-  mImageSize = ImageDimensions( mCroppedImage.GetWidth(), mCroppedImage.GetHeight() );
-
-  mStretchPixelsX.Clear();
-  mStretchPixelsX.PushBack( Uint16Pair( 0, mImageSize.GetWidth() ) );
-  mStretchPixelsY.Clear();
-  mStretchPixelsY.PushBack( Uint16Pair( 0, mImageSize.GetHeight() ) );
+  //Register transform properties
+  mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
 }
 
-void NPatchVisual::ApplyImageToSampler()
+Geometry NPatchVisual::GetNinePatchGeometry( VisualFactoryCache::GeometryType subType )
 {
-  TextureSet textureSet = mImpl->mRenderer.GetTextures();
-  if( textureSet )
+  Geometry geometry = mFactoryCache.GetGeometry( subType );
+  if( !geometry )
   {
-    TextureSetImage( textureSet, 0u, mCroppedImage );
-
-    if( mStretchPixelsX.Size() == 1 && mStretchPixelsY.Size() == 1 )
+    if( DALI_LIKELY( VisualFactoryCache::NINE_PATCH_GEOMETRY == subType ) )
     {
-      //special case for 9 patch
-      Uint16Pair stretchX = mStretchPixelsX[ 0 ];
-      Uint16Pair stretchY = mStretchPixelsY[ 0 ];
-
-      uint16_t stretchWidth = stretchX.GetY() - stretchX.GetX();
-      uint16_t stretchHeight = stretchY.GetY() - stretchY.GetX();
-
-      mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO );
-      mImpl->mRenderer.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) );
-      mImpl->mRenderer.RegisterProperty( "uFixed[2]", Vector2( mImageSize.GetWidth() - stretchWidth, mImageSize.GetHeight() - stretchHeight ) );
-      mImpl->mRenderer.RegisterProperty( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) );
+      geometry = CreateGridGeometry( Uint16Pair( 3, 3 ) );
     }
-    else
+    else if( VisualFactoryCache::NINE_PATCH_BORDER_GEOMETRY == subType )
     {
-      mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsX[0]", Vector2::ZERO );
-      mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsY[0]", Vector2::ZERO );
-
-      RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsX", mStretchPixelsX, mImageSize.GetWidth() );
-      RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsY", mStretchPixelsY, mImageSize.GetHeight() );
+      geometry = CreateBorderGeometry( Uint16Pair( 3, 3 ) );
     }
+    mFactoryCache.SaveGeometry( subType, geometry );
   }
+  return geometry;
 }
 
-Geometry NPatchVisual::CreateGeometry( Uint16Pair gridSize )
+Geometry NPatchVisual::CreateGridGeometry( Uint16Pair gridSize )
 {
   uint16_t gridWidth = gridSize.GetWidth();
   uint16_t gridHeight = gridSize.GetHeight();
@@ -579,7 +515,6 @@ Geometry NPatchVisual::CreateGeometry( Uint16Pair gridSize )
   }
 
   // Create indices
-  //TODO: compare performance with triangle strip when Geometry supports it
   Vector< unsigned short > indices;
   indices.Reserve( gridWidth * gridHeight * 6 );
 
@@ -596,7 +531,7 @@ Geometry NPatchVisual::CreateGeometry( Uint16Pair gridSize )
   return GenerateGeometry( vertices, indices );
 }
 
-Geometry NPatchVisual::CreateGeometryBorder( Uint16Pair gridSize )
+Geometry NPatchVisual::CreateBorderGeometry( Uint16Pair gridSize )
 {
   uint16_t gridWidth = gridSize.GetWidth();
   uint16_t gridHeight = gridSize.GetHeight();
@@ -636,7 +571,6 @@ Geometry NPatchVisual::CreateGeometryBorder( Uint16Pair gridSize )
   }
 
   // Create indices
-  //TODO: compare performance with triangle strip when Geometry supports it
   Vector< unsigned short > indices;
   indices.Reserve( gridWidth * gridHeight * 6 );
 
index b3d2815..1059a7e 100644 (file)
@@ -80,7 +80,7 @@ public:  // from Visual
   /**
    * @copydoc Visual::Base::GetNaturalSize
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Visual::Base::CreatePropertyMap
@@ -134,11 +134,6 @@ protected:
 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 Creates a geometry for this renderer's grid size
    *
    * @return Returns the created geometry for this renderer's grid size
@@ -153,12 +148,24 @@ private:
   Shader CreateShader();
 
   /**
+   * @brief Applies texture and related uniforms
+   */
+  void ApplyTextureAndUniforms();
+
+  /**
+   * Helper method to get the default Nine patch geometry from cache or create and store it there
+   * @param subType to use
+   * @return the geometry
+   */
+  Geometry GetNinePatchGeometry( VisualFactoryCache::GeometryType subType );
+
+  /**
    * @brief Creates a geometry for the grid size to be used by this visuals' shaders
    *
    * @param[in] gridSize The grid size of the solid geometry to create
    * @return Returns the created geometry for the grid size
    */
-  Geometry CreateGeometry( Uint16Pair gridSize );
+  Geometry CreateGridGeometry( Uint16Pair gridSize );
 
   /**
    * @brief Creates a geometry with the border only for the grid size to be used by this visuals' shaders
@@ -181,45 +188,15 @@ private:
    * @param[in] gridSize The grid size of the solid geometry to create
    * @return Returns the created geometry for the grid size
    */
-  Geometry CreateGeometryBorder( Uint16Pair gridSize );
-
-  /**
-   * @brief Creates Image from the image url and parses the image for the stretch borders. Will create a error image if the n patch image is invalid
-   *
-   * @param[in] nPatchImage The NinePatchImage to base our cropped images and stretch borders from
-   */
-  void InitializeFromImage( NinePatchImage nPatchImage );
-
-  /**
-   * @brief Creates an error Image to indicate that there was an error in either the image url or the parsing of the image
-   *
-   */
-  void InitializeFromBrokenImage();
-
-  /**
-   * @brief Applies this renderer's image to the sampler to the texture set used for this renderer
-   */
-  void ApplyImageToSampler();
-
-  /**
-   * @brief Changes the current renderer if the n-patch meta data has changed
-   *
-   * @param[in] oldBorderOnly The old flag indicating if the image should omit the centre of the n-patch and only render the border
-   * @param[in] oldGridX The old horizontal grid size of the solid geometry
-   * @param[in] oldGridY The old vertical grid size of the solid geometry
-   */
-  void ChangeRenderer( bool oldBorderOnly, size_t oldGridX, size_t oldGridY );
+  Geometry CreateBorderGeometry( Uint16Pair gridSize );
 
 private:
 
-  NinePatchImage mImage; ///< The image to render if the visual was set from an NinePatchImage, empty otherwise
-  Image mCroppedImage;
+  NPatchLoader& mLoader;      ///< reference to N patch loader for fast access
+  std::string mImageUrl;      ///< The url to the N patch to load
+  std::size_t mId;            ///< id of the N patch (from loader/cache)
+  bool mBorderOnly;           ///< if only border is desired
 
-  std::string mImageUrl; ///< The url to the image resource to render if the visual was set from an image resource url, empty otherwise
-  NinePatchImage::StretchRanges mStretchPixelsX;
-  NinePatchImage::StretchRanges mStretchPixelsY;
-  ImageDimensions mImageSize;
-  bool mBorderOnly;
 };
 
 } // namespace Internal
index 8285561..5fbde5a 100644 (file)
@@ -394,7 +394,7 @@ void PrimitiveVisual::SetSize( const Vector2& size )
   // ToDo: renderer responds to the size change
 }
 
-void PrimitiveVisual::GetNaturalSize( Vector2& naturalSize ) const
+void PrimitiveVisual::GetNaturalSize( Vector2& naturalSize )
 {
   naturalSize.x = mObjectDimensions.x;
   naturalSize.y = mObjectDimensions.y;
index c039fe3..5239d3f 100644 (file)
@@ -119,7 +119,7 @@ public:  // from Visual
   /**
    * @copydoc Visual::Base::GetNaturalSize
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Visual::Base::CreatePropertyMap
index 652b03d..e7c7aa8 100644 (file)
@@ -116,7 +116,7 @@ void SvgVisual::DoSetOffStage( Actor& actor )
   mPlacementActor.Reset();
 }
 
-void SvgVisual::GetNaturalSize( Vector2& naturalSize ) const
+void SvgVisual::GetNaturalSize( Vector2& naturalSize )
 {
   if( mParsedImage )
   {
index 7beb6d6..e5a2f8e 100644 (file)
@@ -70,7 +70,7 @@ public:  // from Visual
   /**
    * @copydoc Visual::Base::GetNaturalSize
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Visual::Base::SetSize
index c597e27..f7c4f24 100644 (file)
@@ -191,7 +191,7 @@ float TextVisual::GetHeightForWidth( float width ) const
   return mController->GetHeightForWidth( width );
 }
 
-void TextVisual::GetNaturalSize( Vector2& naturalSize ) const
+void TextVisual::GetNaturalSize( Vector2& naturalSize )
 {
   naturalSize = mController->GetNaturalSize().GetVectorXY();
 }
index 47289d1..e1a4f80 100644 (file)
@@ -101,7 +101,7 @@ public: // from Visual::Base
   /**
    * @copydoc Visual::Base::GetNaturalSize()
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Visual::Base::CreatePropertyMap()
index 1b9cec7..9cd41e0 100644 (file)
@@ -109,7 +109,7 @@ float Visual::Base::GetHeightForWidth( float width ) const
   return 0.f;
 }
 
-void Visual::Base::GetNaturalSize( Vector2& naturalSize ) const
+void Visual::Base::GetNaturalSize( Vector2& naturalSize )
 {
   naturalSize = Vector2::ZERO;
 }
@@ -190,8 +190,8 @@ bool Visual::Base::IsPreMultipliedAlphaEnabled() const
 
 void Visual::Base::DoSetOffStage( Actor& actor )
 {
-    actor.RemoveRenderer( mImpl->mRenderer );
-    mImpl->mRenderer.Reset();
+  actor.RemoveRenderer( mImpl->mRenderer );
+  mImpl->mRenderer.Reset();
 }
 
 bool Visual::Base::IsOnStage() const
index 306f2d9..4028ca4 100644 (file)
@@ -99,7 +99,7 @@ public:
   /**
    * @copydoc Toolkit::Visual::Base::GetNaturalSize
    */
-  virtual void GetNaturalSize( Vector2& naturalSize ) const;
+  virtual void GetNaturalSize( Vector2& naturalSize );
 
   /**
    * @copydoc Toolkit::Visual::Base::SetDepthIndex
index 248270b..51c6bc2 100644 (file)
 // CLASS HEADER
 #include "visual-factory-cache.h"
 
-// EXTERNAL HEADER
+// EXTERNAL INCLUDES
 #include <dali/devel-api/common/hash.h>
 #include <dali/public-api/images/resource-image.h>
 
-// INTERNAL HEADER
+// INTERNAL INCLUDES
 #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>
@@ -197,6 +197,11 @@ ImageAtlasManagerPtr VisualFactoryCache::GetAtlasManager()
   return mAtlasManager;
 }
 
+NPatchLoader& VisualFactoryCache::GetNPatchLoader()
+{
+  return mNPatchLoader;
+}
+
 SvgRasterizeThread* VisualFactoryCache::GetSVGRasterizationThread()
 {
   if( !mSvgRasterizeThread )
index cb1b890..0b77e53 100644 (file)
@@ -17,9 +17,6 @@
  * limitations under the License.
  */
 
-// INTERNAL INCLUDES
-#include "svg/svg-rasterize-thread.h"
-
 // EXTERNAL INCLUDES
 #include <dali/public-api/math/uint-16-pair.h>
 #include <dali/public-api/object/ref-object.h>
@@ -29,6 +26,9 @@
 #include <dali/devel-api/common/owner-container.h>
 #include <dali/devel-api/object/weak-handle.h>
 
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/npatch-loader.h>
+#include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
 
 namespace Dali
 {
@@ -42,6 +42,8 @@ namespace Internal
 class ImageAtlasManager;
 typedef IntrusivePtr<ImageAtlasManager> ImageAtlasManagerPtr;
 
+class NPatchLoader;
+
 /**
  * Caches shaders and geometries. Owned by VisualFactory.
  */
@@ -182,13 +184,19 @@ public:
 
   /**
    * Get the image atlas manager.
-   * @return A pointer pointing to the atlas manager
+   * @return A pointer to the atlas manager
    */
   ImageAtlasManagerPtr GetAtlasManager();
 
   /**
+   * Get the N-Patch texture cache.
+   * @return A reference to the N patch loader
+   */
+  NPatchLoader& GetNPatchLoader();
+
+  /**
    * Get the SVG rasterization thread.
-   * @return A pointer pointing to the SVG rasterization thread.
+   * @return A raw pointer pointing to the SVG rasterization thread.
    */
   SvgRasterizeThread* GetSVGRasterizationThread();
 
@@ -248,6 +256,8 @@ private:
   Renderer mWireframeRenderer;
 
   ImageAtlasManagerPtr mAtlasManager;
+  NPatchLoader mNPatchLoader;
+
   SvgRasterizeThread*  mSvgRasterizeThread;
 };