Fix performance down if DefaultFontDescription not prepared
[platform/core/uifw/dali-adaptor.git] / automated-tests / src / dali-adaptor-internal / utc-Dali-FontClient.cpp
1 /*
2  * Copyright (c) 2014 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 <dali-test-suite-utils.h>
21 #include <dali/dali.h>
22 #include <dali/devel-api/text-abstraction/bitmap-font.h>
23 #include <dali/devel-api/text-abstraction/font-client.h>
24 #include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <iostream>
29
30 using namespace Dali;
31
32 int UtcDaliFontClient(void)
33 {
34   const int ORDERED_VALUES[] = {-1, 50, 63, 75, 87, 100, 113, 125, 150, 200};
35
36   const unsigned int NUM_OF_ORDERED_VALUES = sizeof(ORDERED_VALUES) / sizeof(int);
37
38   TestApplication application;
39   int             result = 0;
40
41   tet_infoline("UtcDaliFontClient No table");
42   result = TextAbstraction::Internal::ValueToIndex(100, NULL, 0u);
43   DALI_TEST_EQUALS(-1, result, TEST_LOCATION);
44
45   tet_infoline("UtcDaliFontClient Non defined values");
46   result = TextAbstraction::Internal::ValueToIndex(-1, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
47   DALI_TEST_EQUALS(0, result, TEST_LOCATION);
48   result = TextAbstraction::Internal::ValueToIndex(-3, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
49   DALI_TEST_EQUALS(0, result, TEST_LOCATION);
50
51   tet_infoline("UtcDaliFontClient Between non defined and first of range.");
52   result = TextAbstraction::Internal::ValueToIndex(0, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
53   DALI_TEST_EQUALS(1, result, TEST_LOCATION);
54   result = TextAbstraction::Internal::ValueToIndex(30, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
55   DALI_TEST_EQUALS(1, result, TEST_LOCATION);
56   result = TextAbstraction::Internal::ValueToIndex(49, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
57   DALI_TEST_EQUALS(1, result, TEST_LOCATION);
58
59   tet_infoline("UtcDaliFontClient Defined in range");
60   for(unsigned int index = 1u; index < NUM_OF_ORDERED_VALUES; ++index)
61   {
62     result = TextAbstraction::Internal::ValueToIndex(ORDERED_VALUES[index], ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
63     DALI_TEST_EQUALS(index, result, TEST_LOCATION);
64   }
65
66   tet_infoline("UtcDaliFontClient Non defined in range");
67   result = TextAbstraction::Internal::ValueToIndex(51, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
68   DALI_TEST_EQUALS(1, result, TEST_LOCATION);
69   result = TextAbstraction::Internal::ValueToIndex(55, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
70   DALI_TEST_EQUALS(1, result, TEST_LOCATION);
71   result = TextAbstraction::Internal::ValueToIndex(62, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
72   DALI_TEST_EQUALS(2, result, TEST_LOCATION);
73   result = TextAbstraction::Internal::ValueToIndex(64, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
74   DALI_TEST_EQUALS(2, result, TEST_LOCATION);
75   result = TextAbstraction::Internal::ValueToIndex(151, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
76   DALI_TEST_EQUALS(8, result, TEST_LOCATION);
77   result = TextAbstraction::Internal::ValueToIndex(175, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
78   DALI_TEST_EQUALS(9, result, TEST_LOCATION);
79   result = TextAbstraction::Internal::ValueToIndex(176, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
80   DALI_TEST_EQUALS(9, result, TEST_LOCATION);
81   result = TextAbstraction::Internal::ValueToIndex(199, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
82   DALI_TEST_EQUALS(9, result, TEST_LOCATION);
83
84   tet_infoline("UtcDaliFontClient above of range");
85   result = TextAbstraction::Internal::ValueToIndex(220, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
86   DALI_TEST_EQUALS(9, result, TEST_LOCATION);
87   result = TextAbstraction::Internal::ValueToIndex(500, ORDERED_VALUES, NUM_OF_ORDERED_VALUES - 1u);
88   DALI_TEST_EQUALS(9, result, TEST_LOCATION);
89
90   END_TEST;
91 }
92
93 int UtcDaliFontClientAtlasLimitation(void)
94 {
95   TestApplication             application;
96   bool                        result     = 0;
97   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
98
99   tet_infoline("UtcDaliFontClientAtlasLimitation Default");
100   result = fontClient.IsAtlasLimitationEnabled();
101   DALI_TEST_EQUALS(TextAbstraction::FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED, result, TEST_LOCATION);
102
103   tet_infoline("UtcDaliFontClientAtlasLimitation Enabled");
104   fontClient.EnableAtlasLimitation(true);
105   result = fontClient.IsAtlasLimitationEnabled();
106   DALI_TEST_EQUALS(true, result, TEST_LOCATION);
107
108   tet_infoline("UtcDaliFontClientAtlasLimitation Disabled");
109   fontClient.EnableAtlasLimitation(false);
110   result = fontClient.IsAtlasLimitationEnabled();
111   DALI_TEST_EQUALS(false, result, TEST_LOCATION);
112   END_TEST;
113 }
114
115 const std::string DEFAULT_FONT_DIR("/resources/fonts");
116 const uint32_t    MAX_WIDTH_FIT_IN_ATLAS  = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
117 const uint32_t    MAX_HEIGHT_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
118
119 int UtcDaliFontClientAtlasLimitationEnabled(void)
120 {
121   TestApplication application;
122
123   char*             pathNamePtr = get_current_dir_name();
124   const std::string pathName(pathNamePtr);
125   free(pathNamePtr);
126
127   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
128   fontClient.EnableAtlasLimitation(true);
129
130   // The font file "DejaVuSans.ttf" is copied from Toolkit to Adaptor to make test-case of specific font-family.
131   // Note the block size depends on font-family.
132   // This is to create FontDescription and pass it to GetFontId with point-size (various cases).
133   TextAbstraction::FontDescription fontDescription;
134   fontDescription.path   = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
135   fontDescription.family = "DejaVuSans";
136   fontDescription.width  = TextAbstraction::FontWidth::NONE;
137   fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
138   fontDescription.slant  = TextAbstraction::FontSlant::NONE;
139
140   // Block's width or height are less than 512
141   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=200");
142   uint32_t                         pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
143   TextAbstraction::FontId          fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
144   TextAbstraction::GlyphBufferData glyphBufferData200;
145   glyphBufferData200.width  = 0;
146   glyphBufferData200.height = 0;
147   fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
148
149   DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData200.width, TEST_LOCATION);
150   DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData200.height, TEST_LOCATION);
151
152   // Block's width or height are  greater than 512 and less than 1024
153   uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
154   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=1000");
155   TextAbstraction::FontId          fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
156   TextAbstraction::GlyphBufferData glyphBufferData1000;
157   glyphBufferData1000.width  = 0;
158   glyphBufferData1000.height = 0;
159   fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
160
161   DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData1000.width, TEST_LOCATION);
162   DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData1000.height, TEST_LOCATION);
163
164   // Block's width or height are greater than 1024 and less than 2048
165   uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
166   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=2000");
167   TextAbstraction::FontId          fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
168   TextAbstraction::GlyphBufferData glyphBufferData2000;
169   glyphBufferData2000.width  = 0;
170   glyphBufferData2000.height = 0;
171   fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
172
173   DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData2000.width, TEST_LOCATION);
174   DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData2000.height, TEST_LOCATION);
175
176   END_TEST;
177 }
178
179 int UtcDaliFontClientAtlasLimitationDisabled(void)
180 {
181   TestApplication application;
182
183   char*             pathNamePtr = get_current_dir_name();
184   const std::string pathName(pathNamePtr);
185   free(pathNamePtr);
186
187   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
188   fontClient.EnableAtlasLimitation(false);
189
190   TextAbstraction::FontDescription fontDescription;
191   fontDescription.path   = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
192   fontDescription.family = "DejaVuSans";
193   fontDescription.width  = TextAbstraction::FontWidth::NONE;
194   fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
195   fontDescription.slant  = TextAbstraction::FontSlant::NONE;
196
197   // Block's width or height are less than 512
198   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=200");
199   uint32_t                         pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
200   TextAbstraction::FontId          fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
201   TextAbstraction::GlyphBufferData glyphBufferData200;
202   glyphBufferData200.width  = 0;
203   glyphBufferData200.height = 0;
204   fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
205
206   DALI_TEST_GREATER(512u, glyphBufferData200.width, TEST_LOCATION);  //93u
207   DALI_TEST_GREATER(512u, glyphBufferData200.height, TEST_LOCATION); //115u
208
209   // Block's width or height are  greater than 512 and less than 1024
210   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=1000");
211   uint32_t                         pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
212   TextAbstraction::FontId          fontId1000    = fontClient.GetFontId(fontDescription, pointSize1000);
213   TextAbstraction::GlyphBufferData glyphBufferData1000;
214   glyphBufferData1000.width  = 0;
215   glyphBufferData1000.height = 0;
216   fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
217
218   DALI_TEST_GREATER(512u, glyphBufferData1000.width, TEST_LOCATION);  //462u
219   DALI_TEST_GREATER(glyphBufferData1000.height, 512u, TEST_LOCATION); //574u
220
221   // Block's width or height are greater than 1024 and less than 2048
222   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=2000");
223   uint32_t                         pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
224   TextAbstraction::FontId          fontId2000    = fontClient.GetFontId(fontDescription, pointSize2000);
225   TextAbstraction::GlyphBufferData glyphBufferData2000;
226   glyphBufferData2000.width  = 0;
227   glyphBufferData2000.height = 0;
228   fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
229
230   DALI_TEST_GREATER(1024u, glyphBufferData2000.width, TEST_LOCATION);  //924u
231   DALI_TEST_GREATER(glyphBufferData2000.height, 1024u, TEST_LOCATION); //1148u
232
233   // Test GlyphBufferData move
234   TextAbstraction::GlyphBufferData movedGlyphBufferData2000 = std::move(glyphBufferData2000);
235
236   for(int i = 0; i < 50; ++i)
237   {
238     TextAbstraction::GlyphBufferData dummy = std::move(movedGlyphBufferData2000);
239     movedGlyphBufferData2000               = std::move(dummy);
240
241     // Test moved GlyphBufferData destruct well
242   }
243
244   DALI_TEST_GREATER(1024u, movedGlyphBufferData2000.width, TEST_LOCATION);  //924u
245   DALI_TEST_GREATER(movedGlyphBufferData2000.height, 1024u, TEST_LOCATION); //1148u
246
247   END_TEST;
248 }
249
250 int UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas(void)
251 {
252   TestApplication application;
253   tet_infoline(" UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas ");
254
255   bool                        isChanged;
256   TextAbstraction::FontClient fontClient;
257   fontClient = TextAbstraction::FontClient::Get();
258
259   Size defaultTextAtlasSize              = fontClient.GetDefaultTextAtlasSize();
260   Size maximumTextAtlasSize              = fontClient.GetMaximumTextAtlasSize();
261   Size currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
262
263   // TODO : This UTC pass only if we don't create fontClient plugin. Currently we always create plugin at Get API, due to performance
264   //tet_infoline("CurrentMaximumBlockSizeFitInAtlas start with default ");
265   //DALI_TEST_EQUALS(currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, TEST_LOCATION);
266
267   currentMaximumBlockSizeFitInAtlas = defaultTextAtlasSize;
268
269   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current ");
270   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(currentMaximumBlockSizeFitInAtlas);
271   DALI_TEST_CHECK(isChanged);
272
273   Size decreaseOnlyWidth(currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height);
274   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with width < current ");
275   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyWidth);
276   DALI_TEST_CHECK(isChanged);
277
278   Size decreaseOnlyHeigth(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height - 1u);
279   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with height < current ");
280   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyHeigth);
281   DALI_TEST_CHECK(isChanged);
282
283   Size decreaseBoth(currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height - 1u);
284   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with size < current ");
285   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseBoth);
286   DALI_TEST_CHECK(isChanged);
287
288   Size increaseOnlyWidth(maximumTextAtlasSize.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
289   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with width > max ");
290   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyWidth);
291   DALI_TEST_CHECK(!isChanged);
292
293   Size increaseOnlyHeigth(currentMaximumBlockSizeFitInAtlas.width, maximumTextAtlasSize.height + 1u);
294   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with height > max ");
295   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyHeigth);
296   DALI_TEST_CHECK(!isChanged);
297
298   Size increaseBoth(maximumTextAtlasSize.width + 1u, maximumTextAtlasSize.height + 1u);
299   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size > max ");
300   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseBoth);
301   DALI_TEST_CHECK(!isChanged);
302
303   currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
304   if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
305   {
306     tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current < size < max ");
307     Size increaseWidth = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
308     isChanged          = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseWidth);
309     DALI_TEST_CHECK(isChanged);
310     currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
311
312     Size increaseHeigth = Size(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height + 1u);
313     isChanged           = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseHeigth);
314     DALI_TEST_CHECK(isChanged);
315     currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
316
317     Size sizeLessThanMax = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height + 1u);
318     isChanged            = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(sizeLessThanMax);
319
320     if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
321     {
322       DALI_TEST_CHECK(isChanged);
323     }
324     else
325     {
326       DALI_TEST_CHECK(!isChanged);
327     }
328
329     currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
330
331     DALI_TEST_NOT_EQUALS(currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, 0.0f, TEST_LOCATION);
332     DALI_TEST_EQUALS(currentMaximumBlockSizeFitInAtlas, sizeLessThanMax, TEST_LOCATION);
333
334     tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size == max ");
335     isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(maximumTextAtlasSize);
336     DALI_TEST_CHECK(!isChanged);
337   }
338
339   currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
340   DALI_TEST_NOT_EQUALS(currentMaximumBlockSizeFitInAtlas, maximumTextAtlasSize, 0.0f, TEST_LOCATION);
341
342   END_TEST;
343 }
344
345 int UtcDaliFontClientTextAtlasConstants(void)
346 {
347   TestApplication application;
348   tet_infoline(" UtcDaliFontClientTextAtlasConstants ");
349
350   TextAbstraction::FontClient fontClient;
351   fontClient = TextAbstraction::FontClient::Get();
352
353   Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
354   Size defaultTextAtlasWidthHeight(TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_HEIGHT);
355   DALI_TEST_EQUALS(defaultTextAtlasSize, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE, TEST_LOCATION);
356   DALI_TEST_EQUALS(defaultTextAtlasSize, defaultTextAtlasWidthHeight, TEST_LOCATION);
357
358   Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
359   Size maxTextAtlasWidthHeight(TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT);
360   DALI_TEST_EQUALS(maximumTextAtlasSize, TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE, TEST_LOCATION);
361   DALI_TEST_EQUALS(maximumTextAtlasSize, maxTextAtlasWidthHeight, TEST_LOCATION);
362
363   uint32_t numberOfPointsPerOneUnitOfPointSize = fontClient.GetNumberOfPointsPerOneUnitOfPointSize();
364   DALI_TEST_EQUALS(numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION);
365
366   END_TEST;
367 }
368
369 using namespace Dali::TextAbstraction;
370
371 int UtcDaliFontClientGetDefaultFonts(void)
372 {
373   TestApplication application;
374   tet_infoline(" UtcDaliFontClientGetDefaultFonts ");
375
376   FontClient fontClient;
377   fontClient = FontClient::Get();
378
379   FontList fontList;
380   fontClient.GetDefaultFonts(fontList);
381
382   std::ostringstream oss;
383   oss << fontList << std::endl;
384
385   tet_printf("FontList: %s", oss.str().c_str());
386   DALI_TEST_CHECK(fontList.size() > 0);
387
388   END_TEST;
389 }
390
391 int UtcDaliFontClientGetSystemFonts(void)
392 {
393   TestApplication application;
394   tet_infoline(" UtcDaliFontClientGetSystemFonts ");
395
396   FontClient fontClient;
397   fontClient = FontClient::Get();
398
399   FontList fontList;
400   fontClient.GetSystemFonts(fontList);
401
402   std::ostringstream oss;
403   oss << fontList << std::endl;
404
405   tet_printf("FontList: %s", oss.str().c_str());
406   DALI_TEST_CHECK(fontList.size() > 0);
407
408   const PointSize26Dot6 pointSize = fontClient.GetPointSize(fontList.size());
409   DALI_TEST_EQUALS(pointSize, FontClient::DEFAULT_POINT_SIZE, TEST_LOCATION);
410
411   END_TEST;
412 }
413
414 std::ostream& operator<<(std::ostream& o, const FontDescription& description)
415 {
416   o << "Font path: " << description.path << " family: "
417     << " width : " << description.width << " weight : " << description.weight << " slant : " << description.slant << std::endl;
418   return o;
419 }
420
421 int UtcDaliFontClientGetDefaultPlatformFontDescription(void)
422 {
423   TestApplication application;
424   tet_infoline(" UtcDaliFontClientGetDefaultPlatformFontDescription");
425
426   FontClient fontClient;
427   fontClient = FontClient::Get();
428
429   FontDescription fontDescription;
430   fontClient.GetDefaultPlatformFontDescription(fontDescription);
431
432   std::ostringstream oss;
433   oss << fontDescription;
434   tet_printf("%s", oss.str().c_str());
435
436   DALI_TEST_CHECK(fontDescription.path.empty() == false);
437
438   FontId fontId = fontClient.FindFallbackFont('A',
439                                               fontDescription,
440                                               FontClient::DEFAULT_POINT_SIZE,
441                                               true);
442
443   bool supported = fontClient.IsCharacterSupportedByFont(fontId, 'A');
444   DALI_TEST_EQUALS(supported, true, TEST_LOCATION);
445   END_TEST;
446 }
447
448 namespace
449 {
450 constexpr uint8_t U1               = 1u;
451 constexpr uint8_t U2               = 2u;
452 constexpr uint8_t U3               = 3u;
453 constexpr uint8_t U4               = 4u;
454 constexpr uint8_t U5               = 5u;
455 constexpr uint8_t U6               = 6u;
456 constexpr uint8_t U0               = 0u;
457 constexpr uint8_t UTF8_LENGTH[256] = {
458   U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
459   U1,
460   U1,
461   U1,
462   U1,
463   U1,
464   U1,
465   U1,
466   U1,
467   U1,
468   U1, //
469   U1,
470   U1,
471   U1,
472   U1,
473   U1,
474   U1,
475   U1,
476   U1,
477   U1,
478   U1, //
479   U1,
480   U1,
481   U1,
482   U1,
483   U1,
484   U1,
485   U1,
486   U1,
487   U1,
488   U1, //
489   U1,
490   U1,
491   U1,
492   U1,
493   U1,
494   U1,
495   U1,
496   U1,
497   U1,
498   U1, //
499   U1,
500   U1,
501   U1,
502   U1,
503   U1,
504   U1,
505   U1,
506   U1,
507   U1,
508   U1, //
509   U1,
510   U1,
511   U1,
512   U1,
513   U1,
514   U1,
515   U1,
516   U1,
517   U1,
518   U1, //
519   U1,
520   U1,
521   U1,
522   U1,
523   U1,
524   U1,
525   U1,
526   U1,
527   U1,
528   U1, //
529   U1,
530   U1,
531   U1,
532   U1,
533   U1,
534   U1,
535   U1,
536   U1,
537   U1,
538   U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters)
539   U1,
540   U1,
541   U1,
542   U1,
543   U1,
544   U1,
545   U1,
546   U1,
547   U1,
548   U1, //
549   U1,
550   U1,
551   U1,
552   U1,
553   U1,
554   U1,
555   U1,
556   U1,
557   U1,
558   U1, //
559   U1,
560   U1,
561   U1,
562   U1,
563   U1,
564   U1,
565   U1,
566   U1,
567   U1,
568   U1, //
569   U1,
570   U1,
571   U1,
572   U1,
573   U1,
574   U1,
575   U1,
576   U1,
577   U1,
578   U1, //
579   U1,
580   U1,
581   U1,
582   U1,
583   U1,
584   U1,
585   U1,
586   U1,
587   U1,
588   U1, //
589   U1,
590   U1,
591   U1,
592   U1,
593   U1,
594   U1,
595   U1,
596   U1,
597   U1,
598   U1, //
599   U1,
600   U1,
601   U1,
602   U1,
603   U1,
604   U1,
605   U1,
606   U1,
607   U1,
608   U1, //
609   U1,
610   U1,
611   U1,
612   U1,
613   U1,
614   U1,
615   U1,
616   U1,
617   U1,
618   U1, //
619   U1,
620   U1,
621   U1,
622   U1,
623   U1,
624   U1,
625   U1,
626   U1,
627   U1,
628   U1, //
629   U1,
630   U1,
631   U1,
632   U1,
633   U1,
634   U1,
635   U1,
636   U1,
637   U1,
638   U1, //
639   U1,
640   U1, //
641
642   U2,
643   U2,
644   U2,
645   U2,
646   U2,
647   U2,
648   U2,
649   U2,
650   U2,
651   U2, //
652   U2,
653   U2,
654   U2,
655   U2,
656   U2,
657   U2,
658   U2,
659   U2,
660   U2,
661   U2, // lead byte = 110x xxxx (U+0080 - U+07FF)
662   U2,
663   U2,
664   U2,
665   U2,
666   U2,
667   U2,
668   U2,
669   U2,
670   U2,
671   U2, //
672   U2,
673   U2, //
674
675   U3,
676   U3,
677   U3,
678   U3,
679   U3,
680   U3,
681   U3,
682   U3,
683   U3,
684   U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF)
685   U3,
686   U3,
687   U3,
688   U3,
689   U3,
690   U3, //
691
692   U4,
693   U4,
694   U4,
695   U4,
696   U4,
697   U4,
698   U4,
699   U4, // lead byte = 1111 0xxx (U+10000 - U+1FFFFF)
700
701   U5,
702   U5,
703   U5,
704   U5, // lead byte = 1111 10xx (U+200000 - U+3FFFFFF)
705
706   U6,
707   U6, // lead byte = 1111 110x (U+4000000 - U+7FFFFFFF)
708
709   U0,
710   U0, // Non valid.
711 };
712
713 constexpr uint8_t CR = 0xd;
714 constexpr uint8_t LF = 0xa;
715
716 uint8_t GetUtf8Length(uint8_t utf8LeadByte)
717 {
718   return UTF8_LENGTH[utf8LeadByte];
719 }
720
721 uint32_t Utf8ToUtf32(const uint8_t* const utf8, uint32_t length, uint32_t* utf32)
722 {
723   uint32_t numberOfCharacters = 0u;
724
725   const uint8_t* begin = utf8;
726   const uint8_t* end   = utf8 + length;
727
728   for(; begin < end; ++numberOfCharacters)
729   {
730     const uint8_t leadByte = *begin;
731
732     switch(UTF8_LENGTH[leadByte])
733     {
734       case U1:
735       {
736         if(CR == leadByte)
737         {
738           // Replace CR+LF or CR by LF
739           *utf32++ = LF;
740
741           // Look ahead if the next one is a LF.
742           ++begin;
743           if(begin < end)
744           {
745             if(LF == *begin)
746             {
747               ++begin;
748             }
749           }
750         }
751         else
752         {
753           *utf32++ = leadByte;
754           begin++;
755         }
756         break;
757       }
758
759       case U2:
760       {
761         uint32_t& code = *utf32++;
762         code           = leadByte & 0x1fu;
763         begin++;
764         code <<= 6u;
765         code |= *begin++ & 0x3fu;
766         break;
767       }
768
769       case U3:
770       {
771         uint32_t& code = *utf32++;
772         code           = leadByte & 0x0fu;
773         begin++;
774         code <<= 6u;
775         code |= *begin++ & 0x3fu;
776         code <<= 6u;
777         code |= *begin++ & 0x3fu;
778         break;
779       }
780
781       case U4:
782       {
783         uint32_t& code = *utf32++;
784         code           = leadByte & 0x07u;
785         begin++;
786         code <<= 6u;
787         code |= *begin++ & 0x3fu;
788         code <<= 6u;
789         code |= *begin++ & 0x3fu;
790         code <<= 6u;
791         code |= *begin++ & 0x3fu;
792         break;
793       }
794
795       case U5:
796       {
797         uint32_t& code = *utf32++;
798         code           = leadByte & 0x03u;
799         begin++;
800         code <<= 6u;
801         code |= *begin++ & 0x3fu;
802         code <<= 6u;
803         code |= *begin++ & 0x3fu;
804         code <<= 6u;
805         code |= *begin++ & 0x3fu;
806         code <<= 6u;
807         code |= *begin++ & 0x3fu;
808         break;
809       }
810
811       case U6:
812       {
813         uint32_t& code = *utf32++;
814         code           = leadByte & 0x01u;
815         begin++;
816         code <<= 6u;
817         code |= *begin++ & 0x3fu;
818         code <<= 6u;
819         code |= *begin++ & 0x3fu;
820         code <<= 6u;
821         code |= *begin++ & 0x3fu;
822         code <<= 6u;
823         code |= *begin++ & 0x3fu;
824         code <<= 6u;
825         code |= *begin++ & 0x3fu;
826         break;
827       }
828
829       case U0: // Invalid case
830       {
831         begin++;
832         *utf32++ = 0x20; // Use white space
833         break;
834       }
835     }
836   }
837
838   return numberOfCharacters;
839 }
840
841 TextAbstraction::FontId SetupBitmapFont()
842 {
843   struct GlyphDesc
844   {
845     GlyphDesc()
846     {
847     }
848     GlyphDesc(const std::string& url, const std::string& utf8)
849     {
850       this->url = url;
851       std::copy(utf8.begin(), utf8.end(), this->utf8);
852     }
853     std::string url;
854     uint8_t     utf8[4];
855   };
856   std::vector<GlyphDesc> glyphs;
857
858   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0030.png", ":"});
859   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0031.png", "0"});
860   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0032.png", "1"});
861   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0033.png", "2"});
862   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0034.png", "3"});
863   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0035.png", "4"});
864   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0036.png", "5"});
865   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0037.png", "6"});
866   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0038.png", "7"});
867   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u0039.png", "8"});
868   glyphs.push_back({TEST_RESOURCE_DIR "/fonts/bitmap/u003a.png", "9"});
869
870   TextAbstraction::BitmapFont bitmapFont;
871   bitmapFont.glyphs.reserve(glyphs.size());
872   bitmapFont.name               = "Digits";
873   bitmapFont.underlinePosition  = 0.f;
874   bitmapFont.underlineThickness = 0.f;
875   bitmapFont.isColorFont        = true;
876
877   for(const auto& glyph : glyphs)
878   {
879     uint32_t c = 0u;
880     Utf8ToUtf32(glyph.utf8, GetUtf8Length(glyph.utf8[0u]), &c);
881     TextAbstraction::BitmapGlyph bitmapGlyph(glyph.url, c, 34.f, 0.f);
882     bitmapFont.glyphs.push_back(std::move(bitmapGlyph));
883   }
884
885   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
886   return fontClient.GetFontId(bitmapFont);
887 }
888
889 } // namespace
890
891 int UtcDaliFontClientTestBitmapFont(void)
892 {
893   TestApplication application;
894   tet_infoline(" UtcDaliFontClientTestBitmapFont");
895
896   FontClient fontClient;
897   fontClient = FontClient::Get();
898
899   auto bitmapFontId = SetupBitmapFont();
900
901   FontDescription fontDescription;
902   fontClient.GetDescription(bitmapFontId, fontDescription);
903   std::ostringstream oss;
904   oss << fontDescription;
905   tet_printf("Found: %d: %s", bitmapFontId, oss.str().c_str());
906
907   bool color = fontClient.IsColorGlyph(bitmapFontId, fontClient.GetGlyphIndex(bitmapFontId, '2'));
908   DALI_TEST_EQUALS(color, true, TEST_LOCATION);
909
910   DALI_TEST_EQUALS(fontClient.GetPointSize(bitmapFontId), FontClient::DEFAULT_POINT_SIZE, TEST_LOCATION);
911
912   DALI_TEST_EQUALS(fontClient.IsCharacterSupportedByFont(bitmapFontId, '3'), true, TEST_LOCATION);
913   DALI_TEST_EQUALS(fontClient.IsCharacterSupportedByFont(bitmapFontId, 'a'), false, TEST_LOCATION);
914
915   END_TEST;
916 }