2 * Copyright (c) 2022 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>
28 namespace NPatchUtility
32 Uint16Pair ParseRange(uint32_t& index, uint32_t width, uint8_t*& pixel, uint32_t pixelStride, int32_t testByte, int32_t testBits, int32_t testValue)
34 unsigned int start = 0xFFFF;
35 for(; index < width; ++index, pixel += pixelStride)
37 if((pixel[testByte] & testBits) == testValue)
46 unsigned int end = width;
47 for(; index < width; ++index, pixel += pixelStride)
49 if((pixel[testByte] & testBits) != testValue)
58 return Uint16Pair(start, end);
61 } // unnamed namespace
63 void GetRedOffsetAndMask(Dali::Pixel::Format pixelFormat, int32_t& byteOffset, int32_t& bitMask)
69 case Dali::Pixel::LA88:
75 case Dali::Pixel::RGB888:
76 case Dali::Pixel::RGB8888:
77 case Dali::Pixel::RGBA8888:
83 case Dali::Pixel::BGR8888:
84 case Dali::Pixel::BGRA8888:
90 case Dali::Pixel::RGB565:
96 case Dali::Pixel::BGR565:
102 case Dali::Pixel::RGBA4444:
108 case Dali::Pixel::BGRA4444:
114 case Dali::Pixel::RGBA5551:
120 case Dali::Pixel::BGRA5551:
126 case Dali::Pixel::INVALID:
127 case Dali::Pixel::COMPRESSED_R11_EAC:
128 case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
129 case Dali::Pixel::COMPRESSED_RG11_EAC:
130 case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
131 case Dali::Pixel::COMPRESSED_RGB8_ETC2:
132 case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
133 case Dali::Pixel::COMPRESSED_RGB8_ETC1:
134 case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
135 case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
136 case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
137 case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
138 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
139 case Dali::Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR:
140 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR:
141 case Dali::Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR:
142 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR:
143 case Dali::Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR:
144 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR:
145 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR:
146 case Dali::Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR:
147 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR:
148 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR:
149 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR:
150 case Dali::Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR:
151 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR:
152 case Dali::Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR:
153 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
154 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
155 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
156 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
157 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
158 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
159 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
160 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
161 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
162 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
163 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
164 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
165 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
166 case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
168 DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
173 case Dali::Pixel::RGB16F:
174 case Dali::Pixel::RGB32F:
175 case Dali::Pixel::DEPTH_UNSIGNED_INT:
176 case Dali::Pixel::DEPTH_FLOAT:
177 case Dali::Pixel::DEPTH_STENCIL:
178 case Dali::Pixel::R11G11B10F:
179 case Dali::Pixel::CHROMINANCE_U:
180 case Dali::Pixel::CHROMINANCE_V:
182 DALI_LOG_ERROR("Pixel format not compatible.\n");
190 void ParseBorders(Devel::PixelBuffer& pixelBuffer, StretchRanges& stretchPixelsX, StretchRanges& stretchPixelsY)
192 stretchPixelsX.Clear();
193 stretchPixelsY.Clear();
195 Pixel::Format pixelFormat = pixelBuffer.GetPixelFormat();
197 int32_t alphaByte = 0;
198 int32_t alphaBits = 0;
199 Pixel::GetAlphaOffsetAndMask(pixelFormat, alphaByte, alphaBits);
201 int32_t testByte = alphaByte;
202 int32_t testBits = alphaBits;
203 int32_t testValue = alphaBits; // Opaque == stretch
206 GetRedOffsetAndMask(pixelFormat, testByte, testBits);
207 testValue = 0; // Black == stretch
210 uint32_t bytesPerPixel = Pixel::GetBytesPerPixel(pixelFormat);
211 uint32_t width = pixelBuffer.GetWidth();
212 uint32_t height = pixelBuffer.GetHeight();
213 uint8_t* srcPixels = pixelBuffer.GetBuffer();
214 uint32_t srcStride = width * bytesPerPixel;
217 uint8_t* top = srcPixels + bytesPerPixel;
220 for(; index < width - 2;)
222 Uint16Pair range = ParseRange(index, width - 2, top, bytesPerPixel, testByte, testBits, testValue);
223 if(range.GetX() != 0xFFFF)
225 stretchPixelsX.PushBack(range);
230 uint8_t* left = srcPixels + srcStride;
232 for(; index < height - 2;)
234 Uint16Pair range = ParseRange(index, height - 2, left, srcStride, testByte, testBits, testValue);
235 if(range.GetX() != 0xFFFF)
237 stretchPixelsY.PushBack(range);
241 // If there are no stretch pixels then make the entire image stretchable
242 if(stretchPixelsX.Size() == 0)
244 stretchPixelsX.PushBack(Uint16Pair(0, width - 2));
246 if(stretchPixelsY.Size() == 0)
248 stretchPixelsY.PushBack(Uint16Pair(0, height - 2));
252 bool IsNinePatchUrl(const std::string& url)
256 std::string::const_reverse_iterator iter = url.rbegin();
264 while(iter < url.rend())
274 else if(!isalnum(*iter))
282 if(*iter == '#' || *iter == '9')
298 state = DONE; // Stop testing characters
318 } // namespace NPatchUtility
320 } // namespace Toolkit