2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/devel-api/utility/npatch-utilities.h>
22 #include <dali/integration-api/debug.h>
30 namespace NPatchUtility
36 Uint16Pair ParseRange( uint32_t& index, uint32_t width, uint8_t*& pixel, uint32_t pixelStride, int32_t testByte, int32_t testBits, int32_t testValue )
38 unsigned int start = 0xFFFF;
39 for( ; index < width; ++index, pixel += pixelStride )
41 if( ( pixel[ testByte ] & testBits ) == testValue )
50 unsigned int end = width;
51 for( ; index < width; ++index, pixel += pixelStride )
53 if( ( pixel[ testByte ] & testBits ) != testValue )
62 return Uint16Pair( start, end );
65 } // unnamed namespace
67 void GetRedOffsetAndMask( Dali::Pixel::Format pixelFormat, int32_t& byteOffset, int32_t& bitMask )
73 case Dali::Pixel::LA88:
79 case Dali::Pixel::RGB888:
80 case Dali::Pixel::RGB8888:
81 case Dali::Pixel::RGBA8888:
87 case Dali::Pixel::BGR8888:
88 case Dali::Pixel::BGRA8888:
94 case Dali::Pixel::RGB565:
100 case Dali::Pixel::BGR565:
106 case Dali::Pixel::RGBA4444:
112 case Dali::Pixel::BGRA4444:
118 case Dali::Pixel::RGBA5551:
124 case Dali::Pixel::BGRA5551:
130 case Dali::Pixel::INVALID:
131 case Dali::Pixel::COMPRESSED_R11_EAC:
132 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
133 case Dali::Pixel::COMPRESSED_RG11_EAC:
134 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
135 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
136 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
137 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
138 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
139 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
140 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
141 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
142 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
143 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
144 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
145 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
146 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
147 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
148 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
149 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
150 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
151 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
152 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
153 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
154 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
155 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
156 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
157 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
158 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
159 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
160 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
161 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
162 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
163 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
164 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
165 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
166 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
167 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
168 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
169 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
170 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
172 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
177 case Dali::Pixel::RGB16F:
178 case Dali::Pixel::RGB32F:
179 case Dali::Pixel::DEPTH_UNSIGNED_INT:
180 case Dali::Pixel::DEPTH_FLOAT:
181 case Dali::Pixel::DEPTH_STENCIL:
183 DALI_LOG_ERROR("Pixel format not compatible.\n");
191 void ParseBorders( Devel::PixelBuffer& pixelBuffer, StretchRanges& stretchPixelsX, StretchRanges& stretchPixelsY )
193 stretchPixelsX.Clear();
194 stretchPixelsY.Clear();
196 Pixel::Format pixelFormat = pixelBuffer.GetPixelFormat();
198 int32_t alphaByte = 0;
199 int32_t alphaBits = 0;
200 Pixel::GetAlphaOffsetAndMask( pixelFormat, alphaByte, alphaBits );
202 int32_t testByte = alphaByte;
203 int32_t testBits = alphaBits;
204 int32_t testValue = alphaBits; // Opaque == stretch
207 GetRedOffsetAndMask( pixelFormat, testByte, testBits );
208 testValue = 0; // Black == stretch
211 uint32_t bytesPerPixel = Pixel::GetBytesPerPixel( pixelFormat );
212 uint32_t width = pixelBuffer.GetWidth();
213 uint32_t height = pixelBuffer.GetHeight();
214 uint8_t* srcPixels = pixelBuffer.GetBuffer();
215 uint32_t srcStride = width * bytesPerPixel;
218 uint8_t* top = srcPixels + bytesPerPixel;
221 for( ; index < width - 2; )
223 Uint16Pair range = ParseRange( index, width - 2, top, bytesPerPixel, testByte, testBits, testValue );
224 if( range.GetX() != 0xFFFF )
226 stretchPixelsX.PushBack( range );
231 uint8_t* left = srcPixels + srcStride;
233 for( ; index < height - 2; )
235 Uint16Pair range = ParseRange( index, height - 2, left, srcStride, testByte, testBits, testValue );
236 if( range.GetX() != 0xFFFF )
238 stretchPixelsY.PushBack( range );
242 // If there are no stretch pixels then make the entire image stretchable
243 if( stretchPixelsX.Size() == 0 )
245 stretchPixelsX.PushBack( Uint16Pair( 0, width - 2 ) );
247 if( stretchPixelsY.Size() == 0 )
249 stretchPixelsY.PushBack( Uint16Pair( 0, height - 2 ) );
253 bool IsNinePatchUrl( const std::string& url )
257 std::string::const_reverse_iterator iter = url.rbegin();
258 enum { SUFFIX, HASH, HASH_DOT, DONE } state = SUFFIX;
259 while(iter < url.rend())
269 else if(!isalnum(*iter))
277 if( *iter == '#' || *iter == '9' )
293 state = DONE; // Stop testing characters
313 } // namespace NPatchBuffer
315 } // namespace Toolkit