// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/common/constants.h>
#include <dali/internal/event/common/thread-local-storage.h>
return ticket;
}
-const std::string& ImageFactory::GetRequestPath( const Request* request ) const
+const std::string& ImageFactory::GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const
{
if( request )
{
return String::EMPTY;
}
-const ImageAttributes& ImageFactory::GetActualAttributes( ResourceId resourceId ) const
+const ImageAttributes& ImageFactory::GetActualAttributes( const ResourceTicketPtr& ticket ) const
{
- DALI_ASSERT_DEBUG( resourceId );
-
- ResourceTicketPtr ticket = mResourceClient.RequestResourceTicket( resourceId );
if( ticket )
{
DALI_ASSERT_DEBUG( ticket->GetTypePath().type->id == ResourceBitmap ||
const ImageAttributes& attrib = static_cast<ImageTicket*>(ticket.Get())->GetAttributes();
return attrib;
}
-
- DALI_ASSERT_DEBUG( 0 && "Resource no longer exists in cache" );
return ImageAttributes::DEFAULT_ATTRIBUTES;
}
-const ImageAttributes& ImageFactory::GetRequestAttributes( const Request* request ) const
+const ImageAttributes& ImageFactory::GetRequestAttributes( const ImageFactoryCache::RequestPtr& request ) const
{
if( request && request->attributes )
{
return ImageAttributes::DEFAULT_ATTRIBUTES;
}
+void ImageFactory::GetImageSize( const ImageFactoryCache::RequestPtr& request, const ResourceTicketPtr& ticket, Size& size )
+{
+ if( ticket && ticket->GetLoadingState() != ResourceLoading )
+ {
+ // it is loaded so get the size from actual attributes
+ size = GetActualAttributes( ticket ).GetSize();
+ }
+ else
+ {
+ // not loaded so either loading or not yet loaded, ask platform abstraction
+ Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+ platformAbstraction.GetClosestImageSize( GetRequestPath( request ), GetRequestAttributes( request ), size );
+ }
+}
+
void ImageFactory::ReleaseTicket( ResourceTicket* ticket )
{
ResourceTicketPtr ticketPtr(ticket);
/**
* Get resource path used in request.
- * @param [in] req request pointer
+ * @param [in] request of the image
* @return resource path
*/
- const std::string& GetRequestPath( const ImageFactoryCache::Request* req ) const;
+ const std::string& GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const;
/**
* Get ImageAttributes for an already requested image resource.
* @pre id should mark an existing Resource (Ticket is alive)
- * @param [in] id resource id
+ * @param [in] ticket of the image
* @return ImageAttributes used for request.
* @throws Throws exception if id is not valid.
*/
- const ImageAttributes& GetActualAttributes( ResourceId id ) const;
+ const ImageAttributes& GetActualAttributes( const ResourceTicketPtr& ticket ) const;
/**
* Get ImageAttributes used for request.
* @pre req must point to a Request registered with ImageFactory
- * @param [in] req request pointer
+ * @param [in] request of the image
* @return ImageAttributes used for request.
*/
- const ImageAttributes& GetRequestAttributes( const ImageFactoryCache::Request* req ) const;
+ const ImageAttributes& GetRequestAttributes( const ImageFactoryCache::RequestPtr& request ) const;
+
+ /**
+ * Retrieve the size of an image. This is either the application requested size or
+ * the actual (full size) that is or will be loaded.
+ * @param[in] request of the image
+ * @param[in] ticket of the image
+ * @param[out] size of the image
+ */
+ void GetImageSize( const ImageFactoryCache::RequestPtr& request, const ResourceTicketPtr& ticket, Size& size );
/**
* Prevents releasing and reloading image resources in the same frame
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/object/type-registry.h>
-#include <dali/integration-api/platform-abstraction.h>
#include <dali/integration-api/debug.h>
#include <dali/internal/event/resources/resource-ticket.h>
#include <dali/internal/event/common/thread-local-storage.h>
Dali::SignalConnectorType signalConnector1(mType, Dali::Image::SIGNAL_IMAGE_LOADING_FINISHED, &Image::DoConnectSignal);
Dali::SignalConnectorType signalConnector2(mType, Dali::Image::SIGNAL_IMAGE_UPLOADED, &Image::DoConnectSignal);
+
}
Image::Image( LoadPolicy loadPol, ReleasePolicy releasePol )
-: mWidth(0),
+: mImageFactory(ThreadLocalStorage::Get().GetImageFactory()),
+ mWidth(0),
mHeight(0),
- mLoadPolicy(loadPol),
- mReleasePolicy(releasePol),
mConnectionCount(0),
- mImageFactory(ThreadLocalStorage::Get().GetImageFactory())
+ mLoadPolicy(loadPol),
+ mReleasePolicy(releasePol)
{
}
image = new Image( loadPol, releasePol );
image->Initialize();
- // if the attributes have a size, use that as natural size, otherwise get the size
- const unsigned int width = attributes.GetWidth();
- const unsigned int height = attributes.GetHeight();
- // if one is zero, then there is some scaling calculation so we have to ask the loading logic what it will do
- if( width > 0 && height > 0 )
- {
- image->mWidth = width;
- image->mHeight = height;
- image->mRequest = image->mImageFactory.RegisterRequest( filename, &attributes );
- }
- else
- {
- // TODO do this query only if/when its needed (if someone is calling GetSize)
- Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
- Vector2 closestSize;
- platformAbstraction.GetClosestImageSize( filename, attributes, closestSize );
- image->mWidth = closestSize.width;
- image->mHeight = closestSize.height;
- // need a new request object as we will request for the closest size
- Dali::ImageAttributes newAttributes( attributes );
- newAttributes.SetSize( closestSize );
- image->mRequest = image->mImageFactory.RegisterRequest( filename, &newAttributes );
- }
+ // consider the requested size as natural size, 0 means we don't (yet) know it
+ image->mWidth = attributes.GetWidth();
+ image->mHeight = attributes.GetHeight();
+ image->mRequest = image->mImageFactory.RegisterRequest( filename, &attributes );
if( Dali::Image::Immediate == loadPol )
{
- // Trigger loading of the image on a seperate resource thread as soon as it
- // can be scheduled:
+ // Trigger loading of the image on a as soon as it can be done
image->mTicket = image->mImageFactory.Load( image->mRequest.Get() );
image->mTicket->AddObserver( *image );
}
{
if( mTicket )
{
- return mImageFactory.GetActualAttributes( mTicket->GetId() );
+ return mImageFactory.GetActualAttributes( mTicket );
}
else
{
- return mImageFactory.GetRequestAttributes( mRequest.Get() );
+ return mImageFactory.GetRequestAttributes( mRequest );
}
}
const std::string& Image::GetFilename() const
{
- return mImageFactory.GetRequestPath( mRequest.Get() );
+ return mImageFactory.GetRequestPath( mRequest );
}
void Image::Reload()
unsigned int Image::GetWidth() const
{
+ // if width is 0, it means we've not yet loaded the image
+ if( 0u == mWidth )
+ {
+ Size size;
+ mImageFactory.GetImageSize( mRequest, mTicket, size );
+ mWidth = size.width;
+ }
return mWidth;
}
unsigned int Image::GetHeight() const
{
+ if( 0u == mHeight )
+ {
+ Size size;
+ mImageFactory.GetImageSize( mRequest, mTicket, size );
+ mHeight = size.height;
+ }
return mHeight;
}
Vector2 Image::GetNaturalSize() const
{
Vector2 naturalSize(mWidth, mHeight);
+ if( 0u == mWidth || 0u == mHeight )
+ {
+ mImageFactory.GetImageSize( mRequest, mTicket, naturalSize );
+ mWidth = naturalSize.width;
+ mHeight = naturalSize.height;
+ }
return naturalSize;
}
}
}
-bool Image::IsNinePatchFileName( std::string filename )
+bool Image::IsNinePatchFileName( const std::string& filename )
{
bool match = false;
virtual void Disconnect();
protected:
+
/**
* Second stage initialization
*/
* @param[in] filename The filename to check
* @return true if it is a 9 patch image
*/
- static bool IsNinePatchFileName( std::string filename );
+ static bool IsNinePatchFileName( const std::string& filename );
+protected: //@TODO these should not be protected
-protected:
- unsigned int mWidth;
- unsigned int mHeight;
+ ImageFactory& mImageFactory;
+
+ ImageFactoryCache::RequestPtr mRequest; ///< contains the initially requested attributes for image. Request is reissued when memory was released.
+ ResourceTicketPtr mTicket; ///< smart pointer to the ticket object that gets completed when load finishes
- ResourceTicketPtr mTicket;
- ImageFactoryCache::RequestPtr mRequest; ///< contains the initially requested attributes for image. Request is reissued when memory was released.
- LoadPolicy mLoadPolicy;
- ReleasePolicy mReleasePolicy;
+ mutable unsigned int mWidth; ///< natural width of the image, needs to be mutable for lazy resolving and as the API for GetWidth is const
+ mutable unsigned int mHeight; ///< natural height of the image, needs to be mutable for lazy resolving and as the API for GetHeight is const
unsigned int mConnectionCount; ///< number of on-stage objects using this image
- ImageFactory& mImageFactory;
+
+ LoadPolicy mLoadPolicy:2; ///< 2 bits is enough space
+ ReleasePolicy mReleasePolicy:2; ///< 2 bits is enough space
private:
+
Dali::Image::ImageSignalV2 mLoadingFinishedV2;
Dali::Image::ImageSignalV2 mUploadedV2;