Merge "rollback : support evas engine type" into tizen_2.1
[platform/framework/native/uifw.git] / src / graphics / FGrp_Font.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /*
19  * @file        FGrp_Font.cpp
20  * @brief       This is the implementation file for _Font class.
21  *
22  */
23
24 #include "FGrp_Font.h"
25 #include "FGrp_FontFt2.h"
26
27 #include <unique_ptr.h>
28 #include <dirent.h>
29
30 #include <fontconfig/fontconfig.h>
31 #include <pango/pangocairo.h>
32 #include <unicode/uloc.h>
33
34 #include <FApp_AppInfo.h>
35
36 #include <FBaseByteBuffer.h>
37 #include <FBaseColArrayList.h>
38 #include <FBaseColIList.h>
39 #include <FBaseUtilStringUtil.h>
40 #include <FGrpDimension.h>
41 #include <FGrpPoint.h>
42 #include <FGrpRectangle.h>
43
44 #include <FBaseSysLog.h>
45 #include <FSys_EnvironmentImpl.h>
46 #include <FIoDirectory.h>
47
48 #include "FGrp_FontImpl.h"
49
50 #include "FGrp_CanvasRasterOp.h"
51 #include "FGrp_FontRsrcManager.h"
52 #include "FGrp_FontBidiUtil.h"
53
54 #include "FGrp_Canvas.h"
55
56 #include "util/FGrp_UtilTemplate.h"
57
58 //#define USE_FONTCONFIG
59 #define USE_EMOJI
60 #define SYNCHRONIZATION_2_0
61 #define __pNativeFont __sharedFont.get()
62
63 #define GET_FONT_SIZE_PROPERTY(sizeProperty, rtnValue) \
64         { \
65                 bool rtn = __pNativeFont->GetFontSizeProperty(sizeProperty); \
66                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to get font size property"); \
67         }
68 #define GET_FONT_PROPERTY(property, rtnValue) \
69         { \
70                 bool rtn = __pNativeFont->GetFontProperty(property); \
71                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to get font property"); \
72         }
73 #define LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, rtnValue) \
74         { \
75                 _Font* pThis = const_cast <_Font*>(this); \
76                 bool rtn = pThis->LoadGlyph(character, &pFontGlyphData); \
77                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to load glyph data"); \
78         }
79 #define UNLOAD_GLYPH_DATA_CONST(pFontGlyphData) \
80         { \
81                 _Font* pThis = const_cast <_Font*>(this); \
82                 pThis->UnloadGlyph(&pFontGlyphData); \
83         }
84 #define APPLY_ATTRIBUTE(rtnValue) \
85         { \
86                 _Font* pFont = const_cast <_Font*>(this); \
87                 bool rtn = pFont->ApplyAttribute(); \
88                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to apply font attribute"); \
89         }
90 #define SAMPLE_LANGUAGE_EMPTY ""
91
92
93 using namespace Tizen::Base;
94 using namespace Tizen::Base::Collection;
95 using namespace Tizen::Base::Utility;
96 using namespace Tizen::Graphics;
97 using namespace Tizen::Io;
98 using namespace Tizen::System;
99
100 namespace // unnamed
101 {
102
103 const _Util::FixedPoint26_6 _SYSTEM_DEFAULT_FONT_SIZE(16);
104 const long _MEDIUM_FONT_BOLD_WEIGHT = 600;
105
106 template<typename Type>
107 inline void
108 _ExpandBounds(Type curX, Type curY, Type& x1, Type& y1, Type& x2, Type& y2)
109 {
110         if (curX > x2)
111         {
112                 x2 = curX;
113         }
114
115         if (curX < x1)
116         {
117                 x1 = curX;
118         }
119
120         if (curY > y2)
121         {
122                 y2 = curY;
123         }
124
125         if (curY < y1)
126         {
127                 y1 = curY;
128         }
129 }
130
131 result
132 _GetSystemFontList(Tizen::Base::Collection::IList& list)
133 {
134 #ifdef USE_FONTCONFIG
135         FcPattern* pPattern = null;
136         FcFontSet* pSet = null;
137         FcObjectSet* pObjectSet = null;
138         const char* pLang = null;
139         const char* fcStyle = "Regular";
140
141         pPattern = FcPatternCreate();
142         SysTryCatch(NID_GRP, pPattern, , E_SYSTEM, "[E_SYSTEM] Failed to FcPatternCreate()");
143
144         // language and style
145         FcPatternAddString(pPattern, FC_STYLE, (FcChar8*)fcStyle);
146
147         // RFC3066 formatted 2-level language identifier will be returned.
148         // e.g., en-NR, ar-SD, byn, tig etc.
149         // but, fontconfig only need 1-level language identifier having maximum 3 letters.
150         pLang = uloc_getDefault();
151
152         if (pLang != null)
153         {
154                         char lang3Letters[4] = {0,};
155                         strncpy(lang3Letters, pLang, 3);
156
157                         for (int i = 0; i < 3; i++)
158                         {
159                                 if (lang3Letters[i] == '-' || lang3Letters[i] == '_')
160                                 {
161                                         lang3Letters[i] = 0;
162                                         break;
163                                 }
164                         }
165
166                         FcPatternAddString(pPattern, FC_LANG, (FcChar8*)lang3Letters);
167         }
168
169         pObjectSet = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FILE, NULL);
170         SysTryCatch(NID_GRP, pObjectSet, , E_SYSTEM, "[E_SYSTEM] Failed to FcObjectSetBuild()");
171
172         pSet = FcFontList(NULL, pPattern, pObjectSet);
173         SysTryCatch(NID_GRP, pSet, , E_SYSTEM, "[E_SYSTEM] Failed to init fontconfig");
174
175         {
176                 _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
177                 String defaultFontFaceName(mgr.GetDefaultSystemFont().GetFaceName());
178
179                 bool defaultFontExists = false;
180
181                 list.RemoveAll(true);
182                 FcChar8* pName = null;
183
184                 for (int i = 0; i < pSet->nfont; i++)
185                 {
186                         if (FcPatternGetString(pSet->fonts[i], FC_FILE, 0, &pName) == FcResultMatch)
187                         {
188                                 String* pFamilyName = new (std::nothrow) String(Tizen::Graphics::_Font::GetFaceName(String((char*)pName)));
189                                 SysTryCatch(NID_GRP, pFamilyName, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
190
191                                 list.Add(*pFamilyName);
192
193                                 if (*pFamilyName == defaultFontFaceName)
194                                 {
195                                         defaultFontExists = true;
196                                 }
197                         }
198                 }
199
200                 if (defaultFontExists == false)
201                 {
202                         String* pDefaultFontName = new (std::nothrow) String(defaultFontFaceName);
203                         SysTryCatch(NID_GRP, pDefaultFontName, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
204
205                         list.InsertAt(*pDefaultFontName, 0);
206                 }
207         }
208
209         // destroy
210         FcFontSetDestroy(pSet);
211         FcObjectSetDestroy(pObjectSet);
212         FcPatternDestroy(pPattern);
213
214         return E_SUCCESS;
215
216 CATCH:
217         list.RemoveAll(true);
218
219         // destroy, but before doing that check if those value has been created or not.
220         if (pSet)
221         {
222                 FcFontSetDestroy(pSet);
223         }
224
225         if (pObjectSet)
226         {
227                 FcObjectSetDestroy(pObjectSet);
228         }
229
230         if (pPattern)
231         {
232                 FcPatternDestroy(pPattern);
233         }
234
235         return GetLastResult();
236
237 #else
238         const String FONT_DIR_PATH[] =
239         {
240 //              L"/usr/share/fallback_fonts",
241                 L"/usr/share/fonts"
242         };
243
244         list.RemoveAll(true);
245
246         const int FONT_DIR_PATH_COUNT = sizeof(FONT_DIR_PATH) / sizeof(FONT_DIR_PATH[0]);
247
248         for (int i = 0; i < FONT_DIR_PATH_COUNT; i++)
249         {
250                 Directory directory;
251
252                 result r = directory.Construct(FONT_DIR_PATH[i]);
253
254                 if (!IsFailed(r))
255                 {
256                         std::auto_ptr<DirEnumerator> dirEnumerator(directory.ReadN());
257
258                         while (dirEnumerator->MoveNext() == E_SUCCESS)
259                         {
260                                 DirEntry entry = dirEnumerator->GetCurrentDirEntry();
261
262                                 if (entry.IsDirectory() == false && entry.IsHidden() == false)
263                                 {
264                                         Tizen::Base::Utility::StringTokenizer formatTok(entry.GetName(), ".");
265                                         String token;
266
267                                         while (formatTok.GetTokenCount())
268                                         {
269                                                 formatTok.GetNextToken(token);
270                                         }
271
272                                         if (token.Equals("ttf",false) || token.Equals("ttc",false))
273                                         {
274                                                 String fullName;
275                                                 fullName.Append(FONT_DIR_PATH[i]);
276                                                 fullName.Append(L"/");
277                                                 fullName.Append(entry.GetName());
278
279                                                 bool isNewFont = true;
280
281                                                 String* pFamilyName = new (std::nothrow) String(Tizen::Graphics::_Font::GetFaceName(fullName));
282                                                 SysTryCatch(NID_GRP, pFamilyName, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
283
284                                                 for (int idx = 0; idx < list.GetCount(); idx++)
285                                                 {
286                                                         String* pName = static_cast <String*>(list.GetAt(idx));
287
288                                                         if (pName == null)
289                                                         {
290                                                                 continue;
291                                                         }
292
293                                                         if (*pName == *pFamilyName)
294                                                         {
295                                                                 isNewFont = false;
296                                                                 break;
297                                                         }
298                                                 }
299
300                                                 if (isNewFont)
301                                                 {
302                                                         list.Add(*pFamilyName);
303                                                 }
304                                                 else
305                                                 {
306                                                         delete pFamilyName;
307                                                 }
308                                         }
309                                 }
310                         }
311                 }
312         }
313
314         return E_SUCCESS;
315
316 CATCH:
317
318         list.RemoveAll(true);
319
320         return GetLastResult();
321
322 #endif
323 }
324
325 typedef Tizen::Graphics::_Font::SystemPixel _SystemPixel;
326 typedef Tizen::Graphics::_Util::ScratchPad<_SystemPixel> _ScratchPad32;
327
328
329 unsigned long
330 _ComposeColor(unsigned long color32, int opacity)
331 {
332         unsigned char alpha = (unsigned char) (((color32) >> 24));
333         unsigned char red = (unsigned char) (((color32) >> 16));
334         unsigned char green = (unsigned char) (((color32) >> 8));
335         unsigned char blue = (unsigned char) ((color32));
336
337         alpha = (unsigned char) ((alpha * opacity + 255) >> 8);
338         red = (unsigned char) ((red * opacity + 255) >> 8);
339         green = (unsigned char) ((green * opacity + 255) >> 8);
340         blue = (unsigned char) ((blue * opacity + 255) >> 8);
341
342         return (unsigned long) (((unsigned long) (alpha) << 24) | ((unsigned long) (red) << 16) | ((unsigned long) (green) << 8) | (unsigned long) (blue));
343 }
344
345 void
346 _SetColor(cairo_t* pCairo, unsigned long composedColor)
347 {
348         double a = ((composedColor >> 24) & 0xFF) * 1.0 / 255.0;
349         double r = ((composedColor >> 16) & 0xFF) * 1.0 / 255.0;
350         double g = ((composedColor >> 8) & 0xFF) * 1.0 / 255.0;
351         double b = ((composedColor >> 0) & 0xFF) * 1.0 / 255.0;
352
353         cairo_set_source_rgba(pCairo, r, g, b, a);
354 }
355
356 template<typename T>
357 inline T
358 _TempMin(T a, T b)
359 {
360         return (a < b) ? a : b;
361 }
362 #define BLEND_ALPHA_COMPONEMT(srcA, dstA) (_TempMin <unsigned long>((srcA) + (dstA) - (((srcA) * (dstA)) >> 8), 0xFF));
363
364 struct _NativeGfxEngine
365 {
366         cairo_t* pCairo;
367         cairo_surface_t* pCairoSurface;
368
369         _NativeGfxEngine()
370                 : pCairo(0)
371                 , pCairoSurface(0)
372         {
373         }
374         ~_NativeGfxEngine()
375         {
376                 if (pCairo)
377                 {
378                         cairo_destroy(pCairo);
379                 }
380
381                 if (pCairoSurface)
382                 {
383                         cairo_surface_destroy(pCairoSurface);
384                 }
385
386         }
387 };
388
389 // ISO 15924
390 const char* _SampleLanguages[] =
391 {
392         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_COMMON
393         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_INHERITED
394         "ar",                                                                                                   // G_UNICODE_SCRIPT_ARABIC
395         "hy",                                                                                                   // G_UNICODE_SCRIPT_ARMENIAN
396         "bn",                                                                                                   // G_UNICODE_SCRIPT_BENGALI
397         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_BOPOMOFO
398         "chr",                                                                                                  // G_UNICODE_SCRIPT_CHEROKEE
399         "cop",                                                                                                  // G_UNICODE_SCRIPT_COPTIC
400         "ru",                                                                                                   // G_UNICODE_SCRIPT_CYRILLIC
401         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_DESERET
402         "hi",                                                                                                   // G_UNICODE_SCRIPT_DEVANAGARI
403         "am",                                                                                                   // G_UNICODE_SCRIPT_ETHIOPIC
404         "ka",                                                                                                   // G_UNICODE_SCRIPT_GEORGIAN
405         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_GOTHIC
406         "el",                                                                                                   // G_UNICODE_SCRIPT_GREEK
407         "gu",                                                                                                   // G_UNICODE_SCRIPT_GUJARATI
408         "pa",                                                                                                   // G_UNICODE_SCRIPT_GURMUKHI
409         "zh",                                                                                                   // G_UNICODE_SCRIPT_HAN
410         "ko",                                                                                                   // G_UNICODE_SCRIPT_HANGUL
411         "he",                                                                                                   // G_UNICODE_SCRIPT_HEBREW
412         "ja",                                                                                                   // G_UNICODE_SCRIPT_HIRAGANA
413         "kn",                                                                                                   // G_UNICODE_SCRIPT_KANNADA
414         "ja",                                                                                                   // G_UNICODE_SCRIPT_KATAKANA
415         "km",                                                                                                   // G_UNICODE_SCRIPT_KHMER
416         "lo",                                                                                                   // G_UNICODE_SCRIPT_LAO
417         "en",                                                                                                   // G_UNICODE_SCRIPT_LATIN
418         "ml",                                                                                                   // G_UNICODE_SCRIPT_MALAYALAM
419         "mn",                                                                                                   // G_UNICODE_SCRIPT_MONGOLIAN
420         "my",                                                                                                   // G_UNICODE_SCRIPT_MYANMAR
421         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_OGHAM
422         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_OLD_ITALIC
423         "or",                                                                                                   // G_UNICODE_SCRIPT_ORIYA
424         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_RUNIC
425         "si",                                                                                                   // G_UNICODE_SCRIPT_SINHALA
426         "syr",                                                                                                  // G_UNICODE_SCRIPT_SYRIAC
427         "ta",                                                                                                   // G_UNICODE_SCRIPT_TAMIL
428         "te",                                                                                                   // G_UNICODE_SCRIPT_TELUGU
429         "dv",                                                                                                   // G_UNICODE_SCRIPT_THAANA
430         "th",                                                                                                   // G_UNICODE_SCRIPT_THAI
431         "bo",                                                                                                   // G_UNICODE_SCRIPT_TIBETAN
432         "iu",                                                                                                   // G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL
433         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_YI
434         "tl",                                                                                                   // G_UNICODE_SCRIPT_TAGALOG
435         "hnn",                                                                                                  // G_UNICODE_SCRIPT_HANUNOO
436         "bku",                                                                                                  // G_UNICODE_SCRIPT_BUHID
437         "tbw",                                                                                                  // G_UNICODE_SCRIPT_TAGBANWA
438         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_BRAILLE
439         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_CYPRIOT
440         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_LIMBU
441         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_OSMANYA
442         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_SHAVIAN
443         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_LINEAR_B
444         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_TAI_LE
445         "uga",                                                                                          // G_UNICODE_SCRIPT_UGARITIC
446         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_NEW_TAI_LUE
447         "bug",                                                                                                  // G_UNICODE_SCRIPT_BUGINESE
448         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_GLAGOLITIC
449         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_TIFINAGH
450         "syl",                                                                                                  // G_UNICODE_SCRIPT_SYLOTI_NAGRI
451         "peo",                                                                                                  // G_UNICODE_SCRIPT_OLD_PERSIAN
452         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_KHAROSHTHI
453         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_UNKNOWN
454         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_BALINESE
455         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_CUNEIFORM
456         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_PHOENICIAN
457         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_PHAGS_PA
458         "nqo"                                                                                                   // G_UNICODE_SCRIPT_NKO
459 };
460
461 const int _sampleLanguageCount = sizeof(_SampleLanguages) / sizeof(_SampleLanguages[0]);
462
463 unsigned long
464 GetPredefinedColor(const wchar_t unicode, unsigned long fgColor)
465 {
466 #ifdef USE_EMOJI
467         //
468         // Emoji Unicode List 176 + 76
469         //
470         static const unsigned long _EMOJI_BLACK = 0xFF000000;
471         static const unsigned long _EMOJI_BLUE = 0xFF0000FF;
472         static const unsigned long _EMOJI_GREEN = 0xFF00FF00;
473         static const unsigned long _EMOJI_RED = 0xFFFF0000;
474         static const unsigned long _EMOJI_ORANGE = 0xFFFF6600;
475         static const unsigned long _EMOJI_PURPLE = 0xFF9370DB;
476         static const unsigned long _EMOJI_DEEP_PURPLE = 0xFF800080;
477         static const unsigned long _EMOJI_DARK_BLUE = 0xFF00008B;
478         static const unsigned long _EMOJI_BROWN = 0xFFA52A2A;
479         static const unsigned long _NOT_EMOJI = 0;
480
481         static const wchar_t _MAX_EMOJI_UNICODE = 0xE757;
482         static const wchar_t _MIN_EMOJI_UNICODE = 0xE63E;
483
484         static const unsigned long _emojiTable[] =
485         {
486                 _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_ORANGE,
487                 _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_GREEN, _EMOJI_BLUE,
488                 _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_GREEN, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_PURPLE, _EMOJI_GREEN,
489                 _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_RED,
490                 _EMOJI_BLACK, _EMOJI_PURPLE, _EMOJI_RED, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_PURPLE, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK,
491                 _EMOJI_GREEN, _EMOJI_PURPLE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE,
492                 _EMOJI_BLUE, _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_ORANGE,
493                 _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_RED,
494                 _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_BLACK,
495                 _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE,
496                 _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_GREEN, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI,
497                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI,
498                 _NOT_EMOJI, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI,
499                 _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI,
500                 _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BLACK,
501                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_RED,
502                 _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK,
503                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_RED,
504                 _EMOJI_BLUE, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_ORANGE,
505                 _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_RED, _EMOJI_RED,
506                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_BLACK,
507                 _EMOJI_RED, _EMOJI_DARK_BLUE, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_BROWN, _EMOJI_BROWN, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_GREEN,
508                 _EMOJI_ORANGE, _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_PURPLE, _EMOJI_BLUE, _EMOJI_BLUE,
509                 _EMOJI_RED, _EMOJI_DEEP_PURPLE, _EMOJI_PURPLE, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_PURPLE, _EMOJI_DARK_BLUE, _EMOJI_ORANGE, _EMOJI_BLUE,
510                 _EMOJI_BLUE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_GREEN, _EMOJI_BLACK, _EMOJI_ORANGE,
511                 _EMOJI_RED, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_GREEN,
512                 _EMOJI_RED, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_GREEN, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BROWN,
513                 _EMOJI_ORANGE, _EMOJI_BROWN, _EMOJI_BROWN, _EMOJI_ORANGE, _EMOJI_DARK_BLUE, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BROWN, _EMOJI_ORANGE,
514                 _EMOJI_DEEP_PURPLE, _EMOJI_DEEP_PURPLE
515         };
516
517         if (unicode >= _MIN_EMOJI_UNICODE && unicode <= _MAX_EMOJI_UNICODE)
518         {
519                 if (_emojiTable[unicode - _MIN_EMOJI_UNICODE] != _NOT_EMOJI)
520                 {
521                         fgColor = _emojiTable[unicode - _MIN_EMOJI_UNICODE];
522                 }
523         }
524 #endif
525
526         return fgColor;
527 }
528
529 struct _TextFragment
530 {
531         _Util::String textFragment;
532         _IFont* pUsingFont;
533
534         _TextFragment(const _Util::String& string, _IFont* pFont)
535                 : textFragment(string)
536                 , pUsingFont(pFont)
537         {
538         }
539 };
540
541 }
542
543
544 namespace Tizen { namespace Graphics
545 {
546
547 _Font::_Font()
548 {
549         __fontAttrib.Init();
550 }
551
552 _Font::_Font(const _Font& obj)
553 {
554         this->__fontAttrib = obj.__fontAttrib;
555         this->__sharedFont = obj.__sharedFont;
556
557         return;
558 }
559
560 _Font::~_Font(void)
561 {
562 }
563
564 result
565 _Font::Construct(int style, _Util::FixedPoint26_6 pcSize)
566 {
567         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
568
569         // use default system font
570         _FontRsrcManager::SharedFontResource out;
571         result r = mgr.GetFont(style, pcSize, out);
572         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system default font", GetErrorMessage(r));
573
574         // assign it
575         __sharedFont = out;
576         __UpdateFontAttribute(style, pcSize);
577
578         return E_SUCCESS;
579 }
580
581 result
582 _Font::Construct(const Tizen::Base::String& fontName, int style, _Util::FixedPoint26_6 pcSize, bool isPathEnabled)
583 {
584         bool systemFont = false;
585         String appFontPath = L"";
586         result r = E_SUCCESS;
587
588         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
589         _FontRsrcManager::SharedFontResource out;
590
591         if (!Tizen::App::_AppInfo::IsOspCompat())
592         {
593                 _Util::WString fontNameTemp(fontName.GetPointer());
594                 _Util::WString appFontPathTemp(mgr.FindAppFontName(fontNameTemp));
595                 appFontPath.Append(appFontPathTemp.c_str());
596         }
597
598         // check if user want to use a app font
599         if (!appFontPath.IsEmpty())
600         {
601                 r = mgr.GetFont(appFontPath, style, pcSize, out);
602                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get app font", GetErrorMessage(r));
603         }
604         else
605         {
606                 IList* pList = GetSystemFontListN();
607                 int idx = 0;
608
609                 if (pList)
610                 {
611                         for (idx = 0; idx < pList->GetCount(); idx++)
612                         {
613                                 String* pName = static_cast <String*>(pList->GetAt(idx));
614
615                                 if (pName == null)
616                                 {
617                                         continue;
618                                 }
619
620                                 if (*pName == fontName)
621                                 {
622                                         systemFont = true;
623                                         break;
624                                 }
625                         }
626
627                         pList->RemoveAll(true);
628                         delete pList;
629                 }
630
631                 if (systemFont)
632                 {
633                         r = mgr.GetSystemFont(fontName, style, pcSize, out);
634                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
635                 }
636                 else if (isPathEnabled)
637                 {
638                         r = mgr.GetFont(fontName, style, pcSize, out);
639                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get font", GetErrorMessage(r));
640                 }
641         }
642
643         // assign it
644         __sharedFont = out;
645         __UpdateFontAttribute(style, pcSize);
646
647         return E_SUCCESS;
648 }
649
650 result
651 _Font::Construct(const Tizen::Base::ByteBuffer& fontData, int style, _Util::FixedPoint26_6 pcSize)
652 {
653         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
654
655         const byte* pBuffer = fontData.GetPointer();
656         int buffSize = fontData.GetLimit();
657
658         _FontRsrcManager::SharedFontResource out;
659         result r = mgr.GetFont(pBuffer, buffSize, style, pcSize, out);
660         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
661
662         // assign it
663         __sharedFont = out;
664         __UpdateFontAttribute(style, pcSize);
665
666         return E_SUCCESS;
667 }
668
669 bool
670 _Font::IsConstructed(void) const
671 {
672         return (__sharedFont.get() != null);
673 }
674
675 _Util::FixedPoint26_6
676 _Font::GetMaxHeight(void) const
677 {
678         return __fontAttrib.maxHeight;
679 }
680
681 _Util::FixedPoint26_6
682 _Font::GetMaxWidth(void) const
683 {
684         return __fontAttrib.maxWidth;
685 }
686
687 _Util::FixedPoint26_6
688 _Font::GetAscender(void) const
689 {
690         return __fontAttrib.ascender;
691 }
692
693 _Util::FixedPoint26_6
694 _Font::GetDescender(void) const
695 {
696         return __fontAttrib.descender;
697 }
698
699 result
700 _Font::GetLeftBear(wchar_t character, _Util::FixedPoint22_10& leftBear) const
701 {
702         APPLY_ATTRIBUTE(-1);
703
704         _IFont::Glyph* pFontGlyphData = null;
705         LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, E_SYSTEM);
706
707         // left bear is Glyph::xOffset, set it
708         leftBear = pFontGlyphData->xOffset;
709
710         UNLOAD_GLYPH_DATA_CONST(pFontGlyphData);
711
712         return E_SUCCESS;
713 }
714
715 result
716 _Font::GetRightBear(wchar_t character, _Util::FixedPoint22_10& rightBear) const
717 {
718         APPLY_ATTRIBUTE(-1);
719
720         _IFont::Glyph* pFontGlyphData = null;
721         LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, E_SYSTEM);
722
723         // right bear is Glyph::xOffset + GlyphBitmap::width, set it
724         rightBear = pFontGlyphData->xOffset + _Util::FixedPoint22_10(pFontGlyphData->image.width);
725
726         UNLOAD_GLYPH_DATA_CONST(pFontGlyphData);
727
728         return E_SUCCESS;
729 }
730
731 bool
732 _Font::IsBold(void) const
733 {
734         return ((__fontAttrib.style & FONT_STYLE_BOLD) ? true : false);
735 }
736
737 bool
738 _Font::IsItalic(void) const
739 {
740         return ((__fontAttrib.style & FONT_STYLE_ITALIC) ? true : false);
741 }
742
743 bool
744 _Font::IsPlain(void) const
745 {
746         return ((__fontAttrib.style & FONT_STYLE_PLAIN) ? true : false);
747 }
748
749 bool
750 _Font::IsStrikeOut(void) const
751 {
752         return __fontAttrib.strikeout;
753 }
754
755 bool
756 _Font::IsUnderlined(void) const
757 {
758         return __fontAttrib.underline;
759 }
760
761 _Util::FixedPoint26_6
762 _Font::GetSize(void) const
763 {
764         return __fontAttrib.size;
765 }
766
767 void
768 _Font::SetStrikeOut(bool strikeout)
769 {
770         __fontAttrib.strikeout = strikeout;
771 }
772
773 void
774 _Font::SetUnderline(bool underline)
775 {
776         __fontAttrib.underline = underline;
777 }
778
779 void
780 _Font::SetCharSpace(int pc_space)
781 {
782         __fontAttrib.charSpace = pc_space;
783 }
784
785 int
786 _Font::GetCharSpace(void) const
787 {
788         return __fontAttrib.charSpace;
789 }
790
791 int
792 _Font::GetLineThickness(void) const
793 {
794         return __fontAttrib.lineThickness;
795 }
796
797 Tizen::Base::String
798 _Font::GetFaceName(void) const
799 {
800         _IFont::Property property;
801         GET_FONT_PROPERTY(property, String());
802
803         return ((property.pFamilyName) ? String(property.pFamilyName) : String());
804 }
805
806 Tizen::Base::Collection::IList*
807 _Font::GetSystemFontListN(void)
808 {
809         std::auto_ptr<ArrayList> pList(new (std::nothrow) Tizen::Base::Collection::ArrayList);
810         SysTryReturn(NID_GRP, pList.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Fails to allocate memory");
811
812         result r = _GetSystemFontList(*pList);
813         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
814
815         return pList.release();
816
817 }
818
819 Tizen::Base::String
820 _Font::GetFaceName(const Tizen::Base::String& filePath)
821 {
822         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
823         _FontRsrcManager::SharedFontResource out;
824         String faceName;
825
826         result r = mgr.GetTempFont(filePath, FONT_STYLE_PLAIN, _SYSTEM_DEFAULT_FONT_SIZE, out);
827         SysTryReturn(NID_GRP, r == E_SUCCESS, faceName, r, "[%s] Failed to get font", GetErrorMessage(r));
828
829         if (r == E_SUCCESS)
830         {
831                 _IFont* pTempFont = out.get();
832
833                 _IFont::Property property;
834                 pTempFont->GetFontProperty(property);
835                 faceName = String(property.pFamilyName);
836         }
837
838         return faceName;
839 }
840
841 _IFont*
842 _Font::GetNativeFont(void) const
843 {
844         return __pNativeFont;
845 }
846
847 _Font*
848 _Font::CloneN()
849 {
850         // make the clone
851         _Font* pNativeFont = new (std::nothrow) _Font(*this);
852         SysTryReturn(NID_GRP, pNativeFont, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
853
854         // done
855         return pNativeFont;
856 }
857
858 bool
859 _Font::ApplyAttribute()
860 {
861         _IFont::Attrib fontAttrib;
862         bool rtn = __pNativeFont->GetAttrib(fontAttrib);
863         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
864
865         fontAttrib.size = __fontAttrib.size;
866         fontAttrib.style = _IFont::STYLE_NONE;
867         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
868         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
869         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
870         rtn = __pNativeFont->SetAttrib(fontAttrib);
871         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
872
873         return true;
874 }
875
876 result
877 _Font::GetTextExtent(int width, const _Util::String& text, bool outline, int& count, Dimension& pcDim) const
878 {
879         if (text.pStart == null || text.length <= 0)
880         {
881                 pcDim.SetSize(0, 0);
882                 count = 0;
883                 return E_SUCCESS;
884         }
885
886         _TextBidiPropertyWithReorder bidiProperty(text.pStart, text.length);
887
888         if (bidiProperty.HasBidi())
889         {
890                 typedef _Util::AccumList<_Util::Pair<int, int> > GapList;
891
892                 GapList gapList;
893
894                 result r = this->__GetTextExtentList(bidiProperty, gapList);
895
896                 if (r != E_SUCCESS)
897                 {
898                         return r;
899                 }
900
901                 int left = 0;
902                 int right = 0;
903                 int determinedCount = -1;
904
905                 for (GapList::Iterator i = gapList.Begin(); i != gapList.End(); ++i)
906                 {
907                         left = (i->first < left) ? i->first : left;
908                         right = (i->second > right) ? i->second : right;
909
910                         if (determinedCount < 0 && i->first < width && i->second >= width)
911                         {
912                                 if (i != gapList.Begin())
913                                 {
914                                         if (i - gapList.Begin() - 1 < text.length)
915                                         {
916                                                 determinedCount = bidiProperty.pBidiIndex[i - gapList.Begin() - 1];
917                                         }
918                                         else
919                                         {
920                                                 determinedCount = text.length;
921                                         }
922                                 }
923                                 else
924                                 {
925                                         determinedCount = bidiProperty.pBidiIndex[0];
926                                 }
927                         }
928                 }
929
930                 if (right - left <= width)
931                 {
932                         pcDim.SetSize(right - left, __fontAttrib.size.ToInt());
933                         count = text.length;
934                 }
935                 else if (determinedCount > 0 && right - left > 0)
936                 {
937                         int expectedValue = width * text.length / (right - left);
938                         int tolerance = _Util::Abs(expectedValue - determinedCount);
939                         tolerance = (tolerance == 0) ? 2 : tolerance;
940
941                         int tempCount = expectedValue <= determinedCount ? determinedCount + tolerance : determinedCount + (tolerance * 2);
942                         tempCount = tempCount > text.length ? text.length : tempCount;
943
944                         tempCount++;
945
946                         while (right - left > width)
947                         {
948                                 _TextBidiPropertyWithReorder determinedBidiProperty(text.pStart, --tempCount);
949
950                                 GapList determinedGapList;
951
952                                 result r = this->__GetTextExtentList(determinedBidiProperty, determinedGapList);
953
954                                 if (r != E_SUCCESS)
955                                 {
956                                         return r;
957                                 }
958
959                                 left = 0;
960                                 right = 0;
961
962                                 for (GapList::Iterator i = determinedGapList.Begin(); i != determinedGapList.End(); ++i)
963                                 {
964                                         left = (i->first < left) ? i->first : left;
965                                         right = (i->second > right) ? i->second : right;
966                                 }
967                         }
968
969                         pcDim.SetSize(right - left, __fontAttrib.size.ToInt());
970                         count = tempCount;
971                 }
972                 else
973                 {
974                         pcDim.SetSize(0, 0);
975                         count = 0;
976                 }
977
978                 return E_SUCCESS;
979         }
980         else
981         {
982                 return this->__GetTextExtent(width, text, outline, count, pcDim);
983         }
984
985         return E_SUCCESS;
986 }
987
988 result
989 _Font::__GetTextExtent(int width, const _Util::String& text, bool outline, int& count, Dimension& pcDim) const
990 {
991         if (text.pStart == null)
992         {
993                 pcDim.SetSize(0, 0);
994                 SysTryReturn(NID_GRP, false, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The given string is invalid.");
995         }
996
997         int preX1 = 0x7FFFFFFF;
998         int preY1 = 0x7FFFFFFF;
999         int preX2 = -0x7FFFFFFF;
1000         int preY2 = -0x7FFFFFFF;
1001
1002         int x1 = 0x7FFFFFFF;
1003         int y1 = 0x7FFFFFFF;
1004         int x2 = -0x7FFFFFFF;
1005         int y2 = -0x7FFFFFFF;
1006
1007         int curX = 0;
1008         int curY = 0;
1009
1010         int characters = 0;
1011         int italicSpace = 0;
1012         int boldSpace = 0;
1013
1014         long xVec = 0;
1015         long yVec = 0;
1016         int left = 0;
1017         wchar_t leftChar = 0;
1018
1019         _IFont::Glyph* pFontGlyphData = 0;
1020
1021         if (text.length == 0)
1022         {
1023                 count = 0;
1024                 pcDim.SetSize(0, 0);
1025                 return E_SUCCESS;
1026         }
1027
1028         _Font* pThis = const_cast <_Font*>(this);
1029
1030         APPLY_ATTRIBUTE(E_SYSTEM);
1031
1032         {
1033                 _IFont::SizeProperty sizeProperty;
1034                 GET_FONT_SIZE_PROPERTY(sizeProperty, E_SYSTEM);
1035
1036                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
1037                 {
1038                         italicSpace = (sizeProperty.ascender.ToInt() * 2) >> 4;
1039                 }
1040         }
1041
1042         _IFont::Property property;
1043         GET_FONT_PROPERTY(property, false);
1044
1045         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1046         {
1047                 _IFont::Attrib attr;
1048                 pThis->GetAttrib(attr);
1049                 boldSpace = static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1050         }
1051
1052         const wchar_t* pText = text.pStart;
1053         int length = text.length;
1054
1055         while (*pText && --length >= 0)
1056         {
1057                 // getting proper _Font instance for the specified text
1058                 _IFont* pFont = pThis->__GetFont(*pText);
1059
1060                 if (pFont != __pNativeFont)
1061                 {
1062                         _IFont::Attrib fontAttrib;
1063                         bool rtn = pFont->GetAttrib(fontAttrib);
1064                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
1065
1066                         fontAttrib.size = __fontAttrib.size;
1067                         fontAttrib.style = _IFont::STYLE_NONE;
1068                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1069                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1070                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1071                         rtn = pFont->SetAttrib(fontAttrib);
1072                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
1073                 }
1074
1075                 if (left > 0)
1076                 {
1077                         if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
1078                         {
1079                                 curX += xVec;
1080                         }
1081                 }
1082
1083                 if (pFont->LoadGlyph(*pText++, &pFontGlyphData))
1084                 {
1085                         int glyphBoundX1 = curX;
1086                         int glyphBoundY1 = curY - pFontGlyphData->yOffset.ToInt();
1087                         int glyphBoundX2 = glyphBoundX1 +
1088                                                         ((pFontGlyphData->image.width <= 0) ? pFontGlyphData->xAdvance.ToInt()
1089                                                                                                                                 : (pFontGlyphData->xOffset.ToInt() + pFontGlyphData->image.width));
1090                         int glyphBoundY2 = glyphBoundY1 + pFontGlyphData->image.height;
1091
1092 #ifdef SYNCHRONIZATION_2_0
1093                         // adjusting x2 bounds for synchronizing fuctionality with 2.0
1094                         glyphBoundX2 = glyphBoundX1 + pFontGlyphData->xAdvance.ToInt() + italicSpace + boldSpace;
1095 #endif
1096                         if (outline)
1097                         {
1098                                 glyphBoundX1 -= 1;
1099                                 glyphBoundY1 -= 1;
1100                                 glyphBoundX2 += 1;
1101                                 glyphBoundY2 += 1;
1102                         }
1103
1104                         _ExpandBounds(glyphBoundX1, glyphBoundY1, x1, y1, x2, y2);
1105                         _ExpandBounds(glyphBoundX2, glyphBoundY1, x1, y1, x2, y2);
1106                         _ExpandBounds(glyphBoundX1, glyphBoundY2, x1, y1, x2, y2);
1107                         _ExpandBounds(glyphBoundX2, glyphBoundY2, x1, y1, x2, y2);
1108
1109 #ifdef SYNCHRONIZATION_2_0
1110                         curX += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + italicSpace + boldSpace;
1111 #else
1112                         curX += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + boldSpace;
1113 #endif
1114                         curY += pFontGlyphData->yAdvance.ToInt();
1115
1116                         pFont->UnloadGlyph(&pFontGlyphData);
1117
1118                         // check end condition
1119                         // TODO, shkim, BIDI need to be cared
1120                         if ((x2 - x1) > width)
1121                         {
1122                                 break;
1123                         }
1124
1125                         preX1 = x1;
1126                         preY1 = y1;
1127                         preX2 = x2;
1128                         preY2 = y2;
1129                         characters++;
1130                         left++;
1131                         leftChar = *(pText - 1);
1132                 }
1133         }
1134
1135         if (characters == 0)
1136         {
1137                 pcDim.SetSize(0, 0);
1138                 count = 0;
1139                 return E_SUCCESS;
1140         }
1141
1142         SysTryCatch(NID_GRP, preX1 <= preX2 && preY1 <= preY2, pcDim.SetSize(0, 0); count = 0, E_SYSTEM, "[E_SYSTEM] Failed to calculate text extent");
1143
1144         count = characters;
1145         pcDim.width = preX2 - preX1;
1146 #ifdef SYNCHRONIZATION_2_0
1147         pcDim.height = __fontAttrib.size.ToInt();
1148 #else
1149         pcDim.height = preY2 - preY1;
1150 #endif // SYNCHRONIZATION_2_0
1151
1152         return E_SUCCESS;
1153
1154 CATCH:
1155         return E_SYSTEM;
1156 }
1157
1158 result
1159 _Font::GetTextExtent(int width, const _Util::String& text, bool outline, const Tizen::Base::String& delimiter, int& count, Dimension& dim) const
1160 {
1161         const wchar_t* pText = text.pStart;
1162         const wchar_t* pTextEnd = pText + text.length;
1163
1164         while (pText < pTextEnd)
1165         {
1166                 if (*pText == 0x0D || *pText == 0x0A)
1167                 {
1168                         pTextEnd = pText;
1169                         break;
1170                 }
1171
1172                 ++pText;
1173         }
1174
1175         return this->GetTextExtent(width, _Util::String(text.pStart, pTextEnd - text.pStart), outline, count, dim);
1176 }
1177
1178 result
1179 _Font::__GetTextExtentList(const _Util::String& text, _Util::AccumList<_Util::Pair<int, int> >& outList) const
1180 {
1181         SysAssert(text.pStart != null && text.length > 0);
1182
1183         outList.Clear();
1184
1185         _Font* pThis = const_cast <_Font*>(this);
1186
1187         APPLY_ATTRIBUTE(E_SYSTEM);
1188
1189         int addingSpace = __fontAttrib.charSpace;
1190
1191 #ifdef SYNCHRONIZATION_2_0
1192         {
1193                 _IFont::SizeProperty sizeProperty;
1194
1195                 GET_FONT_SIZE_PROPERTY(sizeProperty, E_SYSTEM);
1196
1197                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
1198                 {
1199                         addingSpace += (sizeProperty.ascender.ToInt() * 2) >> 4;
1200                 }
1201         }
1202 #endif
1203
1204         _IFont::Property property;
1205         GET_FONT_PROPERTY(property, false);
1206
1207         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1208         {
1209                 _IFont::Attrib attr;
1210
1211                 if (pThis->GetAttrib(attr))
1212                 {
1213                         addingSpace += static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1214                 }
1215         }
1216
1217         int curX = 0;
1218         int curY = 0;
1219         wchar_t prevChar = 0;
1220
1221         const wchar_t* pText = text.pStart;
1222         int length = text.length;
1223
1224         --pText;
1225
1226         while (*(++pText) && --length >= 0)
1227         {
1228                 _IFont* pFont = pThis->__GetFont(*pText);
1229
1230                 if (pFont)
1231                 {
1232                         if (pFont != __pNativeFont)
1233                         {
1234                                 _IFont::Attrib fontAttrib;
1235
1236                                 if (pFont->GetAttrib(fontAttrib))
1237                                 {
1238                                         fontAttrib.size = __fontAttrib.size;
1239                                         fontAttrib.style = _IFont::STYLE_NONE;
1240                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1241                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1242                                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1243                                         pFont->SetAttrib(fontAttrib);
1244                                 }
1245                         }
1246
1247                         _IFont::Glyph* pFontGlyphData = 0;
1248
1249                         if (pFont->LoadGlyph(*pText, &pFontGlyphData))
1250                         {
1251                                 // When LoadGlyph fails continuously in the original code, there is a problem to check the kerning on the results of the previous prevChar
1252                                 if (prevChar > 0)
1253                                 {
1254                                         long xVec = 0;
1255                                         long yVec = 0;
1256
1257                                         if (pFont->GetKerning(prevChar, *pText, xVec, yVec))
1258                                         {
1259                                                 curX += xVec;
1260                                         }
1261                                 }
1262
1263                                 int prevX = curX;
1264
1265                                 curX += pFontGlyphData->xAdvance.ToInt() + addingSpace;
1266                                 curY += pFontGlyphData->yAdvance.ToInt();
1267
1268                                 pFont->UnloadGlyph(&pFontGlyphData);
1269
1270                                 prevChar = *pText;
1271                                 outList.Push(_Util::MakePair(prevX, curX));
1272
1273                                 continue;
1274                         }
1275                 }
1276
1277                 // Cannot determine a glyph extent
1278                 prevChar = 0;
1279                 outList.Push(_Util::MakePair(curX, curX));
1280         }
1281
1282         return E_SUCCESS;
1283 }
1284
1285 result
1286 _Font::__GetTextExtentList(_TextBidiPropertyWithReorder& bidiProperty, _Util::AccumList<_Util::Pair<int, int> >& outList) const
1287 {
1288         if (bidiProperty.length <= 0)
1289         {
1290                 outList.Clear();
1291
1292                 return E_SUCCESS;
1293         }
1294
1295         _Util::AccumList<_Util::Pair<int, int> > tempList;
1296
1297         {
1298                 int xDest = 0;
1299                 int yDest = 0;
1300
1301                 int length = bidiProperty.length;
1302
1303                 _Font* pThis = const_cast <_Font*>(this);
1304
1305                 pThis->ApplyAttribute();
1306
1307                 const wchar_t* pReorderedText = bidiProperty.GetReorderedText();
1308
1309                 const wchar_t* pTextFragmentBegin = pReorderedText;
1310                 const wchar_t* pTextFragmentEnd = pTextFragmentBegin + length;
1311
1312                 const wchar_t* pTextSegment = pTextFragmentBegin;
1313
1314                 _IFont* pBaseFont = pThis->__GetFont(*pTextSegment);
1315
1316                 _Util::AccumList<_TextFragment> textFragmentList;
1317
1318                 while (pTextSegment < pTextFragmentEnd)
1319                 {
1320                         if (pBaseFont->CheckGlyph(*pTextSegment) == 0)
1321                         {
1322                                 _IFont* pFallbackFont = pThis->__GetFont(*pTextSegment);
1323
1324                                 if (pBaseFont != pFallbackFont)
1325                                 {
1326                                         textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1327
1328                                         pTextFragmentBegin = pTextSegment;
1329                                         pBaseFont = pFallbackFont;
1330                                 }
1331                         }
1332
1333                         ++pTextSegment;
1334                 }
1335
1336                 textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1337
1338                 /*
1339                  * - In case of LTR
1340                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1341                  *
1342                  * - In case of RTL
1343                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.End(); textFragment != textFragmentList.Begin(); )
1344                  * {
1345                  *     --textFragment;
1346                  *
1347                  */
1348
1349                 for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1350                 {
1351                         if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
1352                         {
1353                                 continue;
1354                         }
1355
1356                         if (textFragment->pUsingFont != __pNativeFont)
1357                         {
1358                                 _IFont::Attrib fontAttrib;
1359
1360                                 if (textFragment->pUsingFont->GetAttrib(fontAttrib))
1361                                 {
1362                                         fontAttrib.size = __fontAttrib.size;
1363                                         fontAttrib.style = _IFont::STYLE_NONE;
1364                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1365                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1366                                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1367
1368                                         textFragment->pUsingFont->SetAttrib(fontAttrib);
1369                                 }
1370                         }
1371
1372                         Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
1373
1374                         const wchar_t firstChar = *textFragment->textFragment.pStart;
1375
1376                         GUnicodeScript script = _TextBidiUtil::GetUnicodeScript(firstChar);
1377                         // need to check if (script < 0 || script >= _sampleLanguageCount) ?
1378
1379                         textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, script);
1380
1381                         int count = glyphList.GetCount();
1382
1383                         for (int i = 0; i < count; i++)
1384                         {
1385                                 _IFont::Glyph *pGlyph = 0;
1386
1387                                 glyphList.GetAt(i, pGlyph);
1388
1389                                 // bug fixed in test case of L"\x9a8\x20\x981\x9a0\x635"
1390                                 //if (pGlyph->xAdvance == 0 && pGlyph->image.width == 0)
1391                                 //{
1392                                 //      continue;
1393                                 //}
1394
1395                                 int prevX = xDest;
1396
1397                                 xDest += pGlyph->xAdvance.ToInt();
1398                                 yDest += pGlyph->yAdvance.ToInt();
1399
1400                                 tempList.Push(_Util::MakePair(prevX, xDest));
1401                                 outList.Push(_Util::MakePair(-1, -1));
1402                         }
1403
1404                         IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
1405
1406                         if (pEnum)
1407                         {
1408                                 while (pEnum->MoveNext() == E_SUCCESS)
1409                                 {
1410                                         _IFont::Glyph* pGlyph;
1411
1412                                         pEnum->GetCurrent(pGlyph);
1413                                         pBaseFont->UnloadGlyph(&pGlyph);
1414                                 }
1415
1416                                 delete pEnum;
1417                         }
1418                 }
1419         }
1420
1421         if (bidiProperty.pBidiIndex)
1422         {
1423                 // Reorder list by using BIDI index
1424                 typedef _Util::Pair<int, int> Gap;
1425                 typedef _Util::AccumList<Gap> GapList;
1426
1427                 GapList::Iterator dstBegin = outList.Begin();
1428
1429                 int index = 0;
1430
1431                 if (bidiProperty.length == int(tempList.Size()))
1432                 {
1433                         for (GapList::ConstIterator src = tempList.Begin(); src != tempList.End(); ++src)
1434                         {
1435                                 *(dstBegin + bidiProperty.pBidiIndex[index++]) = *src;
1436                         }
1437                 }
1438                 else if (bidiProperty.length > int(tempList.Size()))
1439                 {
1440                         _TextBidiUtil::GetReorderedIndexList(bidiProperty, tempList, outList);
1441                 }
1442                 else // if (bidiProperty.length < tempList.Size())
1443                 {
1444                         // under development
1445                         for (GapList::ConstIterator src = tempList.Begin(); src != tempList.End() && index < bidiProperty.length; ++src)
1446                         {
1447                                 *(dstBegin + bidiProperty.pBidiIndex[index++]) = *src;
1448                         }
1449                 }
1450         }
1451         else
1452         {
1453                 typedef _Util::Pair<int, int> Gap;
1454                 typedef _Util::AccumList<Gap> GapList;
1455
1456                 GapList::Iterator dst = outList.Begin();
1457                 GapList::Iterator dstEnd = outList.End();
1458
1459                 GapList::ConstIterator src = tempList.Begin();
1460                 GapList::ConstIterator srcEnd = tempList.End();
1461
1462                 for (; (src != srcEnd) && (dst != dstEnd); ++src, ++dst)
1463                 {
1464                         *dst = *src;
1465                 }
1466         }
1467
1468         return E_SUCCESS;
1469 }
1470
1471 result
1472 _Font::GetTextExtentList(const _Util::String& text, _Util::AccumList<_Util::Pair<int, int> >& outList) const
1473 {
1474         if (text.pStart == null || text.length <= 0)
1475         {
1476                 outList.Clear();
1477                 return E_SUCCESS;
1478         }
1479
1480         _TextBidiPropertyWithReorder bidiProperty(text.pStart, text.length);
1481
1482         if (bidiProperty.HasBidi())
1483         {
1484                 return this->__GetTextExtentList(bidiProperty, outList);
1485         }
1486         else
1487         {
1488                 return this->__GetTextExtentList(text, outList);
1489         }
1490
1491         return E_SUCCESS;
1492 }
1493
1494 result
1495 _Font::SetSize(_Util::FixedPoint26_6 pcSize)
1496 {
1497         __UpdateFontAttribute(__fontAttrib.style, pcSize);
1498
1499         return E_SUCCESS;
1500 }
1501
1502 result
1503 _Font::SetStyle(int style)
1504 {
1505         __fontAttrib.style = style;
1506
1507         return E_SUCCESS;
1508 }
1509
1510 int
1511 _Font::GetStyle(void) const
1512 {
1513         return __fontAttrib.style;
1514 }
1515
1516 _Util::FixedPoint26_6
1517 _Font::GetLeading(void) const
1518 {
1519         return __fontAttrib.maxHeight;
1520 }
1521
1522 result
1523 _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
1524 {
1525         SysTryReturnResult(NID_GRP, canvas.__pScratchPad != null, E_INVALID_ARG, "A canvas is invalid");
1526
1527         const wchar_t* pText = text.GetPointer() + startIndex;
1528
1529         bool rtn = this->ApplyAttribute();
1530         SysTryReturn(NID_GRP, rtn, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fails to apply font attribute.");
1531
1532         _Util::ScratchPad <SystemPixel>& scratchPad = *canvas.__pScratchPad;
1533         scratchPad.RegisterFillRect(_RasterOp::FnFillRectFont32Bit);
1534
1535         Rectangle clipBounds;
1536         canvas.__GetClipBounds(clipBounds);
1537
1538         int xDest = point.x;
1539         int yDest = point.y;
1540         int startX = point.x;
1541         int charHeight = 0;
1542         int italicSpace = 0;
1543         int boldSpace = 0;
1544         int clipX1 = clipBounds.x;
1545         int clipY1 = clipBounds.y;
1546         int clipX2 = clipX1 + clipBounds.width;
1547         int clipY2 = clipY1 + clipBounds.height;
1548         long xVec = 0;
1549         long yVec = 0;
1550         int left = 0;
1551         wchar_t leftChar = 0;
1552         _IFont::Glyph* pFontGlyphData = 0;
1553
1554         _IFont::SizeProperty sizeProperty;
1555         rtn = this->GetFontSizeProperty(sizeProperty);
1556         SysTryReturn(NID_GRP, rtn, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get font sizeProperty.");
1557
1558         // need to revise y value, because _IFont is based on the baseline
1559         {
1560                 if (canvas.__textOrigin == TEXT_ORIGIN_LEFT_TOP)
1561                 {
1562                         yDest += sizeProperty.ascender.ToInt();
1563                 }
1564
1565                 charHeight = sizeProperty.ascender.ToInt() - sizeProperty.descender.ToInt();
1566
1567                 if (this->GetStyle() & FONT_STYLE_ITALIC)
1568                 {
1569                         italicSpace = (sizeProperty.ascender.ToInt() * 2) >> 4;
1570                 }
1571         }
1572
1573         _IFont::Property property;
1574         GET_FONT_PROPERTY(property, false);
1575
1576         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1577         {
1578                 _IFont::Attrib attr;
1579                 this->GetAttrib(attr);
1580                 boldSpace = static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1581         }
1582
1583         unsigned long canvasFgColor = canvas.__fgColor;
1584
1585         _TextBidiPropertyWithReorder bidiProperty(pText, length);
1586
1587         if (bidiProperty.HasBidi())
1588         {
1589                 const wchar_t* pReorderedText = bidiProperty.GetReorderedText();
1590
1591                 const wchar_t* pTextFragmentBegin = pReorderedText;
1592                 const wchar_t* pTextFragmentEnd = pTextFragmentBegin + length;
1593
1594                 const wchar_t* pTextSegment = pTextFragmentBegin;
1595
1596                 _IFont* pBaseFont = this->__GetFont(*pTextSegment);
1597
1598                 _Util::AccumList<_TextFragment> textFragmentList;
1599
1600                 while (pTextSegment < pTextFragmentEnd)
1601                 {
1602                         if (pBaseFont->CheckGlyph(*pTextSegment) == 0)
1603                         {
1604                                 _IFont* pFallbackFont = this->__GetFont(*pTextSegment);
1605
1606                                 if (pBaseFont != pFallbackFont)
1607                                 {
1608                                         textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1609
1610                                         pTextFragmentBegin = pTextSegment;
1611                                         pBaseFont = pFallbackFont;
1612                                 }
1613                         }
1614
1615                         ++pTextSegment;
1616                 }
1617
1618                 textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1619
1620                 /*
1621                  * - In case of LTR
1622                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1623                  *
1624                  * - In case of RTL
1625                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.End(); textFragment != textFragmentList.Begin(); )
1626                  * {
1627                  *     --textFragment;
1628                  *
1629                  */
1630
1631                 for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1632                 {
1633                         if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
1634                         {
1635                                 continue;
1636                         }
1637
1638                         if (textFragment->pUsingFont != __pNativeFont)
1639                         {
1640                                 _IFont::Attrib fontAttrib;
1641
1642                                 if (textFragment->pUsingFont->GetAttrib(fontAttrib))
1643                                 {
1644                                         fontAttrib.size = __fontAttrib.size;
1645                                         fontAttrib.style = _IFont::STYLE_NONE;
1646                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1647                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1648                                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1649
1650                                         textFragment->pUsingFont->SetAttrib(fontAttrib);
1651                                 }
1652                         }
1653
1654                         Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
1655
1656                         const wchar_t firstChar = *textFragment->textFragment.pStart;
1657
1658                         GUnicodeScript script = _TextBidiUtil::GetUnicodeScript(firstChar);
1659
1660                         textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, script);
1661                         // need to check if (script < 0 || script >= _sampleLanguageCount) ?
1662
1663                         int count = glyphList.GetCount();
1664
1665                         for (int i = 0; i < count; i++)
1666                         {
1667                                 /* for debugging
1668                                 static int s_index = 0;
1669                                 const unsigned long COLOR[6] =
1670                                 {
1671                                         0xFFFFFFFF,
1672                                         0xFF40FF40,
1673                                         0xFF40FFFF,
1674                                         0xFFFF4040,
1675                                         0xFFFF40FF,
1676                                         0xFFFFFF40
1677                                 };
1678                                 unsigned long canvasFgColor = COLOR[s_index++ % 6];
1679                                 */
1680
1681                                 typedef unsigned long TPixel;
1682                                 _IFont::Glyph *pGlyph = 0;
1683
1684                                 TPixel srcR, srcG, srcB, srcA;
1685                                 TPixel dstR, dstG, dstB, dstA;
1686
1687                                 srcA = (canvasFgColor >> 24) & 0xFF;
1688                                 srcA += (srcA >> 7);
1689                                 srcR = (canvasFgColor >> 16) & 0xFF;
1690                                 srcG = (canvasFgColor >> 8) & 0xFF;
1691                                 srcB = (canvasFgColor) & 0xFF;
1692
1693                                 SystemPixel* pBufferStartAddr = null;
1694                                 int bufferPitch;
1695
1696                                 scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
1697
1698                                 glyphList.GetAt(i, pGlyph);
1699
1700                                 for (int h = 0; h < pGlyph->image.height; h++)
1701                                 {
1702                                         int y = yDest - pGlyph->yOffset.ToInt() + h;
1703
1704                                         if (y < clipY1)
1705                                         {
1706                                                 continue;
1707                                         }
1708
1709                                         if (y >= clipY2)
1710                                         {
1711                                                 break;
1712                                         }
1713
1714                                         TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pGlyph->xOffset.ToInt();
1715
1716                                         for (int w = 0; w < pGlyph->image.width; w++)
1717                                         {
1718                                                 int x = xDest + pGlyph->xOffset.ToInt() + w;
1719
1720                                                 if (x < clipX1)
1721                                                 {
1722                                                         ++pDest32;
1723                                                         continue;
1724                                                 }
1725
1726                                                 if (x >= clipX2)
1727                                                 {
1728                                                         break;
1729                                                 }
1730
1731                                                 unsigned long alpha = (unsigned long) (pGlyph->image.pBitmap[h * pGlyph->image.bytesPerLine + w]);
1732
1733                                                 if (alpha > 0)
1734                                                 {
1735                                                         // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
1736                                                         alpha = (alpha * srcA) >> 8;
1737                                                         alpha += (alpha >> 7);
1738
1739                                                         dstA = (*pDest32 >> 24) & 0xFF;
1740                                                         dstR = (*pDest32 >> 16) & 0xFF;
1741                                                         dstG = (*pDest32 >> 8) & 0xFF;
1742                                                         dstB = (*pDest32) & 0xFF;
1743
1744                                                         dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
1745                                                         dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
1746                                                         dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
1747                                                         dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
1748
1749                                                         *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
1750
1751                                                 }
1752                                                 ++pDest32;
1753                                         }
1754                                 }
1755
1756                                 xDest += pGlyph->xAdvance.ToInt();
1757                                 yDest += pGlyph->yAdvance.ToInt();
1758                         }
1759
1760                         IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
1761
1762                         if (pEnum)
1763                         {
1764                                 while (pEnum->MoveNext() == E_SUCCESS)
1765                                 {
1766                                         _IFont::Glyph* pGlyph;
1767
1768                                         pEnum->GetCurrent(pGlyph);
1769                                         pBaseFont->UnloadGlyph(&pGlyph);
1770                                 }
1771
1772                                 delete pEnum;
1773                         }
1774                 }
1775         }
1776         else
1777         {
1778                 while (*pText && --length >= 0)
1779                 {
1780                         // find out proper native font
1781                         _IFont* pFont = this->__GetFont(*pText);
1782
1783                         if (pFont == null)
1784                         {
1785                                 continue;
1786                         }
1787
1788                         if (pFont != __pNativeFont)
1789                         {
1790                                 _IFont::Attrib fontAttrib;
1791                                 bool rtn = pFont->GetAttrib(fontAttrib);
1792                                 //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
1793
1794                                 fontAttrib.size = __fontAttrib.size;
1795                                 fontAttrib.style = _IFont::STYLE_NONE;
1796                                 fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1797                                 fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1798                                 fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1799
1800                                 rtn = pFont->SetAttrib(fontAttrib);
1801                                 //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
1802                         }
1803
1804                         _IFont::Property property;
1805                         pFont->GetFontProperty(property);
1806
1807                         unsigned long fgColor = (canvas.__applyEmoji && pFont->IsEmoji()) ? GetPredefinedColor(*pText, canvasFgColor) : canvasFgColor;
1808
1809                         if (left > 0)
1810                         {
1811                                 if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
1812                                 {
1813                                         xDest += xVec;
1814                                 }
1815                         }
1816
1817                         bool rtn = pFont->LoadGlyph(*pText++, &pFontGlyphData);
1818
1819                         if (!rtn)
1820                         {
1821                                 continue;
1822                         }
1823
1824                         typedef unsigned long TPixel;
1825
1826                         TPixel srcA = (fgColor >> 24) & 0xFF;
1827                         srcA += (srcA >> 7);
1828
1829                         TPixel srcR = (fgColor >> 16) & 0xFF;
1830                         TPixel srcG = (fgColor >> 8) & 0xFF;
1831                         TPixel srcB = (fgColor) & 0xFF;
1832
1833                         SystemPixel* pBufferStartAddr = null;
1834                         int bufferPitch = 0;
1835
1836                         scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
1837
1838                         for (int h = 0; h < pFontGlyphData->image.height; h++)
1839                         {
1840                                 int y = yDest - pFontGlyphData->yOffset.ToInt() + h;
1841
1842                                 if (y < clipY1)
1843                                 {
1844                                         continue;
1845                                 }
1846
1847                                 if (y >= clipY2)
1848                                 {
1849                                         break;
1850                                 }
1851
1852                                 TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pFontGlyphData->xOffset.ToInt();
1853
1854                                 for (int w = 0; w < pFontGlyphData->image.width; w++)
1855                                 {
1856                                         int x = xDest + pFontGlyphData->xOffset.ToInt() + w;
1857
1858                                         if (x < clipX1)
1859                                         {
1860                                                 ++pDest32;
1861                                                 continue;
1862                                         }
1863
1864                                         if (x >= clipX2)
1865                                         {
1866                                                 break;
1867                                         }
1868
1869                                         unsigned long alpha = (unsigned long) (pFontGlyphData->image.pBitmap[h * pFontGlyphData->image.bytesPerLine + w]);
1870
1871                                         if (alpha > 0)
1872                                         {
1873                                                 // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
1874                                                 alpha = (alpha * srcA) >> 8;
1875                                                 alpha += (alpha >> 7);
1876
1877                                                 TPixel dstA = (*pDest32 >> 24) & 0xFF;
1878                                                 TPixel dstR = (*pDest32 >> 16) & 0xFF;
1879                                                 TPixel dstG = (*pDest32 >> 8) & 0xFF;
1880                                                 TPixel dstB = (*pDest32) & 0xFF;
1881
1882                                                 dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
1883                                                 dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
1884                                                 dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
1885                                                 dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
1886
1887                                                 *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
1888
1889                                         }
1890                                         ++pDest32;
1891                                 }
1892                         }
1893
1894                         xDest += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + italicSpace + boldSpace;
1895                         yDest += pFontGlyphData->yAdvance.ToInt();
1896                         left++;
1897                         leftChar = *(pText - 1);
1898
1899                         pFont->UnloadGlyph(&pFontGlyphData);
1900
1901                 }
1902         }
1903
1904         if (this->IsUnderlined() || this->IsStrikeOut())
1905         {
1906                 int y = 0;
1907                 int thick = this->GetLineThickness();
1908
1909                 if (canvas.__textOrigin == TEXT_ORIGIN_LEFT_TOP)
1910                 {
1911                         y = point.y + charHeight - 1;
1912                 }
1913                 else
1914                 {
1915                         y = point.y - sizeProperty.descender.ToInt() - 1;
1916                 }
1917
1918                 xDest -= this->GetCharSpace();
1919
1920                 if (this->IsUnderlined())
1921                 {
1922                         canvas.FillRectangle(canvasFgColor, Rectangle(startX, y - thick, xDest - startX, thick));
1923                 }
1924
1925                 if (this->IsStrikeOut())
1926                 {
1927                         y -= charHeight / 2;
1928                         canvas.FillRectangle(canvasFgColor, Rectangle(startX, y - thick, xDest - startX, thick));
1929                 }
1930         }
1931
1932         scratchPad.RegisterFillRect(null);
1933
1934
1935         return E_SUCCESS;
1936 }
1937
1938 #undef BLEND_ALPHA_COMPONEMT
1939
1940 result
1941 _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
1942 {
1943         unsigned long textColor = canvas.__fgColor;
1944         bool applyEmoji = canvas.__applyEmoji;
1945
1946         //sunmi557.shin: draw border of font
1947         canvas.__fgColor = outlineColor.GetRGB32();
1948         canvas.__applyEmoji = false;
1949
1950         this->__DrawText(canvas, Point(point.x - 1, point.y), text, startIndex, length);
1951         this->__DrawText(canvas, Point(point.x + 1, point.y), text, startIndex, length);
1952         this->__DrawText(canvas, Point(point.x, point.y - 1), text, startIndex, length);
1953         this->__DrawText(canvas, Point(point.x, point.y + 1), text, startIndex, length);
1954
1955         //sunmi557.shin: draw original shape of font
1956         canvas.__applyEmoji = applyEmoji;
1957         canvas.__fgColor = textColor;
1958
1959         this->__DrawText(canvas, point, text, startIndex, length);
1960
1961         return E_SUCCESS;
1962 }
1963
1964 bool
1965 _Font::SetAttrib(const _IFont::Attrib& fontAttrib)
1966 {
1967         return __pNativeFont->SetAttrib(fontAttrib);
1968 }
1969
1970 bool
1971 _Font::GetAttrib(_IFont::Attrib& fontAttrib) const
1972 {
1973         return __pNativeFont->GetAttrib(fontAttrib);
1974 }
1975
1976 bool
1977 _Font::GetKerning(unsigned long character1, unsigned long character2, long& xVector, long& yVector) const
1978 {
1979         return __pNativeFont->GetKerning(character1, character2, xVector, yVector);
1980 }
1981
1982 bool
1983 _Font::GetFontSizeProperty(_IFont::SizeProperty& sizeProperty) const
1984 {
1985         return __pNativeFont->GetFontSizeProperty(sizeProperty);
1986 }
1987
1988 bool
1989 _Font::LoadGlyph(unsigned long character, _IFont::Glyph** ppFontGlyphData)
1990 {
1991         // note! we assume that the font attribute has been already applied on _IFont
1992         bool rtn = false;
1993
1994         // if not, loading glyph (character/size/style) and caching it
1995         rtn = __pNativeFont->LoadGlyph(character, ppFontGlyphData);
1996         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to load glyph data");
1997
1998         // return cached glyph
1999         return true;
2000 }
2001
2002 bool
2003 _Font::UnloadGlyph(_IFont::Glyph** ppFontGlyphData)
2004 {
2005         return __pNativeFont->UnloadGlyph(ppFontGlyphData);
2006 }
2007
2008 unsigned long
2009 _Font::CheckGlyph(unsigned long character)
2010 {
2011         return __pNativeFont->CheckGlyph(character);
2012 }
2013
2014 void
2015 _Font::__UpdateFontAttribute(int style, _Util::FixedPoint26_6 pcSize)
2016 {
2017         __fontAttrib.style = style;
2018         __fontAttrib.size = pcSize;
2019         __fontAttrib.lineThickness = pcSize.ToInt() > 0 ? (pcSize.ToInt() / 24) + 1 : 1;
2020
2021         _IFont::SizeProperty sizeProperty;
2022         bool getProperty = false;
2023
2024         if (this->ApplyAttribute())
2025         {
2026                 getProperty = __pNativeFont->GetFontSizeProperty(sizeProperty);
2027         }
2028
2029         if (getProperty)
2030         {
2031                 __fontAttrib.maxWidth = sizeProperty.maxWidth;
2032                 __fontAttrib.maxHeight = sizeProperty.maxHeight;
2033                 __fontAttrib.ascender = sizeProperty.ascender;
2034                 __fontAttrib.descender = sizeProperty.descender;
2035         }
2036         else
2037         {
2038                 // if failed to get property above, each property should be remained as default: -1
2039                 SysLog(NID_GRP, "[] Failed to get font attribute from native font");
2040
2041                 __fontAttrib.maxWidth.Reset(0);
2042                 __fontAttrib.maxHeight.Reset(0);
2043                 __fontAttrib.ascender.Reset(0);
2044                 __fontAttrib.descender.Reset(0);
2045         }
2046 }
2047
2048 result
2049 _Font::__DrawTextLastFallback(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
2050 {
2051         return E_SUCCESS;
2052 }
2053
2054 result
2055 _Font::__DrawTextDefault(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
2056 {
2057         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2058         result r = mgr.GetDefaultSystemFont().__DrawText(canvas, point, text, startIndex, length);
2059         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to draw default system font", GetErrorMessage(r));
2060
2061         return E_SUCCESS;
2062
2063 CATCH:
2064         _Font::__DrawTextLastFallback(canvas, point, text, startIndex, length);
2065         return r;
2066 }
2067
2068 result
2069 _Font::__DrawTextDefault(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
2070 {
2071         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2072         result r = mgr.GetDefaultSystemFont().__DrawText(canvas, point, text, startIndex, length, outlineColor);
2073         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to draw default system font", GetErrorMessage(r));
2074
2075         return E_SUCCESS;
2076
2077 CATCH:
2078         _Font::__DrawTextLastFallback(canvas, point, text, startIndex, length);
2079         return r;
2080 }
2081
2082
2083 result
2084 _Font::DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
2085 {
2086         if (canvas.__pPriorityFont)
2087         {
2088                 return canvas.__pPriorityFont->__DrawText(canvas, point, text, startIndex, length);
2089         }
2090         else if (canvas.__pFont)
2091         {
2092                 return canvas.__pFont->__DrawText(canvas, point, text, startIndex, length);
2093         }
2094         else
2095         {
2096                 return _Font::__DrawTextDefault(canvas, point, text, startIndex, length);
2097         }
2098 }
2099
2100 result
2101 _Font::DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
2102 {
2103         if (canvas.__pPriorityFont)
2104         {
2105                 return canvas.__pPriorityFont->__DrawText(canvas, point, text, startIndex, length, outlineColor);
2106         }
2107         else if (canvas.__pFont)
2108         {
2109                 return canvas.__pFont->__DrawText(canvas, point, text, startIndex, length, outlineColor);
2110         }
2111         else
2112         {
2113                 return _Font::__DrawTextDefault(canvas, point, text, startIndex, length, outlineColor);
2114         }
2115
2116         return E_SUCCESS;
2117 }
2118
2119 _Font*
2120 _Font::GetInstance(_FontImpl& font)
2121 {
2122         return (&font != null) ? font._pNativeFont : null;
2123 }
2124
2125 const _Font*
2126 _Font::GetInstance(const _FontImpl& font)
2127 {
2128         return (&font != null) ? font._pNativeFont : null;
2129 }
2130
2131 _IFont*
2132 _Font::__GetFont(wchar_t character)
2133 {
2134         //------------------------------------------------------
2135         //
2136         // 1. check if this font has a requested glyph
2137         //
2138         //------------------------------------------------------
2139         unsigned long idx = __pNativeFont->CheckGlyph(character);
2140
2141         if (idx > 0)
2142         {
2143                 return __pNativeFont;
2144         }
2145
2146         //------------------------------------------------------
2147         //
2148         // 1-2. check if this glyph is in the fallback list.
2149         //
2150         //------------------------------------------------------
2151         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2152         _IFont::FontMapT* pFallbackFontMap = __pNativeFont->GetFallbackMap();
2153
2154 #ifdef USE_HASHMAP_FOR_FONT
2155         std::auto_ptr<IMapEnumeratorT<_Util::WString, _FontRsrcManager::SharedFontResource> > enumerator(pFallbackFontMap->GetMapEnumeratorN());
2156
2157         while (enumerator->MoveNext() == E_SUCCESS)
2158         {
2159                 _FontRsrcManager::SharedFontResource pTempFont;
2160
2161                 if (enumerator->GetValue(pTempFont) == E_SUCCESS)
2162                 {
2163                         _Util::WString key(L"");
2164                         result r = enumerator->GetKey(key);
2165
2166                         if (r == E_SUCCESS)
2167                         {
2168                                 if (mgr.SearchFont(key))
2169                                 {
2170                                         if (pTempFont.get()->CheckGlyph(character) > 0)
2171                                         {
2172                                                 return  pTempFont.get();
2173                                         }
2174                                 }
2175                                 else
2176                                 {
2177                                         pFallbackFontMap->Remove(key);
2178                                 }
2179                         }
2180                 }
2181         }
2182 #else
2183         for (_FontRsrcManager::FontMapT::const_iterator fontIterator = pFallbackFontMap->begin(); fontIterator != pFallbackFontMap->end(); ++fontIterator)
2184         {
2185                 if (fontIterator->second != null)
2186                 {
2187                         if (fontIterator->second->CheckGlyph(character) > 0)
2188                         {
2189                                 return fontIterator->second.get();
2190                         }
2191                 }
2192         }
2193 #endif
2194
2195         //------------------------------------------------------
2196         //
2197         // 2. Get fallback font list via fontconfig
2198         //
2199         //------------------------------------------------------
2200         Tizen::Base::Collection::ArrayListT<String> fileList;
2201         bool rtn = __GetFallbackFontFileList(character, fileList);
2202
2203         if (!rtn)
2204         {
2205                 // if failed find out fallback font,
2206                 // just use this instance for drawing something for unknown glyph
2207                 return __pNativeFont;
2208         }
2209
2210         //------------------------------------------------------
2211         //
2212         // 3. try to find a font having a requested glyph
2213         //
2214         //------------------------------------------------------
2215         String fontName;
2216         _IFont* pFallbackFont = null;
2217
2218         _FontRsrcManager::SharedFontResource out;
2219
2220         int count = fileList.GetCount();
2221         result r = E_FAILURE;
2222
2223         for (int i = 0; i < count; i++)
2224         {
2225                 fileList.GetAt(i, fontName);
2226
2227                 if (fontName.IsEmpty())
2228                 {
2229                         continue;
2230                 }
2231
2232                 r = mgr.GetTempFont(fontName, __fontAttrib.style, __fontAttrib.size, out);
2233
2234                 if (r == E_SUCCESS)
2235                 {
2236                         unsigned long idx = out.get()->CheckGlyph(character);
2237
2238                         if (idx > 0)
2239                         {
2240                                 _Util::WString fontNameTemp(fontName.GetPointer());
2241
2242                                 // keep it
2243 #ifdef USE_HASHMAP_FOR_FONT
2244                                 r = pFallbackFontMap->Add(fontNameTemp, out);
2245
2246                                 if (r == E_OBJ_ALREADY_EXIST)
2247                                 {
2248                                         pFallbackFont = out.get();
2249                                         break;
2250                                 }
2251
2252                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
2253 #else
2254                                 pFallbackFontMap->push_back(std::make_pair(fontNameTemp, out));
2255 #endif
2256                                 r = mgr.AddFont(fontNameTemp, out);
2257                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
2258
2259                                 pFallbackFont = out.get();
2260                                 break;
2261                         }
2262                 }
2263         }
2264
2265         return (pFallbackFont != null) ? pFallbackFont : __pNativeFont;
2266
2267 CATCH:
2268         // if failed find out fallback font,
2269         //      just use this instance for drawing something for unknown glyph
2270         return __pNativeFont;
2271 }
2272
2273 bool
2274 _Font::__GetFallbackFontFileList(wchar_t character, Tizen::Base::Collection::IListT<String>& out)
2275 {
2276         GUnicodeScript script = g_unichar_get_script(character);
2277         if (script < 0 || script >= _sampleLanguageCount)
2278         {
2279                 return false;
2280         }
2281
2282         _IFont::Property property;
2283         const char* pFamilyName = null;
2284         GET_FONT_PROPERTY(property, false);
2285
2286         pFamilyName = property.pFamilyName;
2287
2288         FcPattern* pPattern = null;
2289         FcFontSet* pSet = null;
2290         FcChar8* pName = null;
2291         FcResult res = FcResultNoMatch;
2292         const char* fcStyle = (__fontAttrib.style & FONT_STYLE_BOLD) ? "Bold" : "Regular";
2293
2294         // getting fallback font list
2295         pPattern = FcPatternBuild(NULL, FC_STYLE, FcTypeString, (FcChar8*)fcStyle, NULL);
2296         SysTryCatch(NID_GRP, pPattern, , E_SYSTEM, "[E_SYSTEM] Failed to FcPatternBuild()");
2297
2298         FcPatternAddString(pPattern, FC_FAMILY, (FcChar8*) pFamilyName);
2299
2300         if (strncmp(SAMPLE_LANGUAGE_EMPTY, _SampleLanguages[script], strlen(SAMPLE_LANGUAGE_EMPTY) + 1) != 0)
2301         {
2302                 FcPatternAddString(pPattern, FC_LANG, (FcChar8*)_SampleLanguages[script]);
2303         }
2304
2305         FcConfigSubstitute(NULL, pPattern, FcMatchPattern);
2306         FcDefaultSubstitute(pPattern);
2307
2308         // do matching
2309         pSet = FcFontSort(NULL, pPattern, FcTrue, NULL, &res);
2310         SysTryCatch(NID_GRP, pSet, , E_SYSTEM, "[E_SYSTEM] Failed to FcFontSort()");
2311
2312         out.RemoveAll();
2313
2314         for (int i = 0; i < pSet->nfont; i++)
2315         {
2316                 if (FcPatternGetString(pSet->fonts[i], FC_FILE, 0, &pName) == FcResultMatch)
2317                 {
2318                                 out.Add(String((char*)pName));
2319                 }
2320         }
2321
2322         // destroy
2323         FcFontSetDestroy(pSet);
2324         FcPatternDestroy(pPattern);
2325
2326         return (out.GetCount() > 0) ? true : false;
2327 CATCH:
2328         if (pSet != null)
2329         {
2330                 FcFontSetDestroy(pSet);
2331         }
2332
2333         if (pPattern != null)
2334         {
2335                 FcPatternDestroy(pPattern);
2336         }
2337
2338         return false;
2339 }
2340
2341 bool
2342 _Font::UpdateDefaultFont(const String& key)
2343 {
2344         if (!key.IsEmpty())
2345         {
2346                 SysLog(NID_GRP, "Request to change the default font");
2347
2348                 _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2349
2350                 return mgr.ReloadDefaultSystemFont();
2351         }
2352
2353         return false;
2354 }
2355
2356 }} // Tizen::Graphics