From: David Steele Date: Wed, 29 Nov 2017 21:11:23 +0000 (+0000) Subject: Added Auxiliary image to NPatch visual. X-Git-Tag: dali_1.3.2~1^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=339af74b081016140d2d5e25dc8609913aabaa31 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 --- 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 0000000..3236edd Binary files /dev/null and b/automated-tests/resources/demo-tile-texture-focused.9.png differ 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 0000000..32a47a5 Binary files /dev/null and b/automated-tests/resources/folder_appicon_empty_bg.png differ 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;