return Dali::Geometry::New();
}
-static void* NPatchBuildInternal(const Devel::PixelBuffer& pixelBuffer, Toolkit::Internal::NPatchLoader::Data* data )
+static void* NPatchBuildInternal(const Devel::PixelBuffer& pixelBuffer, Toolkit::Internal::NPatchData* data )
{
gCallStack.emplace_back( "BuildNPatch" );
fprintf(stderr, "AddOn::NPatchBuild()\n");
DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
- application.GetScene().Remove( actor );
- DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
-
Vector2 naturalSize( 0.0f, 0.0f );
visual.GetNaturalSize( naturalSize );
DALI_TEST_EQUALS( naturalSize, Vector2( imageSize.GetWidth() - 2.0f, imageSize.GetHeight() - 2.0f ), TEST_LOCATION );
END_TEST;
}
+int UtcDaliVisualFactoryGetNPatchVisual8(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliVisualFactoryGetNPatchVisual8: Add 9-patch visual on stage, instantly remove it and add new 9-patch visual with same propertyMap" );
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ // Get actual size of test image
+ ImageDimensions imageSize = Dali::GetClosestImageSize( TEST_9_PATCH_FILE_NAME );
+
+ Property::Map propertyMap;
+ propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::N_PATCH );
+ propertyMap.Insert( ImageVisual::Property::URL, TEST_9_PATCH_FILE_NAME );
+ propertyMap.Insert( ImageVisual::Property::SYNCHRONOUS_LOADING, false );
+ {
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+ DALI_TEST_CHECK( visual );
+
+ Vector2 naturalSize( 0.0f, 0.0f );
+ visual.GetNaturalSize( naturalSize );
+ DALI_TEST_EQUALS( naturalSize, Vector2( imageSize.GetWidth(), imageSize.GetHeight() ), TEST_LOCATION );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ DummyControl actor = DummyControl::New(true);
+
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+ application.GetScene().Add( actor );
+ actor.Unparent();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ visual = factory.CreateVisual( propertyMap );
+ DALI_TEST_CHECK( visual );
+
+ visual.GetNaturalSize( naturalSize );
+ DALI_TEST_EQUALS( naturalSize, Vector2( imageSize.GetWidth(), imageSize.GetHeight() ), TEST_LOCATION );
+
+ actor = DummyControl::New(true);
+
+ DummyControlImpl& dummyImpl2 = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl2.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual );
+
+ actor.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+ application.GetScene().Add( actor );
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger(1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ Renderer renderer = actor.GetRendererAt( 0 );
+ auto textures = renderer.GetTextures();
+
+ DALI_TEST_EQUALS( textures.GetTextureCount(), 1, TEST_LOCATION );
+ }
+
+ END_TEST;
+}
+
int UtcDaliNPatchVisualAuxiliaryImage01(void)
{
ToolkitTestApplication application;
Renderer renderer2 = imageView2.GetRendererAt( 0 );
auto textureSet2 = renderer2.GetTextures();
- DALI_TEST_EQUALS( textureSet1 == textureSet2, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( textureSet1 != textureSet2, true, TEST_LOCATION );
END_TEST;
}
}
}
-Toolkit::Visual::Type GetVisualTypeFromMap( const Property::Map& map )
+/**
+ * Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
+ */
+bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
{
- Property::Value* typeValue = map.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE );
- Toolkit::Visual::Type type = Toolkit::Visual::IMAGE;
- if( typeValue )
+ for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
{
- Scripting::GetEnumerationProperty( *typeValue, VISUAL_TYPE_TABLE, VISUAL_TYPE_TABLE_COUNT, type );
+ if ( (*iter)->index == targetIndex )
+ {
+ return true;
+ }
}
- return type;
+ return false;
}
/**
* Finds visual in given array, returning true if found along with the iterator for that visual as a out parameter
*/
-bool FindVisual( Property::Index targetIndex, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
+bool FindVisual( std::string visualName, const RegisteredVisualContainer& visuals, RegisteredVisualContainer::Iterator& iter )
{
for ( iter = visuals.Begin(); iter != visuals.End(); iter++ )
{
- if ( (*iter)->index == targetIndex )
+ Toolkit::Visual::Base visual = (*iter)->visual;
+ if( visual && visual.GetName() == visualName )
{
return true;
}
const std::string& visualName = (*iter).key;
const Property::Map& toMap = (*iter).entry;
- // is it a candidate for re-creation?
- bool recreate = false;
-
- Toolkit::Visual::Base visual = GetVisualByName( mVisuals, visualName );
- if( visual )
+ Actor self = mControlImpl.Self();
+ RegisteredVisualContainer::Iterator registeredVisualsiter;
+ // Check if visual (visualName) is already registered, this is the current visual.
+ if(FindVisual(visualName, mVisuals, registeredVisualsiter))
{
- Property::Map fromMap;
- visual.CreatePropertyMap( fromMap );
-
- Toolkit::Visual::Type fromType = GetVisualTypeFromMap( fromMap );
- Toolkit::Visual::Type toType = GetVisualTypeFromMap( toMap );
-
- if( fromType != toType )
- {
- recreate = true;
- }
- else
+ Toolkit::Visual::Base& visual = (*registeredVisualsiter)->visual;
+ if(visual)
{
- if( fromType == Toolkit::Visual::IMAGE || fromType == Toolkit::Visual::N_PATCH
- || fromType == Toolkit::Visual::SVG || fromType == Toolkit::Visual::ANIMATED_IMAGE )
- {
- Property::Value* fromUrl = fromMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
- Property::Value* toUrl = toMap.Find( Toolkit::ImageVisual::Property::URL, IMAGE_URL_NAME );
+ // No longer required to know if the replaced visual's resources are ready
+ StopObservingVisual(visual);
- if( fromUrl && toUrl )
+ // If control staged then visuals will be swapped once ready
+ if(self.GetProperty<bool>(Actor::Property::CONNECTED_TO_SCENE))
+ {
+ // Check if visual is currently in the process of being replaced ( is in removal container )
+ RegisteredVisualContainer::Iterator visualQueuedForRemoval;
+ if(FindVisual(visualName, mRemoveVisuals, visualQueuedForRemoval))
{
- std::string fromUrlString;
- std::string toUrlString;
- fromUrl->Get(fromUrlString);
- toUrl->Get(toUrlString);
-
- if( fromUrlString != toUrlString )
- {
- recreate = true;
- }
+ // Visual with same visual name is already in removal container so current visual pending
+ // Only the the last requested visual will be displayed so remove current visual which is staged but not ready.
+ Toolkit::GetImplementation(visual).SetOffScene(self);
+ (*registeredVisualsiter)->visual.Reset();
+ mVisuals.Erase(registeredVisualsiter);
+ }
+ else
+ {
+ // current visual not already in removal container so add now.
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "RegisterVisual Move current registered visual to removal Queue: %s \n", visualName.c_str());
+ MoveVisual(registeredVisualsiter, mVisuals, mRemoveVisuals);
}
}
+ else
+ {
+ // Control not staged or visual disabled so can just erase from registered visuals and new visual will be added later.
+ (*registeredVisualsiter)->visual.Reset();
+ mVisuals.Erase(registeredVisualsiter);
+ }
}
- const Property::Map* instancedMap = instancedProperties.FindConst( visualName );
- if( recreate || instancedMap )
- {
- RemoveVisual( mVisuals, visualName );
- Style::ApplyVisual( handle, visualName, toMap, instancedMap );
- }
- else
- {
- // @todo check to see if we can apply toMap without recreating the visual
- // e.g. by setting only animatable properties
- // For now, recreate all visuals, but merge in instance data.
- RemoveVisual( mVisuals, visualName );
- Style::ApplyVisual( handle, visualName, toMap, instancedMap );
- }
+ const Property::Map* instancedMap = instancedProperties.FindConst(visualName);
+ Style::ApplyVisual(handle, visualName, toMap, instancedMap);
}
}
}
${toolkit_src_dir}/visuals/image-atlas-manager.cpp
${toolkit_src_dir}/visuals/image/image-visual.cpp
${toolkit_src_dir}/visuals/mesh/mesh-visual.cpp
+ ${toolkit_src_dir}/visuals/npatch-data.cpp
${toolkit_src_dir}/visuals/npatch-loader.cpp
${toolkit_src_dir}/visuals/npatch/npatch-visual.cpp
${toolkit_src_dir}/visuals/primitive/primitive-visual.cpp
--- /dev/null
+ /*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-toolkit/internal/visuals/npatch-data.h>
+
+// INTERNAL HEADERS
+#include <dali-toolkit/internal/visuals/rendering-addon.h>
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+NPatchData::NPatchData()
+: mId(INVALID_NPATCH_DATA_ID),
+ mUrl(),
+ mTextureSet(),
+ mHash(0),
+ mCroppedWidth(0),
+ mCroppedHeight(0),
+ mBorder(0, 0, 0, 0),
+ mLoadingState(LoadingState::LOADING),
+ mRenderingMap{nullptr}
+{
+}
+
+NPatchData::~NPatchData()
+{
+ // If there is an opacity map, it has to be destroyed using addon call
+ if( mRenderingMap )
+ {
+ RenderingAddOn::Get().DestroyNPatch( mRenderingMap );
+ }
+}
+
+void NPatchData::SetId(const NPatchDataId id)
+{
+ mId = id;
+}
+
+NPatchData::NPatchDataId NPatchData::GetId() const
+{
+ return mId;
+}
+
+void NPatchData::AddObserver(TextureUploadObserver* textureObserver)
+{
+ mObserverList.PushBack( textureObserver );
+}
+
+void NPatchData::RemoveObserver(TextureUploadObserver* textureObserver)
+{
+ for(uint32_t index = 0; index < mObserverList.Count(); ++index )
+ {
+ if(textureObserver == mObserverList[index])
+ {
+ mObserverList.Erase( mObserverList.begin() + index );
+ break;
+ }
+ }
+}
+
+uint32_t NPatchData::GetObserverCount() const
+{
+ return mObserverList.Count();
+}
+
+void NPatchData::SetUrl(const std::string url)
+{
+ mUrl = url;
+}
+
+std::string NPatchData::GetUrl() const
+{
+ return mUrl;
+}
+
+void NPatchData::SetTextures(const TextureSet textureSet)
+{
+ mTextureSet = textureSet;
+}
+
+TextureSet NPatchData::GetTextures() const
+{
+ return mTextureSet;
+}
+
+void NPatchData::SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX)
+{
+ mStretchPixelsX = stretchPixelsX;
+}
+
+void NPatchData::SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY)
+{
+ mStretchPixelsY = stretchPixelsY;
+}
+
+NPatchUtility::StretchRanges NPatchData::GetStretchPixelsX() const
+{
+ return mStretchPixelsX;
+}
+
+NPatchUtility::StretchRanges NPatchData::GetStretchPixelsY() const
+{
+ return mStretchPixelsY;
+}
+
+void NPatchData::SetHash(std::size_t hash)
+{
+ mHash = hash;
+}
+
+std::size_t NPatchData::GetHash() const
+{
+ return mHash;
+}
+
+void NPatchData::SetCroppedWidth(uint32_t croppedWidth)
+{
+ mCroppedWidth = croppedWidth;
+}
+
+void NPatchData::SetCroppedHeight(uint32_t croppedHeight)
+{
+ mCroppedHeight = croppedHeight;
+}
+
+uint32_t NPatchData::GetCroppedWidth() const
+{
+ return mCroppedWidth;
+}
+
+uint32_t NPatchData::GetCroppedHeight() const
+{
+ return mCroppedHeight;
+}
+
+void NPatchData::SetBorder(const Rect<int> border)
+{
+ mBorder = border;
+}
+
+Rect<int> NPatchData::GetBorder() const
+{
+ return mBorder;
+}
+
+void NPatchData::SetPreMultiplyOnLoad(bool preMultiplyOnLoad)
+{
+ mPreMultiplyOnLoad = preMultiplyOnLoad;
+}
+
+bool NPatchData::IsPreMultiplied() const
+{
+ return mPreMultiplyOnLoad;
+}
+
+void NPatchData::SetLoadingState(const LoadingState loadingState)
+{
+ mLoadingState = loadingState;
+}
+
+NPatchData::LoadingState NPatchData::GetLoadingState() const
+{
+ return mLoadingState;
+}
+
+void* NPatchData::GetRenderingMap() const
+{
+ return mRenderingMap;
+}
+
+void NPatchData::SetLoadedNPatchData( Devel::PixelBuffer& pixelBuffer, bool preMultiplied )
+{
+ if( mBorder == Rect< int >( 0, 0, 0, 0 ) )
+ {
+ NPatchUtility::ParseBorders( pixelBuffer, mStretchPixelsX, mStretchPixelsY );
+
+ // Crop the image
+ pixelBuffer.Crop( 1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2 );
+ }
+ else
+ {
+ mStretchPixelsX.PushBack( Uint16Pair( mBorder.left, ( (pixelBuffer.GetWidth() >= static_cast< unsigned int >( mBorder.right )) ? pixelBuffer.GetWidth() - mBorder.right : 0 ) ) );
+ mStretchPixelsY.PushBack( Uint16Pair( mBorder.top, ( (pixelBuffer.GetHeight() >= static_cast< unsigned int >( mBorder.bottom )) ? pixelBuffer.GetHeight() - mBorder.bottom : 0 ) ) );
+ }
+
+ mCroppedWidth = pixelBuffer.GetWidth();
+ mCroppedHeight = pixelBuffer.GetHeight();
+
+ // Create opacity map
+ mRenderingMap = RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().BuildNPatch(pixelBuffer, this) : nullptr;
+
+ PixelData pixels = Devel::PixelBuffer::Convert( pixelBuffer ); // takes ownership of buffer
+
+ Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
+ texture.Upload( pixels );
+
+ mTextureSet = TextureSet::New();
+ mTextureSet.SetTexture( 0u, texture );
+
+ mPreMultiplyOnLoad = preMultiplied;
+
+ mLoadingState = LoadingState::LOAD_COMPLETE;
+}
+
+void NPatchData::LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied )
+{
+ if(loadSuccess)
+ {
+ SetLoadedNPatchData( pixelBuffer, preMultiplied );
+ }
+ else
+ {
+ mLoadingState = LoadingState::LOAD_FAILED;
+ }
+
+ for(uint32_t index = 0; index < mObserverList.Count(); ++index)
+ {
+ TextureUploadObserver* observer = mObserverList[index];
+ observer->UploadComplete(loadSuccess, TextureManager::INVALID_TEXTURE_ID, mTextureSet, false, Vector4(), preMultiplied);
+ }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef DALI_TOOLKIT_NPATCH_DATA_H
+#define DALI_TOOLKIT_NPATCH_DATA_H
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <dali/public-api/rendering/texture-set.h>
+#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class NPatchData : public Dali::Toolkit::TextureUploadObserver
+{
+public:
+ typedef int32_t NPatchDataId; ///< The NPatchDataId type. This is used as a handle to refer to a particular Npatch Data.
+ static const int INVALID_NPATCH_DATA_ID = -1; ///< Used to represent a null TextureId or error
+
+ /**
+ * @brief Loading State of the NPatch image.
+ */
+ enum class LoadingState
+ {
+ LOADING = 0, ///< NPatch is on loading.
+ LOAD_COMPLETE, ///< NPatch loading is completed successfully.
+ LOAD_FAILED ///< NPatch loading is failed.
+ };
+
+public:
+
+ /**
+ * Constructor
+ */
+ NPatchData();
+
+ /**
+ * Destructor, non-virtual as not a base class
+ */
+ ~NPatchData();
+
+public:
+
+ /**
+ * @brief Set cache data id.
+ *
+ * @param [in] id cache data id
+ */
+ void SetId(const NPatchDataId id);
+
+ /**
+ * @brief Retrieve cache data id
+ *
+ * @return cache data id.
+ */
+ NPatchDataId GetId() const;
+
+ /**
+ * @brief Add TextureUploadObserver that uses the image of this cache data.
+ *
+ * @param [in] textureObserver the TextureUploadObserver that uses the image of this cache data.
+ */
+ void AddObserver(TextureUploadObserver* textureObserver);
+
+ /**
+ * @brief Remove TextureUploadObserver.
+ *
+ * @param [in] textureObserver the TextureUploadObserver that will be removed in this cache data.
+ */
+ void RemoveObserver(TextureUploadObserver* textureObserver);
+
+ /**
+ * @brief Retrieve the number of observer.
+ *
+ * @return Return the number of observer.
+ */
+ uint32_t GetObserverCount() const;
+
+ /**
+ * @brief Set NPatch image url.
+ *
+ * @param [in] url NPatch image url
+ */
+ void SetUrl(const std::string url);
+
+ /**
+ * @brief Retrieve the image url.
+ *
+ * @return Return the image url.
+ */
+ std::string GetUrl() const;
+
+ /**
+ * @brief Set texture set on the cache data
+ *
+ * @param [in] textureSet loaded texture set
+ */
+ void SetTextures(const TextureSet textureSet);
+
+ /**
+ * @brief Retrieve loaded texture set.
+ *
+ * @return Return loaded texture set.
+ */
+ TextureSet GetTextures() const;
+
+ /**
+ * @brief Set X directional stretchPixels
+ *
+ * @param [in] stretchPixelsX stretchPixels for X direction
+ */
+ void SetStretchPixelsX(const NPatchUtility::StretchRanges stretchPixelsX);
+
+ /**
+ * @brief Set Y directional stretchPixels
+ *
+ * @param [in] stretchPixelsY stretchPixels for Y direction
+ */
+ void SetStretchPixelsY(const NPatchUtility::StretchRanges stretchPixelsY);
+
+ /**
+ * @brief Retrieve stretchPixels for X direction.
+ *
+ * @return Return stretchPixels for X direction.
+ */
+ NPatchUtility::StretchRanges GetStretchPixelsX() const;
+
+ /**
+ * @brief Retrieve stretchPixels for Y direction.
+ *
+ * @return Return stretchPixels for Y direction.
+ */
+ NPatchUtility::StretchRanges GetStretchPixelsY() const;
+
+ /**
+ * @brief Set cache data hash.
+ *
+ * @param [in] hash cache hash
+ */
+ void SetHash(std::size_t hash);
+
+ /**
+ * @brief Retrieve hash value of the cache.
+ *
+ * @return Return hash value of the cache.
+ */
+ std::size_t GetHash() const;
+
+ /**
+ * @brief Set croppedWidth of NPatch
+ *
+ * @param [in] croppedWidth croppedWidth of NPatch
+ */
+ void SetCroppedWidth(uint32_t croppedWidth);
+
+ /**
+ * @brief Set croppedHeight of NPatch
+ *
+ * @param [in] croppedHeight croppedHeight of NPatch
+ */
+ void SetCroppedHeight(uint32_t croppedHeight);
+
+ /**
+ * @brief Retrieve croppedWidth of NPatch.
+ *
+ * @return Return croppedWidth of NPatch.
+ */
+ uint32_t GetCroppedWidth() const;
+
+ /**
+ * @brief Retrieve croppedHeight of NPatch.
+ *
+ * @return Return croppedHeight of NPatch.
+ */
+ uint32_t GetCroppedHeight() const;
+
+ /**
+ * @brief Set border of NPatch.
+ *
+ * @param [in] border border of NPatch
+ */
+ void SetBorder(const Rect<int> border);
+
+ /**
+ * @brief Retrieve border of NPatch.
+ *
+ * @return Return border of NPatch.
+ */
+ Rect<int> GetBorder() const;
+
+ /**
+ * @brief Set whether the loaded image is premultiplied or not
+ *
+ * @param [in] preMultiplyOnLoad whether the loaded image is premultiplied or not
+ */
+ void SetPreMultiplyOnLoad(bool preMultiplyOnLoad);
+
+ /**
+ * @brief Retrieve whether the loaded image is premultiplied or not.
+ *
+ * @return Return true if the image is premultiplied alpha.
+ */
+ bool IsPreMultiplied() const;
+
+ /**
+ * @brief Set current loading state.
+ *
+ * @param [in] loadingState current loading state
+ */
+ void SetLoadingState(const LoadingState loadingState);
+
+ /**
+ * @brief Retrieve current loading state.
+ *
+ * @return Return current loading state.
+ */
+ LoadingState GetLoadingState() const;
+
+
+ /**
+ * @brief Retrieve NPatch rendering data.
+ *
+ * @return Return NPatch rendering data.
+ */
+ void* GetRenderingMap() const;
+
+ /**
+ * @brief Set loaded pixel buffer for the cache data.
+ *
+ * @param [in] pixelBuffer loaded pixel buffer.
+ * @param [in] preMultiplied whether the loaded image is premultiplied or not
+ */
+ void SetLoadedNPatchData( Devel::PixelBuffer& pixelBuffer, bool preMultiplied );
+
+private:
+
+ /**
+ * @copydoc TextureUploadObserver::UploadCompleted
+ *
+ * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
+ * This callback is the place to add the renderer as it would be called once the loading is finished.
+ */
+ void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override {}
+
+ /**
+ * @copydoc TextureUploadObserver::LoadComplete
+ *
+ * To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
+ * This callback is the place to add the renderer as it would be called once the loading is finished.
+ */
+ void LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied ) override;
+
+
+private:
+
+ using ObserverListType = Dali::Vector<TextureUploadObserver*>;
+
+ NPatchDataId mId;
+ ObserverListType mObserverList; ///< Container used to store all observer clients of this Texture
+ std::string mUrl; ///< Url of the N-Patch
+ TextureSet mTextureSet; ///< Texture containing the cropped image
+ NPatchUtility::StretchRanges mStretchPixelsX; ///< X stretch pixels
+ NPatchUtility::StretchRanges mStretchPixelsY; ///< Y stretch pixels
+ std::size_t mHash; ///< Hash code for the Url
+ uint32_t mCroppedWidth; ///< Width of the cropped middle part of N-patch
+ uint32_t mCroppedHeight; ///< Height of the cropped middle part of N-patch
+ Rect<int> mBorder; ///< The size of the border
+ LoadingState mLoadingState; ///< True if the data loading is completed
+ bool mPreMultiplyOnLoad; ///< Whether to multiply alpha into color channels on load
+ void* mRenderingMap; ///< NPatch rendering data
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // DALI_TOOLKIT_NPATCH_DATA_H
namespace Internal
{
-namespace NPatchBuffer
+namespace
{
-void SetLoadedNPatchData( NPatchLoader::Data* data, Devel::PixelBuffer& pixelBuffer )
-{
- if( data->border == Rect< int >( 0, 0, 0, 0 ) )
- {
- NPatchUtility::ParseBorders( pixelBuffer, data->stretchPixelsX, data->stretchPixelsY );
-
- // Crop the image
- pixelBuffer.Crop( 1, 1, pixelBuffer.GetWidth() - 2, pixelBuffer.GetHeight() - 2 );
- }
- else
- {
- data->stretchPixelsX.PushBack( Uint16Pair( data->border.left, ( (pixelBuffer.GetWidth() >= static_cast< unsigned int >( data->border.right )) ? pixelBuffer.GetWidth() - data->border.right : 0 ) ) );
- data->stretchPixelsY.PushBack( Uint16Pair( data->border.top, ( (pixelBuffer.GetHeight() >= static_cast< unsigned int >( data->border.bottom )) ? pixelBuffer.GetHeight() - data->border.bottom : 0 ) ) );
- }
-
- data->croppedWidth = pixelBuffer.GetWidth();
- data->croppedHeight = pixelBuffer.GetHeight();
-
- // Create opacity map
- data->renderingMap = RenderingAddOn::Get().IsValid() ? RenderingAddOn::Get().BuildNPatch(pixelBuffer, data ) : nullptr;
-
- PixelData pixels = Devel::PixelBuffer::Convert( pixelBuffer ); // takes ownership of buffer
-
- Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
- texture.Upload( pixels );
+constexpr auto INVALID_CACHE_INDEX = int32_t{-1}; ///< Invalid Cache index
+constexpr auto UNINITIALIZED_ID = int32_t{0}; ///< uninitialised id, use to initialize ids
- data->textureSet = TextureSet::New();
- data->textureSet.SetTexture( 0u, texture );
+} // Anonymous namespace
- data->loadCompleted = true;
-}
-
-} // namespace NPatchBuffer
-
-NPatchLoader::Data::~Data()
+NPatchLoader::NPatchLoader()
+: mCurrentNPatchDataId(0)
{
- // If there is an opacity map, it has to be destroyed using addon call
- if( renderingMap )
- {
- RenderingAddOn::Get().DestroyNPatch( renderingMap );
- }
}
-NPatchLoader::NPatchLoader()
+NPatchLoader::~NPatchLoader()
{
}
-NPatchLoader::~NPatchLoader()
+NPatchData::NPatchDataId NPatchLoader::GenerateUniqueNPatchDataId()
{
+ return mCurrentNPatchDataId++;
}
std::size_t NPatchLoader::Load( TextureManager& textureManager, TextureUploadObserver* textureObserver, const std::string& url, const Rect< int >& border, bool& preMultiplyOnLoad, bool synchronousLoading )
{
std::size_t hash = CalculateHash( url );
- OwnerContainer< Data* >::SizeType index = UNINITIALIZED_ID;
- const OwnerContainer< Data* >::SizeType count = mCache.Count();
- int cachedIndex = -1;
- Data* data;
+ OwnerContainer< NPatchData* >::SizeType index = UNINITIALIZED_ID;
+ const OwnerContainer< NPatchData* >::SizeType count = mCache.Count();
for( ; index < count; ++index )
{
- if( mCache[ index ]->hash == hash )
+ if( mCache[ index ]->GetHash() == hash )
{
// hash match, check url as well in case of hash collision
- if( mCache[ index ]->url == url )
+ if(mCache[ index ]->GetUrl() == url)
{
// Use cached data
- if( mCache[ index ]->border == border )
+ if( mCache[ index ]->GetBorder() == border )
{
- if( mCache[ index ]->loadCompleted )
+ if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOADING )
{
- return index + 1u; // valid indices are from 1 onwards
+ mCache[ index ]->AddObserver( textureObserver );
}
- mCache[ index ]->observerList.PushBack( textureObserver );
- data = mCache[ index ];
- return index + 1u; // valid indices are from 1 onwards
+ return mCache[ index ]->GetId(); // valid indices are from 1 onwards
}
else
{
- if( mCache[ index ]->loadCompleted )
+ if( mCache[ index ]->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
// Same url but border is different - use the existing texture
- Data* data = new Data();
- data->hash = hash;
- data->url = url;
- data->croppedWidth = mCache[ index ]->croppedWidth;
- data->croppedHeight = mCache[ index ]->croppedHeight;
+ NPatchData* newData = new NPatchData();
+ newData->SetId(GenerateUniqueNPatchDataId());
+ newData->SetHash(hash);
+ newData->SetUrl(url);
+ newData->SetCroppedWidth(mCache[ index ]->GetCroppedWidth());
+ newData->SetCroppedHeight(mCache[ index ]->GetCroppedHeight());
- data->textureSet = mCache[ index ]->textureSet;
+ newData->SetTextures(mCache[ index ]->GetTextures());
NPatchUtility::StretchRanges stretchRangesX;
- stretchRangesX.PushBack( Uint16Pair( border.left, ( (data->croppedWidth >= static_cast< unsigned int >( border.right )) ? data->croppedWidth - border.right : 0 ) ) );
+ stretchRangesX.PushBack( Uint16Pair( border.left, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.right )) ? newData->GetCroppedHeight() - border.right : 0 ) ) );
NPatchUtility::StretchRanges stretchRangesY;
- stretchRangesY.PushBack( Uint16Pair( border.top, ( (data->croppedHeight >= static_cast< unsigned int >( border.bottom )) ? data->croppedHeight - border.bottom : 0 ) ) );
+ stretchRangesY.PushBack( Uint16Pair( border.top, ( (newData->GetCroppedWidth() >= static_cast< unsigned int >( border.bottom )) ? newData->GetCroppedHeight() - border.bottom : 0 ) ) );
+
+ newData->SetStretchPixelsX(stretchRangesX);
+ newData->SetStretchPixelsY(stretchRangesY);
+ newData->SetBorder(border);
- data->stretchPixelsX = stretchRangesX;
- data->stretchPixelsY = stretchRangesY;
- data->border = border;
+ newData->SetPreMultiplyOnLoad(mCache[ index ]->IsPreMultiplied());
- data->loadCompleted = mCache[ index ]->loadCompleted;
+ newData->SetLoadingState(NPatchData::LoadingState::LOAD_COMPLETE);
+ newData->AddObserver( textureObserver );
- mCache.PushBack( data );
+ mCache.PushBack( newData );
- return mCache.Count(); // valid ids start from 1u
+ return newData->GetId(); // valid ids start from 1u
}
}
}
}
}
- if( cachedIndex == -1 )
- {
- data = new Data();
- data->loadCompleted = false;
- data->hash = hash;
- data->url = url;
- data->border = border;
-
- mCache.PushBack( data );
-
- cachedIndex = mCache.Count();
- }
+ // If this is new image loading, make new cache data
+ NPatchData* data;
+ data = new NPatchData();
+ data->SetId(GenerateUniqueNPatchDataId());
+ data->SetHash(hash);
+ data->SetUrl(url);
+ data->SetBorder(border);
+ data->SetPreMultiplyOnLoad(preMultiplyOnLoad);
+ data->AddObserver(textureObserver);
+ mCache.PushBack(data);
auto preMultiplyOnLoading = preMultiplyOnLoad ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
: TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
Devel::PixelBuffer pixelBuffer = textureManager.LoadPixelBuffer( url, Dali::ImageDimensions(), FittingMode::DEFAULT,
SamplingMode::BOX_THEN_LINEAR, synchronousLoading,
- textureObserver, true, preMultiplyOnLoading );
+ data, true, preMultiplyOnLoading );
if( pixelBuffer )
{
- NPatchBuffer::SetLoadedNPatchData( data, pixelBuffer );
preMultiplyOnLoad = ( preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD ) ? true : false;
+ data->SetLoadedNPatchData( pixelBuffer, preMultiplyOnLoad );
}
- return cachedIndex;
+ return data->GetId();
}
-void NPatchLoader::SetNPatchData( bool loadSuccess, std::size_t id, Devel::PixelBuffer& pixelBuffer, const Internal::VisualUrl& url, bool preMultiplied )
+int32_t NPatchLoader::GetCacheIndexFromId( const NPatchData::NPatchDataId id )
{
- Data* data;
- data = mCache[ id - 1u ];
+ const unsigned int size = mCache.Count();
- // To prevent recursion.
- // data->loadCompleted will be set true in the NPatchBuffer::SetLoadedNPatchData when the first observer called this method.
- if( data->loadCompleted )
+ for( unsigned int i = 0; i < size; ++i )
{
- return;
+ if( mCache[i]->GetId() == id )
+ {
+ return i;
+ }
}
- NPatchBuffer::SetLoadedNPatchData( data, pixelBuffer );
+ DALI_LOG_ERROR("Wrong NPatchDataId is used\n");
+ return INVALID_CACHE_INDEX;
+}
- while( data->observerList.Count() )
+bool NPatchLoader::GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data )
+{
+ int32_t cacheIndex = GetCacheIndexFromId(id);
+ if( cacheIndex != INVALID_CACHE_INDEX )
{
- TextureUploadObserver* observer = data->observerList[0];
- observer->LoadComplete( loadSuccess, Devel::PixelBuffer(), url, preMultiplied );
- data->observerList.Erase( data->observerList.begin() );
+ data = mCache[cacheIndex];
+ return true;
}
+ data = nullptr;
+ return false;
}
-bool NPatchLoader::GetNPatchData( std::size_t id, const Data*& data )
+void NPatchLoader::Remove( std::size_t id, TextureUploadObserver* textureObserver )
{
- if( ( id > UNINITIALIZED_ID )&&( id <= mCache.Count() ) )
+ int32_t cacheIndex = GetCacheIndexFromId(id);
+ if( cacheIndex == INVALID_CACHE_INDEX )
{
- data = mCache[ id - 1u ]; // id's start from 1u
- return true;
+ return;
+ }
+
+ NPatchData* data;
+ data = mCache[cacheIndex];
+
+ data->RemoveObserver(textureObserver);
+
+ if(data->GetObserverCount() == 0)
+ {
+ mCache.Erase( mCache.Begin() + cacheIndex );
}
- data = NULL;
- return false;
}
} // namespace Internal
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/internal/visuals/npatch-data.h>
#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
#include <dali-toolkit/devel-api/utility/npatch-utilities.h>
{
public:
- enum
- {
- UNINITIALIZED_ID = 0 ///< uninitialised id, use to initialize ids
- };
-
- struct Data
- {
- Data()
- : url(),
- textureSet(),
- hash( 0 ),
- croppedWidth( 0 ),
- croppedHeight( 0 ),
- border( 0, 0, 0, 0 ),
- loadCompleted( false ),
- renderingMap{ nullptr }
- {}
-
- ~Data();
-
- using ObserverListType = Dali::Vector< TextureUploadObserver* >;
-
- ObserverListType observerList; ///< Container used to store all observer clients of this Texture
- std::string url; ///< Url of the N-Patch
- TextureSet textureSet; ///< Texture containing the cropped image
- NPatchUtility::StretchRanges stretchPixelsX; ///< X stretch pixels
- NPatchUtility::StretchRanges stretchPixelsY; ///< Y stretch pixels
- std::size_t hash; ///< Hash code for the Url
- uint32_t croppedWidth; ///< Width of the cropped middle part of N-patch
- uint32_t croppedHeight; ///< Height of the cropped middle part of N-patch
- Rect< int > border; ///< The size of the border
- bool loadCompleted; ///< True if the data loading is completed
- void* renderingMap; ///< NPatch rendering data
- };
-
-public:
-
/**
* Constructor
*/
/**
* @brief Set loaded PixelBuffer and its information
*
- * @param [in] loadSuccess True if the texture load was successful (i.e. the resource is available). If false, then the resource failed to load.
* @param [in] id cache data id
* @param [in] pixelBuffer of loaded image
- * @param [in] url The url address of the loaded image.
* @param [in] preMultiplied True if the image had pre-multiplied alpha applied
*/
- void SetNPatchData( bool loadSuccess, std::size_t id, Devel::PixelBuffer& pixelBuffer, const Internal::VisualUrl& url, bool preMultiplied );
+ void SetNPatchData( std::size_t id, Devel::PixelBuffer& pixelBuffer, bool preMultiplied );
/**
* @brief Retrieve N patch data matching to an id
* @param [in] id of data
- * @param [out] data const pointer to the data
+ * @param [out] data const pointer to the NPatchData
* @return true if data matching to id was really found
*/
- bool GetNPatchData( std::size_t id, const Data*& data );
+ bool GetNPatchData( const NPatchData::NPatchDataId id, const NPatchData*& data );
+
+ /**
+ * @brief Remove a texture matching id.
+ * Erase the observer from the observer list of cache.
+ * If the observer list is empty, the textureSet will be reset.
+ *
+ * @param [in] id cache data id
+ * @param [in] textureObserver The NPatchVisual that requested loading.
+ */
+ void Remove( std::size_t id, TextureUploadObserver* textureObserver );
+
+private:
+
+ NPatchData::NPatchDataId GenerateUniqueNPatchDataId();
+
+ int32_t GetCacheIndexFromId( const NPatchData::NPatchDataId id );
protected:
private:
- OwnerContainer< Data* > mCache;
-
+ NPatchData::NPatchDataId mCurrentNPatchDataId;
+ OwnerContainer< NPatchData* > mCache;
};
} // name Internal
#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
#include <dali-toolkit/devel-api/visuals/image-visual-properties-devel.h>
#include <dali-toolkit/public-api/visuals/visual-properties.h>
#include <dali-toolkit/internal/visuals/npatch-loader.h>
TextureManager& textureManager = mFactoryCache.GetTextureManager();
bool synchronousLoading = mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
- if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() )
+ if( mId == NPatchData::INVALID_NPATCH_DATA_ID && mImageUrl.IsLocalResource() )
{
bool preMultiplyOnLoad = IsPreMultipliedAlphaEnabled() && !mImpl->mCustomShader ? true : false;
mId = mLoader.Load( textureManager, this, mImageUrl.GetUrl(), mBorder, preMultiplyOnLoad, synchronousLoading );
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ const NPatchData* data;
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
- EnablePreMultipliedAlpha( preMultiplyOnLoad );
+ EnablePreMultipliedAlpha( data->IsPreMultiplied() );
}
}
naturalSize.y = 0u;
// load now if not already loaded
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ const NPatchData* data;
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() != NPatchData::LoadingState::LOADING )
{
- naturalSize.x = data->croppedWidth;
- naturalSize.y = data->croppedHeight;
+ naturalSize.x = data->GetCroppedWidth();
+ naturalSize.y = data->GetCroppedHeight();
}
else
{
mImpl->mFlags &= ~Impl::IS_SYNCHRONOUS_RESOURCE_LOADING;
}
}
+
+ Property::Value* releasePolicy = propertyMap.Find( Toolkit::ImageVisual::Property::RELEASE_POLICY, RELEASE_POLICY_NAME );
+ if( releasePolicy )
+ {
+ releasePolicy->Get( mReleasePolicy );
+ }
}
void NPatchVisual::DoSetOnScene( Actor& actor )
// load when first go on stage
LoadImages();
- const NPatchLoader::Data* data;
+ const NPatchData* data;
if( mLoader.GetNPatchData( mId, data ) )
{
Geometry geometry = CreateGeometry();
mImpl->mRenderer = Renderer::New( geometry, shader );
mPlacementActor = actor;
- if( data->loadCompleted )
+ if( data->GetLoadingState() != NPatchData::LoadingState::LOADING )
{
if( RenderingAddOn::Get().IsValid() )
{
- RenderingAddOn::Get().SubmitRenderTask( mImpl->mRenderer, data->renderingMap );
+ RenderingAddOn::Get().SubmitRenderTask( mImpl->mRenderer, data->GetRenderingMap() );
}
ApplyTextureAndUniforms();
void NPatchVisual::DoSetOffScene( Actor& actor )
{
+ if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && mReleasePolicy == Toolkit::ImageVisual::ReleasePolicy::DETACHED)
+ {
+ mLoader.Remove(mId, this);
+ mImpl->mResourceStatus = Toolkit::Visual::ResourceStatus::PREPARING;
+ mId = NPatchData::INVALID_NPATCH_DATA_ID;
+ }
+
actor.RemoveRenderer( mImpl->mRenderer );
mImpl->mRenderer.Reset();
mPlacementActor.Reset();
map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl() );
map.Insert( Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly );
map.Insert( Toolkit::ImageVisual::Property::BORDER, mBorder );
+ map.Insert( Toolkit::ImageVisual::Property::RELEASE_POLICY, mReleasePolicy );
if( mAuxiliaryUrl.IsValid() )
{
mLoader( factoryCache.GetNPatchLoader() ),
mImageUrl(),
mAuxiliaryUrl(),
- mId( NPatchLoader::UNINITIALIZED_ID ),
+ mId(NPatchData::INVALID_NPATCH_DATA_ID),
mBorderOnly( false ),
mBorder(),
- mAuxiliaryImageAlpha( 0.0f )
+ mAuxiliaryImageAlpha( 0.0f ),
+ mReleasePolicy( Toolkit::ImageVisual::ReleasePolicy::DETACHED )
{
EnablePreMultipliedAlpha( mFactoryCache.GetPreMultiplyOnLoad() );
}
NPatchVisual::~NPatchVisual()
{
+ if((mId != NPatchData::INVALID_NPATCH_DATA_ID) && ( mReleasePolicy != Toolkit::ImageVisual::ReleasePolicy::NEVER ))
+ {
+ mLoader.Remove(mId, this);
+ mId = NPatchData::INVALID_NPATCH_DATA_ID;
+ }
}
Geometry NPatchVisual::CreateGeometry()
{
Geometry geometry;
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ const NPatchData* data;
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
- if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 )
+ if( data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1 )
{
if( DALI_UNLIKELY( mBorderOnly ) )
{
}
else
{
- if( data->renderingMap )
+ if( data->GetRenderingMap() )
{
uint32_t elementCount[2];
- geometry = RenderingAddOn::Get().CreateGeometryGrid(data->renderingMap, Uint16Pair(3, 3), elementCount );
+ geometry = RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), Uint16Pair(3, 3), elementCount );
if( mImpl->mRenderer )
{
- RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->renderingMap);
+ RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
}
}
else
}
}
}
- else if( data->stretchPixelsX.Size() > 0 || data->stretchPixelsY.Size() > 0)
+ else if( data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
{
- Uint16Pair gridSize( 2 * data->stretchPixelsX.Size() + 1, 2 * data->stretchPixelsY.Size() + 1 );
- if( !data->renderingMap )
+ Uint16Pair gridSize( 2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1 );
+ if( !data->GetRenderingMap() )
{
geometry = !mBorderOnly ? CreateGridGeometry( gridSize ) : CreateBorderGeometry( gridSize );
}
{
uint32_t elementCount[2];
geometry = !mBorderOnly ?
- RenderingAddOn::Get().CreateGeometryGrid(data->renderingMap, gridSize, elementCount ) : CreateBorderGeometry(gridSize );
+ RenderingAddOn::Get().CreateGeometryGrid(data->GetRenderingMap(), gridSize, elementCount ) : CreateBorderGeometry(gridSize );
if( mImpl->mRenderer )
{
- RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->renderingMap);
+ RenderingAddOn::Get().SubmitRenderTask(mImpl->mRenderer, data->GetRenderingMap());
}
}
}
Shader NPatchVisual::CreateShader()
{
Shader shader;
- const NPatchLoader::Data* data;
+ const NPatchData* data;
// 0 is either no data (load failed?) or no stretch regions on image
// for both cases we use the default shader
NPatchUtility::StretchRanges::SizeType xStretchCount = 0;
// ask loader for the regions
if( mLoader.GetNPatchData( mId, data ) )
{
- xStretchCount = data->stretchPixelsX.Count();
- yStretchCount = data->stretchPixelsY.Count();
+ xStretchCount = data->GetStretchPixelsX().Count();
+ yStretchCount = data->GetStretchPixelsY().Count();
}
if( DALI_LIKELY( !mImpl->mCustomShader ) )
void NPatchVisual::ApplyTextureAndUniforms()
{
- const NPatchLoader::Data* data;
+ const NPatchData* data;
TextureSet textureSet;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
+ if( mLoader.GetNPatchData( mId, data ) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE )
{
- textureSet = data->textureSet;
+ textureSet = data->GetTextures();
- if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 )
+ if( data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1 )
{
//special case for 9 patch
- Uint16Pair stretchX = data->stretchPixelsX[ 0 ];
- Uint16Pair stretchY = data->stretchPixelsY[ 0 ];
+ Uint16Pair stretchX = data->GetStretchPixelsX()[ 0 ];
+ Uint16Pair stretchY = data->GetStretchPixelsY()[ 0 ];
uint16_t stretchWidth = ( stretchX.GetY() >= stretchX.GetX() ) ? stretchX.GetY() - stretchX.GetX() : 0;
uint16_t stretchHeight = ( stretchY.GetY() >= stretchY.GetX() ) ? stretchY.GetY() - stretchY.GetX() : 0;
mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO );
mImpl->mRenderer.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) );
- mImpl->mRenderer.RegisterProperty( "uFixed[2]", Vector2( data->croppedWidth - stretchWidth, data->croppedHeight - stretchHeight ) );
+ mImpl->mRenderer.RegisterProperty( "uFixed[2]", Vector2( data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight ) );
mImpl->mRenderer.RegisterProperty( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) );
}
else
mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsX[0]", Vector2::ZERO );
mImpl->mRenderer.RegisterProperty( "uNinePatchFactorsY[0]", Vector2::ZERO );
- RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsX", data->stretchPixelsX, data->croppedWidth );
- RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsY", data->stretchPixelsY, data->croppedHeight );
+ RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth() );
+ RegisterStretchProperties( mImpl->mRenderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight() );
}
}
else
// If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the
// same size as the unstretched NPatch. This will give slightly higher quality results than just relying
// on GL interpolation alone.
- if( mAuxiliaryPixelBuffer.GetWidth() < data->croppedWidth &&
- mAuxiliaryPixelBuffer.GetHeight() < data->croppedHeight )
+ if( mAuxiliaryPixelBuffer.GetWidth() < data->GetCroppedWidth() &&
+ mAuxiliaryPixelBuffer.GetHeight() < data->GetCroppedHeight() )
{
- mAuxiliaryPixelBuffer.Resize( data->croppedWidth, data->croppedHeight );
+ mAuxiliaryPixelBuffer.Resize( data->GetCroppedWidth(), data->GetCroppedHeight() );
}
// Note, this resets mAuxiliaryPixelBuffer handle
void NPatchVisual::SetResource()
{
- const NPatchLoader::Data* data;
+ const NPatchData* data;
if( mImpl->mRenderer && mLoader.GetNPatchData( mId, data ) )
{
Geometry geometry = CreateGeometry();
}
}
+void NPatchVisual::UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied )
+{
+ EnablePreMultipliedAlpha( preMultiplied );
+ if(!loadSuccess)
+ {
+ // Image loaded and ready to display
+ ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
+ }
+
+ if( mAuxiliaryPixelBuffer || !mAuxiliaryUrl.IsValid() )
+ {
+ SetResource();
+ }
+}
+
void NPatchVisual::LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied )
{
- if( url.GetUrl() == mAuxiliaryUrl.GetUrl() )
+ if( loadSuccess && url.GetUrl() == mAuxiliaryUrl.GetUrl() )
{
mAuxiliaryPixelBuffer = pixelBuffer;
- const NPatchLoader::Data* data;
- if( mLoader.GetNPatchData( mId, data ) && data->loadCompleted )
- {
- SetResource();
- }
+ SetResource();
}
else
{
- Devel::PixelBuffer loadedPixelBuffer;
- if( loadSuccess )
- {
- loadedPixelBuffer = pixelBuffer;
- EnablePreMultipliedAlpha( preMultiplied );
- }
- else
- {
- loadedPixelBuffer = LoadImageFromFile( mFactoryCache.GetTextureManager().GetBrokenImageUrl() );
- }
- mLoader.SetNPatchData( loadSuccess, mId, loadedPixelBuffer, url, preMultiplied );
-
- if( mAuxiliaryPixelBuffer || !mAuxiliaryUrl.IsValid() )
- {
- SetResource();
- }
+ // Image loaded and ready to display
+ ResourceReady( Toolkit::Visual::ResourceStatus::FAILED );
}
}
#include <dali/public-api/object/weak-handle.h>
// INTERNAL INCLUDES
+#include <dali-toolkit/public-api/visuals/image-visual-properties.h>
#include <dali-toolkit/internal/visuals/texture-upload-observer.h>
#include <dali-toolkit/internal/visuals/visual-base-impl.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
* To avoid rendering garbage pixels, renderer should be added to actor after the resources are ready.
* This callback is the place to add the renderer as it would be called once the loading is finished.
*/
- void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override {}
+ void UploadComplete( bool loadSuccess, int32_t textureId, TextureSet textureSet, bool useAtlasing, const Vector4& atlasRect, bool preMultiplied ) override;
/**
* @copydoc TextureUploadObserver::LoadComplete
void LoadComplete( bool loadSuccess, Devel::PixelBuffer pixelBuffer, const VisualUrl& url, bool preMultiplied ) override;
private:
-
- WeakHandle<Actor> mPlacementActor; ///< Weakhandle to contain Actor during texture loading
- NPatchLoader& mLoader; ///< reference to N patch loader for fast access
- VisualUrl mImageUrl; ///< The url to the N patch to load
- VisualUrl mAuxiliaryUrl; ///< An auxiliary image that can be displayed on top of the N-Patch
- std::size_t mId; ///< id of the N patch (from loader/cache)
- Devel::PixelBuffer mAuxiliaryPixelBuffer; ///< pixel buffer of the auxiliary mask image
- bool mBorderOnly; ///< if only border is desired
- Rect<int> mBorder; ///< The size of the border
- float mAuxiliaryImageAlpha; ///< The alpha value for the auxiliary image only
+ WeakHandle<Actor> mPlacementActor; ///< Weakhandle to contain Actor during texture loading
+ NPatchLoader& mLoader; ///< reference to N patch loader for fast access
+ VisualUrl mImageUrl; ///< The url to the N patch to load
+ VisualUrl mAuxiliaryUrl; ///< An auxiliary image that can be displayed on top of the N-Patch
+ NPatchData::NPatchDataId mId; ///< id of the N patch (from loader/cache)
+ Devel::PixelBuffer mAuxiliaryPixelBuffer; ///< pixel buffer of the auxiliary mask image
+ bool mBorderOnly; ///< if only border is desired
+ Rect<int> mBorder; ///< The size of the border
+ float mAuxiliaryImageAlpha; ///< The alpha value for the auxiliary image only
+ Toolkit::ImageVisual::ReleasePolicy::Type mReleasePolicy; ///< The release policy to determine when an image should no longer be cached.
};
} // namespace Internal
}
else
{
- // @todo If the load was unsuccessful, upload the broken image.
textureInfo.loadState = LoadState::LOAD_FAILED;
CheckForWaitingTexture( textureInfo );
NotifyObservers( textureInfo, false );
mBrokenImageUrl = brokenImageUrl;
}
-const std::string TextureManager::GetBrokenImageUrl()
-{
- return mBrokenImageUrl;
-}
-
Geometry TextureManager::GetRenderGeometry(TextureId textureId, uint32_t& frontElements, uint32_t& backElements )
{
return RenderingAddOn::Get().IsValid() ?
void SetBrokenImageUrl(const std::string& brokenImageUrl);
/**
- * @brief Get an image to be used when a visual has failed to correctly render
- * @return Returns The broken image url.
- */
- const std::string GetBrokenImageUrl();
-
- /**
* @brief Returns the geometry associated with texture.
* @param[in] textureId Id of the texture
* @param[out] frontElements number of front elements