END_TEST;
}
+
+
+int UtcDaliImageVisualAlphaMaskCrop(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "Request image visual with an Alpha mask and scale/cropping" );
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK( factory );
+
+ Property::Map propertyMap;
+ propertyMap.Insert( Visual::Property::TYPE, Visual::IMAGE );
+ propertyMap.Insert( ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME );
+ propertyMap.Insert( DevelImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME );
+ propertyMap.Insert( DevelImageVisual::Property::MASK_CONTENT_SCALE, 1.6f );
+ propertyMap.Insert( DevelImageVisual::Property::CROP_TO_MASK, true );
+
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+ DALI_TEST_CHECK( visual );
+
+ Property::Map testMap;
+ visual.CreatePropertyMap(testMap);
+ DALI_TEST_EQUALS( *testMap.Find(DevelImageVisual::Property::ALPHA_MASK_URL),Property::Value(TEST_MASK_IMAGE_FILE_NAME), TEST_LOCATION );
+ DALI_TEST_EQUALS( *testMap.Find(DevelImageVisual::Property::MASK_CONTENT_SCALE), Property::Value(1.6f), TEST_LOCATION );
+ DALI_TEST_EQUALS( *testMap.Find(DevelImageVisual::Property::CROP_TO_MASK),Property::Value(true), TEST_LOCATION );
+
+ // For tesing the LoadResourceFunc is called, a big image size should be set, so the atlasing is not applied.
+ // Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& textureTrace = gl.GetTextureTrace();
+ textureTrace.Enable(true);
+
+ DummyControl actor = DummyControl::New();
+ DummyControlImpl& dummyImpl = static_cast<DummyControlImpl&>(actor.GetImplementation());
+ dummyImpl.RegisterVisual( Control::CONTROL_PROPERTY_END_INDEX + 1, visual );
+
+ actor.SetSize( 200.f, 200.f );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+ DALI_TEST_EQUALS( DevelControl::IsResourceReady( actor ), false, TEST_LOCATION );
+
+ Stage::GetCurrent().Add( actor );
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 2 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ Vector2 size;
+ visual.GetNaturalSize(size);
+
+ DALI_TEST_EQUALS( size, Vector2( 100.0f, 100.0f ), 0.001f, TEST_LOCATION );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+ DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
+ DALI_TEST_EQUALS( DevelControl::IsResourceReady( actor ), true, TEST_LOCATION );
+
+ END_TEST;
+}
* @details Name "frameDelay", type Property::INTEGER, The number of milliseconds between each frame. Note, this is only used with the URLS property above.
*/
FRAME_DELAY = WRAP_MODE_V + 6,
+
+ /**
+ * @brief The scale factor to apply to the content image before masking
+ * @details Name "maskContentScale", type Property::FLOAT, The scale factor
+ * to apply to the content before masking. Note, scaled images are cropped to
+ * the same size as the alpha mask.
+ */
+ MASK_CONTENT_SCALE = WRAP_MODE_V + 7,
+
+ /**
+ * @brief Whether to crop image to mask or scale mask to fit image
+ * @details Name "cropToMask", type Property::BOOLEAN, True if the image should
+ * be cropped to match the mask size, or false if the image should remain the same size.
+ * Note, if this is false, then the mask is scaled to fit the image before being applied.
+ */
+ CROP_TO_MASK = WRAP_MODE_V + 8,
+
};
} //namespace Property
/*
- * 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.
// EXTERNAL HEADERS
#include <cstring> // for strlen()
#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/common/stage.h>
#include <dali/public-api/images/resource-image.h>
#include <dali/public-api/images/native-image.h>
#include <dali/devel-api/images/texture-set-image.h>
mPixelArea( FULL_TEXTURE_RECT ),
mPlacementActor(),
mImageUrl( imageUrl ),
- mAlphaMaskUrl(),
+ mMaskingData( NULL ),
mDesiredSize( size ),
mTextureId( TextureManager::INVALID_TEXTURE_ID ),
- mAlphaMaskId( TextureManager::INVALID_TEXTURE_ID ),
mFittingMode( fittingMode ),
mSamplingMode( samplingMode ),
mWrapModeU( WrapMode::DEFAULT ),
mPixelArea( FULL_TEXTURE_RECT ),
mPlacementActor(),
mImageUrl(),
- mAlphaMaskUrl(),
+ mMaskingData( NULL ),
mDesiredSize(),
mTextureId( TextureManager::INVALID_TEXTURE_ID ),
- mAlphaMaskId( TextureManager::INVALID_TEXTURE_ID ),
mFittingMode( FittingMode::DEFAULT ),
mSamplingMode( SamplingMode::DEFAULT ),
mWrapModeU( WrapMode::DEFAULT ),
ImageVisual::~ImageVisual()
{
- if( mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID )
- {
- TextureManager& textureManager = mFactoryCache.GetTextureManager();
- textureManager.Remove( mAlphaMaskId );
- }
+ delete mMaskingData;
}
void ImageVisual::DoSetProperties( const Property::Map& propertyMap )
{
DoSetProperty( Toolkit::DevelImageVisual::Property::ALPHA_MASK_URL, keyValue.second );
}
+ else if ( keyValue.first == MASK_CONTENT_SCALE_NAME )
+ {
+ DoSetProperty( Toolkit::DevelImageVisual::Property::MASK_CONTENT_SCALE, keyValue.second );
+ }
+ else if ( keyValue.first == CROP_TO_MASK_NAME )
+ {
+ DoSetProperty( Toolkit::DevelImageVisual::Property::CROP_TO_MASK, keyValue.second );
+ }
}
}
- if( mAlphaMaskUrl.IsValid() )
- {
- // Immediately trigger the alpha mask loading (it may just get a cached value)
- TextureManager& textureManager = mFactoryCache.GetTextureManager();
- mAlphaMaskId = textureManager.RequestMaskLoad( mAlphaMaskUrl );
- }
-
if( ( mImpl->mFlags & Impl::IS_SYNCHRONOUS_RESOURCE_LOADING ) && mImageUrl.IsValid() )
{
// if sync loading is required, the loading should start
std::string alphaUrl;
if( value.Get( alphaUrl ) )
{
- mAlphaMaskUrl = VisualUrl( alphaUrl );
+ AllocateMaskData();
+ // Immediately trigger the alpha mask loading (it may just get a cached value)
+ mMaskingData->SetImage( alphaUrl );
}
break;
}
+
+ case Toolkit::DevelImageVisual::Property::MASK_CONTENT_SCALE:
+ {
+ float scale;
+ if( value.Get( scale ) )
+ {
+ AllocateMaskData();
+ mMaskingData->mContentScaleFactor = scale;
+ }
+ break;
+ }
+
+ case Toolkit::DevelImageVisual::Property::CROP_TO_MASK:
+ {
+ bool crop=false;
+ if( value.Get( crop ) )
+ {
+ AllocateMaskData();
+ mMaskingData->mCropToMask = crop;
+ }
+ break;
+ }
+ }
+}
+
+void ImageVisual::AllocateMaskData()
+{
+ if( mMaskingData == NULL )
+ {
+ TextureManager& textureManager = mFactoryCache.GetTextureManager();
+ mMaskingData = new MaskingData(textureManager);
}
}
naturalSize.y = mDesiredSize.GetHeight();
return;
}
+
+ else if( mMaskingData != NULL && mMaskingData->mAlphaMaskUrl.IsValid() &&
+ mMaskingData->mCropToMask )
+ {
+ ImageDimensions dimensions = Dali::GetClosestImageSize( mMaskingData->mAlphaMaskUrl.GetUrl() );
+ if( dimensions != ImageDimensions( 0, 0 ) )
+ {
+ naturalSize.x = dimensions.GetWidth();
+ naturalSize.y = dimensions.GetHeight();
+ }
+ return;
+ }
else if( mImageUrl.IsValid() && mImageUrl.GetLocation() == VisualUrl::LOCAL )
{
ImageDimensions dimensions = Dali::GetClosestImageSize( mImageUrl.GetUrl() );
{
mImpl->mFlags &= ~Impl::IS_ATLASING_APPLIED;
TextureManager& textureManager = mFactoryCache.GetTextureManager();
- if( mAlphaMaskId == TextureManager::INVALID_TEXTURE_ID )
+ if( mMaskingData == NULL )
{
mTextureId = textureManager.RequestLoad( mImageUrl, mDesiredSize, mFittingMode,
mSamplingMode, TextureManager::NO_ATLAS, this );
}
else
{
- mTextureId = textureManager.RequestLoad( mImageUrl, mAlphaMaskId, mDesiredSize,
+ mTextureId = textureManager.RequestLoad( mImageUrl,
+ mMaskingData->mAlphaMaskId,
+ mMaskingData->mContentScaleFactor,
+ mDesiredSize,
mFittingMode, mSamplingMode,
- TextureManager::NO_ATLAS, this );
+ TextureManager::NO_ATLAS,
+ mMaskingData->mCropToMask,
+ this );
}
TextureManager::LoadState loadState = textureManager.GetTextureState( mTextureId );
map.Insert( Toolkit::ImageVisual::Property::WRAP_MODE_V, mWrapModeV );
map.Insert( Toolkit::DevelImageVisual::Property::ATLASING, mAttemptAtlasing );
- map.Insert( Toolkit::DevelImageVisual::Property::ALPHA_MASK_URL, mAlphaMaskUrl.GetUrl() );
+ if( mMaskingData != NULL )
+ {
+ map.Insert( Toolkit::DevelImageVisual::Property::ALPHA_MASK_URL, mMaskingData->mAlphaMaskUrl.GetUrl() );
+ map.Insert( Toolkit::DevelImageVisual::Property::MASK_CONTENT_SCALE, mMaskingData->mContentScaleFactor );
+ map.Insert( Toolkit::DevelImageVisual::Property::CROP_TO_MASK, mMaskingData->mCropToMask );
+ }
}
void ImageVisual::DoCreateInstancePropertyMap( Property::Map& map ) const
}
}
+
+ImageVisual::MaskingData::MaskingData( TextureManager& textureManager )
+: mTextureManager( textureManager ),
+ mAlphaMaskUrl(),
+ mAlphaMaskId( TextureManager::INVALID_TEXTURE_ID ),
+ mContentScaleFactor( 1.0f ),
+ mCropToMask( true )
+{
+}
+
+ImageVisual::MaskingData::~MaskingData()
+{
+ if( Stage::IsInstalled() )
+ {
+ // TextureManager could have been deleted before the actor that contains this
+ // ImageVisual is destroyed (e.g. due to stage shutdown). Ensure the stage
+ // is still valid before accessing texture manager.
+ if( mAlphaMaskId != TextureManager::INVALID_TEXTURE_ID )
+ {
+ mTextureManager.Remove( mAlphaMaskId );
+ }
+ }
+}
+
+void ImageVisual::MaskingData::SetImage( const std::string& maskUrl )
+{
+ mAlphaMaskUrl = maskUrl;
+ mAlphaMaskId = mTextureManager.RequestMaskLoad( mAlphaMaskUrl );
+}
+
} // namespace Internal
} // namespace Toolkit
#define DALI_TOOLKIT_INTERNAL_IMAGE_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.
private:
/**
+ * Allocate the mask data when a masking property is defined in the property map
+ */
+ void AllocateMaskData();
+
+ /**
* @brief Applies the image to the texture set used for this renderer
*
* @param[in] image The Image to apply to the texture set used for this renderer
void DoSetProperty( Property::Index index, const Property::Value& value );
private:
+ struct MaskingData
+ {
+ MaskingData( TextureManager& textureManager );
+ ~MaskingData();
+ void SetImage( const std::string& url );
+
+ TextureManager& mTextureManager;
+ VisualUrl mAlphaMaskUrl;
+ TextureManager::TextureId mAlphaMaskId;
+ float mContentScaleFactor;
+ bool mCropToMask;
+ };
Image mImage;
PixelData mPixels;
Vector4 mPixelArea;
WeakHandle<Actor> mPlacementActor;
VisualUrl mImageUrl;
- VisualUrl mAlphaMaskUrl;
+ MaskingData* mMaskingData;
Dali::ImageDimensions mDesiredSize;
TextureManager::TextureId mTextureId;
- TextureManager::TextureId mAlphaMaskId;
Dali::FittingMode::Type mFittingMode:3;
Dali::SamplingMode::Type mSamplingMode:4;
bool mTextureLoading:1; ///< True if the texture is being loaded asynchronously, or false when it has loaded.
};
+
+
} // namespace Internal
} // namespace Toolkit
const UseAtlas useAtlas,
TextureUploadObserver* observer )
{
- return RequestLoadInternal( url, INVALID_TEXTURE_ID, desiredSize, fittingMode, samplingMode, useAtlas, UPLOAD_TO_TEXTURE, observer );
+ return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas, false, UPLOAD_TO_TEXTURE, observer );
}
TextureManager::TextureId TextureManager::RequestLoad(
const VisualUrl& url,
TextureId maskTextureId,
+ float contentScale,
const ImageDimensions desiredSize,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode,
const UseAtlas useAtlas,
+ bool cropToMask,
TextureUploadObserver* observer )
{
- return RequestLoadInternal( url, maskTextureId, desiredSize, fittingMode, samplingMode, useAtlas, UPLOAD_TO_TEXTURE, observer );
+ return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas, cropToMask, UPLOAD_TO_TEXTURE, observer );
}
TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl )
{
// Use the normal load procedure to get the alpha mask.
- return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, KEEP_PIXEL_BUFFER, NULL );
+ return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL );
}
TextureManager::TextureId TextureManager::RequestLoadInternal(
const VisualUrl& url,
TextureId maskTextureId,
+ float contentScale,
const ImageDimensions desiredSize,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode,
UseAtlas useAtlas,
+ bool cropToMask,
StorageType storageType,
TextureUploadObserver* observer )
{
// We need a new Texture.
textureId = GenerateUniqueTextureId();
mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(),
- desiredSize, fittingMode, samplingMode,
- false, useAtlas, textureHash ) );
+ desiredSize, contentScale, fittingMode, samplingMode,
+ false, cropToMask, useAtlas, textureHash ) );
cacheIndex = mTextureInfoContainer.size() - 1u;
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n", url.GetUrl().c_str(), observer, cacheIndex, textureId );
}
else if( maskLoadState == LOAD_FINISHED )
{
- ApplyMask( pixelBuffer, textureInfo.maskTextureId );
+ ApplyMask( pixelBuffer, textureInfo.maskTextureId, textureInfo.scaleFactor, textureInfo.cropToMask );
UploadTexture( pixelBuffer, textureInfo );
NotifyObservers( textureInfo, true );
}
if( maskTextureInfo.loadState == LOAD_FINISHED )
{
- ApplyMask( pixelBuffer, maskTextureInfo.textureId );
+ ApplyMask( pixelBuffer, maskTextureInfo.textureId, textureInfo.scaleFactor, textureInfo.cropToMask );
UploadTexture( pixelBuffer, textureInfo );
NotifyObservers( textureInfo, true );
}
}
}
-void TextureManager::ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId )
+void TextureManager::ApplyMask(
+ Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
+ float contentScale, bool cropToMask )
{
int maskCacheIndex = GetCacheIndexFromId( maskTextureId );
Devel::PixelBuffer maskPixelBuffer = mTextureInfoContainer[maskCacheIndex].pixelBuffer;
- pixelBuffer.ApplyMask( maskPixelBuffer );
+ pixelBuffer.ApplyMask( maskPixelBuffer, contentScale, cropToMask );
}
void TextureManager::UploadTexture( Devel::PixelBuffer& pixelBuffer, TextureInfo& textureInfo )
* When the client has finished with the Texture, Remove() should be called.
*
* @param[in] url The URL of the image to load
+ * @param[in] maskTextureId The texture id of an image to mask this with (can be INVALID if no masking required)
+ * @param[in] contentScale The scale factor to apply to the image before masking
* @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
* @param[in] fittingMode The FittingMode to use
* @param[in] samplingMode The SamplingMode to use
* @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
* but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
+ * @param[in] cropToMask Only used with masking, this will crop the scaled image to the mask size. If false, then the mask will be scaled to fit the image before being applied.
* @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual.
* This is called when an image load completes (or fails).
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoad( const VisualUrl& url,
TextureId maskTextureId,
+ float contentScale,
const ImageDimensions desiredSize,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode,
const UseAtlas useAtlasing,
+ bool cropToMask,
TextureUploadObserver* observer );
/**
*
* @param[in] url The URL of the image to load
* @param[in] maskTextureId The texture id of an image to use as a mask. If no mask is required, then set to INVALID_TEXTURE_ID
+ * @param[in] contentScale The scaling factor to apply to the content when masking
* @param[in] desiredSize The size the image is likely to appear at. This can be set to 0,0 for automatic
* @param[in] fittingMode The FittingMode to use
* @param[in] samplingMode The SamplingMode to use
* @param[in] useAtlasing Set to USE_ATLAS to attempt atlasing. If atlasing fails, the image will still be loaded, and marked successful,
* but "useAtlasing" will be set to false in the "UploadCompleted" callback from the TextureManagerUploadObserver.
+ * @param[in] cropToMask Whether to crop the target after masking, or scale the mask to the image before masking.
* @param[in] storageType, Whether the pixel data is stored in the cache or uploaded to the GPU
* @param[in] observer The client object should inherit from this and provide the "UploadCompleted" virtual.
* This is called when an image load completes (or fails).
TextureId RequestLoadInternal(
const VisualUrl& url,
TextureId maskTextureId,
+ float contentScale,
const ImageDimensions desiredSize,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode,
UseAtlas useAtlas,
+ bool cropToMask,
StorageType storageType,
TextureUploadObserver* observer );
TextureId maskTextureId,
const VisualUrl& url,
ImageDimensions desiredSize,
+ float scaleFactor,
FittingMode::Type fittingMode,
Dali::SamplingMode::Type samplingMode,
bool loadSynchronously,
+ bool cropToMask,
UseAtlas useAtlas,
TextureManager::TextureHash hash )
: url( url ),
textureId( textureId ),
maskTextureId( maskTextureId ),
hash( hash ),
+ scaleFactor( scaleFactor ),
referenceCount( 1u ),
loadState( NOT_STARTED ),
fittingMode( fittingMode ),
samplingMode( samplingMode ),
storageType( UPLOAD_TO_TEXTURE ),
loadSynchronously( loadSynchronously ),
- useAtlas( useAtlas )
+ useAtlas( useAtlas ),
+ cropToMask( cropToMask )
{
}
TextureId textureId; ///< The TextureId associated with this Texture
TextureId maskTextureId; ///< The mask TextureId to be applied on load
TextureManager::TextureHash hash; ///< The hash used to cache this Texture
+ float scaleFactor; ///< The scale factor to apply to the Texture when masking
int16_t referenceCount; ///< The reference count of clients using this Texture
LoadState loadState:3; ///< The load state showing the load progress of the Texture
FittingMode::Type fittingMode:2; ///< The requested FittingMode
StorageType storageType:1; ///< CPU storage / GPU upload;
bool loadSynchronously:1; ///< True if synchronous loading was requested
UseAtlas useAtlas:1; ///< USE_ATLAS if an atlas was requested. This is updated to false if atlas is not used
+ bool cropToMask:1; ///< true if the image should be cropped to the mask size.
};
// Structs:
* Apply the mask to the pixelBuffer.
* @param[in] pixelBuffer The pixelBuffer to apply the mask to
* @param[in] maskTextureId The texture id of the mask.
+ * @param[in] contentScale The factor to scale the content
+ * @param[in] cropToMask Whether to crop the content to the mask size
*/
- void ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId );
+ void ApplyMask( Devel::PixelBuffer& pixelBuffer, TextureId maskTextureId,
+ float contentScale, bool cropToMask );
/**
* Upload the texture specified in pixelBuffer to the appropriate location
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
TextureId maskTextureId );
-
/**
* @brief Looks up a cached texture by its hash.
* If found, the given parameters are used to check there is no hash-collision.
/*
- * 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.
const char * const BATCH_SIZE_NAME("batchSize");
const char * const CACHE_SIZE_NAME("cacheSize");
const char * const FRAME_DELAY_NAME("frameDelay");
+const char * const MASK_CONTENT_SCALE_NAME("maskContentScale");
+const char * const CROP_TO_MASK_NAME("cropToMask");
// Text visual
const char * const TEXT_PROPERTY( "text" );
#define DALI_TOOLKIT_INTERNAL_VISUAL_STRING_CONSTANTS_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.
extern const char * const BATCH_SIZE_NAME;
extern const char * const CACHE_SIZE_NAME;
extern const char * const FRAME_DELAY_NAME;
+extern const char * const MASK_CONTENT_SCALE_NAME;
+extern const char * const CROP_TO_MASK_NAME;
// Text visual
extern const char * const TEXT_PROPERTY;