#include <dali/integration-api/platform-abstraction.h>
#include <dali/integration-api/glyph-set.h>
+#include <dali/integration-api/resource-cache.h>
+#include <dali/integration-api/resource-types.h>
#include <test-trace-call-stack.h>
namespace Dali
mRequest = new Integration::ResourceRequest(request);
}
+ virtual Integration::ResourcePointer LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath)
+ {
+ mTrace.PushCall("LoadResourceSynchronously", "");
+ return mResources.loadedResource;
+ }
+
/**
* @copydoc PlatformAbstraction::SaveResource()
*/
virtual void LoadResource(const ResourceRequest& request) = 0;
/**
+ * Request a resource from the native filesystem. This is a synchronous request, i.e.
+ * it will block the main loop whilst executing. It should therefore be used sparingly.
+ *
+ * Multi-threading note: this method will be called from the main thread only i.e. not
+ * from within the Core::Render() method.
+ * @param[in] resourceType The type of resource to load
+ * @param[in] resourcePath The path to the resource
+ * @return A pointer to a ref-counted resource
+ */
+ virtual ResourcePointer LoadResourceSynchronously( const ResourceType& resourceType, const std::string& resourcePath ) = 0;
+
+ /**
* Request that a resource be saved to the native filesystem.
* This is an asynchronous request.
*/
namespace Integration
{
-typedef IntrusivePtr<Dali::RefObject> ResourcePointer;
-
/**
* Used to determine why a resource IO operation has failed.
*/
#include <dali/internal/event/actors/image-actor-impl.h>
// INTERNAL INCLUDES
+#include <dali/internal/event/images/nine-patch-image-impl.h>
#include <dali/public-api/object/type-registry.h>
#include <dali/internal/event/common/property-index-ranges.h>
#include <dali/internal/event/images/image-connector.h>
}
}
-ImageActorPtr ImageActor::New( Image* image )
+ImageActorPtr ImageActor::New( Image* anImage )
{
ImageActorPtr actor( new ImageActor() );
+ ImagePtr theImage( anImage );
// Second-phase construction
actor->Initialize();
+ NinePatchImage* ninePatchImage = NULL;
+
+ // Automatically convert upcasted nine-patch images to cropped bitmap
+ ninePatchImage = NinePatchImage::GetNinePatchImage( anImage );
+
+ if( ninePatchImage != NULL )
+ {
+ theImage = ninePatchImage->CreateCroppedBitmapImage();
+ }
// Create the attachment
- actor->mImageAttachment = ImageAttachment::New( *actor->mNode, image );
+ actor->mImageAttachment = ImageAttachment::New( *actor->mNode, theImage.Get() );
actor->Attach( *actor->mImageAttachment );
// Adjust the actor's size
- if( image )
+ if( theImage )
{
- actor->mImageNext.Set( image, false );
- actor->OnImageSet( *image );
- actor->SetNaturalSize( *image );
+ actor->mImageNext.Set( theImage.Get(), false );
+ actor->OnImageSet( *theImage );
+ actor->SetNaturalSize( *theImage );
+ }
+
+ if( ninePatchImage != NULL )
+ {
+ actor->SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
+ Vector4 border = ninePatchImage->GetStretchBorders();
+ actor->SetNinePatchBorder( border, true );
}
return actor;
}
+
ImageActorPtr ImageActor::New( Image* image, const PixelArea& pixelArea )
{
// re-use basic New
#include <dali/internal/event/actors/renderable-actor-impl.h>
#include <dali/internal/event/actor-attachments/image-attachment-impl.h>
#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
namespace Dali
{
typedef Dali::ImageActor::PixelArea PixelArea;
/**
- * Create an initialised image actor.
+ * @brief Create an initialised image actor.
* When the image is loaded the actors size will reset to the image size,
* unless a custom size chosen via Actor:SetSize().
- * @param [in] image A pointer to the image object to display or NULL not to display anything.
+ * @param[in] image A pointer to the image object to display or NULL not to display anything.
* @return A smart-pointer to a newly allocated image actor.
*/
static ImageActorPtr New( Image* image );
/**
- * Create an initialised image actor
+ * @brief Create an initialised image actor.
* When the image is loaded the actors size will reset to the image size,
* unless a custom size chosen via Actor:SetSize().
* @param [in] image A pointer to the image object to display or NULL not to display anything.
namespace Internal
{
-
-BitmapImagePtr BitmapImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, LoadPolicy loadPol, ReleasePolicy releasePol )
+BitmapImage* BitmapImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, LoadPolicy loadPol, ReleasePolicy releasePol )
{
- Internal::BitmapImagePtr internal( new BitmapImage( width, height, pixelformat, loadPol, releasePol ) );
+ BitmapImage* internal = new BitmapImage( width, height, pixelformat, loadPol, releasePol );
internal->Initialize();
-
return internal;
}
-BitmapImagePtr BitmapImage::New( PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol )
+BitmapImage* BitmapImage::New( PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol )
{
- Internal::BitmapImagePtr internal( new BitmapImage( pixBuf, width, height, pixelformat, stride, releasePol ) );
-
+ BitmapImage* internal = new BitmapImage( pixBuf, width, height, pixelformat, stride, releasePol );
+ internal->Initialize();
return internal;
}
void BitmapImage::Initialize()
{
ThreadLocalStorage& tls = ThreadLocalStorage::Get();
- mUpdateManager = &tls.GetUpdateManager();
mResourceClient = &tls.GetResourceClient();
}
class ResourceClient;
class ResourceManager;
-namespace SceneGraph
-{
-class UpdateManager;
-}
/**
* BitmapImage represents an image resource that can be added to actors etc.
* Its pixel buffer data is provided by the application developer.
* @param [in] loadPol controls time of loading a resource from the filesystem (default: load when Image is created).
* @param [in] releasePol optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
*/
- static BitmapImagePtr New(unsigned int width,
- unsigned int height,
- Pixel::Format pixelformat,
- LoadPolicy loadPol=ImageLoadPolicyDefault,
- ReleasePolicy releasePol=ImageReleasePolicyDefault);
+ static BitmapImage* New( unsigned int width,
+ unsigned int height,
+ Pixel::Format pixelformat,
+ LoadPolicy loadPol=ImageLoadPolicyDefault,
+ ReleasePolicy releasePol=ImageReleasePolicyDefault);
/**
* Create a new BitmapImage, which uses external data source.
* @param [in] stride the internal stride of the pixelbuffer in pixels
* @param [in] releasePol optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
*/
- static BitmapImagePtr New(PixelBuffer* pixBuf,
- unsigned int width,
- unsigned int height,
- Pixel::Format pixelformat,
- unsigned int stride,
- ReleasePolicy releasePol=ImageReleasePolicyDefault);
-
+ static BitmapImage* New( PixelBuffer* pixBuf,
+ unsigned int width,
+ unsigned int height,
+ Pixel::Format pixelformat,
+ unsigned int stride,
+ ReleasePolicy releasePol=ImageReleasePolicyDefault );
/**
* Create a new BitmapImage.
Integration::Bitmap * GetBitmap() const;
private:
-
bool mIsDataExternal; ///< whether application holds ownership of pixel buffer or not
ResourceClient* mResourceClient;
- SceneGraph::UpdateManager* mUpdateManager;
+
+protected:
Integration::BitmapPtr mBitmapCached;
};
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/resources/resource-client.h>
#include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
#include <dali/internal/event/common/stage-impl.h>
using namespace Dali::Integration;
Image* Image::New( const std::string& filename, const Dali::ImageAttributes& attributes, LoadPolicy loadPol, ReleasePolicy releasePol )
{
- Image* image = new Image( loadPol, releasePol );
-
- if( ! filename.empty() )
+ if( IsNinePatchFileName(filename) )
{
- Vector2 closestSize;
-
- Internal::ThreadLocalStorage::Get().GetPlatformAbstraction().GetClosestImageSize( filename, attributes, closestSize );
- image->mWidth = closestSize.width;
- image->mHeight = closestSize.height;
+ NinePatchImage* image = new NinePatchImage( filename, attributes, loadPol, releasePol );
+ return image;
}
+ else
+ {
+ Image* image = new Image( loadPol, releasePol );
- image->mRequest = image->mImageFactory.RegisterRequest( filename, &attributes );
+ if( ! filename.empty() )
+ {
+ Vector2 closestSize;
- if( Dali::Image::Immediate == loadPol )
- {
- // Trigger loading of the image on a seperate resource thread as soon as it
- // can be scheduled:
- image->mTicket = image->mImageFactory.Load( image->mRequest.Get() );
- image->mTicket->AddObserver( *image );
- }
- // else lazily load image data later, only when it is needed to draw something:
+ Internal::ThreadLocalStorage::Get().GetPlatformAbstraction().GetClosestImageSize( filename, attributes, closestSize );
+ image->mWidth = closestSize.width;
+ image->mHeight = closestSize.height;
+ }
- DALI_LOG_SET_OBJECT_STRING( image, filename );
+ image->mRequest = image->mImageFactory.RegisterRequest( filename, &attributes );
- return image;
+ if( Dali::Image::Immediate == loadPol )
+ {
+ // Trigger loading of the image on a seperate resource thread as soon as it
+ // can be scheduled:
+ image->mTicket = image->mImageFactory.Load( image->mRequest.Get() );
+ image->mTicket->AddObserver( *image );
+ }
+ // else lazily load image data later, only when it is needed to draw something:
+
+ DALI_LOG_SET_OBJECT_STRING( image, filename );
+
+ return image;
+ }
}
Image* Image::New( NativeImage& nativeImg, LoadPolicy loadPol, ReleasePolicy releasePol )
}
}
+bool Image::IsNinePatchFileName( std::string filename )
+{
+ bool match = false;
+
+ std::string::const_iterator iter = filename.end();
+ iter--;
+ enum { SUFFIX, HASH, HASH_DOT, DONE } state = SUFFIX;
+ while(iter >= filename.begin() && state != DONE)
+ {
+ switch(state)
+ {
+ case SUFFIX:
+ {
+ if(*iter == '.')
+ {
+ state = HASH;
+ }
+ else if(!isalnum(*iter))
+ {
+ state = DONE;
+ }
+ }
+ break;
+ case HASH:
+ {
+ if( *iter == '#' || *iter == '9' )
+ {
+ state = HASH_DOT;
+ }
+ else
+ {
+ state = DONE;
+ }
+ }
+ break;
+ case HASH_DOT:
+ {
+ if(*iter == '.')
+ {
+ state = DONE;
+ match = true;
+ }
+ }
+ break;
+ case DONE:
+ {
+ }
+ break;
+ }
+ iter--;
+ }
+ return match;
+}
+
+
} // namespace Internal
} // namespace Dali
*/
void SetTicket( ResourceTicket* ticket );
+ /**
+ * Helper method to determine if the filename indicates that the image has a 9 patch border.
+ * @param[in] filename The filename to check
+ * @return true if it is a 9 patch image
+ */
+ static bool IsNinePatchFileName( std::string filename );
+
+
protected:
unsigned int mWidth;
unsigned int mHeight;
--- /dev/null
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// CLASS HEADER
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+#include <dali/internal/event/images/bitmap-external.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/event/images/image-factory.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/resource-types.h>
+#include <dali/integration-api/resource-cache.h>
+
+
+namespace
+{
+void GetRedOffsetAndMask(Dali::Pixel::Format pixelFormat, int& byteOffset, int& bitMask)
+{
+ switch (pixelFormat)
+ {
+ case Dali::Pixel::A8:
+ case Dali::Pixel::L8:
+ case Dali::Pixel::LA88:
+ {
+ byteOffset=0;
+ bitMask=0;
+ break;
+ }
+
+ case Dali::Pixel::RGB888:
+ case Dali::Pixel::RGB8888:
+ case Dali::Pixel::RGBA8888:
+ {
+ byteOffset=0;
+ bitMask=0xFF;
+ break;
+ }
+ case Dali::Pixel::BGR8888:
+ case Dali::Pixel::BGRA8888:
+ {
+ byteOffset=2;
+ bitMask=0xff;
+ break;
+ }
+ case Dali::Pixel::RGB565:
+ {
+ byteOffset=0;
+ bitMask=0xf8;
+ break;
+ }
+ case Dali::Pixel::BGR565:
+ {
+ byteOffset=1;
+ bitMask=0x1f;
+ break;
+ }
+
+ case Dali::Pixel::RGBA4444:
+ {
+ byteOffset=0;
+ bitMask=0xf0;
+ break;
+ }
+ case Dali::Pixel::BGRA4444:
+ {
+ byteOffset=1;
+ bitMask=0xf0;
+ break;
+ }
+
+ case Dali::Pixel::RGBA5551:
+ {
+ byteOffset=0;
+ bitMask=0xf8;
+ break;
+ }
+
+ case Dali::Pixel::BGRA5551:
+ {
+ byteOffset=1;
+ bitMask=0x1e;
+ break;
+ }
+
+ case Dali::Pixel::COMPRESSED_R11_EAC:
+ case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
+ case Dali::Pixel::COMPRESSED_RG11_EAC:
+ case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
+ case Dali::Pixel::COMPRESSED_RGB8_ETC2:
+ case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
+ case Dali::Pixel::COMPRESSED_RGB8_ETC1:
+ case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
+ case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
+ byteOffset=0;
+ bitMask=0;
+ break;
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+namespace Dali
+{
+namespace Internal
+{
+
+
+NinePatchImagePtr NinePatchImage::New( const std::string& filename, const Dali::ImageAttributes& attributes, LoadPolicy loadPol, ReleasePolicy releasePol )
+{
+ Internal::NinePatchImagePtr internal( new NinePatchImage( filename, attributes, loadPol, releasePol ) );
+ internal->Initialize();
+ return internal;
+}
+
+NinePatchImage::NinePatchImage( const std::string& filename, const Dali::ImageAttributes& attributes, LoadPolicy loadPol, ReleasePolicy releasePol)
+: Image(Dali::Image::Immediate, Dali::Image::Never),
+ mParsedBorder(false)
+{
+ Initialize();
+
+ Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+
+ Vector2 closestSize;
+ platformAbstraction.GetClosestImageSize( filename, attributes, closestSize );
+ ImageAttributes loadedAttrs;
+ loadedAttrs.SetSize( closestSize );
+ mWidth = closestSize.width;
+ mHeight = closestSize.height;
+ Integration::BitmapResourceType resourceType( loadedAttrs );
+
+ // Note, bitmap is only destroyed when the image is destroyed.
+ Integration::ResourcePointer resource = platformAbstraction.LoadResourceSynchronously(resourceType, filename);
+ mBitmap = static_cast<Integration::Bitmap*>( resource.Get());
+}
+
+NinePatchImage* NinePatchImage::GetNinePatchImage( Image* image)
+{
+ return dynamic_cast<NinePatchImage*>(image);
+}
+
+NinePatchImage::~NinePatchImage()
+{
+}
+
+Vector4 NinePatchImage::GetStretchBorders()
+{
+ if( ! mParsedBorder )
+ {
+ ParseBorders();
+ }
+ return mStretchBorders;
+}
+
+Rect<int> NinePatchImage::GetChildRectangle()
+{
+ if( ! mParsedBorder )
+ {
+ ParseBorders();
+ }
+ return mChildRectangle;
+}
+
+Internal::BitmapImagePtr NinePatchImage::CreateCroppedBitmapImage()
+{
+ Pixel::Format pixelFormat = mBitmap->GetPixelFormat();
+
+ BitmapImagePtr cropped = BitmapImage::New( mWidth-2, mHeight-2, pixelFormat,
+ Dali::Image::Immediate, Dali::Image::Never );
+
+ Integration::Bitmap::PackedPixelsProfile* srcProfile = mBitmap->GetPackedPixelsProfile();
+ DALI_ASSERT_DEBUG( srcProfile && "Wrong profile for source bitmap");
+
+ if( srcProfile )
+ {
+ PixelBuffer* destPixels = cropped->GetBuffer();
+ unsigned int destStride = cropped->GetBufferStride();
+ unsigned int pixelWidth = GetBytesPerPixel(pixelFormat);
+
+ PixelBuffer* srcPixels = mBitmap->GetBuffer();
+ unsigned int srcStride = srcProfile->GetBufferStride();
+
+ for( unsigned int row=1; row < mHeight-1; ++row )
+ {
+ PixelBuffer* src = srcPixels + row*srcStride + pixelWidth;
+ PixelBuffer* dest = destPixels + (row-1)*destStride;
+ memcpy(dest, src, destStride );
+ }
+ }
+
+ RectArea area;
+ cropped->Update(area); // default area has no width or height
+ return cropped;
+}
+
+void NinePatchImage::Initialize()
+{
+ ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+ mResourceClient = &tls.GetResourceClient();
+}
+
+void NinePatchImage::Connect()
+{
+ if( mConnectionCount == 0 && !mTicket )
+ {
+ const ImageTicketPtr& t = mResourceClient->AddBitmapImage(mBitmap.Get());
+ mTicket = t.Get();
+ mTicket->AddObserver(*this);
+ }
+
+ ++mConnectionCount;
+}
+
+void NinePatchImage::Disconnect()
+{
+ if( mConnectionCount > 0 )
+ {
+ --mConnectionCount;
+ }
+}
+
+
+void NinePatchImage::ParseBorders()
+{
+ Pixel::Format pixelFormat = mBitmap->GetPixelFormat();
+
+ Integration::Bitmap::PackedPixelsProfile* srcProfile = mBitmap->GetPackedPixelsProfile();
+ DALI_ASSERT_DEBUG( srcProfile && "Wrong profile for source bitmap");
+
+ if( srcProfile )
+ {
+ unsigned int pixelWidth = GetBytesPerPixel(pixelFormat);
+ PixelBuffer* srcPixels = mBitmap->GetBuffer();
+ unsigned int srcStride = srcProfile->GetBufferStride();
+
+ int alphaByte=0;
+ int alphaBits=0;
+ Pixel::GetAlphaOffsetAndMask(pixelFormat, alphaByte, alphaBits);
+ int redByte=0;
+ int redBits=0;
+ GetRedOffsetAndMask(pixelFormat, redByte, redBits);
+
+ int testByte = alphaByte;
+ int testBits = alphaBits;
+ int testValue = alphaBits; // Opaque == stretch
+ if( ! alphaBits )
+ {
+ testByte = redByte;
+ testBits = redBits;
+ testValue = 0; // Black == stretch
+ }
+
+ int startX1=-1;
+ int endX1=-1;
+ int startY1=-1;
+ int endY1=-1;
+ int startX2=-1;
+ int endX2=-1;
+ int startY2=-1;
+ int endY2=-1;
+
+ PixelBuffer* top = srcPixels + pixelWidth;
+ PixelBuffer* bottom = srcPixels + (mHeight-1)*srcStride + pixelWidth;
+
+ // Read the top and bottom rows:
+ // (Also read the last column to ensure end value gets set)
+ for( unsigned int col=1; col < mWidth; ++col )
+ {
+ if( (top[testByte] & testBits) == testValue )
+ {
+ if(startX1 < 0)
+ {
+ startX1 = col;
+ }
+ }
+ else if(startX1 >= 0 && endX1 < 0)
+ {
+ endX1 = col-1;
+ break;
+ }
+
+ if( (bottom[testByte] & testBits) == testValue )
+ {
+ if(startX2 < 0)
+ {
+ startX2 = col;
+ }
+ }
+ else if(startX2 >= 0 && endX2 < 0)
+ {
+ endX2 = col-1;
+ break;
+ }
+ top+=pixelWidth;
+ bottom+=pixelWidth;
+ }
+
+ // Read the left and right columns:
+ PixelBuffer* left = srcPixels + srcStride;
+ PixelBuffer* right = left + (srcStride - pixelWidth);
+
+ // (Also read the last row to ensure end value gets set)
+ for( unsigned int row=1; row < mHeight; ++row )
+ {
+ if((left[testByte] & testBits) == testValue)
+ {
+ if(startY1 < 0)
+ {
+ startY1 = row;
+ }
+ }
+ else if(startY1 >= 0 && endY1 < 0)
+ {
+ endY1 = row-1;
+ break;
+ }
+
+ if((right[testByte] & testBits) == testValue)
+ {
+ if(startY2 < 0)
+ {
+ startY2 = row;
+ }
+ }
+ else if(startY2 >= 0 && endY2 < 0)
+ {
+ endY2 = row-1;
+ break;
+ }
+ left += srcStride;
+ right += srcStride;
+ }
+
+ mStretchBorders.x = startX1-1;
+ mStretchBorders.y = startY1-1;
+ mStretchBorders.z = mWidth-endX1-1;
+ mStretchBorders.w = mHeight-endY1-1;
+
+ mChildRectangle.x = startX2-1;
+ mChildRectangle.y = startY2-1;
+ mChildRectangle.width = endX2-startX2;
+ mChildRectangle.height = endY2-startY2;
+
+ mParsedBorder = true;
+ }
+}
+
+} // namespace Internal
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_INTERNAL_NINE_PATCH_IMAGE_H__
+#define __DALI_INTERNAL_NINE_PATCH_IMAGE_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/nine-patch-image.h>
+#include <dali/internal/event/images/bitmap-image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class NinePatchImage;
+typedef IntrusivePtr<NinePatchImage> NinePatchImagePtr;
+
+class ResourceClient;
+class ResourceManager;
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+/**
+ * NinePatchImage represents an image resource that can be added to actors etc.
+ * It's image data has a border which determines stretch and fill areas
+ * Its pixel buffer data is loaded synchronously from file.
+ */
+class NinePatchImage : public Image
+{
+public:
+
+ /**
+ * Create a new NinePatchImage.
+ * Also a pixel buffer for image data is allocated.
+ * Dali has ownership of the buffer.
+ * @param [in] filename File to load synchronously into buffer
+ * @param [in] attributes Image attributes of the file
+ * @param [in] loadPol controls time of loading a resource from the filesystem (default: load when Image is created).
+ * @param [in] releasePol optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+ */
+ static NinePatchImagePtr New( const std::string& filename,
+ const ImageAttributes& attributes,
+ LoadPolicy loadPol = ImageLoadPolicyDefault,
+ ReleasePolicy releasePol = ImageReleasePolicyDefault );
+
+ /**
+ * Create a new NinePatchImage
+ * For better performance and portability use power of two dimensions.
+ * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+ * @param [in] filename File to load synchronously into buffer
+ * @param [in] attributes Image attributes of the file
+ * @param [in] loadPol controls time of loading a resource from the filesystem (default: load when Image is created).
+ * @param [in] releasePol optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+ */
+ NinePatchImage( const std::string& filename,
+ const ImageAttributes& attributes,
+ LoadPolicy loadPol = ImageLoadPolicyDefault,
+ ReleasePolicy releasePol = ImageReleasePolicyDefault );
+
+ /**
+ * Convert Image object to a 9 patch image object if possible.
+ * @param[in] image The image to convert
+ * @return A pointer to the 9 patch image object, or NULL
+ * if the conversion is not possible.
+ */
+ static NinePatchImage* GetNinePatchImage( Image* image);
+
+
+protected:
+ /**
+ * A reference counted object may only be deleted by calling Unreference()
+ */
+ virtual ~NinePatchImage();
+
+public:
+ /**
+ * Get the stretch borders
+ * @return The border in pixels from the left, top, right, and bottom of the image respectively.
+ */
+ Vector4 GetStretchBorders();
+
+ /**
+ * Get the child rectangle
+ * @return the position and size of the child rectangle
+ */
+ Rect<int> GetChildRectangle();
+
+ /**
+ * @brief Create a cropped image from the bitmap with the 1 pixel border cropped off.
+ * This does not change the internal bitmap.
+ *
+ * @return the cropped bitmap.
+ */
+ BitmapImagePtr CreateCroppedBitmapImage();
+
+private:
+ /**
+ * Initializes internal data.
+ */
+ void Initialize();
+
+protected: // From Resource
+ /**
+ * @copydoc Dali::Internal::Image::Connect
+ */
+ virtual void Connect();
+
+ /**
+ * @copydoc Dali::Internal::Image::Disconnect
+ */
+ virtual void Disconnect();
+
+private:
+ /**
+ * Read the borders of the bitmap and determine the child area
+ * and stretch borders
+ */
+ void ParseBorders();
+
+private:
+ ResourceClient* mResourceClient;
+ Integration::BitmapPtr mBitmap;
+ SceneGraph::UpdateManager* mUpdateManager;
+ Vector4 mStretchBorders;
+ Rect<int> mChildRectangle;
+ bool mParsedBorder;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::NinePatchImage& GetImplementation(Dali::NinePatchImage& handle)
+{
+ DALI_ASSERT_ALWAYS( handle && "NinePatchImage handle is empty" );
+
+ BaseObject& image = handle.GetBaseObject();
+
+ return static_cast<Internal::NinePatchImage&>(image);
+}
+
+inline const Internal::NinePatchImage& GetImplementation(const Dali::NinePatchImage& handle)
+{
+ DALI_ASSERT_ALWAYS( handle && "NinePatchImage handle is empty" );
+
+ const BaseObject& image = handle.GetBaseObject();
+
+ return static_cast<const Internal::NinePatchImage&>(image);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_NINE_PATCH_IMAGE_H__
$(internal_src_dir)/event/images/image-connector.cpp \
$(internal_src_dir)/event/images/image-factory.cpp \
$(internal_src_dir)/event/images/image-factory-cache.cpp \
+ $(internal_src_dir)/event/images/nine-patch-image-impl.cpp \
$(internal_src_dir)/event/modeling/animatable-mesh-impl.cpp \
$(internal_src_dir)/event/modeling/entity-impl.cpp \
$(internal_src_dir)/event/modeling/light-impl.cpp \
#include <dali/internal/update/common/scene-graph-buffers.h>
#include <dali/internal/common/bitmap-upload.h>
#include <dali/integration-api/resource-declarations.h>
+#include <dali/integration-api/bitmap.h>
namespace Dali
{
-namespace Integration
-{
-class Bitmap;
-}
-
namespace Internal
{
typedef Integration::ResourceId ResourceId;
#include <dali/public-api/geometry/spline.h>
#include <dali/public-api/images/distance-field.h>
+#include <dali/public-api/images/nine-patch-image.h>
#include <dali/public-api/modeling/bone.h>
#include <dali/public-api/modeling/entity-animator-map.h>
$(public_api_src_dir)/images/bitmap-image.cpp \
$(public_api_src_dir)/images/frame-buffer-image.cpp \
$(public_api_src_dir)/images/encoded-buffer-image.cpp \
+ $(public_api_src_dir)/images/nine-patch-image.cpp \
$(public_api_src_dir)/math/angle-axis.cpp \
$(public_api_src_dir)/math/compile-time-math.cpp \
$(public_api_src_dir)/math/degree.cpp \
$(public_api_src_dir)/geometry/spline.h
public_api_core_images_header_files = \
- $(public_api_src_dir)/images/distance-field.h
+ $(public_api_src_dir)/images/distance-field.h \
+ $(public_api_src_dir)/images/nine-patch-image.h
public_api_core_math_header_files =
--- /dev/null
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// CLASS HEADER
+#include <dali/public-api/images/nine-patch-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image-attributes.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+
+
+namespace Dali
+{
+
+NinePatchImage::NinePatchImage()
+{
+}
+
+NinePatchImage::NinePatchImage(Internal::NinePatchImage* internal)
+: Image(internal)
+{
+}
+
+NinePatchImage::~NinePatchImage()
+{
+}
+
+NinePatchImage NinePatchImage::New( const std::string& filename )
+{
+ ImageAttributes defaultAttrs;
+
+ Internal::NinePatchImagePtr internal = Internal::NinePatchImage::New( filename, defaultAttrs, Image::Immediate, Image::Never );
+ return NinePatchImage(internal.Get());
+}
+
+NinePatchImage NinePatchImage::DownCast( BaseHandle handle )
+{
+ return NinePatchImage( dynamic_cast<Dali::Internal::NinePatchImage*>(handle.GetObjectPtr()) );
+}
+
+Vector4 NinePatchImage::GetStretchBorders()
+{
+ return GetImplementation(*this).GetStretchBorders();
+}
+
+Rect<int> NinePatchImage::GetChildRectangle()
+{
+ return GetImplementation(*this).GetChildRectangle();
+}
+
+BitmapImage NinePatchImage::CreateCroppedBitmapImage()
+{
+ Internal::BitmapImagePtr internal = GetImplementation(*this).CreateCroppedBitmapImage();
+ return BitmapImage(internal.Get());
+}
+
+
+} // namespace Dali
--- /dev/null
+#ifndef __DALI_NINE_PATCH_IMAGE_H__
+#define __DALI_NINE_PATCH_IMAGE_H__
+
+//
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://floralicense.org/license/
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/bitmap-image.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Internal DALI_INTERNAL
+{
+class NinePatchImage;
+}
+
+
+/**
+ * @brief NinePatchImage represents an image resource that can be added to ImageActors.
+ * It contains a bitmap that is synchronously loaded from the file system that contains
+ * a 9 patch border - a 1 pixel border that describes the stretch borders and the child
+ * area.
+ *
+ * The class offers an API to read the stretch area and child area, but it does not
+ * remove the border from it's bitmap. An API can be used to obtain a BitmapImage with
+ * the border removed.
+ *
+ * Adding this image to an ImageActor using an Image handle will automatically convert
+ * to use the cropped BitmapImage - if you don't retain a handle to this object, it will
+ * be automatically destroyed.
+ */
+class NinePatchImage : public Image
+{
+public:
+ /**
+ * @brief Constructor which creates an uninitialized NinePatchImage object.
+ *
+ * Use Image::New(...) to create an initialised object.
+ */
+ NinePatchImage();
+
+ /**
+ * @brief Create a new NinePatchImage.
+ *
+ * A pixel buffer for image data is allocated and loaded from the filesystem.
+ * Dali has ownership of the buffer.
+ * @note: default resource management policies are Immediate and Never
+ *
+ * @param [in] filename File to load synchronously into buffer
+ * @return a handle to a new instance of NinePatchImage
+ */
+ static NinePatchImage New( const std::string& filename );
+
+ /**
+ * @brief Downcast an Object handle to NinePatchImage.
+ *
+ * If handle points to a NinePatchImage the downcast produces valid
+ * handle. If not the returned handle is left uninitialized.
+ *
+ * @param[in] handle to An object
+ * @return handle to a NinePatchImage or an uninitialized handle
+ */
+ static NinePatchImage DownCast( BaseHandle handle );
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~NinePatchImage();
+
+ /**
+ * @copydoc Dali::BaseHandle::operator=
+ */
+ using BaseHandle::operator=;
+
+ /**
+ * Get the stretch borders
+ * @return The border in pixels from the left, top, right, and bottom of the image respectively.
+ */
+ Vector4 GetStretchBorders();
+
+ /**
+ * Get the child rectangle
+ * @return the position and size of the child rectangle
+ */
+ Rect<int> GetChildRectangle();
+
+ /**
+ * Creates a bitmap image from the bitmap with the 1 pixel border cropped off.
+ * This does not change the internal bitmap.
+ *
+ * @return The cropped BitmapImage
+ */
+ BitmapImage CreateCroppedBitmapImage();
+
+public: // Not intended for application developers
+
+ explicit DALI_INTERNAL NinePatchImage(Internal::NinePatchImage*);
+};
+
+} // namespace Dali
+
+#endif // __DALI_NINE_PATCH_IMAGE_H__
{
switch (pixelFormat)
{
- case L8:
case A8:
+ {
+ byteOffset = 0;
+ bitMask = 0xFF;
+ }
+ break;
+
+ case L8:
case RGB888:
case RGB565:
case RGB8888: