To prevent scaling quality issues, image visual images are pre-multiplied after loading.
By default, this is on, but it can be turned off via a new API in VisualFactory.
Change-Id: I53757be33894effdd61b719631fb79527e8a4fbe
Signed-off-by: David Steele <david.steele@samsung.com>
DummyVisualPtr DummyVisual::New( const Property::Map& properties )
{
- VisualFactoryCachePtr factoryCache = new VisualFactoryCache;
+ VisualFactoryCachePtr factoryCache = new VisualFactoryCache(false);
DummyVisualPtr dummyVisualPtr( new DummyVisual( *( factoryCache.Get() ) ) );
TextureManager::NO_ATLAS,
&observer,
true,
- TextureManager::ReloadPolicy::CACHED );
+ TextureManager::ReloadPolicy::CACHED,
+ TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY );
const VisualUrl& url = textureManager.GetVisualUrl( textureId );
VisualFactory factory = VisualFactory::Get();
DALI_TEST_CHECK( factory );
+ factory.SetPreMultiplyOnLoad( true );
+
+ Property::Map propertyMap;
+ propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::IMAGE );
+ propertyMap.Insert( ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME );
+
+ Visual::Base visual = factory.CreateVisual( propertyMap );
+ DALI_TEST_CHECK( visual );
+
+ // 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( DummyControl::Property::TEST_VISUAL, visual );
+
+ actor.SetSize( 200.f, 200.f );
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+ Stage::GetCurrent().Add( actor );
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( Test::WaitForEventThreadTrigger( 1 ), true, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+ auto renderer = actor.GetRendererAt(0);
+ auto preMultipliedIndex = renderer.GetPropertyIndex( "preMultipliedAlpha" );
+ DALI_TEST_CHECK( preMultipliedIndex != Property::INVALID_INDEX );
+ auto preMultipliedAlpha = renderer.GetProperty<float>( preMultipliedIndex );
+ auto preMultipliedAlpha2 = renderer.GetProperty<bool>( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+ DALI_TEST_EQUALS( preMultipliedAlpha, 1.0f, TEST_LOCATION );
+ DALI_TEST_EQUALS( preMultipliedAlpha2, true, TEST_LOCATION );
+ DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
+
+ Stage::GetCurrent().Remove( actor );
+ DALI_TEST_CHECK( actor.GetRendererCount() == 0u );
+
+ END_TEST;
+}
+
+
+int UtcDaliImageVisualNoPremultipliedAlpha01(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline( "Request image visual without pre-multiplied alpha" );
+
+ VisualFactory factory = VisualFactory::Get();
+ DALI_TEST_CHECK( factory );
+ factory.SetPreMultiplyOnLoad( false );
Property::Map propertyMap;
propertyMap.Insert( Toolkit::Visual::Property::TYPE, Visual::IMAGE );
application.Render();
DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+ auto renderer = actor.GetRendererAt(0);
+ auto preMultipliedIndex = renderer.GetPropertyIndex( "preMultipliedAlpha" );
+ DALI_TEST_CHECK( preMultipliedIndex != Property::INVALID_INDEX );
+ auto preMultipliedAlpha = renderer.GetProperty<bool>( preMultipliedIndex );
+ auto preMultipliedAlpha2 = renderer.GetProperty<bool>( Renderer::Property::BLEND_PRE_MULTIPLIED_ALPHA );
+
+ DALI_TEST_EQUALS( preMultipliedAlpha, false, TEST_LOCATION );
+ DALI_TEST_EQUALS( preMultipliedAlpha2, false, TEST_LOCATION );
DALI_TEST_EQUALS( textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION );
return GetImplementation( *this ).CreateVisual( url, size );
}
+void VisualFactory::SetPreMultiplyOnLoad( bool preMultiply )
+{
+ GetImplementation( *this ).SetPreMultiplyOnLoad( preMultiply );
+}
+
+bool VisualFactory::GetPreMultiplyOnLoad() const
+{
+ return GetImplementation( *this ).GetPreMultiplyOnLoad();
+}
+
} // namespace Toolkit
} // namespace Dali
*/
Visual::Base CreateVisual( const std::string& url, ImageDimensions size );
+ /**
+ * @brief Enable or disable premultiplying alpha in images and image visuals.
+ *
+ * The default is to enable pre-multiplication on load.
+ *
+ * Applications that have assets with pre-multiplied alpha already applied should
+ * turn this option off.
+ *
+ * @param[in] preMultiply True if loaded images for image visuals should have
+ * alpha multiplied into the color channels.
+ */
+ void SetPreMultiplyOnLoad( bool preMultiply );
+
+ /**
+ * @brief Get the setting for automatically pre-multiplying image visual images
+ * on load.
+ *
+ * @return True if loaded images have pre-multiplied alpha applied on load,
+ * false otherwise.
+ */
+ bool GetPreMultiplyOnLoad() const;
+
private:
explicit DALI_INTERNAL VisualFactory(Internal::VisualFactory *impl);
synchronousLoading, mImageUrls[ mUrlIndex ].mTextureId, textureRect,
atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT,
Dali::WrapMode::Type::DEFAULT, this,
- atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED );
+ atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED,
+ TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY );
if( loadingStatus == false ) // not loading, means it's already ready.
{
synchronousLoading, mImageUrls[ imageFrame.mFrameNumber ].mTextureId, textureRect,
atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT,
Dali::WrapMode::Type::DEFAULT, NULL,
- atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED );
+ atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY );
}
mFrameIndex += batchSize;
synchronousLoading, mImageUrls[ imageFrame.mUrlIndex ].mTextureId, textureRect,
atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT,
Dali::WrapMode::Type::DEFAULT, this,
- atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED );
+ atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED,
+ TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY );
mRequestingLoad = false;
}
//Register transform properties
mImpl->mTransform.RegisterUniforms( mImpl->mRenderer, Direction::LEFT_TO_RIGHT );
+
+ if( IsPreMultipliedAlphaEnabled() )
+ {
+ EnablePreMultipliedAlpha( true );
+ }
}
void ImageVisual::CreateNativeImageRenderer( NativeImage& nativeImage )
atlasUploadObserver = this;
}
+ auto preMultiplyOnLoad = mFactoryCache.GetPreMultiplyOnLoad()
+ ? TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD
+ : TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
+
textures = textureManager.LoadTexture( mImageUrl, mDesiredSize, mFittingMode, mSamplingMode,
mMaskingData, IsSynchronousResourceLoading(), mTextureId,
atlasRect, atlasing, mLoading, mWrapModeU,
mWrapModeV, textureObserver, atlasUploadObserver, atlasManager,
- mOrientationCorrection,
- forceReload );
+ mOrientationCorrection, forceReload, preMultiplyOnLoad);
+
+ if( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
+ {
+ EnablePreMultipliedAlpha( true );
+ }
if( atlasing ) // Flag needs to be set before creating renderer
{
bool& atlasingStatus, bool& loadingStatus, Dali::WrapMode::Type wrapModeU,
Dali::WrapMode::Type wrapModeV, TextureUploadObserver* textureObserver,
AtlasUploadObserver* atlasObserver, ImageAtlasManagerPtr imageAtlasManager, bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy )
+ TextureManager::ReloadPolicy reloadPolicy, TextureManager::MultiplyOnLoad preMultiplyOnLoad )
{
TextureSet textureSet;
orientationCorrection );
if( pixelBuffer )
{
+ if( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD )
+ {
+ pixelBuffer.MultiplyColorByAlpha();
+ }
+
data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
}
}
Devel::PixelBuffer pixelBuffer = LoadImageFromFile( BROKEN_IMAGE_URL );
if( pixelBuffer )
{
+ if( preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD)
+ {
+ pixelBuffer.MultiplyColorByAlpha();
+ }
data = Devel::PixelBuffer::Convert(pixelBuffer); // takes ownership of buffer
}
Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, data.GetPixelFormat(),
if( !maskInfo )
{
textureId = RequestLoad( url, desiredSize, fittingMode, samplingMode, TextureManager::NO_ATLAS,
- textureObserver, orientationCorrection, reloadPolicy );
+ textureObserver, orientationCorrection, reloadPolicy, preMultiplyOnLoad );
}
else
{
maskInfo->mCropToMask,
textureObserver,
orientationCorrection,
- reloadPolicy );
+ reloadPolicy, preMultiplyOnLoad );
}
TextureManager::LoadState loadState = GetTextureStateInternal( textureId );
const UseAtlas useAtlas,
TextureUploadObserver* observer,
bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy )
+ TextureManager::ReloadPolicy reloadPolicy,
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad )
{
return RequestLoadInternal( url, INVALID_TEXTURE_ID, 1.0f, desiredSize, fittingMode, samplingMode, useAtlas,
- false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy );
+ false, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad );
}
TextureManager::TextureId TextureManager::RequestLoad(
bool cropToMask,
TextureUploadObserver* observer,
bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy )
+ TextureManager::ReloadPolicy reloadPolicy,
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad )
{
return RequestLoadInternal( url, maskTextureId, contentScale, desiredSize, fittingMode, samplingMode, useAtlas,
- cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy );
+ cropToMask, UPLOAD_TO_TEXTURE, observer, orientationCorrection, reloadPolicy, preMultiplyOnLoad );
}
TextureManager::TextureId TextureManager::RequestMaskLoad( const VisualUrl& maskUrl )
// Use the normal load procedure to get the alpha mask.
return RequestLoadInternal( maskUrl, INVALID_TEXTURE_ID, 1.0f, ImageDimensions(), FittingMode::SCALE_TO_FILL,
SamplingMode::NO_FILTER, NO_ATLAS, false, KEEP_PIXEL_BUFFER, NULL, true,
- TextureManager::ReloadPolicy::CACHED );
+ TextureManager::ReloadPolicy::CACHED, TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY);
}
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,
- bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy )
+ TextureId maskTextureId,
+ float contentScale,
+ const ImageDimensions desiredSize,
+ FittingMode::Type fittingMode,
+ Dali::SamplingMode::Type samplingMode,
+ UseAtlas useAtlas,
+ bool cropToMask,
+ StorageType storageType,
+ TextureUploadObserver* observer,
+ bool orientationCorrection,
+ TextureManager::ReloadPolicy reloadPolicy,
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad)
{
// First check if the requested Texture is cached.
const TextureHash textureHash = GenerateHash( url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
- maskTextureId );
+ maskTextureId, preMultiplyOnLoad );
TextureManager::TextureId textureId = INVALID_TEXTURE_ID;
// Look up the texture by hash. Note: The extra parameters are used in case of a hash collision.
int cacheIndex = FindCachedTexture( textureHash, url.GetUrl(), desiredSize, fittingMode, samplingMode, useAtlas,
- maskTextureId );
+ maskTextureId, preMultiplyOnLoad );
// Check if the requested Texture exists in the cache.
if( cacheIndex != INVALID_CACHE_INDEX )
textureId = GenerateUniqueTextureId();
mTextureInfoContainer.push_back( TextureInfo( textureId, maskTextureId, url.GetUrl(),
desiredSize, contentScale, fittingMode, samplingMode,
- false, cropToMask, useAtlas, textureHash, orientationCorrection ) );
+ false, cropToMask, useAtlas, textureHash, orientationCorrection, preMultiplyOnLoad ) );
cacheIndex = mTextureInfoContainer.size() - 1u;
DALI_LOG_INFO( gTextureManagerLogFilter, Debug::Concise, "TextureManager::RequestLoad( url=%s observer=%p ) New texture, cacheIndex:%d, textureId=%d\n",
Texture texture = Texture::New( Dali::TextureType::TEXTURE_2D, pixelBuffer.GetPixelFormat(),
pixelBuffer.GetWidth(), pixelBuffer.GetHeight() );
+ if( textureInfo.preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD )
+ {
+ pixelBuffer.MultiplyColorByAlpha();
+ }
+
PixelData pixelData = Devel::PixelBuffer::Convert( pixelBuffer );
texture.Upload( pixelData );
if ( ! textureInfo.textureSet )
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode,
const UseAtlas useAtlas,
- TextureId maskTextureId )
+ TextureId maskTextureId,
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad)
{
std::string hashTarget( url );
const size_t urlLength = hashTarget.length();
if( maskTextureId != INVALID_TEXTURE_ID )
{
- hashTarget.resize( urlLength + sizeof( TextureId ) );
- TextureId* hashTargetPtr = reinterpret_cast<TextureId*>(&( hashTarget[ urlLength ] ));
+ auto textureIdIndex = hashTarget.length();
+ hashTarget.resize( hashTarget.length() + sizeof( TextureId ) );
+ unsigned char* hashTargetPtr = reinterpret_cast<unsigned char*>(&( hashTarget[ textureIdIndex ] ));
- // Append the hash target to the end of the URL byte by byte:
+ // Append the texture id to the end of the URL byte by byte:
// (to avoid SIGBUS / alignment issues)
for( size_t byteIter = 0; byteIter < sizeof( TextureId ); ++byteIter )
{
}
}
+ auto premultipliedIndex = hashTarget.length();
+ hashTarget.resize( premultipliedIndex + 1 );
+ char* preMultPtr = &( hashTarget[ premultipliedIndex ] );
+ *preMultPtr = (preMultiplyOnLoad == TextureManager::MultiplyOnLoad::MULTIPLY_ON_LOAD) ? 't':'f';
+
return Dali::CalculateHash( hashTarget );
}
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
- TextureId maskTextureId)
+ TextureId maskTextureId,
+ TextureManager::MultiplyOnLoad preMultiplyOnLoad )
{
// Default to an invalid ID, in case we do not find a match.
int cacheIndex = INVALID_CACHE_INDEX;
( useAtlas == textureInfo.useAtlas ) &&
( maskTextureId == textureInfo.maskTextureId ) &&
( size == textureInfo.desiredSize ) &&
+ ( preMultiplyOnLoad == textureInfo.preMultiplyOnLoad ) &&
( ( size.GetWidth() == 0 && size.GetHeight() == 0 ) ||
( fittingMode == textureInfo.fittingMode &&
samplingMode == textureInfo.samplingMode ) ) )
}
}
+
TextureManager::AsyncLoadingHelper::AsyncLoadingHelper(TextureManager& textureManager)
: AsyncLoadingHelper(Toolkit::AsyncImageLoader::New(), textureManager,
AsyncLoadingInfoContainerType())
};
/**
- * @breif Types of reloading policies
- */
+ * @brief Types of reloading policies
+ */
enum class ReloadPolicy
{
CACHED = 0, ///< Loads cached texture if it exists.
FORCED ///< Forces reloading of texture.
};
+ /**
+ * @brief Whether to multiply alpha into color channels on load
+ */
+ enum class MultiplyOnLoad
+ {
+ LOAD_WITHOUT_MULTIPLY = 0, ///< Don't modify the image
+ MULTIPLY_ON_LOAD ///< Multiply alpha into color channels on load
+ };
+
public:
struct MaskingData
AtlasUploadObserver* atlasObserver,
ImageAtlasManagerPtr imageAtlasManager,
bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy );
+ TextureManager::ReloadPolicy reloadPolicy,
+ MultiplyOnLoad preMultiplyOnLoad );
/**
* @brief Requests an image load of the given URL.
* This is called when an image load completes (or fails).
* @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
* @param[in] reloadPolicy Forces a reload of the texture even if already cached
+ * @param[in] preMultiplyOnLoad True if the image color should be multiplied by it's alpha
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoad( const VisualUrl& url,
const UseAtlas useAtlasing,
TextureUploadObserver* observer,
bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy );
+ TextureManager::ReloadPolicy reloadPolicy,
+ MultiplyOnLoad preMultiplyOnLoad );
/**
* @brief Requests an image load of the given URL, when the texture has
* This is called when an image load completes (or fails).
* @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
* @param[in] reloadPolicy Forces a reload of the texture even if already cached
+ * @param[in] preMultiplyOnLoad True if the image color should be multiplied by it's alpha
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoad( const VisualUrl& url,
bool cropToMask,
TextureUploadObserver* observer,
bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy );
+ TextureManager::ReloadPolicy reloadPolicy,
+ MultiplyOnLoad preMultiplyOnLoad );
/**
* Requests a masking image to be loaded. This mask is not uploaded to GL,
* This is called when an image load completes (or fails).
* @param[in] orientationCorrection Whether to rotate image to match embedded orientation data
* @param[in] reloadPolicy Forces a reload of the texture even if already cached
+ * @param[in] preMultiplyOnLoad True if the image color should be multiplied by it's alpha
* @return A TextureId to use as a handle to reference this Texture
*/
TextureId RequestLoadInternal(
StorageType storageType,
TextureUploadObserver* observer,
bool orientationCorrection,
- TextureManager::ReloadPolicy reloadPolicy );
+ TextureManager::ReloadPolicy reloadPolicy,
+ MultiplyOnLoad preMultiplyOnLoad );
/**
* @brief Get the current state of a texture
bool cropToMask,
UseAtlas useAtlas,
TextureManager::TextureHash hash,
- bool orientationCorrection )
+ bool orientationCorrection,
+ MultiplyOnLoad preMultiplyOnLoad )
: url( url ),
desiredSize( desiredSize ),
useSize( desiredSize ),
loadSynchronously( loadSynchronously ),
useAtlas( useAtlas ),
cropToMask( cropToMask ),
- orientationCorrection( true )
+ orientationCorrection( true ),
+ preMultiplyOnLoad( preMultiplyOnLoad )
{
}
///< This is updated to false if atlas is not used
bool cropToMask:1; ///< true if the image should be cropped to the mask size.
bool orientationCorrection:1; ///< true if the image should be rotated to match exif orientation data
+ MultiplyOnLoad preMultiplyOnLoad; ///< true if the image's color should be multiplied by it's alpha
};
// Structs:
TextureHash GenerateHash( const std::string& url, const ImageDimensions size,
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode, const UseAtlas useAtlas,
- TextureId maskTextureId );
+ TextureId maskTextureId,
+ MultiplyOnLoad preMultiplyOnLoad);
/**
* @brief Looks up a cached texture by its hash.
* If found, the given parameters are used to check there is no hash-collision.
const FittingMode::Type fittingMode,
const Dali::SamplingMode::Type samplingMode,
const bool useAtlas,
- TextureId maskTextureId );
+ TextureId maskTextureId,
+ MultiplyOnLoad preMultiplyOnLoad);
private:
RoundRobinContainerView< AsyncLoadingHelper > mAsyncRemoteLoaders; ///< The Asynchronous image loaders used to provide all remote async loads
std::vector< ExternalTextureInfo > mExternalTextures; ///< Externally provided textures
TextureId mCurrentTextureId; ///< The current value used for the unique Texture Id generation
-
};
namespace Internal
{
-VisualFactoryCache::VisualFactoryCache()
-: mSvgRasterizeThread( NULL )
+VisualFactoryCache::VisualFactoryCache( bool preMultiplyOnLoad )
+: mSvgRasterizeThread( NULL ),
+ mPreMultiplyOnLoad( preMultiplyOnLoad )
{
}
return ResourceImage::New( BROKEN_VISUAL_IMAGE_URL );
}
+void VisualFactoryCache::SetPreMultiplyOnLoad( bool preMultiply )
+{
+ mPreMultiplyOnLoad = preMultiply;
+}
+
+bool VisualFactoryCache::GetPreMultiplyOnLoad()
+{
+ return mPreMultiplyOnLoad;
+}
+
} // namespace Internal
} // namespace Toolkit
/**
* @brief Constructor
+ *
+ * @param[in] preMultiplyOnLoad True if image visuals should pre-multiply alpha on image load.
*/
- VisualFactoryCache();
+ VisualFactoryCache( bool preMultiplyOnLoad );
/**
* Request geometry of the given type.
*/
static Image GetBrokenVisualImage();
+ /**
+ * @copydoc Toolkit::VisualFactory::SetPreMultiplyOnLoad()
+ */
+ void SetPreMultiplyOnLoad( bool preMultiply );
+
+ /**
+ * @copydoc Toolkit::VisualFactory::GetPreMultiplyOnLoad()
+ */
+ bool GetPreMultiplyOnLoad();
+
public:
/**
* Get the image atlas manager.
TextureManager mTextureManager;
NPatchLoader mNPatchLoader;
SvgRasterizeThread* mSvgRasterizeThread;
+ bool mPreMultiplyOnLoad;
};
} // namespace Internal
} // namespace
VisualFactory::VisualFactory( bool debugEnabled )
-:mDebugEnabled( debugEnabled )
+: mDebugEnabled( debugEnabled ),
+ mPreMultiplyOnLoad( true )
{
}
Toolkit::Visual::Base VisualFactory::CreateVisual( const Property::Map& propertyMap )
{
- // Create factory cache if it hasn't already been
- if( !mFactoryCache )
- {
- mFactoryCache = new VisualFactoryCache();
- }
-
Visual::BasePtr visualPtr;
Property::Value* typeValue = propertyMap.Find( Toolkit::Visual::Property::TYPE, VISUAL_TYPE );
{
case Toolkit::Visual::BORDER:
{
- visualPtr = BorderVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = BorderVisual::New( GetFactoryCache(), propertyMap );
break;
}
case Toolkit::Visual::COLOR:
{
- visualPtr = ColorVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = ColorVisual::New( GetFactoryCache(), propertyMap );
break;
}
case Toolkit::Visual::GRADIENT:
{
- visualPtr = GradientVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = GradientVisual::New( GetFactoryCache(), propertyMap );
break;
}
{
case VisualUrl::N_PATCH:
{
- visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ), visualUrl, propertyMap );
+ visualPtr = NPatchVisual::New( GetFactoryCache(), visualUrl, propertyMap );
break;
}
case VisualUrl::SVG:
{
- visualPtr = SvgVisual::New( *( mFactoryCache.Get() ), visualUrl, propertyMap );
+ visualPtr = SvgVisual::New( GetFactoryCache(), visualUrl, propertyMap );
break;
}
case VisualUrl::GIF:
{
- visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), visualUrl, propertyMap );
+ visualPtr = AnimatedImageVisual::New( GetFactoryCache(), visualUrl, propertyMap );
break;
}
case VisualUrl::REGULAR_IMAGE:
{
- visualPtr = ImageVisual::New( *( mFactoryCache.Get() ), visualUrl, propertyMap );
+ visualPtr = ImageVisual::New( GetFactoryCache(), visualUrl, propertyMap );
break;
}
}
Property::Array* array = imageURLValue->GetArray();
if( array )
{
- visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), *array, propertyMap );
+ visualPtr = AnimatedImageVisual::New( GetFactoryCache(), *array, propertyMap );
}
}
}
case Toolkit::Visual::MESH:
{
- visualPtr = MeshVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = MeshVisual::New( GetFactoryCache(), propertyMap );
break;
}
case Toolkit::Visual::PRIMITIVE:
{
- visualPtr = PrimitiveVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = PrimitiveVisual::New( GetFactoryCache(), propertyMap );
break;
}
case Toolkit::Visual::WIREFRAME:
{
- visualPtr = WireframeVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = WireframeVisual::New( GetFactoryCache(), propertyMap );
break;
}
case Toolkit::Visual::TEXT:
{
- visualPtr = TextVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = TextVisual::New( GetFactoryCache(), propertyMap );
break;
}
std::string imageUrl;
if( imageURLValue && imageURLValue->Get( imageUrl ) )
{
- visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ), imageUrl, propertyMap );
+ visualPtr = NPatchVisual::New( GetFactoryCache(), imageUrl, propertyMap );
}
break;
}
std::string imageUrl;
if( imageURLValue && imageURLValue->Get( imageUrl ) )
{
- visualPtr = SvgVisual::New( *( mFactoryCache.Get() ), imageUrl, propertyMap );
+ visualPtr = SvgVisual::New( GetFactoryCache(), imageUrl, propertyMap );
}
break;
}
{
if( imageURLValue->Get( imageUrl ) )
{
- visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), imageUrl, propertyMap );
+ visualPtr = AnimatedImageVisual::New( GetFactoryCache(), imageUrl, propertyMap );
}
else
{
Property::Array* array = imageURLValue->GetArray();
if( array )
{
- visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), *array, propertyMap );
+ visualPtr = AnimatedImageVisual::New( GetFactoryCache(), *array, propertyMap );
}
}
}
case Toolkit::DevelVisual::ANIMATED_GRADIENT:
{
- visualPtr = AnimatedGradientVisual::New( *( mFactoryCache.Get() ), propertyMap );
+ visualPtr = AnimatedGradientVisual::New( GetFactoryCache(), propertyMap );
break;
}
}
if( mDebugEnabled && visualType != Toolkit::DevelVisual::WIREFRAME )
{
//Create a WireframeVisual if we have debug enabled
- visualPtr = WireframeVisual::New( *( mFactoryCache.Get() ), visualPtr, propertyMap );
+ visualPtr = WireframeVisual::New(GetFactoryCache(), visualPtr, propertyMap );
}
return Toolkit::Visual::Base( visualPtr.Get() );
Toolkit::Visual::Base VisualFactory::CreateVisual( const Image& image )
{
- if( !mFactoryCache )
- {
- mFactoryCache = new VisualFactoryCache();
- }
-
Visual::BasePtr visualPtr;
if( image )
NinePatchImage npatchImage = NinePatchImage::DownCast( image );
if( npatchImage )
{
- visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ), npatchImage );
+ visualPtr = NPatchVisual::New( GetFactoryCache(), npatchImage );
}
else
{
- visualPtr = ImageVisual::New( *( mFactoryCache.Get() ), image );
+ visualPtr = ImageVisual::New(GetFactoryCache(), image );
}
}
if( mDebugEnabled )
{
//Create a WireframeVisual if we have debug enabled
- visualPtr = WireframeVisual::New( *( mFactoryCache.Get() ), visualPtr );
+ visualPtr = WireframeVisual::New( GetFactoryCache(), visualPtr );
}
return Toolkit::Visual::Base( visualPtr.Get() );
Toolkit::Visual::Base VisualFactory::CreateVisual( const std::string& url, ImageDimensions size )
{
- if( !mFactoryCache )
- {
- mFactoryCache = new VisualFactoryCache();
- }
-
Visual::BasePtr visualPtr;
if( !url.empty() )
{
case VisualUrl::N_PATCH:
{
- visualPtr = NPatchVisual::New( *( mFactoryCache.Get() ), visualUrl );
+ visualPtr = NPatchVisual::New( GetFactoryCache(), visualUrl );
break;
}
case VisualUrl::SVG:
{
- visualPtr = SvgVisual::New( *( mFactoryCache.Get() ), visualUrl );
+ visualPtr = SvgVisual::New( GetFactoryCache(), visualUrl );
break;
}
case VisualUrl::GIF:
{
- visualPtr = AnimatedImageVisual::New( *( mFactoryCache.Get() ), visualUrl );
+ visualPtr = AnimatedImageVisual::New( GetFactoryCache(), visualUrl );
break;
}
case VisualUrl::REGULAR_IMAGE:
{
- visualPtr = ImageVisual::New( *( mFactoryCache.Get() ), visualUrl, size );
+ visualPtr = ImageVisual::New(GetFactoryCache(), visualUrl, size );
break;
}
}
if( mDebugEnabled )
{
//Create a WireframeVisual if we have debug enabled
- visualPtr = WireframeVisual::New( *( mFactoryCache.Get() ), visualPtr );
+ visualPtr = WireframeVisual::New( GetFactoryCache(), visualPtr );
}
return Toolkit::Visual::Base( visualPtr.Get() );
}
+void VisualFactory::SetPreMultiplyOnLoad( bool preMultiply )
+{
+ if( mPreMultiplyOnLoad != preMultiply )
+ {
+ GetFactoryCache().SetPreMultiplyOnLoad( preMultiply );
+ }
+ mPreMultiplyOnLoad = preMultiply;
+}
+
+bool VisualFactory::GetPreMultiplyOnLoad() const
+{
+ return mPreMultiplyOnLoad;
+}
+
Internal::TextureManager& VisualFactory::GetTextureManager()
{
+ return GetFactoryCache().GetTextureManager();
+}
+
+Internal::VisualFactoryCache& VisualFactory::GetFactoryCache()
+{
if( !mFactoryCache )
{
- mFactoryCache = new VisualFactoryCache();
+ mFactoryCache = new VisualFactoryCache( mPreMultiplyOnLoad );
}
- return mFactoryCache->GetTextureManager();
+ return *(mFactoryCache.Get());
}
} // namespace Internal
VisualFactory( bool debugEnabled );
/**
- * @copydoc Toolkit::RenderFactory::CreateVisual( const Property::Map& )
+ * @copydoc Toolkit::VisualFactory::CreateVisual( const Property::Map& )
*/
Toolkit::Visual::Base CreateVisual( const Property::Map& propertyMap );
/**
- * @copydoc Toolkit::RenderFactory::CreateVisual( const Image& )
+ * @copydoc Toolkit::VisualFactory::CreateVisual( const Image& )
*/
Toolkit::Visual::Base CreateVisual( const Image& image );
/**
- * @copydoc Toolkit::RenderFactory::CreateVisual( const std::string&, ImageDimensions )
+ * @copydoc Toolkit::VisualFactory::CreateVisual( const std::string&, ImageDimensions )
*/
Toolkit::Visual::Base CreateVisual( const std::string& image, ImageDimensions size );
/**
+ * @copydoc Toolkit::VisualFactory::SetPreMultiplyOnLoad()
+ */
+ void SetPreMultiplyOnLoad( bool preMultiply );
+
+ /**
+ * @copydoc Toolkit::VisualFactory::GetPreMultiplyOnLoad()
+ */
+ bool GetPreMultiplyOnLoad() const;
+
+ /**
* @return the reference to texture manager
*/
Internal::TextureManager& GetTextureManager();
virtual ~VisualFactory();
private:
-
/**
- * Undefined copy constructor.
+ * Get the factory cache, creating it if necessary.
*/
- VisualFactory(const VisualFactory&);
+ Internal::VisualFactoryCache& GetFactoryCache();
- /**
- * Undefined assignment operator.
- */
- VisualFactory& operator=(const VisualFactory& rhs);
+ VisualFactory(const VisualFactory&) = delete;
+
+ VisualFactory& operator=(const VisualFactory& rhs) = delete;
private:
VisualFactoryCachePtr mFactoryCache;
- bool mDebugEnabled;
+ bool mDebugEnabled:1;
+ bool mPreMultiplyOnLoad:1; ///< Local store for this flag ( as mFactoryCache is lazy laoded )
};
/**