/*
- * Copyright (c) 2014 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.
#include <dali/public-api/object/type-registry.h>
#include <dali/integration-api/bitmap.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
break;
}
+ case Dali::Pixel::INVALID:
case Dali::Pixel::COMPRESSED_R11_EAC:
case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
case Dali::Pixel::COMPRESSED_RG11_EAC:
case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
+ case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
{
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;
}
+
+ case Dali::Pixel::RGB16F:
+ case Dali::Pixel::RGB32F:
+ {
+ DALI_LOG_ERROR("Pixel format not compatible.\n");
+ byteOffset=0;
+ bitMask=0;
+ break;
+ }
}
}
TypeRegistration mType( typeid( Dali::NinePatchImage ), typeid( Dali::Image ), NULL );
} // unnamed namespace
-NinePatchImagePtr NinePatchImage::New( const std::string& filename, const ImageAttributes& attributes, ReleasePolicy releasePol )
+NinePatchImagePtr NinePatchImage::New( const std::string& filename )
{
- Internal::NinePatchImagePtr internal( new NinePatchImage( filename, attributes, releasePol ) );
+ Internal::NinePatchImagePtr internal( new NinePatchImage( filename ) );
internal->Initialize();
return internal;
}
-NinePatchImage::NinePatchImage( const std::string& filename, const ImageAttributes& attributes, ReleasePolicy releasePol )
-: ResourceImage( IMAGE_LOAD_POLICY_DEFAULT, releasePol ),
+NinePatchImage::NinePatchImage( const std::string& filename )
+: ResourceImage(),
mParsedBorder(false)
{
+ mUrl = filename;
ThreadLocalStorage& tls = ThreadLocalStorage::Get();
- mResourceClient = &tls.GetResourceClient();
Integration::PlatformAbstraction& platformAbstraction = tls.GetPlatformAbstraction();
- Integration::BitmapResourceType resourceType( ImageDimensions::FromFloatVec2( attributes.GetSize() ), attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
+ Integration::BitmapResourceType resourceType;
// Note, bitmap is only destroyed when the image is destroyed.
- Integration::ResourcePointer resource = platformAbstraction.LoadResourceSynchronously( resourceType, filename );
+ Integration::ResourcePointer resource = platformAbstraction.LoadImageSynchronously( resourceType, filename );
if( resource )
{
mBitmap = static_cast<Integration::Bitmap*>( resource.Get());
+
mWidth = mBitmap->GetImageWidth();
mHeight = mBitmap->GetImageHeight();
+ mTexture = Texture::New( Dali::TextureType::TEXTURE_2D, mBitmap->GetPixelFormat(), mWidth, mHeight );
+
+ size_t bufferSize = mBitmap->GetBufferSize();
+ unsigned char* buffer = new unsigned char[bufferSize];
+ memcpy( buffer, mBitmap->GetBuffer(), bufferSize );
+ PixelDataPtr pixelData = PixelData::New( buffer, bufferSize, mWidth, mHeight, mBitmap->GetPixelFormat(), Dali::PixelData::DELETE_ARRAY );
+ mTexture->Upload( pixelData );
}
else
{
{
}
-Vector4 NinePatchImage::GetStretchBorders()
+const NinePatchImage::StretchRanges& NinePatchImage::GetStretchPixelsX()
+{
+ if( ! mParsedBorder )
+ {
+ ParseBorders();
+ }
+ return mStretchPixelsX;
+}
+
+const NinePatchImage::StretchRanges& NinePatchImage::GetStretchPixelsY()
{
if( ! mParsedBorder )
{
ParseBorders();
}
- return mStretchBorders;
+ return mStretchPixelsY;
}
Rect<int> NinePatchImage::GetChildRectangle()
{
Pixel::Format pixelFormat = mBitmap->GetPixelFormat();
- cropped = BufferImage::New( mWidth-2, mHeight-2, pixelFormat, Dali::Image::NEVER );
+ cropped = BufferImage::New( mWidth-2, mHeight-2, pixelFormat );
Integration::Bitmap::PackedPixelsProfile* srcProfile = mBitmap->GetPackedPixelsProfile();
DALI_ASSERT_DEBUG( srcProfile && "Wrong profile for source bitmap");
return cropped;
}
-void NinePatchImage::Connect()
-{
- if( !mTicket )
- {
- if( mBitmap )
- {
- const ImageTicketPtr& t = mResourceClient->AddBitmapImage(mBitmap.Get());
- mTicket = t.Get();
- mTicket->AddObserver(*this);
- }
- }
-
- ++mConnectionCount;
-}
-
-void NinePatchImage::Disconnect()
+const std::string& NinePatchImage::GetUrl() const
{
- if( mConnectionCount > 0 )
- {
- --mConnectionCount;
- }
+ return mUrl;
}
-
void NinePatchImage::ParseBorders()
{
- if( ! mBitmap )
+ if( !mBitmap )
{
DALI_LOG_ERROR( "NinePatchImage: Bitmap not loaded, cannot perform operation\n");
return;
}
+ mStretchPixelsX.Clear();
+ mStretchPixelsY.Clear();
+
Pixel::Format pixelFormat = mBitmap->GetPixelFormat();
- Integration::Bitmap::PackedPixelsProfile* srcProfile = mBitmap->GetPackedPixelsProfile();
- DALI_ASSERT_DEBUG( srcProfile && "Wrong profile for source bitmap");
+ const 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 alphaByte = 0;
+ int alphaBits = 0;
+ Pixel::GetAlphaOffsetAndMask( pixelFormat, alphaByte, alphaBits );
int testByte = alphaByte;
int testBits = alphaBits;
int testValue = alphaBits; // Opaque == stretch
if( ! alphaBits )
{
- testByte = redByte;
- testBits = redBits;
+ GetRedOffsetAndMask( pixelFormat, testByte, testBits );
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 )
+ unsigned int pixelWidth = GetBytesPerPixel( pixelFormat );
+ const PixelBuffer* srcPixels = mBitmap->GetBuffer();
+ unsigned int srcStride = srcProfile->GetBufferStride();
+
+ //TOP
+ const PixelBuffer* top = srcPixels + pixelWidth;
+ unsigned int index = 0;
+ unsigned int width = mBitmap->GetImageWidth();
+ unsigned int height = mBitmap->GetImageHeight();
+
+ for(; index < width - 2; )
{
- if( (top[testByte] & testBits) == testValue )
- {
- if(startX1 < 0)
- {
- startX1 = col;
- }
- }
- else if(startX1 >= 0 && endX1 < 0)
+ Uint16Pair range = ParseRange( index, width - 2, top, pixelWidth, testByte, testBits, testValue );
+ if( range.GetX() != 0xFFFF )
{
- endX1 = col;
+ mStretchPixelsX.PushBack( range );
}
+ }
- if( (bottom[testByte] & testBits) == testValue )
- {
- if(startX2 < 0)
- {
- startX2 = col;
- }
- }
- else if(startX2 >= 0 && endX2 < 0)
+ //LEFT
+ const PixelBuffer* left = srcPixels + srcStride;
+ index = 0;
+ for(; index < height - 2; )
+ {
+ Uint16Pair range = ParseRange( index, height - 2, left, srcStride, testByte, testBits, testValue );
+ if( range.GetX() != 0xFFFF )
{
- endX2 = col;
+ mStretchPixelsY.PushBack( range );
}
+ }
- if ( ( endX2 > 0 ) && ( endX1 > 0 ) )
- {
+ //If there are no stretch pixels then make the entire image stretchable
+ if( mStretchPixelsX.Size() == 0 )
+ {
+ mStretchPixelsX.PushBack( Uint16Pair( 0, width - 2 ) );
+ }
+ if( mStretchPixelsY.Size() == 0 )
+ {
+ mStretchPixelsY.PushBack( Uint16Pair( 0, height - 2 ) );
+ }
+
+ //Child Rectangle
+ //BOTTOM
+ const PixelBuffer* bottom = srcPixels + ( height - 1 ) * srcStride + pixelWidth;
+ index = 0;
+ Uint16Pair contentRangeX = ParseRange( index, width - 2, bottom, pixelWidth, testByte, testBits, testValue );
+ if( contentRangeX.GetX() == 0xFFFF )
+ {
+ contentRangeX = Uint16Pair();
+ }
+
+ //RIGHT
+ const PixelBuffer* right = srcPixels + srcStride + ( width - 1 ) * pixelWidth;
+ index = 0;
+ Uint16Pair contentRangeY = ParseRange( index, height - 2, right, srcStride, testByte, testBits, testValue );
+ if( contentRangeY.GetX() == 0xFFFF )
+ {
+ contentRangeY = Uint16Pair();
+ }
+
+ mChildRectangle.x = contentRangeX.GetX() + 1;
+ mChildRectangle.y = contentRangeY.GetX() + 1;
+ mChildRectangle.width = contentRangeX.GetY() - contentRangeX.GetX();
+ mChildRectangle.height = contentRangeY.GetY() - contentRangeY.GetX();
+
+ mParsedBorder = true;
+ }
+}
+
+Uint16Pair NinePatchImage::ParseRange( unsigned int& index, unsigned int width, const PixelBuffer* & pixel, unsigned int pixelStride, int testByte, int testBits, int testValue )
+{
+ unsigned int start = 0xFFFF;
+ for( ; index < width; ++index, pixel += pixelStride )
+ {
+ if( ( pixel[ testByte ] & testBits ) == testValue )
+ {
+ start = index;
+ ++index;
+ pixel += pixelStride;
break;
- }
+ }
+ }
- top+=pixelWidth;
- bottom+=pixelWidth;
+ unsigned int end = width;
+ for( ; index < width; ++index, pixel += pixelStride )
+ {
+ if( ( pixel[ testByte ] & testBits ) != testValue )
+ {
+ end = index;
+ ++index;
+ pixel += pixelStride;
+ break;
}
+ }
- // Read the left and right columns:
- PixelBuffer* left = srcPixels + srcStride;
- PixelBuffer* right = left + (srcStride - pixelWidth);
+ return Uint16Pair( start, end );
+}
- // (Also read the last row to ensure end value gets set)
- for( unsigned int row=1; row < mHeight; ++row )
+bool NinePatchImage::IsNinePatchUrl( const std::string& url )
+{
+ bool match = false;
+
+ std::string::const_reverse_iterator iter = url.rbegin();
+ enum { SUFFIX, HASH, HASH_DOT, DONE } state = SUFFIX;
+ while(iter < url.rend())
+ {
+ switch(state)
{
- if((left[testByte] & testBits) == testValue)
+ case SUFFIX:
{
- if(startY1 < 0)
+ if(*iter == '.')
{
- startY1 = row;
+ state = HASH;
+ }
+ else if(!isalnum(*iter))
+ {
+ state = DONE;
}
}
- else if(startY1 >= 0 && endY1 < 0)
- {
- endY1 = row;
- }
-
- if((right[testByte] & testBits) == testValue)
+ break;
+ case HASH:
{
- if(startY2 < 0)
+ if( *iter == '#' || *iter == '9' )
{
- startY2 = row;
+ state = HASH_DOT;
+ }
+ else
+ {
+ state = DONE;
}
}
- else if(startY2 >= 0 && endY2 < 0)
+ break;
+ case HASH_DOT:
{
- endY2 = row;
+ if(*iter == '.')
+ {
+ match = true;
+ }
+ state = DONE; // Stop testing characters
}
- left += srcStride;
- right += srcStride;
-
- if ( ( endY2 > 0 ) && ( endY1 > 0 ) )
+ break;
+ case DONE:
{
- break;
}
+ break;
}
- mStretchBorders.x = startX1;
- mStretchBorders.y = startY1;
- mStretchBorders.z = mWidth-endX1;
- mStretchBorders.w = mHeight-endY1;
-
- mChildRectangle.x = startX2;
- mChildRectangle.y = startY2;
- mChildRectangle.width = endX2-startX2;
- mChildRectangle.height = endY2-startY2;
+ // Satisfy prevent
+ if( state == DONE )
+ {
+ break;
+ }
- mParsedBorder = true;
+ ++iter;
}
+ return match;
}
} // namespace Internal