From: Adeel Kazmi Date: Thu, 24 Sep 2015 13:09:46 +0000 (-0700) Subject: Merge "Marked new API's since 1.1.4" into devel/master X-Git-Tag: dali_1.1.4~3 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=618c084142032296c60a188b9438d63a81a2d264;hp=874974e96f49a99ac0650a6115f758e876ce2f05 Merge "Marked new API's since 1.1.4" into devel/master --- diff --git a/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp index a49de61..c132161 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp @@ -28,6 +28,129 @@ using namespace Dali::Toolkit; namespace { const char* TEST_IMAGE_FILE_NAME = "gallery_image_01.jpg"; +const char* TEST_NPATCH_FILE_NAME = "gallery_image_01.9.jpg"; + +Integration::Bitmap* CreateBitmap( unsigned int imageWidth, unsigned int imageHeight, unsigned int initialColor, Pixel::Format pixelFormat ) +{ + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight ); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + memset( pixbuffer, initialColor, imageHeight * imageWidth * bytesPerPixel ); + + return bitmap; +} + +void InitialiseRegionsToZeroAlpha( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, Pixel::Format pixelFormat ) +{ + PixelBuffer* pixbuffer = image->GetBuffer(); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + for( unsigned int row = 0; row < imageWidth; ++row ) + { + unsigned int pixelOffset = row * bytesPerPixel; + pixbuffer[ pixelOffset + 3 ] = 0x00; + pixelOffset += ( imageHeight - 1 ) * imageWidth * bytesPerPixel; + pixbuffer[ pixelOffset + 3 ] = 0x00; + } + + for ( unsigned int column = 0; column < imageHeight; ++column ) + { + unsigned int pixelOffset = column * imageWidth * bytesPerPixel; + pixbuffer[ pixelOffset + 3 ] = 0x00; + pixelOffset += ( imageWidth -1 ) * bytesPerPixel; + pixbuffer[ pixelOffset + 3 ] = 0x00; + } +} + +void AddStretchRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredStretchBorder, Pixel::Format pixelFormat ) +{ + PixelBuffer* pixbuffer = image->GetBuffer(); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + for( unsigned int column = requiredStretchBorder.x; column < imageWidth - requiredStretchBorder.z; ++column ) + { + unsigned int pixelOffset = column * bytesPerPixel; + pixbuffer[ pixelOffset ] = 0x00; + pixbuffer[ pixelOffset + 1 ] = 0x00; + pixbuffer[ pixelOffset + 2 ] = 0x00; + pixbuffer[ pixelOffset + 3 ] = 0xFF; + } + + for( unsigned int row = requiredStretchBorder.y; row < imageHeight - requiredStretchBorder.w; ++row ) + { + unsigned int pixelOffset = row * imageWidth * bytesPerPixel; + pixbuffer[ pixelOffset ] = 0x00; + pixbuffer[ pixelOffset + 1 ] = 0x00; + pixbuffer[ pixelOffset + 2 ] = 0x00; + pixbuffer[ pixelOffset + 3 ] = 0xFF; + } +} + +void AddChildRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredChildRegion, Pixel::Format pixelFormat ) +{ + PixelBuffer* pixbuffer = image->GetBuffer(); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + Integration::Bitmap::PackedPixelsProfile* srcProfile = image->GetPackedPixelsProfile(); + unsigned int bufferStride = srcProfile->GetBufferStride(); + + // Add bottom child region + for( unsigned int column = requiredChildRegion.x; column < imageWidth - requiredChildRegion.z; ++column ) + { + unsigned int pixelOffset = column * bytesPerPixel; + pixelOffset += ( imageHeight - 1 ) * bufferStride; + pixbuffer[ pixelOffset ] = 0x00; + pixbuffer[ pixelOffset + 1 ] = 0x00; + pixbuffer[ pixelOffset + 2 ] = 0x00; + pixbuffer[ pixelOffset + 3 ] = 0xFF; + } + + // Add right child region + for ( unsigned int row = requiredChildRegion.y; row < imageHeight - requiredChildRegion.w; ++row ) + { + unsigned int pixelOffset = row * bufferStride + ( imageWidth - 1 ) * bytesPerPixel; + pixbuffer[ pixelOffset ] = 0x00; + pixbuffer[ pixelOffset + 1 ] = 0x00; + pixbuffer[ pixelOffset + 2 ] = 0x00; + pixbuffer[ pixelOffset + 3 ] = 0xFF; + } +} + +Integration::ResourcePointer CustomizeNinePatch( TestApplication& application, + unsigned int ninePatchImageWidth, + unsigned int ninePatchImageHeight, + const Vector4& requiredStretchBorder, + bool addChildRegion = false, + Vector4 requiredChildRegion = Vector4::ZERO ) +{ + TestPlatformAbstraction& platform = application.GetPlatform(); + + Pixel::Format pixelFormat = Pixel::RGBA8888; + + tet_infoline("Create Bitmap"); + platform.SetClosestImageSize(Vector2( ninePatchImageWidth, ninePatchImageHeight)); + Integration::Bitmap* bitmap = CreateBitmap( ninePatchImageWidth, ninePatchImageHeight, 0xFF, pixelFormat ); + + tet_infoline("Clear border regions"); + InitialiseRegionsToZeroAlpha( bitmap, ninePatchImageWidth, ninePatchImageHeight, pixelFormat ); + + tet_infoline("Add Stretch regions to Bitmap"); + AddStretchRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, pixelFormat ); + + if( addChildRegion ) + { + tet_infoline("Add Child regions to Bitmap"); + AddChildRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredChildRegion, pixelFormat ); + } + + tet_infoline("Getting resource"); + Integration::ResourcePointer resourcePtr(bitmap); + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); + + return resourcePtr; +} + } // namespace @@ -162,6 +285,87 @@ int UtcDaliRendererFactoryGetColorRenderer2(void) END_TEST; } +int UtcDaliRendererFactoryGetBorderRenderer1(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliRendererFactoryGetBorderRenderer1: Request border renderer with a Property::Map" ); + + RendererFactory factory = RendererFactory::Get(); + DALI_TEST_CHECK( factory ); + + Property::Map propertyMap; + Vector4 testColor( 1.f, 0.5f, 0.3f, 0.2f ); + float testSize = 5.f; + propertyMap.Insert("renderer-type", "border-renderer"); + propertyMap.Insert("border-color", testColor); + propertyMap.Insert("border-size", testSize); + + 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 ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualColor(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uBorderColor", actualColor ) ); + DALI_TEST_EQUALS( actualColor, testColor, TEST_LOCATION ); + + float actualSize = 0.f; + DALI_TEST_CHECK( gl.GetUniformValue( "uBorderSize", actualSize ) ); + DALI_TEST_EQUALS( actualSize, testSize, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererFactoryGetBorderRenderer2(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliRendererFactoryGetBorderRenderer2: Request border renderer with a borderSize and a borderColor" ); + + RendererFactory factory = RendererFactory::Get(); + DALI_TEST_CHECK( factory ); + + Vector4 testColor( 1.f, 0.5f, 0.3f, 0.2f ); + float testSize = 5.f; + + ControlRenderer controlRenderer = factory.GetControlRenderer(testSize, testColor); + 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 ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualColor(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uBorderColor", actualColor ) ); + DALI_TEST_EQUALS( actualColor, testColor, TEST_LOCATION ); + + float actualSize = 0.f; + DALI_TEST_CHECK( gl.GetUniformValue( "uBorderSize", actualSize ) ); + DALI_TEST_EQUALS( actualSize, testSize, TEST_LOCATION ); + + END_TEST; +} + + int UtcDaliRendererFactoryGetLinearGradientRenderer(void) { ToolkitTestApplication application; @@ -356,6 +560,176 @@ int UtcDaliRendererFactoryGetImageRenderer2(void) END_TEST; } +int UtcDaliRendererFactoryGetNPatchRenderer1(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliRendererFactoryGetNPatchRenderer1: Request n-patch renderer with a Property::Map" ); + + RendererFactory factory = RendererFactory::Get(); + DALI_TEST_CHECK( factory ); + + const unsigned int ninePatchImageHeight = 18; + const unsigned int ninePatchImageWidth = 28; + const Vector4 requiredStretchBorder( 3, 4, 5, 6 ); + Integration::ResourcePointer ninePatchResource = CustomizeNinePatch( application, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder ); + + Property::Map propertyMap; + propertyMap.Insert( "renderer-type", "n-patch-renderer" ); + propertyMap.Insert( "image-url", TEST_NPATCH_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, ninePatchResource ); + } + + 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; +} + +int UtcDaliRendererFactoryGetNPatchRenderer2(void) +{ + ToolkitTestApplication application; + tet_infoline( "UtcDaliRendererFactoryGetNPatchRenderer2: Request n-patch renderer with an image url" ); + + RendererFactory factory = RendererFactory::Get(); + DALI_TEST_CHECK( factory ); + + const unsigned int ninePatchImageHeight = 18; + const unsigned int ninePatchImageWidth = 28; + const Vector4 requiredStretchBorder( 3, 4, 5, 6 ); + Integration::ResourcePointer ninePatchResource = CustomizeNinePatch( application, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder ); + + ControlRenderer controlRenderer = factory.GetControlRenderer( TEST_NPATCH_FILE_NAME ); + 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, ninePatchResource ); + } + + application.Render(); + application.SendNotification(); + + DALI_TEST_CHECK(application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc)); + + int textureUnit = -1; + DALI_TEST_CHECK( gl.GetUniformValue< int >( "sTexture", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererFactoryGetNPatchRendererN1(void) +{ + //This should still load but display an error image + + ToolkitTestApplication application; + tet_infoline( "UtcDaliRendererFactoryGetNPatchRendererN: Request n-patch renderer with an invalid image url" ); + + RendererFactory factory = RendererFactory::Get(); + DALI_TEST_CHECK( factory ); + + ControlRenderer controlRenderer = factory.GetControlRenderer( "ERROR.9.jpg" ); + 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(); + + int textureUnit = -1; + DALI_TEST_CHECK( gl.GetUniformValue< int >( "sTexture", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererFactoryGetNPatchRendererN2(void) +{ + //This should still load but display an error image + + ToolkitTestApplication application; + tet_infoline( "UtcDaliRendererFactoryGetNPatchRendererN: Request n-patch renderer with an invalid Property::Map" ); + + RendererFactory factory = RendererFactory::Get(); + DALI_TEST_CHECK( factory ); + + Property::Map propertyMap; + propertyMap.Insert( "renderer-type", "n-patch-renderer" ); + propertyMap.Insert( "image-url", 111 ); + + 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(); + + int textureUnit = -1; + DALI_TEST_CHECK( gl.GetUniformValue< int >( "sTexture", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + + END_TEST; +} + int UtcDaliRendererFactoryResetRenderer1(void) { ToolkitTestApplication application; diff --git a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp index a5918ef..ce70893 100644 --- a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp +++ b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.cpp @@ -97,6 +97,11 @@ bool RendererFactory::ResetRenderer( ControlRenderer& renderer, const Vector4& c return GetImplementation( *this ).ResetRenderer( renderer, color ); } +ControlRenderer RendererFactory::GetControlRenderer( float borderSize, const Vector4& borderColor ) +{ + return GetImplementation( *this ).GetControlRenderer( borderSize, borderColor ); +} + ControlRenderer RendererFactory::GetControlRenderer( const Image& image ) { return GetImplementation( *this ).GetControlRenderer( image ); diff --git a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h index d15dc68..da948db 100644 --- a/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h +++ b/dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h @@ -115,6 +115,15 @@ public: bool ResetRenderer( ControlRenderer& renderer, const Vector4& color ); /** + * @brief Request the control renderer to renderer the border with the given size and color. + * + * @param[in] borderSize The size of the border. Border size is the same along all edges. + * @param[in] borderColor The color of the border. + * @return The pointer pointing to the control renderer + */ + ControlRenderer GetControlRenderer( float borderSize, const Vector4& borderColor ); + + /** * @brief Request the control renderer to render the image. * * @param[in] image The image to be rendered. diff --git a/dali-toolkit/images/magnifier-image-frame.png b/dali-toolkit/images/magnifier-image-frame.png deleted file mode 100644 index aa4559d..0000000 Binary files a/dali-toolkit/images/magnifier-image-frame.png and /dev/null differ diff --git a/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp b/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp index d956e36..45a3152 100644 --- a/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp +++ b/dali-toolkit/internal/controls/magnifier/magnifier-impl.cpp @@ -27,6 +27,9 @@ #include #include +// INTERNAL INCLUDES +#include + namespace Dali { @@ -54,9 +57,7 @@ DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, Magnifier, "source-position", VE DALI_TYPE_REGISTRATION_END() -const char* DEFAULT_FRAME_IMAGE_PATH = DALI_IMAGE_DIR "magnifier-image-frame.png"; - -const float IMAGE_BORDER_INDENT = 14.0f; ///< Indent of border in pixels. +const float IMAGE_BORDER_INDENT = 5.0f; ///< Indent of border in pixels. struct CameraActorPositionConstraint { @@ -253,20 +254,22 @@ void Magnifier::SetFrameVisibility(bool visible) { Actor self(Self()); - Image image = ResourceImage::New( DEFAULT_FRAME_IMAGE_PATH ); - mFrame = ImageActor::New( image ); - mFrame.SetStyle( ImageActor::STYLE_NINE_PATCH ); + mFrame = Actor::New( ); mFrame.SetPositionInheritanceMode(DONT_INHERIT_POSITION); mFrame.SetInheritScale(true); mFrame.SetResizePolicy( ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT, Dimension::ALL_DIMENSIONS ); Vector3 sizeOffset(IMAGE_BORDER_INDENT*2.f - 2.f, IMAGE_BORDER_INDENT*2.f - 2.f, 0.0f); mFrame.SetSizeModeFactor( sizeOffset ); + //TODO Set the renderer onto the control self when Actor::RemoveRenderer is supported + Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get(); + Toolkit::ControlRenderer borderRenderer = rendererFactory.GetControlRenderer(IMAGE_BORDER_INDENT, Color::WHITE); + borderRenderer.SetOnStage( mFrame ); + Constraint constraint = Constraint::New( mFrame, Actor::Property::POSITION, EqualToConstraint() ); constraint.AddSource( ParentSource( Actor::Property::WORLD_POSITION ) ); constraint.Apply(); - mFrame.SetNinePatchBorder( Vector4::ONE * IMAGE_BORDER_INDENT ); self.Add(mFrame); } else if(!visible && mFrame) diff --git a/dali-toolkit/internal/controls/magnifier/magnifier-impl.h b/dali-toolkit/internal/controls/magnifier/magnifier-impl.h index d8b990f..63d0a43 100644 --- a/dali-toolkit/internal/controls/magnifier/magnifier-impl.h +++ b/dali-toolkit/internal/controls/magnifier/magnifier-impl.h @@ -152,7 +152,7 @@ private: RenderTask mTask; ///< Render Task to render the source actor contents. CameraActor mCameraActor; ///< CameraActor attached to RenderTask - ImageActor mFrame; ///< The Magnifier Frame + Actor mFrame; ///< The Magnifier Frame Actor mSourceActor; ///< Source Delegate Actor represents the source position to read. float mDefaultCameraDistance; ///< Default RenderTask's camera distance from target. Vector3 mActorSize; ///< The Actor size diff --git a/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp b/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp new file mode 100644 index 0000000..1450460 --- /dev/null +++ b/dali-toolkit/internal/controls/renderers/border/border-renderer.cpp @@ -0,0 +1,235 @@ +/* + * 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 "border-renderer.h" + +// EXTERNAL INCLUDES +#include + +//INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ +const char * const COLOR_NAME("border-color"); +const char * const COLOR_UNIFORM_NAME("uBorderColor"); +const char * const SIZE_NAME("border-size"); +const char * const SIZE_UNIFORM_NAME("uBorderSize"); + +const char * const POSITION_ATTRIBUTE_NAME("aPosition"); +const char * const DRIFT_ATTRIBUTE_NAME("aDrift"); +const char * const INDEX_NAME("indices"); + + +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + attribute mediump vec2 aDrift;\n + uniform mediump mat4 uMvpMatrix;\n + uniform mediump vec3 uSize;\n + uniform mediump float uBorderSize;\n + \n + void main()\n + {\n + vec2 position = aPosition*uSize.xy + aDrift*uBorderSize;\n + gl_Position = uMvpMatrix * vec4(position, 0.0, 1.0);\n + }\n +); + +const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( + uniform lowp vec4 uColor;\n + uniform lowp vec4 uBorderColor;\n + \n + void main()\n + {\n + gl_FragColor = uBorderColor*uColor;\n + }\n +); +} + +BorderRenderer::BorderRenderer() +: ControlRenderer(), + mBorderColor( Color::TRANSPARENT ), + mBorderSize( 0.f ), + mBorderColorIndex( Property::INVALID_INDEX ), + mBorderSizeIndex( Property::INVALID_INDEX ) +{ +} + +BorderRenderer::~BorderRenderer() +{ +} + +void BorderRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) +{ + Initialize( factoryCache ); + + Property::Value* color = propertyMap.Find( COLOR_NAME ); + if( !( color && color->Get(mBorderColor) ) ) + { + DALI_LOG_ERROR( "Fail to provide a border color to the BorderRenderer object" ); + } + + Property::Value* size = propertyMap.Find( SIZE_NAME ); + if( !( size && size->Get(mBorderSize) ) ) + { + DALI_LOG_ERROR( "Fail to provide a border size to the BorderRenderer object" ); + } +} + +void BorderRenderer::SetClipRect( const Rect& clipRect ) +{ + ControlRenderer::SetClipRect( clipRect ); + + //ToDo: renderer responds to the clipRect change +} + +void BorderRenderer::DoSetOnStage( Actor& actor ) +{ + mBorderColorIndex = (mImpl->mRenderer).RegisterProperty( COLOR_UNIFORM_NAME, mBorderColor ); + if( mBorderColor.a < 1.f ) + { + (mImpl->mRenderer).GetMaterial().SetBlendMode( BlendingMode::ON ); + } + mBorderSizeIndex = (mImpl->mRenderer).RegisterProperty( SIZE_UNIFORM_NAME, mBorderSize ); +} + +void BorderRenderer::Initialize( RendererFactoryCache& factoryCache) +{ + mImpl->mGeometry = factoryCache.GetGeometry( RendererFactoryCache::BORDER_GEOMETRY ); + if( !(mImpl->mGeometry) ) + { + mImpl->mGeometry = CreateBorderGeometry(); + factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, mImpl->mGeometry ); + } + + mImpl->mShader = factoryCache.GetShader( RendererFactoryCache::BORDER_SHADER ); + if( !(mImpl->mShader) ) + { + mImpl->mShader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); + factoryCache.SaveShader( RendererFactoryCache::COLOR_SHADER, mImpl->mShader ); + } +} + +void BorderRenderer::SetBorderColor(const Vector4& color) +{ + mBorderColor = color; + + if( mImpl->mIsOnStage ) + { + (mImpl->mRenderer).SetProperty( mBorderColorIndex, color ); + if( color.a < 1.f && (mImpl->mRenderer).GetMaterial().GetBlendMode() != BlendingMode::ON) + { + (mImpl->mRenderer).GetMaterial().SetBlendMode( BlendingMode::ON ); + } + } +} + +void BorderRenderer::SetBorderSize( float size ) +{ + mBorderSize = size; + + if( mImpl->mIsOnStage ) + { + (mImpl->mRenderer).SetProperty( mBorderSizeIndex, size ); + } +} + +/** + * Vertices and triangles of the border geometry: + * + * vertex position = aPosition*uSize.xy + aDrift*uBorderSize; + * + * 0--1--2--3 + * | /| /| /| + * |/ |/ |/ | + * 4--5--6--7 + * | /| | /| + * |/ | |/ | + * 8--9--10-11 + * | /| /| /| + * |/ |/ |/ | + * 12-13-14-15 + */ +Geometry BorderRenderer::CreateBorderGeometry() +{ + const float halfWidth = 0.5f; + const float halfHeight = 0.5f; + struct BorderVertex { Vector2 position; Vector2 drift;}; + BorderVertex borderVertexData[16] = + { + { Vector2(-halfWidth, -halfHeight), Vector2(0.f, 0.f) }, + { Vector2(-halfWidth, -halfHeight), Vector2(1.f, 0.f) }, + { Vector2(halfWidth, -halfHeight), Vector2(-1.f, 0.f) }, + { Vector2(halfWidth, -halfHeight), Vector2(0.f, 0.f) }, + + { Vector2(-halfWidth, -halfHeight), Vector2(0.f, 1.f) }, + { Vector2(-halfWidth, -halfHeight), Vector2(1.f, 1.f) }, + { Vector2(halfWidth, -halfHeight), Vector2(-1.f, 1.f) }, + { Vector2(halfWidth, -halfHeight), Vector2(0.f, 1.f) }, + + { Vector2(-halfWidth, halfHeight), Vector2(0.f, -1.f) }, + { Vector2(-halfWidth, halfHeight), Vector2(1.f, -1.f) }, + { Vector2(halfWidth, halfHeight), Vector2(-1.f, -1.f) }, + { Vector2(halfWidth, halfHeight), Vector2(0.f, -1.f) }, + + { Vector2(-halfWidth, halfHeight), Vector2(0.f, 0.f) }, + { Vector2(-halfWidth, halfHeight), Vector2(1.f, 0.f) }, + { Vector2(halfWidth, halfHeight), Vector2(-1.f, 0.f) }, + { Vector2(halfWidth, halfHeight), Vector2(0.f, 0.f) }, + }; + + Property::Map borderVertexFormat; + borderVertexFormat[POSITION_ATTRIBUTE_NAME] = Property::VECTOR2; + borderVertexFormat[DRIFT_ATTRIBUTE_NAME] = Property::VECTOR2; + PropertyBuffer borderVertices = PropertyBuffer::New( borderVertexFormat, 16 ); + borderVertices.SetData(borderVertexData); + + // Create indices + unsigned int indexData[48] = { 0, 4, 1, 1, 4, 5, 1, 5, 2, 2, 5, 6, 2, 6,3, 3, 6, 7, + 4, 8, 5, 5, 8, 9, 6, 10, 7, 7, 10, 11, + 8, 12, 9, 9, 12, 13, 9, 13, 10, 10, 13, 14, 10, 11, 14, 11, 14, 15}; + + Property::Map indexFormat; + indexFormat[INDEX_NAME] = Property::INTEGER; + PropertyBuffer indices = PropertyBuffer::New( indexFormat, 48 ); + indices.SetData(indexData); + + // Create the geometry object + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( borderVertices ); + geometry.SetIndexBuffer( indices ); + + return geometry; +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/renderers/border/border-renderer.h b/dali-toolkit/internal/controls/renderers/border/border-renderer.h new file mode 100644 index 0000000..5a1f575 --- /dev/null +++ b/dali-toolkit/internal/controls/renderers/border/border-renderer.h @@ -0,0 +1,128 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_BORDER_RENDERER_H__ +#define __DALI_TOOLKIT_INTERNAL_BORDER_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. + * + */ +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * The renderer which renders a solid color to the control's quad border fixed to a specified size. + * + * The following properties are required for create a BorderRender + * + * | %Property Name | Type | + * |------------------|-------------| + * | border-color | VECTOR4 | + * | border-size | FLOAT | + */ + +class BorderRenderer : public ControlRenderer +{ +public: + + /** + * @brief Constructor. + */ + BorderRenderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + virtual ~BorderRenderer(); + +public: // from ControlRenderer + + /** + * @copydoc ControlRenderer::Initialize + */ + virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ); + + /** + * @copydoc ControlRenderer::SetClipRect + */ + virtual void SetClipRect( const Rect& clipRect ); + +protected: + /** + * @copydoc ControlRenderer::DoSetOnStage + */ + virtual void DoSetOnStage( Actor& actor ); + +public: + + /** + * Request the geometry and shader from the cache, if not available, create and save to the cache for sharing. + * + * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object + */ + void Initialize( RendererFactoryCache& factoryCache ); + + /** + * Set the color of the border. + * @param[in] color The border color. + */ + void SetBorderColor( const Vector4& color); + + /** + * Set the size of the border. + * @param[in] size The border size. + */ + void SetBorderSize( float size ); + +private: + + /** + * Create the geometry which presents the border. + * @return The border geometry + */ + Geometry CreateBorderGeometry(); + + // Undefined + BorderRenderer( const BorderRenderer& borderRenderer ); + + // Undefined + BorderRenderer& operator=( const BorderRenderer& borderRenderer ); + +private: + + Vector4 mBorderColor; + float mBorderSize; + + Property::Index mBorderColorIndex; + Property::Index mBorderSizeIndex; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif /* __DALI_TOOLKIT_INTERNAL_BORDER_RENDERER_H__ */ diff --git a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp index 05d0c8e..50fa5b8 100644 --- a/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp +++ b/dali-toolkit/internal/controls/renderers/image/image-renderer.cpp @@ -44,8 +44,6 @@ 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 diff --git a/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp new file mode 100644 index 0000000..d757712 --- /dev/null +++ b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.cpp @@ -0,0 +1,514 @@ +/* + * 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 "npatch-renderer.h" + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL IINCLUDES +#include +#include +#include +#include + + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +namespace +{ + +const char * const IMAGE_URL_NAME("image-url"); +const char * const BORDER_ONLY("border-only"); + +std::string TEXTURE_UNIFORM_NAME = "sTexture"; + +const char* VERTEX_SHADER_3X3 = DALI_COMPOSE_SHADER( + attribute mediump vec2 aPosition;\n + varying mediump vec2 vTexCoord;\n + uniform mediump mat4 uModelMatrix;\n + uniform mediump mat4 uMvpMatrix;\n + uniform mediump vec3 uSize;\n + uniform mediump vec2 uFixed[ 3 ];\n + uniform mediump vec2 uStretchTotal;\n + \n + void main()\n + {\n + mediump vec2 scale = vec2( length( uModelMatrix[ 0 ].xyz ), length( uModelMatrix[ 1 ].xyz ) );\n + mediump vec2 size = uSize.xy * scale;\n + \n + mediump vec2 fixedFactor = vec2( uFixed[ int( ( aPosition.x + 1.0 ) * 0.5 ) ].x, uFixed[ int( ( aPosition.y + 1.0 ) * 0.5 ) ].y );\n + mediump vec2 stretch = floor( aPosition * 0.5 );\n + mediump vec2 fixedTotal = uFixed[ 2 ];\n + \n + mediump vec4 vertexPosition = vec4( fixedFactor + ( size - fixedTotal ) * stretch, 0.0, 1.0 );\n + vertexPosition.xy -= size * vec2( 0.5, 0.5 );\n + vertexPosition.xy = vertexPosition.xy / scale;\n + \n + vertexPosition = uMvpMatrix * vertexPosition;\n + \n + vTexCoord = ( fixedFactor + stretch * uStretchTotal ) / ( fixedTotal + uStretchTotal );\n + \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 +); + +/** + * @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 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 ); + + 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 int >& 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 ); +} + +void AddVertex( Vector< Vector2 >& vertices, unsigned int x, unsigned int y ) +{ + vertices.PushBack( Vector2( x, y ) ); +} + +} //unnamed namespace + +/////////////////NPatchRenderer//////////////// + +NPatchRenderer::NPatchRenderer() +: ControlRenderer(), + mBorderOnly( false ) +{ +} + +NPatchRenderer::~NPatchRenderer() +{ +} + +void NPatchRenderer::Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ) +{ + Initialize(factoryCache); + + Property::Value* imageURLValue = propertyMap.Find( IMAGE_URL_NAME ); + if( imageURLValue ) + { + //Read the border-only property first since InitialiseFromImage relies on mBorderOnly to be properly set + Property::Value* borderOnlyValue = propertyMap.Find( BORDER_ONLY ); + if( borderOnlyValue ) + { + borderOnlyValue->Get( mBorderOnly ); + } + + if( imageURLValue->Get( mImageUrl ) ) + { + NinePatchImage nPatch = NinePatchImage::New( mImageUrl ); + InitialiseFromImage( nPatch ); + } + else + { + CreateErrorImage(); + DALI_LOG_ERROR( "The property '%s' is not a string\n", IMAGE_URL_NAME ); + } + } +} + +void NPatchRenderer::SetClipRect( const Rect& clipRect ) +{ + ControlRenderer::SetClipRect( clipRect ); + //ToDo: renderer responds to the clipRect change +} + +void NPatchRenderer::SetOffset( const Vector2& offset ) +{ + //ToDo: renderer applies the offset +} + +void NPatchRenderer::DoSetOnStage( Actor& actor ) +{ + if( !mCroppedImage ) + { + if( !mImageUrl.empty() ) + { + NinePatchImage nPatch = NinePatchImage::New( mImageUrl ); + InitialiseFromImage( nPatch ); + } + else if( mImage ) + { + InitialiseFromImage( mImage ); + } + } + + if( mCroppedImage ) + { + ApplyImageToSampler(); + } +} + +void NPatchRenderer::DoSetOffStage( Actor& actor ) +{ + mCroppedImage.Reset(); +} + +void NPatchRenderer::Initialize( RendererFactoryCache& factoryCache ) +{ + mNinePatchGeometry = factoryCache.GetGeometry( RendererFactoryCache::NINE_PATCH_GEOMETRY ); + if( !(mNinePatchGeometry) ) + { + mNinePatchGeometry = CreateGeometry( Uint16Pair( 3, 3 ) ); + factoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_GEOMETRY, mNinePatchGeometry ); + } + + mNinePatchBorderGeometry = factoryCache.GetGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY ); + if( !(mNinePatchBorderGeometry) ) + { + mNinePatchBorderGeometry = CreateGeometryBorder( Uint16Pair( 3, 3 ) ); + factoryCache.SaveGeometry( RendererFactoryCache::NINE_PATCH_BORDER_GEOMETRY, mNinePatchBorderGeometry ); + } + + mNinePatchShader = factoryCache.GetShader( RendererFactoryCache::NINE_PATCH_SHADER ); + if( !mNinePatchShader ) + { + mNinePatchShader = Shader::New( VERTEX_SHADER_3X3, FRAGMENT_SHADER ); + factoryCache.SaveShader( RendererFactoryCache::NINE_PATCH_SHADER, mNinePatchShader ); + } + + mImpl->mGeometry = mNinePatchGeometry; + mImpl->mShader = mNinePatchShader; + + mImageUrl.clear(); +} + +void NPatchRenderer::SetImage( const std::string& imageUrl, bool borderOnly ) +{ + mBorderOnly = borderOnly; + mImage.Reset(); + if( mImageUrl == imageUrl ) + { + return; + } + + mImageUrl = imageUrl; + NinePatchImage nPatch = NinePatchImage::New( mImageUrl ); + InitialiseFromImage( nPatch ); + + if( mCroppedImage && mImpl->mIsOnStage ) + { + ApplyImageToSampler(); + } +} + +void NPatchRenderer::SetImage( NinePatchImage image, bool borderOnly ) +{ + mBorderOnly = borderOnly; + mImageUrl.empty(); + if( mImage == image ) + { + return; + } + + mImage = image; + InitialiseFromImage( mImage ); + + if( mCroppedImage && mImpl->mIsOnStage ) + { + ApplyImageToSampler(); + } +} + +void NPatchRenderer::InitialiseFromImage( NinePatchImage nPatch ) +{ + mCroppedImage = nPatch.CreateCroppedBufferImage(); + if( !mCroppedImage ) + { + DALI_LOG_ERROR("'%s' specify a valid 9 patch image\n", mImageUrl.c_str() ); + CreateErrorImage(); + return; + } + + mImageSize = ImageDimensions( mCroppedImage.GetWidth(), mCroppedImage.GetHeight() ); + + mStretchPixelsX = nPatch.GetStretchPixelsX(); + mStretchPixelsY = nPatch.GetStretchPixelsY(); + + if( mStretchPixelsX.Size() > 0 && mStretchPixelsY.Size() > 0 ) + { + //only 9 patch supported for now + mImpl->mGeometry = !mBorderOnly ? mNinePatchGeometry : mNinePatchBorderGeometry; + mImpl->mShader = mNinePatchShader; + } +} + +void NPatchRenderer::CreateErrorImage() +{ + mImageSize = ImageDimensions( 1, 1 ); + + BufferImage bufferImage = BufferImage::New( mImageSize.GetWidth(), mImageSize.GetHeight(), Pixel::RGBA8888 ); + mCroppedImage = bufferImage; + PixelBuffer* pixbuf = bufferImage.GetBuffer(); + + for( size_t i = 0; i < mImageSize.GetWidth() * mImageSize.GetHeight() * 4u; ) + { + pixbuf[ i++ ] = 0; + pixbuf[ i++ ] = 0; + pixbuf[ i++ ] = 0; + pixbuf[ i++ ] = 255; + } + + mStretchPixelsX.Clear(); + mStretchPixelsX.PushBack( Uint16Pair( 0, mImageSize.GetWidth() ) ); + mStretchPixelsY.Clear(); + mStretchPixelsY.PushBack( Uint16Pair( 0, mImageSize.GetHeight() ) ); + + mImpl->mGeometry = mNinePatchGeometry; + mImpl->mShader = mNinePatchShader; +} + +void NPatchRenderer::ApplyImageToSampler() +{ + Material material = mImpl->mRenderer.GetMaterial(); + if( material ) + { + Sampler sampler; + for( std::size_t i = 0; i < material.GetNumberOfSamplers(); ++i ) + { + sampler = material.GetSamplerAt( i ); + if( sampler.GetUniformName() == TEXTURE_UNIFORM_NAME ) + { + sampler.SetImage( mCroppedImage ); + break; + } + } + if( !sampler ) + { + sampler = Sampler::New( mCroppedImage, TEXTURE_UNIFORM_NAME ); + material.AddSampler( sampler ); + } + + if( mStretchPixelsX.Size() > 0 && mStretchPixelsY.Size() > 0 ) + { + //only 9 patch supported for now + Uint16Pair stretchX = mStretchPixelsX[ 0 ]; + Uint16Pair stretchY = mStretchPixelsY[ 0 ]; + + uint16_t stretchWidth = stretchX.GetY() - stretchX.GetX(); + uint16_t stretchHeight = stretchY.GetY() - stretchY.GetX(); + + sampler.RegisterProperty( "uFixed[0]", Vector2::ZERO ); + sampler.RegisterProperty( "uFixed[1]", Vector2( stretchX.GetX(), stretchY.GetX()) ); + sampler.RegisterProperty( "uFixed[2]", Vector2( mImageSize.GetWidth() - stretchWidth, mImageSize.GetHeight() - stretchHeight ) ); + sampler.RegisterProperty( "uStretchTotal", Vector2( stretchWidth, stretchHeight ) ); + } + } +} + +Geometry NPatchRenderer::CreateGeometry( 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 ) + { + for( int x = 0; x < gridWidth + 1; ++x ) + { + AddVertex( vertices, x, y ); + } + } + + // Create indices + //TODO: compare performance with triangle strip when Geometry supports it + Vector< unsigned int > 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 NPatchRenderer::CreateGeometryBorder( Uint16Pair gridSize ) +{ + uint16_t gridWidth = gridSize.GetWidth(); + uint16_t gridHeight = gridSize.GetHeight(); + + // Create vertices + Vector< Vector2 > vertices; + vertices.Reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) ); + + //top + int y = 0; + for(; y < 2; ++y) + { + for( int x = 0; x < gridWidth + 1; ++x ) + { + AddVertex( vertices, x, y ); + } + } + + for(; y < gridHeight - 1; ++y) + { + //left + AddVertex( vertices, 0, y ); + AddVertex( vertices, 1, y ); + + //right + AddVertex( vertices, gridWidth - 1, y ); + AddVertex( vertices, gridWidth, y ); + } + + //bottom + for(; y < gridHeight + 1; ++y) + { + for( int x = 0; x < gridWidth + 1; ++x ) + { + AddVertex( vertices, x, y ); + } + } + + // Create indices + //TODO: compare performance with triangle strip when Geometry supports it + Vector< unsigned int > indices; + indices.Reserve( gridWidth * gridHeight * 6 ); + + //top + unsigned int rowIdx = 0 ; + unsigned int nextRowIdx = gridWidth + 1; + for( int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx ) + { + AddQuadIndices( indices, rowIdx, nextRowIdx ); + } + + if(gridHeight > 2) + { + rowIdx = gridWidth + 1; + nextRowIdx = ( gridWidth + 1 ) * 2; + + unsigned increment = gridWidth - 1; + if(gridHeight > 3) + { + increment = 2; + //second row left + AddQuadIndices( indices, rowIdx, nextRowIdx ); + + rowIdx = gridWidth * 2; + nextRowIdx = ( gridWidth + 1 ) * 2 + 2; + //second row right + AddQuadIndices( indices, rowIdx, nextRowIdx ); + + //left and right + rowIdx = nextRowIdx - 2; + nextRowIdx = rowIdx + 4; + for(int y = 2; y < 2*(gridHeight - 3); ++y, rowIdx += 2, nextRowIdx += 2) + { + AddQuadIndices( indices, rowIdx, nextRowIdx ); + } + } + + //second row left + AddQuadIndices( indices, rowIdx, nextRowIdx ); + + rowIdx += increment; + nextRowIdx += gridWidth - 1; + //second row right + AddQuadIndices( indices, rowIdx, nextRowIdx ); + } + + //bottom + rowIdx = nextRowIdx - gridWidth + 1; + nextRowIdx = rowIdx + gridWidth + 1; + for( int x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx ) + { + AddQuadIndices( indices, rowIdx, nextRowIdx ); + } + + return GenerateGeometry( vertices, indices ); +} + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali diff --git a/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h new file mode 100644 index 0000000..b2ead54 --- /dev/null +++ b/dali-toolkit/internal/controls/renderers/npatch/npatch-renderer.h @@ -0,0 +1,191 @@ +#ifndef __DALI_TOOLKIT_INTERNAL_N_PATCH_RENDERER_H__ +#define __DALI_TOOLKIT_INTERNAL_N_PATCH_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 + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Toolkit +{ + +namespace Internal +{ + +/** + * The renderer which renders an 9 patch image to the control's quad + * + * The following properties are optional + * + * | %Property Name | Type | + * |---------------------------|------------------| + * | image-url | STRING | + * + */ +class NPatchRenderer: public ControlRenderer +{ +public: + + /** + * @brief Constructor. + */ + NPatchRenderer(); + + /** + * @brief A reference counted object may only be deleted by calling Unreference(). + */ + ~NPatchRenderer(); + +public: // from ControlRenderer + + /** + * @copydoc ControlRenderer::Initialize + */ + virtual void Initialize( RendererFactoryCache& factoryCache, const Property::Map& propertyMap ); + + /** + * @copydoc ControlRenderer::SetClipRect + */ + virtual void SetClipRect( const Rect& 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: + + /** + * Request the geometry and shader from the cache, if not available, create and save to the cache for sharing. + * + * @param[in] factoryCache A pointer pointing to the RendererFactoryCache object + */ + void Initialize( RendererFactoryCache& factoryCache ); + + /** + * @brief Sets the 9 patch image of this renderer to the resource at imageUrl + * The renderer will load the image synchronously when the associated actor is put on stage, and destroy the image when it is off stage + * + * @param[in] imageUrl The URL to 9 patch image resource to use + * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border + */ + void SetImage( const std::string& imageUrl, bool borderOnly = false ); + + /** + * @brief Sets the 9 patch image of this renderer to the 9 patch image + * + * @param[in] image The NinePatchImage to use + * @param[in] borderOnly A Flag to indicate if the image should omit the centre of the n-patch and only render the border + */ + void SetImage( NinePatchImage image, bool borderOnly = false ); + +private: + + /** + * @brief Creates a geometry for the grid size to be used by this renderers' shaders + * + * @param gridSize The grid size of the solid geometry to create + * @return Returns the created geometry for the grid size + */ + Geometry CreateGeometry( Uint16Pair gridSize ); + + /** + * @brief Creates a geometry with the border only for the grid size to be used by this renderers' shaders + * e.g. a 5x4 grid would create a geometry that would look like: + * + * --------------------- + * | /| /| /| /| /| + * |/ |/ |/ |/ |/ | + * --------------------- + * | /| | /| + * |/ | |/ | + * ----- ----- + * | /| | /| + * |/ | |/ | + * --------------------- + * | /| /| /| /| /| + * |/ |/ |/ |/ |/ | + * --------------------- + * + * @param gridSize The grid size of the solid geometry to create + * @return Returns the created geometry for the grid size + */ + Geometry CreateGeometryBorder( Uint16Pair gridSize ); + + /** + * @brief Creates Image from the image url and parses the image for the stretch borders. Will create a error image if the n patch image is invalid + * + * @param nPatchImage The NinePatchImage to base our cropped images and stretch borders from + */ + void InitialiseFromImage( NinePatchImage nPatchImage ); + + /** + * @brief Creates a black Image to indicate that there was an error in either the image url or the parsing of the image + * + */ + void CreateErrorImage(); + + /** + * @brief Applies this renderer's image to the sampler to the material used for this renderer + */ + void ApplyImageToSampler(); + +private: + + NinePatchImage mImage; ///< The image to render if the renderer was set from an NinePatchImage, empty otherwise + Image mCroppedImage; + Geometry mNinePatchGeometry; + Geometry mNinePatchBorderGeometry; + Shader mNinePatchShader; + + std::string mImageUrl; ///< The url to the image resource to render if the renderer was set from an image resource url, empty otherwise + NinePatchImage::StretchRanges mStretchPixelsX; + NinePatchImage::StretchRanges mStretchPixelsY; + ImageDimensions mImageSize; + bool mBorderOnly; +}; + +} // namespace Internal + +} // namespace Toolkit + +} // namespace Dali + +#endif /* __DALI_TOOLKIT_INTERNAL_N_PATCH_RENDERER_H__ */ diff --git a/dali-toolkit/internal/controls/renderers/renderer-factory-cache.cpp b/dali-toolkit/internal/controls/renderers/renderer-factory-cache.cpp index 462e29c..cf8c47a 100644 --- a/dali-toolkit/internal/controls/renderers/renderer-factory-cache.cpp +++ b/dali-toolkit/internal/controls/renderers/renderer-factory-cache.cpp @@ -58,7 +58,7 @@ Geometry RendererFactoryCache::GetGeometry( GeometryType type ) return mGeometry[type]; } -void RendererFactoryCache::SaveGeometry( GeometryType type, Geometry geometry) +void RendererFactoryCache::SaveGeometry( GeometryType type, Geometry geometry ) { mGeometry[type] = geometry; } diff --git a/dali-toolkit/internal/controls/renderers/renderer-factory-cache.h b/dali-toolkit/internal/controls/renderers/renderer-factory-cache.h index e6c8d88..ab589c2 100644 --- a/dali-toolkit/internal/controls/renderers/renderer-factory-cache.h +++ b/dali-toolkit/internal/controls/renderers/renderer-factory-cache.h @@ -48,7 +48,7 @@ public: GRADIENT_SHADER_LINEAR, GRADIENT_SHADER_RADIAL, IMAGE_SHADER, - N_PATCH_SHADER, + NINE_PATCH_SHADER, SVG_SHADER, SHADER_TYPE_MAX = SVG_SHADER }; @@ -59,8 +59,10 @@ public: enum GeometryType { QUAD_GEOMETRY, + BORDER_GEOMETRY, NINE_PATCH_GEOMETRY, - GEOMETRY_TYPE_MAX = NINE_PATCH_GEOMETRY + NINE_PATCH_BORDER_GEOMETRY, + GEOMETRY_TYPE_MAX = NINE_PATCH_BORDER_GEOMETRY }; public: diff --git a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp index 11070c9..92fd3bf 100644 --- a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp +++ b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.cpp @@ -25,17 +25,22 @@ #include // Internal HEADER +#include #include #include +#include #include #include namespace { const char * const RENDERER_TYPE_NAME( "renderer-type" ); + const char * const COLOR_RENDERER("color-renderer"); +const char * const BORDER_RENDERER("border-renderer"); const char * const GRADIENT_RENDERER("gradient-renderer"); const char * const IMAGE_RENDERER("image-renderer"); +const char * const N_PATCH_RENDERER("n-patch-renderer"); } namespace Dali @@ -90,6 +95,14 @@ Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Property::Ma { rendererPtr = new ImageRenderer(); } + else if( typeValue == N_PATCH_RENDERER ) + { + rendererPtr = new NPatchRenderer(); + } + else if( typeValue == BORDER_RENDERER ) + { + rendererPtr = new BorderRenderer(); + } } if( rendererPtr ) @@ -138,57 +151,124 @@ bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const V } } -Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Image& image ) +Toolkit::ControlRenderer RendererFactory::GetControlRenderer( float borderSize, const Vector4& borderColor ) { - ImageRenderer* rendererPtr = new ImageRenderer(); + BorderRenderer* rendererPtr = new BorderRenderer(); + if( !mFactoryCache ) { mFactoryCache = new RendererFactoryCache(); } rendererPtr->Initialize( *( mFactoryCache.Get() ) ); - rendererPtr->SetImage( image ); + + rendererPtr->SetBorderSize( borderSize ); + rendererPtr->SetBorderColor( borderColor ); return Toolkit::ControlRenderer( rendererPtr ); } -bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Image& image ) +Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const Image& image ) { - ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); - if( rendererPtr ) + if( !mFactoryCache ) + { + mFactoryCache = new RendererFactoryCache(); + } + + NinePatchImage npatchImage = NinePatchImage::DownCast( image ); + if( npatchImage ) { + NPatchRenderer* rendererPtr = new NPatchRenderer(); + rendererPtr->Initialize( *( mFactoryCache.Get() ) ); + rendererPtr->SetImage( npatchImage ); + + return Toolkit::ControlRenderer( rendererPtr ); + } + else + { + ImageRenderer* rendererPtr = new ImageRenderer(); + rendererPtr->Initialize( *( mFactoryCache.Get() ) ); rendererPtr->SetImage( image ); - return false; + + return Toolkit::ControlRenderer( rendererPtr ); + } +} + +bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const Image& image ) +{ + NinePatchImage npatchImage = NinePatchImage::DownCast( image ); + if( npatchImage ) + { + NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( npatchImage ); + return false; + } } else { - renderer = GetControlRenderer( image ); - return true; + ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( image ); + return false; + } } + + renderer = GetControlRenderer( image ); + return true; } Toolkit::ControlRenderer RendererFactory::GetControlRenderer( const std::string& url ) { - ImageRenderer* rendererPtr = new ImageRenderer(); - if( !mFactoryCache ) + if( NinePatchImage::IsNinePatchUrl( url ) ) { - mFactoryCache = new RendererFactoryCache(); + NPatchRenderer* rendererPtr = new NPatchRenderer(); + if( !mFactoryCache ) + { + mFactoryCache = new RendererFactoryCache(); + } + rendererPtr->Initialize( *( mFactoryCache.Get() ) ); + rendererPtr->SetImage( url ); + + return Toolkit::ControlRenderer( rendererPtr ); } - rendererPtr->Initialize( *( mFactoryCache.Get() ) ); - rendererPtr->SetImage( url ); + else + { + ImageRenderer* rendererPtr = new ImageRenderer(); + if( !mFactoryCache ) + { + mFactoryCache = new RendererFactoryCache(); + } + rendererPtr->Initialize( *( mFactoryCache.Get() ) ); + rendererPtr->SetImage( url ); - return Toolkit::ControlRenderer( rendererPtr ); + return Toolkit::ControlRenderer( rendererPtr ); + } } bool RendererFactory::ResetRenderer( Toolkit::ControlRenderer& renderer, const std::string& url ) { - ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); - if( rendererPtr ) + if( NinePatchImage::IsNinePatchUrl( url ) ) { - rendererPtr->SetImage( url ); - return false; + NPatchRenderer* rendererPtr = dynamic_cast< NPatchRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( url ); + return false; + } } else { + ImageRenderer* rendererPtr = dynamic_cast< ImageRenderer* >( &GetImplementation( renderer ) ); + if( rendererPtr ) + { + rendererPtr->SetImage( url ); + return false; + } + } + + { renderer = GetControlRenderer( url ); return true; } diff --git a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h index d65e747..4ed7e7f 100644 --- a/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h +++ b/dali-toolkit/internal/controls/renderers/renderer-factory-impl.h @@ -65,6 +65,11 @@ public: bool ResetRenderer( Toolkit::ControlRenderer& renderer, const Vector4& color ); /** + * @copydoc Toolkit::RenderFactory::GetControlRenderer( float, const Vector4& ) + */ + Toolkit::ControlRenderer GetControlRenderer( float borderSize, const Vector4& borderColor ); + + /** * @copydoc Toolkit::RenderFactory::GetControlRenderer( const Image& ) */ Toolkit::ControlRenderer GetControlRenderer( const Image& image ); diff --git a/dali-toolkit/internal/file.list b/dali-toolkit/internal/file.list index 6351be0..6c8c9b7 100644 --- a/dali-toolkit/internal/file.list +++ b/dali-toolkit/internal/file.list @@ -15,8 +15,10 @@ toolkit_src_files = \ $(toolkit_src_dir)/controls/renderers/control-renderer-impl.cpp \ $(toolkit_src_dir)/controls/renderers/renderer-factory-cache.cpp \ $(toolkit_src_dir)/controls/renderers/renderer-factory-impl.cpp \ + $(toolkit_src_dir)/controls/renderers/border/border-renderer.cpp \ $(toolkit_src_dir)/controls/renderers/color/color-renderer.cpp \ $(toolkit_src_dir)/controls/renderers/image/image-renderer.cpp \ + $(toolkit_src_dir)/controls/renderers/npatch/npatch-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 \ diff --git a/dali-toolkit/public-api/controls/control.h b/dali-toolkit/public-api/controls/control.h index 4a6d2af..bac8835 100644 --- a/dali-toolkit/public-api/controls/control.h +++ b/dali-toolkit/public-api/controls/control.h @@ -279,8 +279,6 @@ public: /** * @brief Sets an image as the background of the control. * - * The color of this image is blended with the background color @see SetBackgroundColor - * * @param[in] image The image to set as the background. */ void SetBackgroundImage( Image image ); diff --git a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json index ad05fea..c45b44e 100644 --- a/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/480x800/dali-toolkit-default-theme.json @@ -99,7 +99,7 @@ distributing this software or its derivatives. "popup-divider-color":[0.23,0.72,0.8,0.11], "popup-icon-color":[1.0,1.0,1.0,1.0], "popup-pressed-color":[0.24,0.72,0.8,0.11], - "background-image": { + "background": { "filename": "{DALI_IMAGE_DIR}selection-popup-bg.9.png" }, "popup-fade-in-duration":0.25, diff --git a/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json b/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json index 8a0fc66..694e2db 100644 --- a/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json +++ b/dali-toolkit/styles/720x1280/dali-toolkit-default-theme.json @@ -99,7 +99,7 @@ distributing this software or its derivatives. "popup-divider-color":[0.23,0.72,0.8,0.11], "popup-icon-color":[1.0,1.0,1.0,1.0], "popup-pressed-color":[0.24,0.72,0.8,0.11], - "background-image": { + "background": { "filename": "{DALI_IMAGE_DIR}selection-popup-bg.9.png" }, "popup-fade-in-duration":0.25,