97f4ee3edea55bff0e6ff86e3bc46833def60272
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-NinePatchImages.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <iostream>
19
20 #include <stdlib.h>
21 #include <dali/public-api/dali-core.h>
22 #include <dali-test-suite-utils.h>
23
24 using namespace Dali;
25
26 namespace {
27
28 Integration::Bitmap* CreateBitmap( unsigned int imageWidth, unsigned int imageHeight, unsigned int initialColor, Pixel::Format pixelFormat )
29 {
30   Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
31   Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight );
32   unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat );
33
34   memset( pixbuffer, initialColor, imageHeight * imageWidth * bytesPerPixel );
35
36   return bitmap;
37 }
38
39 void InitialiseRegionsToZeroAlpha( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, Pixel::Format pixelFormat )
40 {
41   PixelBuffer* pixbuffer = image->GetBuffer();
42   unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat );
43
44   for( unsigned int row = 0; row < imageWidth; ++row )
45   {
46     unsigned int pixelOffset = row * bytesPerPixel;
47     pixbuffer[ pixelOffset + 3 ] = 0x00;
48     pixelOffset += ( imageHeight - 1 ) * imageWidth * bytesPerPixel;
49     pixbuffer[ pixelOffset + 3 ] = 0x00;
50   }
51
52   for ( unsigned int column = 0; column < imageHeight; ++column )
53   {
54     unsigned int pixelOffset = column * imageWidth * bytesPerPixel;
55     pixbuffer[ pixelOffset + 3 ] = 0x00;
56     pixelOffset += ( imageWidth -1 ) * bytesPerPixel;
57     pixbuffer[ pixelOffset + 3 ] = 0x00;
58   }
59 }
60
61 void AddStretchRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredStretchBorder, Pixel::Format pixelFormat )
62 {
63   PixelBuffer* pixbuffer = image->GetBuffer();
64   unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat );
65
66   for( unsigned int column = requiredStretchBorder.x; column < imageWidth - requiredStretchBorder.z; ++column )
67   {
68     unsigned int pixelOffset = column * bytesPerPixel;
69     pixbuffer[ pixelOffset ] = 0x00;
70     pixbuffer[ pixelOffset + 1 ] = 0x00;
71     pixbuffer[ pixelOffset + 2 ] = 0x00;
72     pixbuffer[ pixelOffset + 3 ] = 0xFF;
73   }
74
75   for( unsigned int row = requiredStretchBorder.y; row < imageHeight - requiredStretchBorder.w; ++row )
76   {
77     unsigned int pixelOffset = row * imageWidth * bytesPerPixel;
78     pixbuffer[ pixelOffset ] = 0x00;
79     pixbuffer[ pixelOffset + 1 ] = 0x00;
80     pixbuffer[ pixelOffset + 2 ] = 0x00;
81     pixbuffer[ pixelOffset + 3 ] = 0xFF;
82   }
83 }
84
85 void AddChildRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredChildRegion, Pixel::Format pixelFormat )
86 {
87   PixelBuffer* pixbuffer = image->GetBuffer();
88   unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat );
89
90   Integration::Bitmap::PackedPixelsProfile* srcProfile = image->GetPackedPixelsProfile();
91   unsigned int bufferStride = srcProfile->GetBufferStride();
92
93   // Add bottom child region
94   for( unsigned int column = requiredChildRegion.x; column < imageWidth - requiredChildRegion.z; ++column )
95   {
96     unsigned int pixelOffset = column * bytesPerPixel;
97     pixelOffset += ( imageHeight - 1 ) * bufferStride;
98     pixbuffer[ pixelOffset ] = 0x00;
99     pixbuffer[ pixelOffset + 1 ] = 0x00;
100     pixbuffer[ pixelOffset + 2 ] = 0x00;
101     pixbuffer[ pixelOffset + 3 ] = 0xFF;
102   }
103
104   // Add right child region
105   for ( unsigned int row = requiredChildRegion.y; row < imageHeight - requiredChildRegion.w; ++row )
106   {
107     unsigned int pixelOffset = row * bufferStride + ( imageWidth - 1 ) * bytesPerPixel;
108     pixbuffer[ pixelOffset ] = 0x00;
109     pixbuffer[ pixelOffset + 1 ] = 0x00;
110     pixbuffer[ pixelOffset + 2 ] = 0x00;
111     pixbuffer[ pixelOffset + 3 ] = 0xFF;
112   }
113 }
114
115 NinePatchImage CustomizeNinePatch( TestApplication& application,
116                                 unsigned int ninePatchImageWidth,
117                                 unsigned int ninePatchImageHeight,
118                                 const Vector4& requiredStretchBorder,
119                                 bool addChildRegion = false,
120                                 Vector4 requiredChildRegion = Vector4::ZERO )
121 {
122   TestPlatformAbstraction& platform = application.GetPlatform();
123
124   Pixel::Format pixelFormat = Pixel::RGBA8888;
125
126   tet_infoline("Create Bitmap");
127   platform.SetClosestImageSize(Vector2( ninePatchImageWidth, ninePatchImageHeight));
128   Integration::Bitmap* bitmap = CreateBitmap( ninePatchImageWidth, ninePatchImageHeight, 0xFF, pixelFormat );
129
130   tet_infoline("Clear border regions");
131   InitialiseRegionsToZeroAlpha( bitmap, ninePatchImageWidth, ninePatchImageHeight, pixelFormat );
132
133   tet_infoline("Add Stretch regions to Bitmap");
134   AddStretchRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, pixelFormat );
135
136   if( addChildRegion )
137   {
138     tet_infoline("Add Child regions to Bitmap");
139     AddChildRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredChildRegion, pixelFormat );
140   }
141
142   tet_infoline("Setting resource as it's loaded synchronously");
143   Integration::ResourcePointer resourcePtr(bitmap);
144   platform.SetSynchronouslyLoadedResource( resourcePtr );
145
146   Image image = ResourceImage::New( "blah.#.png" );
147
148   tet_infoline("Assign image to image rendering actor");
149   Actor actor = CreateRenderableActor( image );
150   Stage::GetCurrent().Add( actor );
151
152   tet_infoline("Downcast Image to a nine-patch image\n");
153   NinePatchImage ninePatchImage = NinePatchImage::DownCast( image );
154
155   return ninePatchImage;
156
157 }
158
159 } // namespace
160
161 int UtcDaliNinePatchImageNew(void)
162 {
163   TestApplication application;
164   tet_infoline("UtcDaliNinePatchImageNew - NinePatchImage::New(const std::string&)");
165
166   // invoke default handle constructor
167   NinePatchImage image;
168
169   DALI_TEST_CHECK( !image );
170
171   // initialise handle
172   image = NinePatchImage::New( "blah.#.png" );
173
174   DALI_TEST_CHECK( image );
175   END_TEST;
176 }
177
178 int UtcDaliNinePatchImageDowncast(void)
179 {
180   TestApplication application;
181   tet_infoline("UtcDaliNinePatchImageDowncast - NinePatchImage::DownCast(BaseHandle)");
182
183   NinePatchImage image = NinePatchImage::New( "blah.#.png" );
184
185   BaseHandle object( image );
186
187   NinePatchImage image2 = NinePatchImage::DownCast( object );
188   DALI_TEST_CHECK( image2 );
189
190   NinePatchImage image3 = DownCast< NinePatchImage >( object );
191   DALI_TEST_CHECK( image3 );
192
193   BaseHandle unInitializedObject;
194   NinePatchImage image4 = NinePatchImage::DownCast( unInitializedObject );
195   DALI_TEST_CHECK( !image4 );
196
197   NinePatchImage image5 = DownCast< NinePatchImage >( unInitializedObject );
198   DALI_TEST_CHECK( !image5 );
199
200   Image image6 = NinePatchImage::New( "blah.#.png" );
201   NinePatchImage image7 = NinePatchImage::DownCast( image6 );
202   DALI_TEST_CHECK( image7 );
203   END_TEST;
204 }
205
206 int UtcDaliNinePatchImageCopyConstructor(void)
207 {
208   TestApplication application;
209
210   tet_infoline("UtcDaliNinePatchImageCopyConstructor - NinePatchImage::NinePatchImage( const NinePatchImage& )");
211
212   NinePatchImage image1;
213   DALI_TEST_CHECK( !image1 );
214
215   image1 = NinePatchImage::New( "blah.#.png" );
216   NinePatchImage image2( image1 );
217
218   DALI_TEST_CHECK( image2 );
219   DALI_TEST_EQUALS( image1, image2, TEST_LOCATION );
220
221   END_TEST;
222 }
223
224 int UtcDaliNinePatchImageGetStrechBorders(void)
225 {
226   TestApplication application;
227   tet_infoline("UtcDaliNinePatchImageGetStrechBorders - NinePatchImage::GetStretchBorders()");
228
229   /* Stretch region left(2) top(2) right (2) bottom (2)
230     *    ss
231     *  OOOOOO
232     *  OOOOOOc
233     * sOOooOOc
234     * sOOooOOc
235     *  OOOOOOc
236     *  OOOOOO
237     *   cccc
238     */
239
240    const unsigned int ninePatchImageHeight = 18;
241    const unsigned int ninePatchImageWidth = 28;
242    const Vector4 requiredStretchBorder( 3, 4, 5, 6 );
243
244    NinePatchImage ninePatchImage = CustomizeNinePatch( application, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder );
245    DALI_TEST_CHECK( ninePatchImage );
246
247    if( ninePatchImage )
248    {
249      tet_infoline("Get Stretch regions from NinePatch");
250
251      const NinePatchImage::StretchRanges& stretchPixelsX = ninePatchImage.GetStretchPixelsX();
252      const NinePatchImage::StretchRanges& stretchPixelsY = ninePatchImage.GetStretchPixelsY();
253
254      DALI_TEST_CHECK( stretchPixelsX.Size() == 1 );
255      DALI_TEST_CHECK( stretchPixelsY.Size() == 1 );
256
257      Vector4 stretchBorders;
258      //The NinePatchImage stretch pixels are in the cropped image space, inset by 1 to get it to uncropped image space
259      stretchBorders.x = stretchPixelsX[ 0 ].GetX() + 1;
260      stretchBorders.y = stretchPixelsY[ 0 ].GetX() + 1;
261      stretchBorders.z = ninePatchImageWidth - stretchPixelsX[ 0 ].GetY() - 1;
262      stretchBorders.w = ninePatchImageHeight - stretchPixelsY[ 0 ].GetY() - 1;
263
264      tet_printf("stretchBorders left(%f) right(%f) top(%f) bottom(%f)\n", stretchBorders.x, stretchBorders.z, stretchBorders.y, stretchBorders.w );
265      DALI_TEST_CHECK( stretchBorders == requiredStretchBorder );
266
267      Vector4 actualStretchBorders = ninePatchImage.GetStretchBorders();
268      DALI_TEST_EQUALS( actualStretchBorders, requiredStretchBorder, 0.001, TEST_LOCATION );
269    }
270    else
271    {
272      tet_infoline("Image not NinePatch");
273      test_return_value = TET_FAIL;
274    }
275
276   END_TEST;
277 }
278
279 int UtcDaliNinePatchImageGetChildRectangle(void)
280 {
281   TestApplication application;
282   tet_infoline("UtcDaliNinePatchImageGetChildRectangle - NinePatchImage::GetChildRectangle()");
283
284   /* Child region x(2) y(2) width (4) height (4)
285    *
286    *    ss
287    *  OOOOOO
288    *  OOOOOOc
289    * sOOooOOc
290    * sOOooOOc
291    *  OOOOOOc
292    *  OOOOOO
293    *   cccc
294    */
295
296   const unsigned int ninePatchImageHeight = 18;
297   const unsigned int ninePatchImageWidth = 28;
298   const Vector4 requiredChildRegion( 2, 2, 2, 2 );
299   const Vector4 requiredStretchBorder( 3, 4, 5, 6 );
300
301   NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, true, requiredChildRegion );
302   DALI_TEST_CHECK( ninePatchImage );
303
304   if ( ninePatchImage )
305   {
306     tet_infoline("Get Child regions from NinePatch");
307     Rect< int > childRectangle = ninePatchImage.GetChildRectangle();
308     tet_printf("childRectange x(%d) y(%d) width(%d) height(%d)\n", childRectangle.x, childRectangle.y, childRectangle.width, childRectangle.height );
309     Rect< int > childRegion(requiredChildRegion.x, requiredChildRegion.y, ninePatchImageWidth - requiredChildRegion.x - requiredChildRegion.z, ninePatchImageHeight - requiredChildRegion.y - requiredChildRegion.w );
310     DALI_TEST_CHECK( childRegion == childRectangle );
311   }
312   else
313   {
314     tet_infoline("Image not NinePatch");
315     test_return_value = TET_FAIL;
316   }
317
318   END_TEST;
319 }
320
321 int UtcDaliNinePatchImageCreateCroppedBufferImage(void)
322 {
323   TestApplication application;
324   tet_infoline("UtcDaliNinePatchImageCreateCroppedBufferImage - NinePatchImage::CreateCroppedBufferImage()");
325
326   const unsigned int ninePatchImageHeight = 8;
327   const unsigned int ninePatchImageWidth = 8;
328   const Vector4 requiredStretchBorder( 1, 1, 1, 1 );
329
330   NinePatchImage ninePatchImage = CustomizeNinePatch( application, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder  );
331   DALI_TEST_CHECK( ninePatchImage );
332
333   if ( ninePatchImage )
334   {
335     BufferImage newImage = ninePatchImage.CreateCroppedBufferImage();
336     DALI_TEST_CHECK( newImage );
337
338     DALI_TEST_EQUALS( newImage.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
339
340     DALI_TEST_EQUALS( newImage.GetBufferSize(), 144u/* 36*4 */, TEST_LOCATION );
341   }
342   else
343   {
344     tet_infoline("Image not NinePatch");
345     test_return_value = TET_FAIL;
346   }
347
348   END_TEST;
349 }
350
351 int UtcDaliNinePatchImageIsNinePatchUrl(void)
352 {
353   TestApplication application;
354   tet_infoline("UtcDaliNinePatchImageIsNinePatchUrl - NinePatchImage::IsNinePatchUrl(const std::string&)");
355
356   DALI_TEST_CHECK( NinePatchImage::IsNinePatchUrl( "test.9.jpg" ) );
357   DALI_TEST_CHECK( NinePatchImage::IsNinePatchUrl( "test.#.jpg" ) );
358   DALI_TEST_CHECK( !NinePatchImage::IsNinePatchUrl( "test.9" ) );
359   DALI_TEST_CHECK( !NinePatchImage::IsNinePatchUrl( "test.#" ) );
360   DALI_TEST_CHECK( !NinePatchImage::IsNinePatchUrl( "test" ) );
361
362   END_TEST;
363 }