using namespace Dali;
using namespace Dali::Toolkit;
+namespace
+{
+const char* TEST_IMAGE_FILE_NAME = "gallery_image_01.jpg";
+} // namespace
+
+
void dali_renderer_factory_startup(void)
{
test_return_value = TET_UNDEF;
END_TEST;
}
+
+int UtcDaliRendererFactoryGetImageRenderer(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "UtcDaliRendererFactoryGetImageRenderer" );
+
+ RendererFactory factory = RendererFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ Property::Map propertyMap;
+ propertyMap.Insert( "renderer-type", "image-renderer" );
+ propertyMap.Insert( "image-url", TEST_IMAGE_FILE_NAME );
+
+ ControlRenderer controlRenderer = factory.GetControlRenderer( propertyMap );
+ DALI_TEST_CHECK( controlRenderer );
+
+ Actor actor = Actor::New();
+ actor.SetSize( 200.f, 200.f );
+ Stage::GetCurrent().Add( actor );
+ controlRenderer.SetSize( Vector2(200.f, 200.f) );
+ controlRenderer.SetOnStage( actor );
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+ DALI_TEST_CHECK( actor.GetRendererAt(0u).GetMaterial().GetNumberOfSamplers() == 1u );
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ application.SendNotification();
+ application.Render();
+
+ Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
+ if(request)
+ {
+ application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD)));
+ }
+
+ application.Render();
+ application.SendNotification();
+
+ DALI_TEST_CHECK(application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc));
+
+ DALI_TEST_CHECK( actor.GetRendererCount() == 1u );
+
+ int textureUnit = -1;
+ DALI_TEST_CHECK( gl.GetUniformValue< int >( "sTexture", textureUnit ) );
+ DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION );
+
+ END_TEST;
+}
//ToDo: renderer applies the offset
}
-void ColorRenderer::SetOnStage( Actor& actor )
+void ColorRenderer::DoSetOnStage( Actor& actor )
{
- ControlRenderer::SetOnStage(actor);
(mImpl->mRenderer).RegisterProperty( COLOR_UNIFORM_NAME, mBlendColor );
if( mBlendColor.a < 1.f )
{
*/
virtual void SetOffset( const Vector2& offset );
+protected:
/**
- * @copydoc ControlRenderer::SetOnStage
+ * @copydoc ControlRenderer::DoSetOnStage
*/
- virtual void SetOnStage( Actor& actor );
+ virtual void DoSetOnStage( Actor& actor );
private:
Vector2 mOffset;
Rect<int> mClipRect;
float mDepthIndex;
+ bool mIsOnStage;
};
} // namespace Internal
ControlRenderer::ControlRenderer()
: mImpl( new Impl() )
{
+ mImpl->mIsOnStage = false;
}
ControlRenderer::~ControlRenderer()
mImpl->mRenderer = Renderer::New( mImpl->mGeometry, material );
mImpl->mRenderer.SetDepthIndex( mImpl->mDepthIndex );
actor.AddRenderer( mImpl->mRenderer );
+ mImpl->mIsOnStage = true;
+
+ DoSetOnStage( actor );
}
void ControlRenderer::SetOffStage( Actor& actor )
{
+ DoSetOffStage( actor );
+
actor.RemoveRenderer( mImpl->mRenderer );
mImpl->mRenderer.Reset();
+
+ mImpl->mIsOnStage = false;
+}
+
+void ControlRenderer::DoSetOnStage( Actor& actor )
+{
+}
+
+void ControlRenderer::DoSetOffStage( Actor& actor )
+{
}
} // namespace Internal
/**
* @copydoc Toolkit::ControlRenderer::SetOnStage
+ * @pre Impl->mGeometry must be created before this method is called
*/
- virtual void SetOnStage( Actor& actor );
+ void SetOnStage( Actor& actor );
/**
* ToDo: Add this function to Toolkit::ControlRenderer when the Renderer can be removed from actor properly.
*/
virtual ~ControlRenderer();
+protected:
+
+ /**
+ * Called by SetOnStage() allowing sub classes to respond to the SetOnStage event
+ *
+ * @param[in] actor The actor applying this renderer.
+ */
+ virtual void DoSetOnStage( Actor& actor );
+
+ /**
+ * Called by SetOffStage() allowing sub classes to respond to the SetOffStage event
+ *
+ * @param[in] actor The actor applying this renderer.
+ */
+ virtual void DoSetOffStage( Actor& actor );
+
private:
// Undefined
//ToDo: renderer applies the offset
}
-void GradientRenderer::SetOnStage( Actor& actor )
+void GradientRenderer::DoSetOnStage( Actor& actor )
{
- ControlRenderer::SetOnStage(actor);
-
mGradientTransformIndex = (mImpl->mRenderer).RegisterProperty( UNIFORM_ALIGNMENT_MATRIX_NAME, mGradientTransform );
Dali::BufferImage lookupTexture = mGradient->GenerateLookupTexture();
Sampler sampler = Sampler::New( lookupTexture, UNIFORM_TEXTULRE_NAME );
Sampler::WrapMode wrap = GetWrapMode( mGradient->GetSpreadMethod() );
sampler.SetWrapMode( wrap, wrap );
- ((mImpl->mRenderer).GetMaterial()).AddSampler( sampler );
+
+ Material material = (mImpl->mRenderer).GetMaterial();
+ if( material )
+ {
+ material.AddSampler( sampler );
+ }
}
bool GradientRenderer::NewGradient(Type gradientType, const Property::Map& propertyMap)
*/
virtual void SetOffset( const Vector2& offset );
+protected:
/**
- * @copydoc ControlRenderer::SetOnStage
+ * @copydoc ControlRenderer::DoSetOnStage
*/
- virtual void SetOnStage( Actor& actor );
+ virtual void DoSetOnStage( Actor& actor );
private:
--- /dev/null
+/*
+ * Copyright (c) 2015 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 "image-renderer.h"
+
+#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
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+
+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");
+
+std::string TEXTURE_UNIFORM_NAME = "sTexture";
+
+#define MAKE_SHADER(A)#A
+
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+ attribute mediump vec2 aPosition;\n
+ varying mediump vec2 vTexCoord;\n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump vec3 uSize;\n
+ \n
+ void main()\n
+ {\n
+ mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
+ vertexPosition.xyz *= uSize;\n
+ vertexPosition = uMvpMatrix * vertexPosition;\n
+ \n
+ vTexCoord = aPosition + vec2(0.5);\n
+ gl_Position = vertexPosition;\n
+ }\n
+);
+
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+ varying mediump vec2 vTexCoord;\n
+ uniform sampler2D sTexture;\n
+ uniform lowp vec4 uColor;\n
+ \n
+ void main()\n
+ {\n
+ gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
+ }\n
+);
+
+} //unnamed namespace
+
+ImageRenderer::ImageRenderer()
+: ControlRenderer(),
+ mDesiredSize(),
+ mFittingMode( FittingMode::DEFAULT ),
+ mSamplingMode( SamplingMode::DEFAULT )
+{
+}
+
+ImageRenderer::~ImageRenderer()
+{
+}
+
+void ImageRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap )
+{
+ 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();
+
+ Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME );
+ if( imageURLValue )
+ {
+ imageURLValue->Get( mImageUrl );
+
+ Property::Value* fittingValue = propertyMap.Find( IMAGE_FITTING_MODE );
+ if( fittingValue )
+ {
+ std::string fitting;
+ fittingValue->Get( fitting );
+
+ mFittingMode = FittingMode::DEFAULT;
+ if( fitting == "shrink-to-fit" )
+ {
+ mFittingMode = FittingMode::SHRINK_TO_FIT;
+ }
+ else if( fitting == "scale-to-fill" )
+ {
+ mFittingMode = FittingMode::SCALE_TO_FILL;
+ }
+ else if( fitting == "fit-width" )
+ {
+ mFittingMode = FittingMode::FIT_WIDTH;
+ }
+ else if( fitting == "fit-height" )
+ {
+ mFittingMode = FittingMode::FIT_HEIGHT;
+ }
+ else if( fitting == "default" )
+ {
+ mFittingMode = FittingMode::DEFAULT;
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS("Unknown fitting mode");
+ }
+ }
+
+ Property::Value* samplingValue = propertyMap.Find( IMAGE_SAMPLING_MODE );
+ if( samplingValue )
+ {
+ std::string sampling;
+ samplingValue->Get( sampling );
+
+ mSamplingMode = SamplingMode::DEFAULT;
+ if( sampling == "box" )
+ {
+ mSamplingMode = SamplingMode::BOX;
+ }
+ else if( sampling == "nearest" )
+ {
+ mSamplingMode = SamplingMode::NEAREST;
+ }
+ else if( sampling == "linear" )
+ {
+ mSamplingMode = SamplingMode::LINEAR;
+ }
+ else if( sampling == "box-then-nearest" )
+ {
+ mSamplingMode = SamplingMode::BOX_THEN_NEAREST;
+ }
+ else if( sampling == "box-then-linear" )
+ {
+ mSamplingMode = SamplingMode::BOX_THEN_LINEAR;
+ }
+ else if( sampling == "no-filter" )
+ {
+ mSamplingMode = SamplingMode::NO_FILTER;
+ }
+ else if( sampling == "dont-care" )
+ {
+ mSamplingMode = SamplingMode::DONT_CARE;
+ }
+ else if( sampling == "default" )
+ {
+ mSamplingMode = SamplingMode::DEFAULT;
+ }
+ else
+ {
+ DALI_ASSERT_ALWAYS("Unknown sampling mode");
+ }
+ }
+
+ int desiredWidth = 0;
+ Property::Value* desiredWidthValue = propertyMap.Find( IMAGE_DESIRED_WIDTH );
+ if( desiredWidthValue )
+ {
+ desiredWidthValue->Get( desiredWidth );
+ }
+
+ int desiredHeight = 0;
+ Property::Value* desiredHeightValue = propertyMap.Find( IMAGE_DESIRED_HEIGHT );
+ if( desiredHeightValue )
+ {
+ desiredHeightValue->Get( desiredHeight );
+ }
+
+ mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
+ }
+
+ mImage.Reset();
+}
+
+void ImageRenderer::SetSize( const Vector2& size )
+{
+ ControlRenderer::SetSize( size );
+ // ToDo: renderer responds to the size change
+}
+
+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::DoSetOnStage( Actor& actor )
+{
+ if( !mImageUrl.empty() && !mImage )
+ {
+ mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+ }
+
+ ApplyImageToSampler();
+}
+
+void ImageRenderer::DoSetOffStage( Actor& actor )
+{
+ //If we own the image then make sure we release it when we go off stage
+ if( !mImageUrl.empty() )
+ {
+ mImage.Reset();
+ }
+
+ ControlRenderer::SetOffStage( actor );
+}
+
+void ImageRenderer::SetImage( const std::string& imageUrl )
+{
+ SetImage( imageUrl, 0, 0, Dali::FittingMode::DEFAULT, Dali::SamplingMode::DEFAULT );
+}
+
+void ImageRenderer::SetImage( const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode )
+{
+ if( mImageUrl != imageUrl )
+ {
+ mImageUrl = imageUrl;
+ mDesiredSize = ImageDimensions( desiredWidth, desiredHeight );
+ mFittingMode = fittingMode;
+ mSamplingMode = samplingMode;
+
+ if( !mImageUrl.empty() && mImpl->mIsOnStage )
+ {
+ mImage = Dali::ResourceImage::New( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode );
+ ApplyImageToSampler();
+ }
+ else
+ {
+ mImage.Reset();
+ }
+ }
+}
+
+void ImageRenderer::SetImage( Image image )
+{
+ if( mImage != image )
+ {
+ mImageUrl.clear();
+ mDesiredSize = ImageDimensions();
+ mFittingMode = FittingMode::DEFAULT;
+ mSamplingMode = SamplingMode::DEFAULT;
+ mImage = image;
+
+ if( mImage && mImpl->mIsOnStage )
+ {
+ ApplyImageToSampler();
+ }
+ }
+}
+
+void ImageRenderer::ApplyImageToSampler()
+{
+ if( mImage )
+ {
+ Material material = mImpl->mRenderer.GetMaterial();
+ if( material )
+ {
+ for( std::size_t i = 0; i < material.GetNumberOfSamplers(); ++i )
+ {
+ Sampler sampler = material.GetSamplerAt( i );
+ if( sampler.GetUniformName() == TEXTURE_UNIFORM_NAME )
+ {
+ sampler.SetImage( mImage );
+ return;
+ }
+ }
+
+ Sampler sampler = Sampler::New( mImage, TEXTURE_UNIFORM_NAME );
+ material.AddSampler( sampler );
+ }
+ }
+}
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_TOOLKIT_INTERNAL_IMAGE_RENDERER_H__
+#define __DALI_TOOLKIT_INTERNAL_IMAGE_RENDERER_H__
+
+/*
+ * Copyright (c) 2015 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/controls/renderers/control-renderer-impl.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/image-operations.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Internal
+{
+
+class ImageRenderer;
+typedef IntrusivePtr< ImageRenderer > ImageRendererPtr;
+
+/**
+ * The renderer which renders an image to the control's quad
+ *
+ * The following properties are optional
+ *
+ * | %Property Name | Type |
+ * |---------------------------|------------------|
+ * | image-url | STRING |
+ * | image-fitting-mode | STRING |
+ * | image-sampling-mode | STRING |
+ * | image-desired-width | INT |
+ * | image-desired-height | INT |
+ *
+ * where image-fitting-mode should be one of the following fitting modes:
+ * "shrink-to-fit"
+ * "scale-to-fill"
+ * "fit-width"
+ * "fit-height"
+ * "default"
+ *
+ * where image-sampling-mode should be one of the following sampling modes:
+ * "box"
+ * "nearest"
+ * "linear"
+ * "box-then-nearest"
+ * "box-then-linear"
+ * "no-filter"
+ * "dont-care"
+ * "default"
+ *
+ */
+class ImageRenderer: public ControlRenderer
+{
+public:
+
+ /**
+ * @brief Constructor.
+ */
+ ImageRenderer();
+
+ /**
+ * @brief A reference counted object may only be deleted by calling Unreference().
+ */
+ ~ImageRenderer();
+
+public: // from ControlRenderer
+ /**
+ * @copydoc ControlRenderer::Initialize
+ */
+ virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap );
+
+ /**
+ * @copydoc ControlRenderer::SetSize
+ */
+ virtual void SetSize( const Vector2& size );
+
+ /**
+ * @copydoc ControlRenderer::SetClipRect
+ */
+ virtual void SetClipRect( const Rect<int>& clipRect );
+
+ /**
+ * @copydoc ControlRenderer::SetOffset
+ */
+ virtual void SetOffset( const Vector2& offset );
+
+protected:
+ /**
+ * @copydoc ControlRenderer::DoSetOnStage
+ */
+ virtual void DoSetOnStage( Actor& actor );
+
+ /**
+ * @copydoc ControlRenderer::DoSetOffStage
+ */
+ virtual void DoSetOffStage( Actor& actor );
+
+public:
+
+ /**
+ * @brief Sets the image of this renderer to the resource at imageUrl
+ * The renderer will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
+ *
+ * @param[in] imageUrl The URL to to image resource to use
+ */
+ void SetImage( const std::string& imageUrl );
+
+ /**
+ * @brief Sets the image of this renderer to the resource at imageUrl
+ * The renderer will load the Image asynchronously when the associated actor is put on stage, and destroy the image when it is off stage
+ *
+ * @param[in] imageUrl The URL to to image resource to use
+ * @param[in] desiredWidth The desired width of the resource to load
+ * @param[in] desiredHeight The desired height of the resource to load
+ * @param[in] fittingMode The FittingMode of the resource to load
+ * @param[in] samplingMode The SamplingMode of the resource to load
+ */
+ void SetImage( const std::string& imageUrl, int desiredWidth, int desiredHeight, Dali::FittingMode::Type fittingMode, Dali::SamplingMode::Type samplingMode );
+
+ /**
+ * @brief Sets the image of this renderer to use
+ *
+ * @param[in] image The image to use
+ */
+ void SetImage( Image image );
+
+private:
+
+ /**
+ * @brief Applies this renderer's image to the sampler to the material used for this renderer
+ */
+ void ApplyImageToSampler();
+
+private:
+ Image mImage;
+
+ std::string mImageUrl;
+ Dali::ImageDimensions mDesiredSize;
+ Dali::FittingMode::Type mFittingMode;
+ Dali::SamplingMode::Type mSamplingMode;
+
+};
+
+} // namespace Internal
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif /* __DALI_TOOLKIT_INTERNAL_IMAGE_RENDERER_H__ */
// Internal HEADER
#include <dali-toolkit/internal/controls/renderers/color/color-renderer.h>
#include <dali-toolkit/internal/controls/renderers/gradient/gradient-renderer.h>
+#include <dali-toolkit/internal/controls/renderers/image/image-renderer.h>
#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
namespace
const char * const RENDERER_TYPE_NAME( "renderer-type" );
const char * const COLOR_RENDERER("color-renderer");
const char * const GRADIENT_RENDERER("gradient-renderer");
+const char * const IMAGE_RENDERER("image-renderer");
}
namespace Dali
{
rendererPtr = new GradientRenderer();
}
+ else if( typeValue == IMAGE_RENDERER )
+ {
+ rendererPtr = new ImageRenderer();
+ }
}
if( rendererPtr )
$(toolkit_src_dir)/controls/renderers/renderer-factory-cache.cpp \
$(toolkit_src_dir)/controls/renderers/renderer-factory-impl.cpp \
$(toolkit_src_dir)/controls/renderers/color/color-renderer.cpp \
+ $(toolkit_src_dir)/controls/renderers/image/image-renderer.cpp \
$(toolkit_src_dir)/controls/renderers/gradient/gradient.cpp \
$(toolkit_src_dir)/controls/renderers/gradient/linear-gradient.cpp \
$(toolkit_src_dir)/controls/renderers/gradient/radial-gradient.cpp \