Support to use NpatchImage in broken Image.
Application can use custom broken image from this patch.
when they set 3 type of broken image(small,normal,large),
dali show the proper broken image considering size.
Change-Id: I7e2be85d4715d07356fd2782be2d011931fde5c2
#include <dali-toolkit/devel-api/visuals/visual-properties-devel.h>
#include <dali-toolkit/public-api/image-loader/image.h>
#include <dali-toolkit/public-api/image-loader/image-url.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
#include <test-native-image.h>
#include <test-encoded-image-buffer.h>
const char* TEST_IMAGE_1 = TEST_RESOURCE_DIR "/TB-gloss.png";
const char* TEST_IMAGE_2 = TEST_RESOURCE_DIR "/tb-norm.png";
+const char* TEST_BROKEN_IMAGE_DEFAULT = TEST_RESOURCE_DIR "/broken.png";
+const char* TEST_BROKEN_IMAGE_S = TEST_RESOURCE_DIR "/broken_s.9.png";
+const char* TEST_BROKEN_IMAGE_M = TEST_RESOURCE_DIR "/broken_m.9.png";
+const char* TEST_BROKEN_IMAGE_L = TEST_RESOURCE_DIR "/broken_l.9.png";
+const char* TEST_BROKEN_IMAGE_01 = TEST_RESOURCE_DIR "/button-up.9.png";
+const char* TEST_BROKEN_IMAGE_02 = TEST_RESOURCE_DIR "/heartsframe.9.png";
+
// resolution: 34*34, pixel format: RGBA8888
static const char* gImage_34_RGBA = TEST_RESOURCE_DIR "/icon-edit.png";
// resolution: 600*600, pixel format: RGB888
}
END_TEST;
}
+int UtcDaliImageViewImageLoadFailure01(void)
+{
+ ToolkitTestApplication application;
+
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_S);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+ std::string brokenUrl;
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_S, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+ ImageView imageView = ImageView::New("invalidUrl.png");
+ imageView.SetProperty( Actor::Property::SIZE, Vector2( 200.f, 200.f ) );
+
+ application.GetScene().Add( imageView );
+ application.SendNotification();
+ application.Render(16);
+
+ // loading started, this waits for the loader thread
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure02(void)
+{
+ ToolkitTestApplication application;
+
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_DEFAULT);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_M);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE, TEST_BROKEN_IMAGE_L);
+
+ std::string brokenUrl;
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_DEFAULT, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_M, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::LARGE);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_L, brokenUrl, TEST_LOCATION);
+
+ ImageView imageView = ImageView::New("invalidUrl.png");
+ imageView.SetProperty( Actor::Property::SIZE, Vector2( 30.f, 30.f ) );
+ application.GetScene().Add( imageView );
+ application.SendNotification();
+ application.Render(16);
+
+ // loading started, this waits for the loader thread
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliImageViewImageLoadFailure03(void)
+{
+ ToolkitTestApplication application;
+
+ Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL, TEST_BROKEN_IMAGE_01);
+ DevelStyleManager::SetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL, TEST_BROKEN_IMAGE_02);
+
+ std::string brokenUrl;
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::SMALL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_01, brokenUrl, TEST_LOCATION);
+
+ brokenUrl = DevelStyleManager::GetBrokenImageUrl(styleManager, DevelStyleManager::BrokenImageType::NORMAL);
+ DALI_TEST_EQUALS( TEST_BROKEN_IMAGE_02, brokenUrl, TEST_LOCATION);
+
+ ImageView imageView = ImageView::New("invalidUrl.png");
+ imageView.SetProperty( Actor::Property::SIZE, Vector2( 100.f, 100.f ) );
+ application.GetScene().Add( imageView );
+ application.SendNotification();
+ application.Render(16);
+
+ // loading started, this waits for the loader thread
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ END_TEST;
+}
namespace
{
return GetImpl(styleManager).GetConfigurations();
}
+void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+ return GetImpl(styleManager).SetBrokenImageUrl(brokenImageType, brokenImageUrl);
+}
+
+std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType)
+{
+ return GetImpl(styleManager).GetBrokenImageUrl(brokenImageType);
+}
+
+std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager)
+{
+ return GetImpl(styleManager).GetBrokenImageUrlList();
+}
+
+BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager)
+{
+ return GetImpl(styleManager).BrokenImageChangedSignal();
+}
+
} // namespace DevelStyleManager
} // namespace Toolkit
{
namespace DevelStyleManager
{
+/**
+ * @brief The Type of BrokenImage
+ */
+enum class BrokenImageType
+{
+ SMALL,
+ NORMAL,
+ LARGE
+};
+
+using BrokenImageChangedSignalType = Signal<void(StyleManager)>;
+
/**
* @brief Gets all currently defined configurations.
*
**/
DALI_TOOLKIT_API const Property::Map GetConfigurations(StyleManager styleManager);
+/**
+ * @brief Sets an image to be used when a visual has failed to correctly render
+ * @param[in] styleManager The instance of StyleManager
+ * @param[in] brokenImageType The type of broken image
+ * @param[in] brokenImageUrl The broken image url
+ */
+DALI_TOOLKIT_API void SetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+/**
+ * @brief Gets an image to be used when a visual has failed to correctly render
+ * @param[in] styleManager The instance of StyleManager
+ * @param[in] brokenImageType BrokenImage type
+ */
+DALI_TOOLKIT_API std::string GetBrokenImageUrl(StyleManager styleManager, DevelStyleManager::BrokenImageType brokenImageType);
+
+/**
+ * @brief Get the Broken Image Url List
+ *
+ * This list is broken images stored in order of SMALL, NORMAL, and LARGE values except if the value is empty.
+ * This API just makes the list without comparing size, so the application must set a value that matches the size.
+ * @param styleManager The instance of StyleManager
+ * @return A List of Broken Image Url
+ */
+DALI_TOOLKIT_API std::vector<std::string> GetBrokenImageUrlList(StyleManager styleManager);
+
+/**
+ * @brief This signal is emitted when the URL of the broken image is set
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void YourCallbackName(StyleManager styleManager)
+ * @endcode
+ * @param styleManager The instance of StyleManager
+ * @return The signal to connect to
+ */
+DALI_TOOLKIT_API BrokenImageChangedSignalType& BrokenImageChangedSignal(StyleManager styleManager);
+
} // namespace DevelStyleManager
} // namespace Toolkit
const char* DEFAULT_TOOLKIT_PACKAGE_PATH = "/toolkit/";
+static constexpr int32_t COUNT_BROKEN_IMAGE_MAX = 3;
+
#if defined(DEBUG_ENABLED)
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_STYLE");
#endif
// Sound & haptic style
mFeedbackStyle = new FeedbackStyle();
+
+ // Initialize BrokenImages
+ mBrokenImageUrls.assign(COUNT_BROKEN_IMAGE_MAX, "");
}
StyleManager::~StyleManager()
return mControlStyleChangeSignal;
}
+Toolkit::DevelStyleManager::BrokenImageChangedSignalType& StyleManager::BrokenImageChangedSignal()
+{
+ return mBrokenImageChangedSignal;
+}
+
void StyleManager::SetTheme(const std::string& themeFile)
{
bool themeLoaded = false;
return result;
}
+void StyleManager::SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl)
+{
+ int brokenType = static_cast<int>(brokenImageType);
+ mBrokenImageUrls[brokenType] = brokenImageUrl;
+ Toolkit::StyleManager styleManager = StyleManager::Get();
+ mBrokenImageChangedSignal.Emit(styleManager);
+}
+
+std::string StyleManager::GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType)
+{
+ int brokenType = static_cast<int>(brokenImageType);
+ return mBrokenImageUrls[brokenType];
+}
+
+std::vector<std::string> StyleManager::GetBrokenImageUrlList()
+{
+ // create a list for brokenImage
+ std::vector<std::string> brokenImageUrlList;
+ for(int i = 0; i < COUNT_BROKEN_IMAGE_MAX; i++)
+ {
+ if(!mBrokenImageUrls[i].empty())
+ {
+ brokenImageUrlList.push_back(mBrokenImageUrls[i]);
+ }
+ }
+ return brokenImageUrlList;
+}
+
bool StyleManager::LoadFile(const std::string& filename, std::string& stringOut)
{
DALI_ASSERT_DEBUG(0 != filename.length());
#include <dali-toolkit/devel-api/builder/builder.h>
#include <dali-toolkit/internal/builder/style.h>
#include <dali-toolkit/public-api/styling/style-manager.h>
+#include <dali-toolkit/devel-api/styling/style-manager-devel.h>
namespace Dali
{
*/
const Property::Map GetConfigurations();
+ /**
+ * @copydoc Toolkit::DevelStyleManager::SetBrokenImageUrl
+ */
+ void SetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType, const std::string& brokenImageUrl);
+
+ /**
+ * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrl
+ */
+ std::string GetBrokenImageUrl(DevelStyleManager::BrokenImageType brokenImageType);
+
+ /**
+ * @copydoc Toolkit::DevelStyleManager::GetBrokenImageUrlList
+ */
+ std::vector<std::string> GetBrokenImageUrlList();
+
/**
* @brief Apply the theme style to a control.
*
*/
Toolkit::StyleManager::StyleChangedSignalType& ControlStyleChangeSignal();
+ /**
+ * This signal is sent to the visual factory following a broken image change.
+ * It should not be exposed in the public API
+ */
+ Toolkit::DevelStyleManager::BrokenImageChangedSignalType& BrokenImageChangedSignal();
+
private:
typedef std::vector<std::string> StringList;
Toolkit::Internal::FeedbackStyle* mFeedbackStyle; ///< Feedback style
+ std::vector<std::string> mBrokenImageUrls; ///< Broken Image Urls received from user
+
// Signals
- Toolkit::StyleManager::StyleChangedSignalType mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
- Toolkit::StyleManager::StyleChangedSignalType mStyleChangedSignal; ///< Emitted after the controls have been styled
+ Toolkit::StyleManager::StyleChangedSignalType mControlStyleChangeSignal; ///< Emitted when the style( theme/font ) changes for the controls to style themselves
+ Toolkit::StyleManager::StyleChangedSignalType mStyleChangedSignal; ///< Emitted after the controls have been styled
+ Toolkit::DevelStyleManager::BrokenImageChangedSignalType mBrokenImageChangedSignal; ///< Emitted after brokenImageChangedSignal
};
} // namespace Internal
DALI_LOG_INFO(gAnimImgLogFilter, Debug::Concise, "ResourceReady(ResourceStatus::FAILED)\n");
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
- TextureSet textureSet = TextureSet::New();
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
+ Actor actor = mPlacementActor.GetHandle();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ TextureSet textureSet = mImpl->mRenderer.GetTextures();
if(mFrameDelayTimer)
{
if(mLoadFailed)
{
- TextureSet textureSet = TextureSet::New();
- mImpl->mRenderer.SetTextures(textureSet);
-
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
-
+ Vector2 imageSize = Vector2::ZERO;
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
-
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
}
else
}
else
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
+ Actor actor = mPlacementActor.GetHandle();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ Texture brokenImage = mImpl->mRenderer.GetTextures().GetTexture(0);
naturalSize.x = brokenImage.GetWidth();
naturalSize.y = brokenImage.GetWidth();
}
}
else if(mLoadState == TextureManager::LoadState::LOAD_FAILED)
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
- mTextures = TextureSet::New();
- mTextures.SetTexture(0u, brokenImage);
- mImpl->mRenderer.SetTextures(mTextures);
-
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
mPlacementActor.Reset();
EnablePreMultipliedAlpha(preMultiplied);
Actor actor = mPlacementActor.GetHandle();
- if(actor)
+ if(!loadingSuccess)
{
- actor.AddRenderer(mImpl->mRenderer);
- // reset the weak handle so that the renderer only get added to actor once
- mPlacementActor.Reset();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ textureSet = mImpl->mRenderer.GetTextures();
}
-
- if(!loadingSuccess)
+ else
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
-
- textureSet = TextureSet::New();
- textureSet.SetTexture(0u, brokenImage);
+ Sampler sampler = Sampler::New();
+ sampler.SetWrapMode(mWrapModeU, mWrapModeV);
+ textureSet.SetSampler(0u, sampler);
mImpl->mRenderer.SetTextures(textureSet);
}
- Sampler sampler = Sampler::New();
- sampler.SetWrapMode(mWrapModeU, mWrapModeV);
- textureSet.SetSampler(0u, sampler);
- mImpl->mRenderer.SetTextures(textureSet);
+ if(actor)
+ {
+ actor.AddRenderer(mImpl->mRenderer);
+ // reset the weak handle so that the renderer only get added to actor once
+ mPlacementActor.Reset();
+ }
}
// Storing TextureSet needed when renderer staged.
newData->AddObserver(textureObserver);
mCache.PushBack(newData);
-
return newData->GetId(); // valid ids start from 1u
}
}
preMultiplyOnLoad = (preMultiplyOnLoading == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? true : false;
data->SetLoadedNPatchData(pixelBuffer, preMultiplyOnLoad);
}
-
return data->GetId();
}
DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str());
textureSet = TextureSet::New();
- Texture croppedImage = mFactoryCache.GetBrokenVisualImage();
+ Actor actor = mPlacementActor.GetHandle();
+ Vector2 imageSize = Vector2::ZERO;
+ if(actor)
+ {
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ }
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
+ Texture croppedImage = mImpl->mRenderer.GetTextures().GetTexture(0);
textureSet.SetTexture(0u, croppedImage);
mImpl->mRenderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
mImpl->mRenderer.RegisterProperty("uFixed[1]", Vector2::ZERO);
if(mLoadFailed)
{
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
-
+ Vector2 imageSize = Vector2::ZERO;
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
ResourceReady(Toolkit::Visual::ResourceStatus::FAILED);
Actor actor = mPlacementActor.GetHandle();
if(actor)
{
- TextureSet textureSet = mImpl->mRenderer.GetTextures();
-
- Texture brokenImage = mFactoryCache.GetBrokenVisualImage();
- textureSet.SetTexture(0u, brokenImage);
-
+ Vector2 imageSize = Vector2::ZERO;
+ imageSize = actor.GetProperty(Actor::Property::SIZE).Get<Vector2>();
+ mFactoryCache.UpdateBrokenImageRenderer(mImpl->mRenderer, imageSize);
actor.AddRenderer(mImpl->mRenderer);
}
#include <dali-toolkit/internal/visuals/color/color-visual.h>
#include <dali-toolkit/internal/visuals/image-atlas-manager.h>
#include <dali-toolkit/internal/visuals/svg/svg-visual.h>
+#include <dali-toolkit/internal/graphics/builtin-shader-extern-gen.h>
+#include <dali/integration-api/debug.h>
namespace Dali
{
{
namespace Internal
{
+namespace
+{
+
+/**
+ * @brief Creates the geometry formed from the vertices and indices
+ *
+ * @param[in] vertices The vertices to generate the geometry from
+ * @param[in] indices The indices to generate the geometry from
+ * @return The geometry formed from the vertices and indices
+ */
+Geometry GenerateGeometry(const Vector<Vector2>& vertices, const Vector<unsigned short>& indices)
+{
+ Property::Map vertexFormat;
+ vertexFormat["aPosition"] = Property::VECTOR2;
+ VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
+ if(vertices.Size() > 0)
+ {
+ vertexBuffer.SetData(&vertices[0], vertices.Size());
+ }
+
+ // Create the geometry object
+ Geometry geometry = Geometry::New();
+ geometry.AddVertexBuffer(vertexBuffer);
+ if(indices.Size() > 0)
+ {
+ geometry.SetIndexBuffer(&indices[0], indices.Size());
+ }
+
+ return geometry;
+}
+
+/**
+ * @brief Adds the indices to form a quad composed off two triangles where the indices are organised in a grid
+ *
+ * @param[out] indices The indices to add to
+ * @param[in] rowIdx The row index to start the quad
+ * @param[in] nextRowIdx The index to the next row
+ */
+void AddQuadIndices(Vector<unsigned short>& indices, unsigned int rowIdx, unsigned int nextRowIdx)
+{
+ indices.PushBack(rowIdx);
+ indices.PushBack(nextRowIdx + 1);
+ indices.PushBack(rowIdx + 1);
+
+ indices.PushBack(rowIdx);
+ indices.PushBack(nextRowIdx);
+ indices.PushBack(nextRowIdx + 1);
+}
+
+/**
+ * @brief Adds the vertices to create for npatch
+ * @param[out] vertices The vertices to add to
+ * @param[in] x The x value of vector
+ * @param[in] y The y value of vector
+ */
+void AddVertex(Vector<Vector2>& vertices, unsigned int x, unsigned int y)
+{
+ vertices.PushBack(Vector2(x, y));
+}
+
+} //unnamed namespace
+
VisualFactoryCache::VisualFactoryCache(bool preMultiplyOnLoad)
: mSvgRasterizeThread(NULL),
mVectorAnimationManager(),
- mBrokenImageUrl(""),
- mPreMultiplyOnLoad(preMultiplyOnLoad)
+ mPreMultiplyOnLoad(preMultiplyOnLoad),
+ mBrokenImageInfoContainer()
{
}
if(!mAtlasManager)
{
mAtlasManager = new ImageAtlasManager();
- mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+ if(!mBrokenImageInfoContainer.empty())
+ {
+ mAtlasManager->SetBrokenImage(mBrokenImageInfoContainer[0].url);
+ }
}
return mAtlasManager;
return geometry;
}
-Texture VisualFactoryCache::GetBrokenVisualImage()
+Texture VisualFactoryCache::GetBrokenVisualImage(uint32_t brokenIndex)
{
- if(!mBrokenImageTexture && mBrokenImageUrl.size())
+ if(!(mBrokenImageInfoContainer[brokenIndex].texture))
{
- PixelData data;
- Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageUrl);
+ PixelData pixelData;
+ Devel::PixelBuffer pixelBuffer = LoadImageFromFile(mBrokenImageInfoContainer[brokenIndex].url);
if(pixelBuffer)
{
- data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
- mBrokenImageTexture = Texture::New(Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(), data.GetWidth(), data.GetHeight());
- mBrokenImageTexture.Upload(data);
+ pixelData = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
+ mBrokenImageInfoContainer[brokenIndex].texture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
+ mBrokenImageInfoContainer[brokenIndex].texture.Upload(pixelData);
+ mBrokenImageInfoContainer[brokenIndex].width = pixelData.GetWidth();
+ mBrokenImageInfoContainer[brokenIndex].height = pixelData.GetHeight();
}
}
- return mBrokenImageTexture;
+ return mBrokenImageInfoContainer[brokenIndex].texture;
}
void VisualFactoryCache::SetPreMultiplyOnLoad(bool preMultiply)
return mPreMultiplyOnLoad;
}
-void VisualFactoryCache::SetBrokenImageUrl(const std::string& brokenImageUrl)
+void VisualFactoryCache::SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList)
{
- mBrokenImageUrl = brokenImageUrl;
+ mBrokenImageInfoContainer.clear();
+ mBrokenImageInfoContainer.assign(brokenImageUrlList.size(), BrokenImageInfo());
+ for(unsigned int i = 0; i < brokenImageUrlList.size(); i++)
+ {
+ mBrokenImageInfoContainer[i].url = brokenImageUrlList[i];
+ }
+}
- if(!mAtlasManager)
+VisualUrl::Type VisualFactoryCache::GetBrokenImageVisualType(int index)
+{
+ return mBrokenImageInfoContainer[index].visualType;
+}
+
+Geometry VisualFactoryCache::CreateNPatchGeometry(Uint16Pair gridSize)
+{
+ uint16_t gridWidth = gridSize.GetWidth();
+ uint16_t gridHeight = gridSize.GetHeight();
+
+ // Create vertices
+ Vector<Vector2> vertices;
+ vertices.Reserve((gridWidth + 1) * (gridHeight + 1));
+
+ for(int y = 0; y < gridHeight + 1; ++y)
{
- mAtlasManager = new ImageAtlasManager();
+ for(int x = 0; x < gridWidth + 1; ++x)
+ {
+ AddVertex(vertices, x, y);
+ }
+ }
+
+ // Create indices
+ Vector<unsigned short> indices;
+ indices.Reserve(gridWidth * gridHeight * 6);
+
+ unsigned int rowIdx = 0;
+ unsigned int nextRowIdx = gridWidth + 1;
+ for(int y = 0; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx)
+ {
+ for(int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
+ {
+ AddQuadIndices(indices, rowIdx, nextRowIdx);
+ }
+ }
+
+ return GenerateGeometry(vertices, indices);
+}
+
+Geometry VisualFactoryCache::GetNPatchGeometry(int index)
+{
+ Geometry geometry;
+ const NPatchData* data;
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+ {
+ if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+ {
+ geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+ if(!geometry)
+ {
+ geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+ SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+ }
+ }
+ else if(data->GetStretchPixelsX().Size() > 0 || data->GetStretchPixelsY().Size() > 0)
+ {
+ Uint16Pair gridSize(2 * data->GetStretchPixelsX().Size() + 1, 2 * data->GetStretchPixelsY().Size() + 1);
+ geometry = CreateNPatchGeometry(gridSize);
+ }
+ }
+ else
+ {
+ // no N patch data so use default geometry
+ geometry = GetGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY);
+ if(!geometry)
+ {
+ geometry = CreateNPatchGeometry(Uint16Pair(3,3));
+ SaveGeometry(VisualFactoryCache::NINE_PATCH_GEOMETRY, geometry);
+ }
+ }
+ return geometry;
+}
+
+Shader VisualFactoryCache::GetNPatchShader(int index)
+{
+ Shader shader;
+ 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;
+ NPatchUtility::StretchRanges::SizeType yStretchCount = 0;
+
+ // ask loader for the regions
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data))
+ {
+ xStretchCount = data->GetStretchPixelsX().Count();
+ yStretchCount = data->GetStretchPixelsY().Count();
+ }
+
+ if(DALI_LIKELY((xStretchCount == 0 && yStretchCount == 0)))
+ {
+ shader = GetShader(VisualFactoryCache::NINE_PATCH_SHADER);
+ if(DALI_UNLIKELY(!shader))
+ {
+ shader = Shader::New(SHADER_NPATCH_VISUAL_3X3_SHADER_VERT, SHADER_NPATCH_VISUAL_SHADER_FRAG);
+
+ // Only cache vanilla 9 patch shaders
+ SaveShader(VisualFactoryCache::NINE_PATCH_SHADER, shader);
+ }
+ }
+ else if(xStretchCount > 0 || yStretchCount > 0)
+ {
+ std::stringstream vertexShader;
+ vertexShader << "#define FACTOR_SIZE_X " << xStretchCount + 2 << "\n"
+ << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n"
+ << SHADER_NPATCH_VISUAL_SHADER_VERT;
+ shader = Shader::New(vertexShader.str(), SHADER_NPATCH_VISUAL_SHADER_FRAG);
+ }
+ return shader;
+}
+
+void VisualFactoryCache::RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent)
+{
+ uint16_t prevEnd = 0;
+ uint16_t prevFix = 0;
+ uint16_t prevStretch = 0;
+ unsigned int i = 1;
+ for(NPatchUtility::StretchRanges::ConstIterator it = stretchPixels.Begin(); it != stretchPixels.End(); ++it, ++i)
+ {
+ uint16_t start = it->GetX();
+ uint16_t end = it->GetY();
+
+ uint16_t fix = prevFix + start - prevEnd;
+ uint16_t stretch = prevStretch + end - start;
+
+ std::stringstream uniform;
+ uniform << uniformName << "[" << i << "]";
+ renderer.RegisterProperty(uniform.str(), Vector2(fix, stretch));
+
+ prevEnd = end;
+ prevFix = fix;
+ prevStretch = stretch;
+ }
+
+ {
+ prevFix += imageExtent - prevEnd;
+ std::stringstream uniform;
+ uniform << uniformName << "[" << i << "]";
+ renderer.RegisterProperty(uniform.str(), Vector2(prevFix, prevStretch));
+ }
+}
+
+void VisualFactoryCache::ApplyTextureAndUniforms(Renderer& renderer, int index)
+{
+ const NPatchData* data;
+ TextureSet textureSet;
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+ {
+ textureSet = data->GetTextures();
+ mBrokenImageInfoContainer[index].texture = data->GetTextures().GetTexture(0);
+
+ if(data->GetStretchPixelsX().Size() == 1 && data->GetStretchPixelsY().Size() == 1)
+ {
+ //special case for 9 patch
+ 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;
+
+ renderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
+ renderer.RegisterProperty("uFixed[1]", Vector2(stretchX.GetX(), stretchY.GetX()));
+ renderer.RegisterProperty("uFixed[2]", Vector2(data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight));
+ renderer.RegisterProperty("uStretchTotal", Vector2(stretchWidth, stretchHeight));
+ }
+ else
+ {
+ renderer.RegisterProperty("uNinePatchFactorsX[0]", Vector2::ZERO);
+ renderer.RegisterProperty("uNinePatchFactorsY[0]", Vector2::ZERO);
+
+ RegisterStretchProperties(renderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth());
+ RegisterStretchProperties(renderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight());
+ }
+ renderer.SetTextures(textureSet);
+ }
+}
+
+void VisualFactoryCache::UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size)
+{
+ // Load Information for broken image
+ for(uint32_t index = 0; index < mBrokenImageInfoContainer.size(); index++)
+ {
+ if(mBrokenImageInfoContainer[index].width == 0 && mBrokenImageInfoContainer[index].height == 0)
+ {
+ if(!mBrokenImageInfoContainer[index].url.empty())
+ {
+ VisualUrl visualUrl(mBrokenImageInfoContainer[index].url);
+ mBrokenImageInfoContainer[index].visualType = visualUrl.GetType();
+ if(mBrokenImageInfoContainer[index].visualType == VisualUrl::Type::N_PATCH)
+ {
+ const NPatchData* data;
+ Rect<int> border;
+ mBrokenImageInfoContainer[index].npatchId = mNPatchLoader.Load( mTextureManager, NULL, mBrokenImageInfoContainer[index].url, border, mPreMultiplyOnLoad, true);
+ if(mNPatchLoader.GetNPatchData(mBrokenImageInfoContainer[index].npatchId, data) && data->GetLoadingState() == NPatchData::LoadingState::LOAD_COMPLETE)
+ {
+ mBrokenImageInfoContainer[index].width = data->GetCroppedWidth();
+ mBrokenImageInfoContainer[index].height = data->GetCroppedHeight();
+ }
+ else
+ {
+ DALI_LOG_ERROR("Can't update renderer for broken image. maybe image loading is failed [path:%s] \n",mBrokenImageInfoContainer[index].url.c_str());
+ }
+ }
+ else
+ {
+ GetBrokenVisualImage(index);
+ }
+ }
+ }
+ }
+
+ // Set Texutre to renderer
+ int brokenIndex = GetProperBrokenImageIndex(size);
+ if(GetBrokenImageVisualType(brokenIndex) == VisualUrl::N_PATCH)
+ {
+ // Set geometry and shader for npatch
+ Geometry geometry = GetNPatchGeometry(brokenIndex);
+ Shader shader = GetNPatchShader(brokenIndex);
+ renderer.SetGeometry(geometry);
+ renderer.SetShader(shader);
+ ApplyTextureAndUniforms(renderer, brokenIndex);
+ }
+ else
+ {
+ Texture brokenImage = GetBrokenVisualImage(brokenIndex);
+ TextureSet textureSet = TextureSet::New();
+ textureSet.SetTexture(0u, brokenImage);
+ renderer.SetTextures(textureSet);
+ }
+}
+
+int32_t VisualFactoryCache::GetProperBrokenImageIndex(const Vector2& size)
+{
+ // Sets the default broken type
+ int32_t returnIndex = 0;
+ if((size.width == 0 || size.height == 0))
+ {
+ // To do : Need to add observer about size
+ return returnIndex;
+ }
+
+ // Find the proper value if we know the size of the image
+ for(int32_t index = static_cast<int32_t>(mBrokenImageInfoContainer.size()) - 1; index >= 0; index--)
+ {
+ // Skip if the value is not set
+ if(mBrokenImageInfoContainer[index].width == 0 || mBrokenImageInfoContainer[index].height == 0)
+ {
+ continue;
+ }
+
+ if(mBrokenImageInfoContainer[index].width < size.width && mBrokenImageInfoContainer[index].height < size.height)
+ {
+ returnIndex = index;
+ break;
+ }
}
- mAtlasManager->SetBrokenImage(mBrokenImageUrl);
+ return returnIndex;
}
} // namespace Internal
#include <dali-toolkit/internal/visuals/npatch-loader.h>
#include <dali-toolkit/internal/visuals/svg/svg-rasterize-thread.h>
#include <dali-toolkit/internal/visuals/texture-manager-impl.h>
+#include <dali/devel-api/rendering/renderer-devel.h>
namespace Dali
{
*/
static Geometry CreateGridGeometry(Uint16Pair gridSize);
- /**
- * @brief Returns a new Texture to use when a visual has failed to correctly render
- * @return The broken image texture.
- */
- Texture GetBrokenVisualImage();
-
/**
* @copydoc Toolkit::VisualFactory::SetPreMultiplyOnLoad()
*/
/**
* @brief Set an image to be used when a visual has failed to correctly render
- * @param[in] brokenImageUrl The broken image url.
+ * @param[in] brokenImageUrlList The broken image url list
*/
- void SetBrokenImageUrl(const std::string& brokenImageUrl);
+ void SetBrokenImageUrl(const std::vector<std::string>& brokenImageUrlList);
+
+ /**
+ * @brief Update the broken image Renderer object
+ * @param[in,out] renderer renderer for broken image
+ * @param[in] size the size of actor
+ */
+ void UpdateBrokenImageRenderer(Renderer& renderer, const Vector2& size);
public:
/**
VisualFactoryCache& operator=(const VisualFactoryCache& rhs);
private:
+ /**
+ * @brief Returns a cached Texture to use when a visual has failed to correctly render
+ * @param[in] brokenIndex The index of broken image
+ *
+ * @return The broken image texture.
+ */
+ Texture GetBrokenVisualImage(uint32_t brokenIndex);
+
+ /**
+ * @brief Gets the Proper broken image index
+ * @param[in] size The size of actor
+ *
+ * @return The index of broken image
+ */
+ int32_t GetProperBrokenImageIndex(const Vector2& size);
+
+ /**
+ * @brief Apply a texture and uniforms
+ *
+ * @param[in,out] renderer The renderer for broken image
+ * @param[in] index The index of broken image
+ */
+ void ApplyTextureAndUniforms(Renderer& renderer, int index);
+
+ /**
+ * @brief Creates a Npatch Geometry object
+ *
+ * @param[in] gridSize The gridSize for creating a geometry
+ * @return The Geometry for NPatch
+ */
+ Geometry CreateNPatchGeometry(Uint16Pair gridSize);
+
+ /**
+ * @brief Gets a geometry for npatch image
+ *
+ * @param[in] index the index of broken image
+ * @return The Geometry for NPatch
+ */
+ Geometry GetNPatchGeometry(int index);
+
+ /**
+ * @brief Gets the Npatch Shader object
+ *
+ * @param[in] index The index of broken image
+ * @return The Shader for NPatch
+ */
+ Shader GetNPatchShader(int index);
+
+ /**
+ * @brief Registers a properties for Stretch Ranges
+ *
+ * @param[in,out] renderer The renderer for broken image
+ * @param[in] uniformName The name of the uniform
+ * @param[in] stretchPixels The stretchable pixels in the cropped image space
+ * @param[in] imageExtent The imageExtent
+ */
+ void RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent);
+
+ /**
+ * @brief Returns a broken image type
+ * @param[in] index BrokenImage index
+ * @return The broken image type.
+ */
+ VisualUrl::Type GetBrokenImageVisualType(int index);
+
+private:
+ struct BrokenImageInfo
+ {
+ BrokenImageInfo()
+ :visualType(),
+ url(""),
+ npatchId(NPatchData::INVALID_NPATCH_DATA_ID),
+ texture(),
+ width(0),
+ height(0)
+ {
+ }
+
+ ~BrokenImageInfo()
+ {
+ }
+
+ // Data
+ VisualUrl::Type visualType;
+ std::string url;
+ NPatchData::NPatchDataId npatchId;
+ Texture texture;
+ uint32_t width;
+ uint32_t height;
+ };
+
Geometry mGeometry[GEOMETRY_TYPE_MAX + 1];
Shader mShader[SHADER_TYPE_MAX + 1];
ImageAtlasManagerPtr mAtlasManager;
TextureManager mTextureManager;
NPatchLoader mNPatchLoader;
- Texture mBrokenImageTexture;
+
SvgRasterizeThread* mSvgRasterizeThread;
std::unique_ptr<VectorAnimationManager> mVectorAnimationManager;
- std::string mBrokenImageUrl;
bool mPreMultiplyOnLoad;
+ std::vector<BrokenImageInfo> mBrokenImageInfoContainer;
};
} // namespace Internal
{
if(type == StyleChange::THEME_CHANGE)
{
- const std::string imageDirPath = AssetManager::GetDaliImagePath();
- std::string brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
- Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
- config["brokenImageUrl"].Get(brokenImageUrl);
-
- if(mFactoryCache)
- {
- mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
- }
+ SetBrokenImageUrl(styleManager);
}
}
+void VisualFactory::OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager)
+{
+ SetBrokenImageUrl(styleManager);
+}
+
Toolkit::Visual::Base VisualFactory::CreateVisual(const Property::Map& propertyMap)
{
Visual::BasePtr visualPtr;
return GetFactoryCache().GetTextureManager();
}
+void VisualFactory::SetBrokenImageUrl(Toolkit::StyleManager& styleManager)
+{
+ const std::string imageDirPath = AssetManager::GetDaliImagePath();
+ std::string brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
+ std::vector<std::string> customBrokenImageUrlList;
+
+ if(styleManager)
+ {
+ customBrokenImageUrlList = Toolkit::DevelStyleManager::GetBrokenImageUrlList(styleManager);
+ if(customBrokenImageUrlList.size() == 0)
+ {
+ Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
+ config["brokenImageUrl"].Get(brokenImageUrl);
+ customBrokenImageUrlList.push_back(brokenImageUrl);
+ }
+ mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+ }
+ else
+ {
+ // Set default image
+ customBrokenImageUrlList.push_back(brokenImageUrl);
+ mFactoryCache->SetBrokenImageUrl(customBrokenImageUrlList);
+ }
+}
+
Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
{
if(!mFactoryCache)
{
mFactoryCache = std::unique_ptr<VisualFactoryCache>(new VisualFactoryCache(mPreMultiplyOnLoad));
-
- const std::string imageDirPath = AssetManager::GetDaliImagePath();
- std::string brokenImageUrl = imageDirPath + BROKEN_IMAGE_FILE_NAME;
-
Toolkit::StyleManager styleManager = Toolkit::StyleManager::Get();
if(styleManager)
{
- Property::Map config = Toolkit::DevelStyleManager::GetConfigurations(styleManager);
- config["brokenImageUrl"].Get(brokenImageUrl);
styleManager.StyleChangedSignal().Connect(mSlotDelegate, &VisualFactory::OnStyleChangedSignal);
+ Toolkit::DevelStyleManager::BrokenImageChangedSignal(styleManager).Connect(mSlotDelegate, &VisualFactory::OnBrokenImageChangedSignal);
}
-
- mFactoryCache->SetBrokenImageUrl(brokenImageUrl);
+ SetBrokenImageUrl(styleManager);
}
return *mFactoryCache;
}
*/
void OnStyleChangedSignal(Toolkit::StyleManager styleManager, StyleChange::Type type);
+ /**
+ * @brief BrokenImageChanged callback
+ *
+ * @param[in] styleManager Handle for style manager.
+ */
+ void OnBrokenImageChangedSignal(Toolkit::StyleManager styleManager);
+
/**
* @copydoc Toolkit::VisualFactory::CreateVisual( const Property::Map& )
*/
~VisualFactory() override;
private:
+ /**
+ * @brief Set the Broken Image url
+ * @param[in] styleManager The instance of StyleManager
+ */
+ void SetBrokenImageUrl(Toolkit::StyleManager& styleManager);
+
/**
* Get the factory cache, creating it if necessary.
*/