From 339af74b081016140d2d5e25dc8609913aabaa31 Mon Sep 17 00:00:00 2001 From: David Steele Date: Wed, 29 Nov 2017 21:11:23 +0000 Subject: [PATCH] Added Auxiliary image to NPatch visual. Auxiliary image sits on top of the NPatch, and scales with the visual, not with the NPatch stretching. A new Alpha property enables just the auxiliary image to be faded. Change-Id: I391f39f2a422ddf97cdf847e70d12a6a254e941a Signed-off-by: David Steele --- .../resources/demo-tile-texture-focused.9.png | Bin 0 -> 13038 bytes .../resources/folder_appicon_empty_bg.png | Bin 0 -> 6233 bytes .../dali-toolkit-test-utils/dummy-control.cpp | 18 +++ .../dali-toolkit-test-utils/dummy-control.h | 1 + .../src/dali-toolkit/utc-Dali-Visual.cpp | 15 +- .../src/dali-toolkit/utc-Dali-VisualFactory.cpp | 71 ++++++++- .../visuals/image-visual-properties-devel.h | 20 +++ .../internal/visuals/npatch/npatch-visual.cpp | 173 +++++++++++++++++---- .../internal/visuals/npatch/npatch-visual.h | 23 ++- .../internal/visuals/visual-factory-cache.h | 1 + .../internal/visuals/visual-string-constants.cpp | 2 + .../internal/visuals/visual-string-constants.h | 2 + 12 files changed, 285 insertions(+), 41 deletions(-) create mode 100644 automated-tests/resources/demo-tile-texture-focused.9.png create mode 100644 automated-tests/resources/folder_appicon_empty_bg.png diff --git a/automated-tests/resources/demo-tile-texture-focused.9.png b/automated-tests/resources/demo-tile-texture-focused.9.png new file mode 100644 index 0000000000000000000000000000000000000000..3236edda84aa82e99760e72d02f5fd627c2a0848 GIT binary patch literal 13038 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 LN3~q}McDrU23mr9 literal 0 HcmV?d00001 diff --git a/automated-tests/resources/folder_appicon_empty_bg.png b/automated-tests/resources/folder_appicon_empty_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..32a47a58e2d1e7f424c72cc6b992b065173cf588 GIT binary patch literal 6233 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 DJo>-v literal 0 HcmV?d00001 diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp index 5e843c2..96699ec 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.cpp @@ -192,6 +192,7 @@ Property::Value DummyControlImpl::GetProperty( BaseObject* object, Dali::Propert return value; } + Toolkit::DummyControl Impl::DummyControl::New() { IntrusivePtr< Toolkit::Impl::DummyControl > impl = new Toolkit::Impl::DummyControl; @@ -300,6 +301,23 @@ void Impl::DummyControl::SetRelayoutCallback( RelayoutCallbackFunc callback ) mRelayoutCallback = callback; } +Vector3 Impl::DummyControl::GetNaturalSize() +{ + Vector2 currentSize; + + for( auto elem : mRegisteredVisualIndices ) + { + Vector2 naturalSize; + Visual::Base visual = GetVisual(elem); + visual.GetNaturalSize( naturalSize ); + currentSize.width = std::max( naturalSize.width, currentSize.width ); + currentSize.height = std::max( naturalSize.height, currentSize.height ); + } + + return Vector3( currentSize ); +} + + DummyControl DummyControl::New( bool override ) { diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h index 69a5c88..5988284 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/dummy-control.h @@ -162,6 +162,7 @@ private: // From Internal::Control virtual void OnPan(const PanGesture& pan); virtual void OnTap(const TapGesture& tap); virtual void OnLongPress(const LongPressGesture& longPress); + virtual Vector3 GetNaturalSize(); private: // From CustomActorImpl diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp index af56d92..b1f2e2e 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Visual.cpp @@ -25,8 +25,10 @@ #include #include #include +#include #include #include + #include "dummy-control.h" using namespace Dali; @@ -36,12 +38,13 @@ namespace { const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif"; const char* TEST_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/gallery-small-1.jpg"; -const char* TEST_NPATCH_FILE_NAME = "gallery_image_01.9.jpg"; +const char* TEST_NPATCH_FILE_NAME = TEST_RESOURCE_DIR "/button-up.9.png"; const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg"; const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj"; const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl"; const char* TEST_RESOURCE_LOCATION = TEST_RESOURCE_DIR "/"; + const std::string DEFAULT_FONT_DIR( "/resources/fonts" ); Property::Map DefaultTransform() @@ -764,6 +767,8 @@ int UtcDaliVisualGetPropertyMap6(void) propertyMap.Insert( ImageVisual::Property::URL, TEST_NPATCH_FILE_NAME ); propertyMap.Insert( ImageVisual::Property::BORDER_ONLY, true ); propertyMap.Insert( ImageVisual::Property::BORDER, border ); + propertyMap.Insert( DevelImageVisual::Property::AUXILIARY_IMAGE, "application-icon-30.png" ); + propertyMap.Insert( DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, 0.9f ); Visual::Base nPatchVisual = factory.CreateVisual( propertyMap ); Property::Map resultMap; @@ -790,6 +795,14 @@ int UtcDaliVisualGetPropertyMap6(void) DALI_TEST_CHECK( value ); DALI_TEST_CHECK( value->Get< Rect< int > >() == border ); + value = resultMap.Find( DevelImageVisual::Property::AUXILIARY_IMAGE, Property::STRING ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == "application-icon-30.png" ); + + value = resultMap.Find( DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, Property::FLOAT ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == 0.9f ); + Vector4 border1( 1.0f, 1.0f, 1.0f, 1.0f ); Property::Map propertyMap1; diff --git a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp index 950b3e1..54a45a3 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-VisualFactory.cpp @@ -20,8 +20,9 @@ #include #include #include -#include #include +#include +#include #include "dummy-control.h" using namespace Dali; @@ -31,12 +32,13 @@ namespace { typedef NinePatchImage::StretchRanges StretchRanges; -const char* TEST_NPATCH_FILE_NAME = TEST_RESOURCE_DIR "/button-up-1.9.png"; +const char* TEST_NPATCH_FILE_NAME = TEST_RESOURCE_DIR "/demo-tile-texture-focused.9.png"; const char* TEST_SVG_FILE_NAME = TEST_RESOURCE_DIR "/svg1.svg"; const char* TEST_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube.obj"; const char* TEST_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal.mtl"; const char* TEST_SIMPLE_OBJ_FILE_NAME = TEST_RESOURCE_DIR "/Cube-Points-Only.obj"; const char* TEST_SIMPLE_MTL_FILE_NAME = TEST_RESOURCE_DIR "/ToyRobot-Metal-Simple.mtl"; +const char* TEST_AUX_IMAGE = TEST_RESOURCE_DIR "/folder_appicon_empty_bg.png"; // resolution: 50*50, frame count: 4, frame delay: 0.2 second for each frame const char* TEST_GIF_FILE_NAME = TEST_RESOURCE_DIR "/anim.gif"; @@ -837,7 +839,11 @@ int UtcDaliVisualFactoryGetNPatchVisual5(void) stretchRangesY.PushBack( Uint16Pair( 8, 12 ) ); stretchRangesY.PushBack( Uint16Pair( 15, 16 ) ); stretchRangesY.PushBack( Uint16Pair( 25, 27 ) ); - Integration::ResourcePointer ninePatchResource = CustomizeNinePatch( application, ninePatchImageWidth, ninePatchImageHeight, stretchRangesX, stretchRangesY ); + Integration::ResourcePointer ninePatchResource = CustomizeNinePatch( application, + ninePatchImageWidth, + ninePatchImageHeight, + stretchRangesX, + stretchRangesY ); Visual::Base visual = factory.CreateVisual( TEST_NPATCH_FILE_NAME, ImageDimensions() ); DALI_TEST_CHECK( visual ); @@ -856,6 +862,65 @@ int UtcDaliVisualFactoryGetNPatchVisual5(void) END_TEST; } + +int UtcDaliNPatchVisualAuxiliaryImage(void) +{ + ToolkitTestApplication application; + tet_infoline( "NPatchVisual with aux image" ); + + VisualFactory factory = VisualFactory::Get(); + Property::Map properties; + Property::Map shader; + + Property::Map transformMap; + transformMap["size"] = Vector2( 0.5f, 0.5f ) ; + transformMap["offset"] = Vector2( 20.0f, 0.0f ) ; + transformMap["offsetPolicy"] = Vector2( Visual::Transform::Policy::ABSOLUTE, Visual::Transform::Policy::ABSOLUTE ); + transformMap["anchorPoint"] = Align::CENTER; + transformMap["origin"] = Align::CENTER; + properties[Visual::Property::TRANSFORM] = transformMap; + + properties[Visual::Property::TYPE] = Visual::IMAGE; + properties[Visual::Property::MIX_COLOR] = Color::BLUE; + properties[Visual::Property::SHADER]=shader; + properties[ImageVisual::Property::URL] = TEST_NPATCH_FILE_NAME; + properties[DevelImageVisual::Property::AUXILIARY_IMAGE] = TEST_AUX_IMAGE; + properties[DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA] = 0.9f; + + const unsigned int ninePatchImageWidth = 256; + const unsigned int ninePatchImageHeight = 256; + StretchRanges stretchRangesX; + stretchRangesX.PushBack( Uint16Pair( 10, 246 ) ); + StretchRanges stretchRangesY; + stretchRangesY.PushBack( Uint16Pair( 15, 241 ) ); + Integration::ResourcePointer ninePatchResource = CustomizeNinePatch( application, + ninePatchImageWidth, + ninePatchImageHeight, + stretchRangesX, + stretchRangesY ); + + Visual::Base visual = factory.CreateVisual( properties ); + + // trigger creation through setting on stage + DummyControl dummy = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummy.GetImplementation()); + dummyImpl.RegisterVisual( DummyControl::Property::TEST_VISUAL, visual ); + dummyImpl.SetLayout( DummyControl::Property::TEST_VISUAL, transformMap ); + dummy.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + dummy.SetParentOrigin(ParentOrigin::CENTER); + Stage::GetCurrent().Add(dummy); + application.SendNotification(); + application.Render(); + + Renderer renderer = dummy.GetRendererAt( 0 ); + auto textures = renderer.GetTextures(); + DALI_TEST_EQUALS( textures.GetTextureCount(), 2, TEST_LOCATION ); + + + END_TEST; +} + + int UtcDaliVisualFactoryGetNPatchVisualN1(void) { //This should still load but display an error image diff --git a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h index acb9b11..e87af5d 100644 --- a/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h +++ b/dali-toolkit/devel-api/visuals/image-visual-properties-devel.h @@ -112,6 +112,26 @@ enum Type * @note Default true */ ORIENTATION_CORRECTION = CROP_TO_MASK + 3, + + /** + * @brief Overlays the auxiliary iamge on top of an NPatch image. + * + * The resulting visual image will be at least as large as the + * smallest possible n-patch or the auxiliary image, whichever is + * larger. + * + * @details Name "auxiliaryImage", Type Property::STRING, URL of the image. + * @note Default true + */ + AUXILIARY_IMAGE = CROP_TO_MASK + 4, + + /** + * @brief An alpha value for mixing between the masked main NPatch image and the auxiliary image + * @details Name "auxiliaryImageAlpha", Type Property::FLOAT, between 0 and 1 + * @note Default 0 + */ + AUXILIARY_IMAGE_ALPHA = CROP_TO_MASK + 5, + }; } //namespace Property diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp index d5976dd..33a4842 100755 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.cpp @@ -21,11 +21,14 @@ // EXTERNAL INCLUDES #include #include +#include #include +#include #include // INTERNAL INCLUDES #include +#include #include #include #include @@ -47,6 +50,8 @@ namespace { const char * const BORDER_ONLY( "borderOnly" ); const char * const BORDER( "border" ); +const char * const AUXILIARY_IMAGE_NAME( "auxiliaryImage" ); +const char * const AUXILIARY_IMAGE_ALPHA_NAME( "auxiliaryImageAlpha" ); const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n @@ -57,7 +62,7 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( uniform mediump vec2 uNinePatchFactorsY[ FACTOR_SIZE_Y ];\n \n - //Visual size and offset + // Visual size and offset uniform mediump vec2 offset;\n uniform mediump vec2 size;\n uniform mediump vec4 offsetSizeMode;\n @@ -72,16 +77,17 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( mediump vec2 fixedTotal = vec2( uNinePatchFactorsX[ FACTOR_SIZE_X - 1 ].x, uNinePatchFactorsY[ FACTOR_SIZE_Y - 1 ].x );\n mediump vec2 stretchTotal = vec2( uNinePatchFactorsX[ FACTOR_SIZE_X - 1 ].y, uNinePatchFactorsY[ FACTOR_SIZE_Y - 1 ].y );\n \n - vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n - - mediump vec4 vertexPosition = vec4( ( fixedFactor + ( visualSize.xy - fixedTotal ) * stretch / stretchTotal ) + anchorPoint*visualSize + (visualOffset + origin)*uSize.xy, 0.0, 1.0 );\n + \n + mediump vec4 gridPosition = vec4( fixedFactor + ( visualSize.xy - fixedTotal ) * stretch / stretchTotal, 0.0, 1.0 );\n + mediump vec4 vertexPosition = gridPosition;\n vertexPosition.xy -= visualSize.xy * vec2( 0.5, 0.5 );\n - + vertexPostion.xy += anchorPoint*visualSize + (visualOffset + origin)*uSize.xy;\n vertexPosition = uMvpMatrix * vertexPosition;\n \n vTexCoord = ( fixedFactor + stretch ) / ( fixedTotal + stretchTotal );\n + vMaskTexCoord = gridPosition.xy / visualSize;\n \n gl_Position = vertexPosition;\n }\n @@ -90,39 +96,41 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( const char* VERTEX_SHADER_3X3 = DALI_COMPOSE_SHADER( attribute mediump vec2 aPosition;\n varying mediump vec2 vTexCoord;\n + varying mediump vec2 vMaskTexCoord;\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 - //Visual size and offset uniform mediump vec2 offset;\n uniform mediump vec2 size;\n uniform mediump vec4 offsetSizeMode;\n uniform mediump vec2 origin;\n uniform mediump vec2 anchorPoint;\n - + \n void main()\n {\n vec2 visualSize = mix(uSize.xy*size, size, offsetSizeMode.zw );\n vec2 visualOffset = mix( offset, offset/uSize.xy, offsetSizeMode.xy);\n - + \n mediump vec2 size = visualSize.xy;\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 ); + mediump vec4 gridPosition = vec4( fixedFactor + ( size - fixedTotal ) * stretch, 0.0, 1.0 );\n + mediump vec4 vertexPosition = gridPosition;\n vertexPosition.xy -= size * vec2( 0.5, 0.5 );\n - vertexPosition.xy = vertexPosition.xy + anchorPoint*size + (visualOffset + origin)*uSize.xy;\ + vertexPosition.xy += anchorPoint*size + (visualOffset + origin)*uSize.xy;\n \n vertexPosition = uMvpMatrix * vertexPosition;\n \n vTexCoord = ( fixedFactor + stretch * uStretchTotal ) / ( fixedTotal + uStretchTotal );\n \n + vMaskTexCoord = gridPosition.xy / size;\n gl_Position = vertexPosition;\n }\n ); @@ -144,6 +152,36 @@ const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( }\n ); +const char* FRAGMENT_MASK_SHADER = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord;\n + varying mediump vec2 vMaskTexCoord;\n + uniform sampler2D sTexture;\n + uniform sampler2D sMask;\n + uniform lowp vec4 uColor;\n + uniform lowp vec3 mixColor;\n + uniform lowp float opacity;\n + uniform lowp float preMultipliedAlpha;\n + uniform mediump float auxiliaryImageAlpha;\n + lowp vec4 visualMixColor()\n + {\n + return vec4( mixColor * mix( 1.0, opacity, preMultipliedAlpha ), opacity );\n + }\n + void main()\n + {\n + // Where mask image is transparent, all of background image must show through. + // where mask image is opaque, only mask should be shown + // where mask is translucent, less of background should be shown. + // auxiliaryImageAlpha controls how much of mask is visible + + mediump vec4 color = texture2D( sTexture, vTexCoord );\n + mediump vec4 mask = texture2D( sMask, vMaskTexCoord );\n + + mediump vec3 mixedColor = color.rgb * mix( 1.0-mask.a, 1.0, 1.0-auxiliaryImageAlpha) + + mask.rgb*mask.a * auxiliaryImageAlpha;\n + gl_FragColor = vec4(mixedColor,1.0) * uColor * visualMixColor();\n + }\n +); + /** * @brief Creates the geometry formed from the vertices and indices * @@ -256,22 +294,41 @@ NPatchVisualPtr NPatchVisual::New( VisualFactoryCache& factoryCache, NinePatchIm return nPatchVisual; } +void NPatchVisual::LoadImages() +{ + if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() ) + { + mId = mLoader.Load( mImageUrl.GetUrl(), mBorder ); + } + + if( ! mAuxiliaryPixelBuffer && mAuxiliaryUrl.IsValid() && mAuxiliaryUrl.IsLocalResource() ) + { + // Load the auxiliary image synchronously + mAuxiliaryPixelBuffer = Dali::LoadImageFromFile( mAuxiliaryUrl.GetUrl(), ImageDimensions(), + FittingMode::DEFAULT, SamplingMode::BOX_THEN_LINEAR, true ); + } +} + void NPatchVisual::GetNaturalSize( Vector2& naturalSize ) { naturalSize.x = 0u; naturalSize.y = 0u; // load now if not already loaded - if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() ) - { - mId = mLoader.Load( mImageUrl.GetUrl(), mBorder ); - } + LoadImages(); + const NPatchLoader::Data* data; if( mLoader.GetNPatchData( mId, data ) ) { naturalSize.x = data->croppedWidth; naturalSize.y = data->croppedHeight; } + + if( mAuxiliaryPixelBuffer ) + { + naturalSize.x = std::max( naturalSize.x, float(mAuxiliaryPixelBuffer.GetWidth()) ); + naturalSize.y = std::max( naturalSize.y, float(mAuxiliaryPixelBuffer.GetHeight()) ); + } } void NPatchVisual::DoSetProperties( const Property::Map& propertyMap ) @@ -297,15 +354,28 @@ void NPatchVisual::DoSetProperties( const Property::Map& propertyMap ) mBorder.top = static_cast< int >( border.w ); } } + + Property::Value* auxImage = propertyMap.Find( Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, AUXILIARY_IMAGE_NAME ); + if( auxImage ) + { + std::string url; + if( auxImage->Get( url ) ) + { + mAuxiliaryUrl = url; + } + } + + Property::Value* auxImageAlpha = propertyMap.Find( Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, AUXILIARY_IMAGE_ALPHA_NAME ); + if( auxImageAlpha ) + { + auxImageAlpha->Get( mAuxiliaryImageAlpha ); + } } void NPatchVisual::DoSetOnStage( Actor& actor ) { // load when first go on stage - if( NPatchLoader::UNINITIALIZED_ID == mId && mImageUrl.IsLocalResource() ) - { - mId = mLoader.Load( mImageUrl.GetUrl(), mBorder ); - } + LoadImages(); Geometry geometry = CreateGeometry(); Shader shader = CreateShader(); @@ -340,20 +410,32 @@ void NPatchVisual::DoCreatePropertyMap( Property::Map& map ) const map.Insert( Toolkit::ImageVisual::Property::URL, mImageUrl.GetUrl() ); map.Insert( Toolkit::ImageVisual::Property::BORDER_ONLY, mBorderOnly ); map.Insert( Toolkit::ImageVisual::Property::BORDER, mBorder ); + + if( mAuxiliaryUrl.IsValid() ) + { + map.Insert( Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl() ); + map.Insert( Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha ); + } } void NPatchVisual::DoCreateInstancePropertyMap( Property::Map& map ) const { - // Do nothing + if( mAuxiliaryUrl.IsValid() ) + { + map.Insert( Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE, mAuxiliaryUrl.GetUrl() ); + map.Insert( Toolkit::DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, mAuxiliaryImageAlpha ); + } } NPatchVisual::NPatchVisual( VisualFactoryCache& factoryCache ) : Visual::Base( factoryCache ), mLoader( factoryCache.GetNPatchLoader() ), mImageUrl(), + mAuxiliaryUrl(), mId( NPatchLoader::UNINITIALIZED_ID ), mBorderOnly( false ), - mBorder() + mBorder(), + mAuxiliaryImageAlpha( 0.0f ) { } @@ -401,6 +483,11 @@ Shader NPatchVisual::CreateShader() NinePatchImage::StretchRanges::SizeType xStretchCount = 0; NinePatchImage::StretchRanges::SizeType yStretchCount = 0; + auto fragmentShader = mAuxiliaryPixelBuffer ? FRAGMENT_MASK_SHADER + : FRAGMENT_SHADER; + auto shaderType = mAuxiliaryPixelBuffer ? VisualFactoryCache::NINE_PATCH_MASK_SHADER + : VisualFactoryCache::NINE_PATCH_SHADER; + // ask loader for the regions if( mLoader.GetNPatchData( mId, data ) ) { @@ -413,11 +500,12 @@ Shader NPatchVisual::CreateShader() if( DALI_LIKELY( ( xStretchCount == 1 && yStretchCount == 1 ) || ( xStretchCount == 0 && yStretchCount == 0 ) ) ) { - shader = mFactoryCache.GetShader( VisualFactoryCache::NINE_PATCH_SHADER ); + shader = mFactoryCache.GetShader( shaderType ); if( DALI_UNLIKELY( !shader ) ) { - shader = Shader::New( VERTEX_SHADER_3X3, FRAGMENT_SHADER ); - mFactoryCache.SaveShader( VisualFactoryCache::NINE_PATCH_SHADER, shader ); + shader = Shader::New( VERTEX_SHADER_3X3, fragmentShader ); + // Only cache vanilla 9 patch shaders + mFactoryCache.SaveShader( shaderType, shader ); } } else if( xStretchCount > 0 || yStretchCount > 0) @@ -427,12 +515,11 @@ Shader NPatchVisual::CreateShader() << "#define FACTOR_SIZE_Y " << yStretchCount + 2 << "\n" << VERTEX_SHADER; - shader = Shader::New( vertexShader.str(), FRAGMENT_SHADER ); + shader = Shader::New( vertexShader.str(), fragmentShader ); } } else { - const char* fragmentShader = FRAGMENT_SHADER; Dali::Shader::Hint::Value hints = Dali::Shader::Hint::NONE; if( !mImpl->mCustomShader->mFragmentShader.empty() ) @@ -470,10 +557,12 @@ Shader NPatchVisual::CreateShader() void NPatchVisual::ApplyTextureAndUniforms() { const NPatchLoader::Data* data; + TextureSet textureSet; + if( mLoader.GetNPatchData( mId, data ) ) { - TextureSet textures( data->textureSet ); - mImpl->mRenderer.SetTextures( textures ); + textureSet = data->textureSet; + if( data->stretchPixelsX.Size() == 1 && data->stretchPixelsY.Size() == 1 ) { //special case for 9 patch @@ -500,8 +589,8 @@ void NPatchVisual::ApplyTextureAndUniforms() else { DALI_LOG_ERROR("The N patch image '%s' is not a valid N patch image\n", mImageUrl.GetUrl().c_str() ); - TextureSet textureSet = TextureSet::New(); - mImpl->mRenderer.SetTextures( textureSet ); + textureSet = TextureSet::New(); + Image croppedImage = VisualFactoryCache::GetBrokenVisualImage(); TextureSetImage( textureSet, 0u, croppedImage ); mImpl->mRenderer.RegisterProperty( "uFixed[0]", Vector2::ZERO ); @@ -510,7 +599,31 @@ void NPatchVisual::ApplyTextureAndUniforms() mImpl->mRenderer.RegisterProperty( "uStretchTotal", Vector2( croppedImage.GetWidth(), croppedImage.GetHeight() ) ); } - //Register transform properties + if( mAuxiliaryPixelBuffer ) + { + // If the auxiliary image is smaller than the un-stretched NPatch, use CPU resizing to enlarge it to the + // same size as the unstretched NPatch. This will give slightly higher quality results than just relying + // on GL interpolation alone. + if( mAuxiliaryPixelBuffer.GetWidth() < data->croppedWidth && + mAuxiliaryPixelBuffer.GetHeight() < data->croppedHeight ) + { + mAuxiliaryPixelBuffer.Resize( data->croppedWidth, data->croppedHeight ); + } + + // Note, this resets mAuxiliaryPixelBuffer handle + auto auxiliaryPixelData = Devel::PixelBuffer::Convert( mAuxiliaryPixelBuffer ); + + auto texture = Texture::New( TextureType::TEXTURE_2D, + auxiliaryPixelData.GetPixelFormat(), auxiliaryPixelData.GetWidth(), + auxiliaryPixelData.GetHeight() ); + texture.Upload( auxiliaryPixelData ); + textureSet.SetTexture( 1, texture ); + DevelHandle::RegisterProperty( mImpl->mRenderer, DevelImageVisual::Property::AUXILIARY_IMAGE_ALPHA, + AUXILIARY_IMAGE_ALPHA_NAME, mAuxiliaryImageAlpha ); + } + mImpl->mRenderer.SetTextures( textureSet ); + + // Register transform properties mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT ); } diff --git a/dali-toolkit/internal/visuals/npatch/npatch-visual.h b/dali-toolkit/internal/visuals/npatch/npatch-visual.h index 901211d..d10e687 100644 --- a/dali-toolkit/internal/visuals/npatch/npatch-visual.h +++ b/dali-toolkit/internal/visuals/npatch/npatch-visual.h @@ -2,7 +2,7 @@ #define DALI_TOOLKIT_INTERNAL_N_PATCH_VISUAL_H /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 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. @@ -53,7 +53,8 @@ typedef IntrusivePtr< NPatchVisual > NPatchVisualPtr; * | url | STRING | * | borderOnly | BOOLEAN | * | border | RECTANGLE | - * + * | auxiliaryImage | STRING | + * | auxiliaryImageAlpha | FLOAT | */ class NPatchVisual: public Visual::Base { @@ -144,6 +145,11 @@ protected: private: /** + * Loads the NPatch image and the Auxiliary image if needed + */ + void LoadImages(); + + /** * @brief Creates a geometry for this renderer's grid size * * @return Returns the created geometry for this renderer's grid size @@ -202,11 +208,14 @@ private: private: - NPatchLoader& mLoader; ///< reference to N patch loader for fast access - VisualUrl mImageUrl; ///< The url to the N patch to load - std::size_t mId; ///< id of the N patch (from loader/cache) - bool mBorderOnly; ///< if only border is desired - Rect< int > mBorder; ///< The size of the border + NPatchLoader& mLoader; ///< reference to N patch loader for fast access + VisualUrl mImageUrl; ///< The url to the N patch to load + VisualUrl mAuxiliaryUrl; ///< An auxiliary image that can be displayed on top of the N-Patch + std::size_t mId; ///< id of the N patch (from loader/cache) + Devel::PixelBuffer mAuxiliaryPixelBuffer; ///< pixel buffer of the auxiliary mask image + bool mBorderOnly; ///< if only border is desired + Rect mBorder; ///< The size of the border + float mAuxiliaryImageAlpha; ///< The alpha value for the auxiliary image only }; } // namespace Internal diff --git a/dali-toolkit/internal/visuals/visual-factory-cache.h b/dali-toolkit/internal/visuals/visual-factory-cache.h index 7f13da6..778a48f 100644 --- a/dali-toolkit/internal/visuals/visual-factory-cache.h +++ b/dali-toolkit/internal/visuals/visual-factory-cache.h @@ -67,6 +67,7 @@ public: IMAGE_SHADER_ATLAS_DEFAULT_WRAP, IMAGE_SHADER_ATLAS_CUSTOM_WRAP, NINE_PATCH_SHADER, + NINE_PATCH_MASK_SHADER, SVG_SHADER, TEXT_SHADER_MULTI_COLOR_TEXT, TEXT_SHADER_MULTI_COLOR_TEXT_WITH_STYLE, diff --git a/dali-toolkit/internal/visuals/visual-string-constants.cpp b/dali-toolkit/internal/visuals/visual-string-constants.cpp index 661e251..9e889cb 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.cpp +++ b/dali-toolkit/internal/visuals/visual-string-constants.cpp @@ -90,6 +90,8 @@ const char * const CROP_TO_MASK_NAME("cropToMask"); const char * const LOAD_POLICY_NAME("loadPolicy"); const char * const RELEASE_POLICY_NAME("releasePolicy"); const char * const ORIENTATION_CORRECTION_NAME("orientationCorrection"); +const char * const AUXILIARY_IMAGE_NAME("auxiliaryImage"); +const char * const AUXILIARY_IMAGE_ALPHA_NAME("auxiliaryImageAlpha"); // Text visual const char * const TEXT_PROPERTY( "text" ); diff --git a/dali-toolkit/internal/visuals/visual-string-constants.h b/dali-toolkit/internal/visuals/visual-string-constants.h index 50f809f..eb0b617 100644 --- a/dali-toolkit/internal/visuals/visual-string-constants.h +++ b/dali-toolkit/internal/visuals/visual-string-constants.h @@ -76,6 +76,8 @@ extern const char * const CROP_TO_MASK_NAME; extern const char * const LOAD_POLICY_NAME; extern const char * const RELEASE_POLICY_NAME; extern const char * const ORIENTATION_CORRECTION_NAME; +extern const char * const AUXILLARY_IMAGE_NAME; +extern const char * const AUXILLARY_IMAGE_ALPHA_NAME; // Text visual extern const char * const TEXT_PROPERTY; -- 2.7.4