// CLASS HEADER
#include "image-renderer.h"
+// EXTERNAL HEADER
+#include <dali/public-api/images/resource-image.h>
+#include <dali/integration-api/debug.h>
+
+// INTERNAL HEADER
#include <dali-toolkit/internal/controls/renderers/renderer-factory-impl.h>
#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
#include <dali-toolkit/internal/controls/renderers/control-renderer-impl.h>
#include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
-#include <dali/public-api/images/resource-image.h>
namespace Dali
{
const char * const RENDERER_TYPE_VALUE("image-renderer");
// property names
-const char * const IMAGE_URL_NAME("image-url");
-const char * const IMAGE_FITTING_MODE("image-fitting-mode");
-const char * const IMAGE_SAMPLING_MODE("image-sampling-mode");
-const char * const IMAGE_DESIRED_WIDTH("image-desired-width");
-const char * const IMAGE_DESIRED_HEIGHT("image-desired-height");
+const char * const IMAGE_URL_NAME( "image-url" );
+const char * const IMAGE_FITTING_MODE( "image-fitting-mode" );
+const char * const IMAGE_SAMPLING_MODE( "image-sampling-mode" );
+const char * const IMAGE_DESIRED_WIDTH( "image-desired-width" );
+const char * const IMAGE_DESIRED_HEIGHT( "image-desired-height" );
// fitting modes
const char * const SHRINK_TO_FIT("shrink-to-fit");
}\n
);
+Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsigned int >& indices )
+{
+ Property::Map vertexFormat;
+ vertexFormat[ "aPosition" ] = Property::VECTOR2;
+ PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat, vertices.Size() );
+ if( vertices.Size() > 0 )
+ {
+ vertexPropertyBuffer.SetData( &vertices[ 0 ] );
+ }
+
+ Property::Map indexFormat;
+ indexFormat[ "indices" ] = Property::INTEGER;
+ PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat, indices.Size() );
+ if( indices.Size() > 0 )
+ {
+ indexPropertyBuffer.SetData( &indices[ 0 ] );
+ }
+
+ // Create the geometry object
+ Geometry geometry = Geometry::New();
+ geometry.AddVertexBuffer( vertexPropertyBuffer );
+ geometry.SetIndexBuffer( indexPropertyBuffer );
+ geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
+
+ return geometry;
+}
+
+Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gridSize )
+{
+ Geometry geometry;
+
+ if( gridSize == ImageDimensions( 1, 1 ) )
+ {
+ geometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
+ if( !geometry )
+ {
+ geometry = factoryCache.CreateQuadGeometry();
+ factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
+ }
+ }
+ else
+ {
+ 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 )
+ {
+ for( int x = 0; x < gridWidth + 1; ++x )
+ {
+ vertices.PushBack( Vector2( (float)x/gridWidth - 0.5f, (float)y/gridHeight - 0.5f) );
+ }
+ }
+
+ // Create indices
+ Vector< unsigned int > indices;
+ indices.Reserve( (gridWidth+2)*gridHeight*2 - 2);
+
+ for( unsigned int row = 0u; row < gridHeight; ++row )
+ {
+ unsigned int rowStartIndex = row*(gridWidth+1u);
+ unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
+
+ if( row != 0u ) // degenerate index on non-first row
+ {
+ indices.PushBack( rowStartIndex );
+ }
+
+ for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
+ {
+ indices.PushBack( rowStartIndex + column);
+ indices.PushBack( nextRowStartIndex + column);
+ }
+
+ if( row != gridHeight-1u ) // degenerate index on non-last row
+ {
+ indices.PushBack( nextRowStartIndex + gridWidth );
+ }
+ }
+
+ return GenerateGeometry( vertices, indices );
+ }
+
+ return geometry;
+}
+
} //unnamed namespace
-ImageRenderer::ImageRenderer()
-: ControlRenderer(),
+ImageRenderer::ImageRenderer( RendererFactoryCache& factoryCache )
+: ControlRenderer( factoryCache ),
mDesiredSize(),
mFittingMode( FittingMode::DEFAULT ),
mSamplingMode( SamplingMode::DEFAULT )
{
}
-void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+void ImageRenderer::DoInitialize( const Property::Map& propertyMap )
{
- Initialize(factoryCache);
-
Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME );
if( imageURLValue )
{
imageURLValue->Get( mImageUrl );
+ if( !mImageUrl.empty() )
+ {
+ SetCachedRendererKey( mImageUrl );
+ mImage.Reset();
+ }
Property::Value* fittingValue = propertyMap.Find( IMAGE_FITTING_MODE );
if( fittingValue )
mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
}
-
- mImage.Reset();
}
void ImageRenderer::SetSize( const Vector2& size )
{
ControlRenderer::SetSize( size );
- // ToDo: renderer responds to the size change
+}
+
+void ImageRenderer::GetNaturalSize( Vector2& naturalSize ) const
+{
+ if(mImage)
+ {
+ naturalSize.x = mImage.GetWidth();
+ naturalSize.y = mImage.GetHeight();
+ return;
+ }
+ else if( mDesiredSize.GetWidth()>0 && mDesiredSize.GetHeight()>0)
+ {
+ naturalSize.x = mDesiredSize.GetWidth();
+ naturalSize.y = mDesiredSize.GetHeight();
+ return;
+ }
+ else if( !mImageUrl.empty() )
+ {
+ ImageDimensions dimentions = ResourceImage::GetImageSize( mImageUrl );
+ naturalSize.x = dimentions.GetWidth();
+ naturalSize.y = dimentions.GetHeight();
+ return;
+ }
+
+ naturalSize = Vector2::ZERO;
}
void ImageRenderer::SetClipRect( const Rect<int>& clipRect )
{
ControlRenderer::SetClipRect( clipRect );
- //ToDo: renderer responds to the clipRect change
}
void ImageRenderer::SetOffset( const Vector2& offset )
{
- //ToDo: renderer applies the offset
+}
+
+void ImageRenderer::InitializeRenderer( Renderer& renderer )
+{
+ Geometry geometry;
+ Shader shader;
+ if( !mImpl->mCustomShader )
+ {
+ geometry = CreateGeometry( mFactoryCache, ImageDimensions( 1, 1 ) );
+
+ shader = mFactoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, shader );
+ }
+ }
+ else
+ {
+ geometry = CreateGeometry( mFactoryCache, mImpl->mCustomShader->mGridSize );
+
+ if( mImpl->mCustomShader->mVertexShader.empty() && mImpl->mCustomShader->mFragmentShader.empty() )
+ {
+ shader = mFactoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
+ if( !shader )
+ {
+ shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
+ mFactoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, shader );
+ }
+ }
+ else
+ {
+ shader = Shader::New( mImpl->mCustomShader->mVertexShader.empty() ? VERTEX_SHADER : mImpl->mCustomShader->mVertexShader,
+ mImpl->mCustomShader->mFragmentShader.empty() ? FRAGMENT_SHADER : mImpl->mCustomShader->mFragmentShader,
+ mImpl->mCustomShader->mHints );
+ }
+ }
+
+ if( !renderer )
+ {
+ Material material = Material::New( shader );
+ renderer = Renderer::New( geometry, material );
+ }
+ else
+ {
+ renderer.SetGeometry( geometry );
+ Material material = renderer.GetMaterial();
+ if( material )
+ {
+ material.SetShader( shader );
+ }
+ }
}
void ImageRenderer::DoSetOnStage( Actor& actor )
{
if( !mImageUrl.empty() && !mImage )
{
- mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+ Dali::ResourceImage resourceImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+ resourceImage.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded );
+
+ mImage = resourceImage;
}
ApplyImageToSampler();
}
}
-void ImageRenderer::CreatePropertyMap( Property::Map& map ) const
+void ImageRenderer::DoCreatePropertyMap( Property::Map& map ) const
{
map.Clear();
map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
}
}
-void ImageRenderer::Initialize( RendererFactoryCache& factoryCache )
-{
- mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
- if( !(mImpl->mGeometry) )
- {
- mImpl->mGeometry = factoryCache.CreateQuadGeometry();
- factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry );
- }
-
- mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::IMAGE_SHADER );
- if( !mImpl->mShader )
- {
- mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
- factoryCache.SaveShader( RendererFactoryCache::IMAGE_SHADER, mImpl->mShader );
- }
-
- mDesiredSize = ImageDimensions();
- mFittingMode = FittingMode::DEFAULT;
- mSamplingMode = SamplingMode::DEFAULT;
- mImageUrl.clear();
-}
-
void ImageRenderer::SetImage( const std::string& imageUrl )
{
SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT );
if( mImageUrl != imageUrl )
{
mImageUrl = imageUrl;
+ SetCachedRendererKey( mImageUrl );
mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
mFittingMode = fittingMode;
mSamplingMode = samplingMode;
if( !mImageUrl.empty() && mImpl->mIsOnStage )
{
- mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+ Dali::ResourceImage resourceImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+ resourceImage.LoadingFinishedSignal().Connect( this, &ImageRenderer::OnImageLoaded );
+ mImage = resourceImage;
+
ApplyImageToSampler();
}
else
Material material = mImpl->mRenderer.GetMaterial();
if( material )
{
- for( std::size_t i = 0; i < material.GetNumberOfSamplers(); ++i )
+ int index = material.GetTextureIndex(TEXTURE_UNIFORM_NAME);
+ if( index != -1 )
{
- Sampler sampler = material.GetSamplerAt( i );
- if( sampler.GetUniformName() == TEXTURE_UNIFORM_NAME )
- {
- sampler.SetImage( mImage );
- return;
- }
+ material.SetTextureImage( index, mImage );
+ return;
}
- Sampler sampler = Sampler::New( mImage, TEXTURE_UNIFORM_NAME );
- material.AddSampler( sampler );
+ material.AddTexture( mImage,TEXTURE_UNIFORM_NAME );
+ }
+ }
+}
+
+void ImageRenderer::OnImageLoaded( ResourceImage image )
+{
+ if( image.GetLoadingState() == Dali::ResourceLoadingFailed )
+ {
+ mImage = RendererFactory::GetBrokenRendererImage();
+ if( mImpl->mIsOnStage )
+ {
+ ApplyImageToSampler();
}
}
}