fixed drawing bold font bug(P130605-6845)
[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 { namespace _Util
545 {
546
547 template <>
548 inline Tizen::Graphics::_TextBidiProperty::BidiHint Convert<Tizen::Graphics::TextBidiHint, Tizen::Graphics::_TextBidiProperty::BidiHint>(const Tizen::Graphics::TextBidiHint& bidiHint)
549 {
550         switch (bidiHint)
551         {
552         case TEXT_BIDI_HINT_LTR:
553                 return _TextBidiProperty::BIDI_HINT_LTR;
554         case TEXT_BIDI_HINT_RTL:
555                 return _TextBidiProperty::BIDI_HINT_RTL;
556         default:
557                 return _TextBidiProperty::BIDI_HINT_NONE;
558         }
559 }
560
561 }}} // Tizen::Graphics::_Util
562
563
564 namespace Tizen { namespace Graphics
565 {
566
567 _Font::_Font()
568 {
569         __fontAttrib.Init();
570 }
571
572 _Font::_Font(const _Font& obj)
573 {
574         this->__fontAttrib = obj.__fontAttrib;
575         this->__sharedFont = obj.__sharedFont;
576
577         return;
578 }
579
580 _Font::~_Font(void)
581 {
582 }
583
584 result
585 _Font::Construct(int style, _Util::FixedPoint26_6 pcSize)
586 {
587         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
588
589         // use default system font
590         _FontRsrcManager::SharedFontResource out;
591         result r = mgr.GetFont(style, pcSize, out);
592         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system default font", GetErrorMessage(r));
593
594         // assign it
595         __sharedFont = out;
596         __UpdateFontAttribute(style, pcSize);
597
598         return E_SUCCESS;
599 }
600
601 result
602 _Font::Construct(const Tizen::Base::String& fontName, int style, _Util::FixedPoint26_6 pcSize, bool isPathEnabled)
603 {
604         bool systemFont = false;
605         String appFontPath = L"";
606         result r = E_SUCCESS;
607
608         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
609         _FontRsrcManager::SharedFontResource out;
610
611         if (!Tizen::App::_AppInfo::IsOspCompat())
612         {
613                 _Util::WString fontNameTemp(fontName.GetPointer());
614                 _Util::WString appFontPathTemp(mgr.FindAppFontName(fontNameTemp));
615                 appFontPath.Append(appFontPathTemp.c_str());
616         }
617
618         // check if user want to use a app font
619         if (!appFontPath.IsEmpty())
620         {
621                 r = mgr.GetFont(appFontPath, style, pcSize, out);
622                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get app font", GetErrorMessage(r));
623         }
624         else
625         {
626                 IList* pList = GetSystemFontListN();
627                 int idx = 0;
628
629                 if (pList)
630                 {
631                         for (idx = 0; idx < pList->GetCount(); idx++)
632                         {
633                                 String* pName = static_cast <String*>(pList->GetAt(idx));
634
635                                 if (pName == null)
636                                 {
637                                         continue;
638                                 }
639
640                                 if (*pName == fontName)
641                                 {
642                                         systemFont = true;
643                                         break;
644                                 }
645                         }
646
647                         pList->RemoveAll(true);
648                         delete pList;
649                 }
650
651                 if (systemFont)
652                 {
653                         r = mgr.GetSystemFont(fontName, style, pcSize, out);
654                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
655                 }
656                 else if (isPathEnabled)
657                 {
658                         r = mgr.GetFont(fontName, style, pcSize, out);
659                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get font", GetErrorMessage(r));
660                 }
661         }
662
663         // assign it
664         __sharedFont = out;
665         __UpdateFontAttribute(style, pcSize);
666
667         return E_SUCCESS;
668 }
669
670 result
671 _Font::Construct(const Tizen::Base::ByteBuffer& fontData, int style, _Util::FixedPoint26_6 pcSize)
672 {
673         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
674
675         const byte* pBuffer = fontData.GetPointer();
676         int buffSize = fontData.GetLimit();
677
678         _FontRsrcManager::SharedFontResource out;
679         result r = mgr.GetFont(pBuffer, buffSize, style, pcSize, out);
680         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
681
682         // assign it
683         __sharedFont = out;
684         __UpdateFontAttribute(style, pcSize);
685
686         return E_SUCCESS;
687 }
688
689 bool
690 _Font::IsConstructed(void) const
691 {
692         return (__sharedFont.get() != null);
693 }
694
695 _Util::FixedPoint26_6
696 _Font::GetMaxHeight(void) const
697 {
698         return __fontAttrib.maxHeight;
699 }
700
701 _Util::FixedPoint26_6
702 _Font::GetMaxWidth(void) const
703 {
704         return __fontAttrib.maxWidth;
705 }
706
707 _Util::FixedPoint26_6
708 _Font::GetAscender(void) const
709 {
710         return __fontAttrib.ascender;
711 }
712
713 _Util::FixedPoint26_6
714 _Font::GetDescender(void) const
715 {
716         return __fontAttrib.descender;
717 }
718
719 result
720 _Font::GetLeftBear(wchar_t character, _Util::FixedPoint22_10& leftBear) const
721 {
722         APPLY_ATTRIBUTE(-1);
723
724         _IFont::Glyph* pFontGlyphData = null;
725         LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, E_SYSTEM);
726
727         // left bear is Glyph::xOffset, set it
728         leftBear = pFontGlyphData->xOffset;
729
730         UNLOAD_GLYPH_DATA_CONST(pFontGlyphData);
731
732         return E_SUCCESS;
733 }
734
735 result
736 _Font::GetRightBear(wchar_t character, _Util::FixedPoint22_10& rightBear) const
737 {
738         APPLY_ATTRIBUTE(-1);
739
740         _IFont::Glyph* pFontGlyphData = null;
741         LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, E_SYSTEM);
742
743         // right bear is Glyph::xOffset + GlyphBitmap::width, set it
744         rightBear = pFontGlyphData->xOffset + _Util::FixedPoint22_10(pFontGlyphData->image.width);
745
746         UNLOAD_GLYPH_DATA_CONST(pFontGlyphData);
747
748         return E_SUCCESS;
749 }
750
751 bool
752 _Font::IsBold(void) const
753 {
754         return ((__fontAttrib.style & FONT_STYLE_BOLD) ? true : false);
755 }
756
757 bool
758 _Font::IsItalic(void) const
759 {
760         return ((__fontAttrib.style & FONT_STYLE_ITALIC) ? true : false);
761 }
762
763 bool
764 _Font::IsPlain(void) const
765 {
766         return ((__fontAttrib.style & FONT_STYLE_PLAIN) ? true : false);
767 }
768
769 bool
770 _Font::IsStrikeOut(void) const
771 {
772         return __fontAttrib.strikeout;
773 }
774
775 bool
776 _Font::IsUnderlined(void) const
777 {
778         return __fontAttrib.underline;
779 }
780
781 _Util::FixedPoint26_6
782 _Font::GetSize(void) const
783 {
784         return __fontAttrib.size;
785 }
786
787 void
788 _Font::SetStrikeOut(bool strikeout)
789 {
790         __fontAttrib.strikeout = strikeout;
791 }
792
793 void
794 _Font::SetUnderline(bool underline)
795 {
796         __fontAttrib.underline = underline;
797 }
798
799 void
800 _Font::SetCharSpace(int pc_space)
801 {
802         __fontAttrib.charSpace = pc_space;
803 }
804
805 int
806 _Font::GetCharSpace(void) const
807 {
808         return __fontAttrib.charSpace;
809 }
810
811 int
812 _Font::GetLineThickness(void) const
813 {
814         return __fontAttrib.lineThickness;
815 }
816
817 Tizen::Base::String
818 _Font::GetFaceName(void) const
819 {
820         _IFont::Property property;
821         GET_FONT_PROPERTY(property, String());
822
823         return ((property.pFamilyName) ? String(property.pFamilyName) : String());
824 }
825
826 Tizen::Base::Collection::IList*
827 _Font::GetSystemFontListN(void)
828 {
829         std::auto_ptr<ArrayList> pList(new (std::nothrow) Tizen::Base::Collection::ArrayList);
830         SysTryReturn(NID_GRP, pList.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Fails to allocate memory");
831
832         result r = _GetSystemFontList(*pList);
833         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
834
835         return pList.release();
836
837 }
838
839 Tizen::Base::String
840 _Font::GetFaceName(const Tizen::Base::String& filePath)
841 {
842         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
843         _FontRsrcManager::SharedFontResource out;
844         String faceName;
845
846         result r = mgr.GetTempFont(filePath, FONT_STYLE_PLAIN, _SYSTEM_DEFAULT_FONT_SIZE, out);
847         SysTryReturn(NID_GRP, r == E_SUCCESS, faceName, r, "[%s] Failed to get font", GetErrorMessage(r));
848
849         if (r == E_SUCCESS)
850         {
851                 _IFont* pTempFont = out.get();
852
853                 _IFont::Property property;
854                 pTempFont->GetFontProperty(property);
855                 faceName = String(property.pFamilyName);
856         }
857
858         return faceName;
859 }
860
861 _IFont*
862 _Font::GetNativeFont(void) const
863 {
864         return __pNativeFont;
865 }
866
867 _Font*
868 _Font::CloneN()
869 {
870         // make the clone
871         _Font* pNativeFont = new (std::nothrow) _Font(*this);
872         SysTryReturn(NID_GRP, pNativeFont, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
873
874         // done
875         return pNativeFont;
876 }
877
878 bool
879 _Font::ApplyAttribute()
880 {
881         _IFont::Attrib fontAttrib;
882         bool rtn = __pNativeFont->GetAttrib(fontAttrib);
883         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
884
885         fontAttrib.size = __fontAttrib.size;
886         fontAttrib.style = _IFont::STYLE_NONE;
887         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
888         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
889         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
890         rtn = __pNativeFont->SetAttrib(fontAttrib);
891         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
892
893         return true;
894 }
895
896 result
897 _Font::GetTextExtent(int width, const _Util::String& text, bool outline, int& count, Dimension& pcDim) const
898 {
899         if (text.pStart == null || text.length <= 0)
900         {
901                 pcDim.SetSize(0, 0);
902                 count = 0;
903                 return E_SUCCESS;
904         }
905
906         result r = this->__GetTextExtentEx(width, text, outline, count, pcDim);
907
908         if (r == E_SUCCESS)
909         {
910                 return r;
911         }
912
913         _TextBidiPropertyWithReorder bidiProperty(text.pStart, text.length, _Util::Convert<TextBidiHint, _TextBidiProperty::BidiHint>(_GetTextBidiHint()));
914
915         if (bidiProperty.HasComplexText())
916         {
917                 typedef _Util::AccumList<_Util::Pair<int, int> > GapList;
918
919                 GapList gapList;
920
921                 result r = this->__GetTextExtentList(bidiProperty, gapList);
922
923                 if (r != E_SUCCESS)
924                 {
925                         return r;
926                 }
927
928                 int left = 0;
929                 int right = 0;
930                 int determinedCount = -1;
931
932                 for (GapList::Iterator i = gapList.Begin(); i != gapList.End(); ++i)
933                 {
934                         left = (i->first < left) ? i->first : left;
935                         right = (i->second > right) ? i->second : right;
936
937                         if (determinedCount < 0 && i->first < width && i->second >= width)
938                         {
939                                 if (i != gapList.Begin())
940                                 {
941                                         if (i - gapList.Begin() - 1 < text.length)
942                                         {
943                                                 determinedCount = bidiProperty.pBidiIndex[i - gapList.Begin() - 1];
944                                         }
945                                         else
946                                         {
947                                                 determinedCount = text.length;
948                                         }
949                                 }
950                                 else
951                                 {
952                                         determinedCount = bidiProperty.pBidiIndex[0];
953                                 }
954                         }
955                 }
956
957                 if (right - left <= width)
958                 {
959                         pcDim.SetSize(right - left, __fontAttrib.size.ToInt());
960                         count = text.length;
961                 }
962                 else if (determinedCount > 0 && right - left > 0)
963                 {
964                         int expectedValue = width * text.length / (right - left);
965                         int tolerance = _Util::Abs(expectedValue - determinedCount);
966                         tolerance = (tolerance == 0) ? 2 : tolerance;
967
968                         int tempCount = expectedValue <= determinedCount ? determinedCount + tolerance : determinedCount + (tolerance * 2);
969                         tempCount = tempCount > text.length ? text.length : tempCount;
970
971                         tempCount++;
972
973                         while (right - left > width)
974                         {
975                                 _TextBidiPropertyWithReorder determinedBidiProperty(text.pStart, --tempCount, _Util::Convert<TextBidiHint, _TextBidiProperty::BidiHint>(_GetTextBidiHint()));
976
977                                 GapList determinedGapList;
978
979                                 result r = this->__GetTextExtentList(determinedBidiProperty, determinedGapList);
980
981                                 if (r != E_SUCCESS)
982                                 {
983                                         return r;
984                                 }
985
986                                 left = 0;
987                                 right = 0;
988
989                                 for (GapList::Iterator i = determinedGapList.Begin(); i != determinedGapList.End(); ++i)
990                                 {
991                                         left = (i->first < left) ? i->first : left;
992                                         right = (i->second > right) ? i->second : right;
993                                 }
994                         }
995
996                         pcDim.SetSize(right - left, __fontAttrib.size.ToInt());
997                         count = tempCount;
998                 }
999                 else
1000                 {
1001                         pcDim.SetSize(0, 0);
1002                         count = 0;
1003                 }
1004
1005                 return E_SUCCESS;
1006         }
1007         else
1008         {
1009                 return this->__GetTextExtent(width, text, outline, count, pcDim);
1010         }
1011
1012         return E_SUCCESS;
1013 }
1014
1015 result
1016 _Font::__GetTextExtentEx(int width, const _Util::String& text, bool outline, int& count, Dimension& pcDim) const
1017 {
1018         int preX1 = 0x7FFFFFFF;
1019         int preY1 = 0x7FFFFFFF;
1020         int preX2 = -0x7FFFFFFF;
1021         int preY2 = -0x7FFFFFFF;
1022
1023         int x1 = 0x7FFFFFFF;
1024         int y1 = 0x7FFFFFFF;
1025         int x2 = -0x7FFFFFFF;
1026         int y2 = -0x7FFFFFFF;
1027
1028         int curX = 0;
1029         int curY = 0;
1030
1031         int characters = 0;
1032         int italicSpace = 0;
1033         int boldSpace = 0;
1034
1035         long xVec = 0;
1036         long yVec = 0;
1037         int left = 0;
1038         wchar_t leftChar = 0;
1039
1040         _IFont::Glyph* pFontGlyphData = 0;
1041
1042         _Font* pThis = const_cast <_Font*>(this);
1043
1044         APPLY_ATTRIBUTE(E_SYSTEM);
1045
1046         {
1047                 _IFont::SizeProperty sizeProperty;
1048                 GET_FONT_SIZE_PROPERTY(sizeProperty, E_SYSTEM);
1049
1050                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
1051                 {
1052                         italicSpace = (sizeProperty.ascender.ToInt() * 2) >> 4;
1053                 }
1054         }
1055
1056         _IFont::Property property;
1057         GET_FONT_PROPERTY(property, false);
1058
1059         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1060         {
1061                 _IFont::Attrib attr;
1062                 pThis->GetAttrib(attr);
1063                 boldSpace = static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1064         }
1065
1066         const wchar_t* pText = text.pStart;
1067         int length = text.length;
1068
1069         while (*pText && --length >= 0)
1070         {
1071                 {
1072                         FriBidiCharType type = fribidi_get_bidi_type((FriBidiChar) *pText);
1073
1074                         GUnicodeScript script = g_unichar_get_script(*pText);
1075
1076                         if (FRIBIDI_IS_LETTER(type) && FRIBIDI_IS_RTL(type))
1077                         {
1078                                 return E_SYSTEM;
1079                         }
1080                         else if (script == G_UNICODE_SCRIPT_DEVANAGARI || script == G_UNICODE_SCRIPT_BENGALI)
1081                         {
1082                                 return E_SYSTEM;
1083                         }
1084                 }
1085
1086                 // getting proper _Font instance for the specified text
1087                 _IFont* pFont = pThis->__GetFont(*pText);
1088
1089                 if (pFont != __pNativeFont)
1090                 {
1091                         _IFont::Attrib fontAttrib;
1092                         bool rtn = pFont->GetAttrib(fontAttrib);
1093                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
1094
1095                         fontAttrib.size = __fontAttrib.size;
1096                         fontAttrib.style = _IFont::STYLE_NONE;
1097                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1098                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1099                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1100                         rtn = pFont->SetAttrib(fontAttrib);
1101                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
1102                 }
1103
1104                 if (left > 0)
1105                 {
1106                         if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
1107                         {
1108                                 curX += xVec;
1109                         }
1110                 }
1111
1112                 if (pFont->LoadGlyph(*pText++, &pFontGlyphData))
1113                 {
1114                         int glyphBoundX1 = curX;
1115                         int glyphBoundY1 = curY - pFontGlyphData->yOffset.ToInt();
1116                         int glyphBoundX2 = glyphBoundX1 +
1117                                                         ((pFontGlyphData->image.width <= 0) ? pFontGlyphData->xAdvance.ToInt()
1118                                                                                                                                 : (pFontGlyphData->xOffset.ToInt() + pFontGlyphData->image.width));
1119                         int glyphBoundY2 = glyphBoundY1 + pFontGlyphData->image.height;
1120
1121 #ifdef SYNCHRONIZATION_2_0
1122                         // adjusting x2 bounds for synchronizing fuctionality with 2.0
1123                         glyphBoundX2 = glyphBoundX1 + pFontGlyphData->xAdvance.ToInt() + italicSpace + boldSpace;
1124 #endif
1125                         if (outline)
1126                         {
1127                                 glyphBoundX1 -= 1;
1128                                 glyphBoundY1 -= 1;
1129                                 glyphBoundX2 += 1;
1130                                 glyphBoundY2 += 1;
1131                         }
1132
1133                         _ExpandBounds(glyphBoundX1, glyphBoundY1, x1, y1, x2, y2);
1134                         _ExpandBounds(glyphBoundX2, glyphBoundY1, x1, y1, x2, y2);
1135                         _ExpandBounds(glyphBoundX1, glyphBoundY2, x1, y1, x2, y2);
1136                         _ExpandBounds(glyphBoundX2, glyphBoundY2, x1, y1, x2, y2);
1137
1138 #ifdef SYNCHRONIZATION_2_0
1139                         curX += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + italicSpace + boldSpace;
1140 #else
1141                         curX += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + boldSpace;
1142 #endif
1143                         curY += pFontGlyphData->yAdvance.ToInt();
1144
1145                         pFont->UnloadGlyph(&pFontGlyphData);
1146
1147                         // check end condition
1148                         // TODO, shkim, BIDI need to be cared
1149                         if ((x2 - x1) > width)
1150                         {
1151                                 break;
1152                         }
1153
1154                         preX1 = x1;
1155                         preY1 = y1;
1156                         preX2 = x2;
1157                         preY2 = y2;
1158                         characters++;
1159                         left++;
1160                         leftChar = *(pText - 1);
1161                 }
1162         }
1163
1164         if (characters == 0)
1165         {
1166                 pcDim.SetSize(0, 0);
1167                 count = 0;
1168                 return E_SUCCESS;
1169         }
1170
1171         SysTryCatch(NID_GRP, preX1 <= preX2 && preY1 <= preY2, pcDim.SetSize(0, 0); count = 0, E_SYSTEM, "[E_SYSTEM] Failed to calculate text extent");
1172
1173         count = characters;
1174         pcDim.width = preX2 - preX1;
1175 #ifdef SYNCHRONIZATION_2_0
1176         pcDim.height = __fontAttrib.size.ToInt();
1177 #else
1178         pcDim.height = preY2 - preY1;
1179 #endif // SYNCHRONIZATION_2_0
1180
1181         return E_SUCCESS;
1182
1183 CATCH:
1184         return E_SYSTEM;
1185 }
1186
1187 result
1188 _Font::__GetTextExtent(int width, const _Util::String& text, bool outline, int& count, Dimension& pcDim) const
1189 {
1190         if (text.pStart == null)
1191         {
1192                 pcDim.SetSize(0, 0);
1193                 SysTryReturn(NID_GRP, false, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] The given string is invalid.");
1194         }
1195
1196         int preX1 = 0x7FFFFFFF;
1197         int preY1 = 0x7FFFFFFF;
1198         int preX2 = -0x7FFFFFFF;
1199         int preY2 = -0x7FFFFFFF;
1200
1201         int x1 = 0x7FFFFFFF;
1202         int y1 = 0x7FFFFFFF;
1203         int x2 = -0x7FFFFFFF;
1204         int y2 = -0x7FFFFFFF;
1205
1206         int curX = 0;
1207         int curY = 0;
1208
1209         int characters = 0;
1210         int italicSpace = 0;
1211         int boldSpace = 0;
1212
1213         long xVec = 0;
1214         long yVec = 0;
1215         int left = 0;
1216         wchar_t leftChar = 0;
1217
1218         _IFont::Glyph* pFontGlyphData = 0;
1219
1220         if (text.length == 0)
1221         {
1222                 count = 0;
1223                 pcDim.SetSize(0, 0);
1224                 return E_SUCCESS;
1225         }
1226
1227         _Font* pThis = const_cast <_Font*>(this);
1228
1229         APPLY_ATTRIBUTE(E_SYSTEM);
1230
1231         {
1232                 _IFont::SizeProperty sizeProperty;
1233                 GET_FONT_SIZE_PROPERTY(sizeProperty, E_SYSTEM);
1234
1235                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
1236                 {
1237                         italicSpace = (sizeProperty.ascender.ToInt() * 2) >> 4;
1238                 }
1239         }
1240
1241         _IFont::Property property;
1242         GET_FONT_PROPERTY(property, false);
1243
1244         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1245         {
1246                 _IFont::Attrib attr;
1247                 pThis->GetAttrib(attr);
1248                 boldSpace = static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1249         }
1250
1251         const wchar_t* pText = text.pStart;
1252         int length = text.length;
1253
1254         while (*pText && --length >= 0)
1255         {
1256                 // getting proper _Font instance for the specified text
1257                 _IFont* pFont = pThis->__GetFont(*pText);
1258
1259                 if (pFont != __pNativeFont)
1260                 {
1261                         _IFont::Attrib fontAttrib;
1262                         bool rtn = pFont->GetAttrib(fontAttrib);
1263                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
1264
1265                         fontAttrib.size = __fontAttrib.size;
1266                         fontAttrib.style = _IFont::STYLE_NONE;
1267                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1268                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1269                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1270                         rtn = pFont->SetAttrib(fontAttrib);
1271                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
1272                 }
1273
1274                 if (left > 0)
1275                 {
1276                         if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
1277                         {
1278                                 curX += xVec;
1279                         }
1280                 }
1281
1282                 if (pFont->LoadGlyph(*pText++, &pFontGlyphData))
1283                 {
1284                         int glyphBoundX1 = curX;
1285                         int glyphBoundY1 = curY - pFontGlyphData->yOffset.ToInt();
1286                         int glyphBoundX2 = glyphBoundX1 +
1287                                                         ((pFontGlyphData->image.width <= 0) ? pFontGlyphData->xAdvance.ToInt()
1288                                                                                                                                 : (pFontGlyphData->xOffset.ToInt() + pFontGlyphData->image.width));
1289                         int glyphBoundY2 = glyphBoundY1 + pFontGlyphData->image.height;
1290
1291 #ifdef SYNCHRONIZATION_2_0
1292                         // adjusting x2 bounds for synchronizing fuctionality with 2.0
1293                         glyphBoundX2 = glyphBoundX1 + pFontGlyphData->xAdvance.ToInt() + italicSpace + boldSpace;
1294 #endif
1295                         if (outline)
1296                         {
1297                                 glyphBoundX1 -= 1;
1298                                 glyphBoundY1 -= 1;
1299                                 glyphBoundX2 += 1;
1300                                 glyphBoundY2 += 1;
1301                         }
1302
1303                         _ExpandBounds(glyphBoundX1, glyphBoundY1, x1, y1, x2, y2);
1304                         _ExpandBounds(glyphBoundX2, glyphBoundY1, x1, y1, x2, y2);
1305                         _ExpandBounds(glyphBoundX1, glyphBoundY2, x1, y1, x2, y2);
1306                         _ExpandBounds(glyphBoundX2, glyphBoundY2, x1, y1, x2, y2);
1307
1308 #ifdef SYNCHRONIZATION_2_0
1309                         curX += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + italicSpace + boldSpace;
1310 #else
1311                         curX += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + boldSpace;
1312 #endif
1313                         curY += pFontGlyphData->yAdvance.ToInt();
1314
1315                         pFont->UnloadGlyph(&pFontGlyphData);
1316
1317                         // check end condition
1318                         // TODO, shkim, BIDI need to be cared
1319                         if ((x2 - x1) > width)
1320                         {
1321                                 break;
1322                         }
1323
1324                         preX1 = x1;
1325                         preY1 = y1;
1326                         preX2 = x2;
1327                         preY2 = y2;
1328                         characters++;
1329                         left++;
1330                         leftChar = *(pText - 1);
1331                 }
1332         }
1333
1334         if (characters == 0)
1335         {
1336                 pcDim.SetSize(0, 0);
1337                 count = 0;
1338                 return E_SUCCESS;
1339         }
1340
1341         SysTryCatch(NID_GRP, preX1 <= preX2 && preY1 <= preY2, pcDim.SetSize(0, 0); count = 0, E_SYSTEM, "[E_SYSTEM] Failed to calculate text extent");
1342
1343         count = characters;
1344         pcDim.width = preX2 - preX1;
1345 #ifdef SYNCHRONIZATION_2_0
1346         pcDim.height = __fontAttrib.size.ToInt();
1347 #else
1348         pcDim.height = preY2 - preY1;
1349 #endif // SYNCHRONIZATION_2_0
1350
1351         return E_SUCCESS;
1352
1353 CATCH:
1354         return E_SYSTEM;
1355 }
1356
1357 result
1358 _Font::GetTextExtent(int width, const _Util::String& text, bool outline, const Tizen::Base::String& delimiter, int& count, Dimension& dim) const
1359 {
1360         const wchar_t* pText = text.pStart;
1361         const wchar_t* pTextEnd = pText + text.length;
1362
1363         while (pText < pTextEnd)
1364         {
1365                 if (*pText == 0x0D || *pText == 0x0A)
1366                 {
1367                         pTextEnd = pText;
1368                         break;
1369                 }
1370
1371                 ++pText;
1372         }
1373
1374         return this->GetTextExtent(width, _Util::String(text.pStart, pTextEnd - text.pStart), outline, count, dim);
1375 }
1376
1377 result
1378 _Font::__GetTextExtentList(const _Util::String& text, _Util::AccumList<_Util::Pair<int, int> >& outList) const
1379 {
1380         SysAssert(text.pStart != null && text.length > 0);
1381
1382         outList.Clear();
1383
1384         _Font* pThis = const_cast <_Font*>(this);
1385
1386         APPLY_ATTRIBUTE(E_SYSTEM);
1387
1388         int addingSpace = __fontAttrib.charSpace;
1389
1390 #ifdef SYNCHRONIZATION_2_0
1391         {
1392                 _IFont::SizeProperty sizeProperty;
1393
1394                 GET_FONT_SIZE_PROPERTY(sizeProperty, E_SYSTEM);
1395
1396                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
1397                 {
1398                         addingSpace += (sizeProperty.ascender.ToInt() * 2) >> 4;
1399                 }
1400         }
1401 #endif
1402
1403         _IFont::Property property;
1404         GET_FONT_PROPERTY(property, false);
1405
1406         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1407         {
1408                 _IFont::Attrib attr;
1409
1410                 if (pThis->GetAttrib(attr))
1411                 {
1412                         addingSpace += static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1413                 }
1414         }
1415
1416         int curX = 0;
1417         int curY = 0;
1418         wchar_t prevChar = 0;
1419
1420         const wchar_t* pText = text.pStart;
1421         int length = text.length;
1422
1423         --pText;
1424
1425         while (*(++pText) && --length >= 0)
1426         {
1427                 _IFont* pFont = pThis->__GetFont(*pText);
1428
1429                 if (pFont)
1430                 {
1431                         if (pFont != __pNativeFont)
1432                         {
1433                                 _IFont::Attrib fontAttrib;
1434
1435                                 if (pFont->GetAttrib(fontAttrib))
1436                                 {
1437                                         fontAttrib.size = __fontAttrib.size;
1438                                         fontAttrib.style = _IFont::STYLE_NONE;
1439                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1440                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1441                                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1442                                         pFont->SetAttrib(fontAttrib);
1443                                 }
1444                         }
1445
1446                         _IFont::Glyph* pFontGlyphData = 0;
1447
1448                         if (pFont->LoadGlyph(*pText, &pFontGlyphData))
1449                         {
1450                                 // When LoadGlyph fails continuously in the original code, there is a problem to check the kerning on the results of the previous prevChar
1451                                 if (prevChar > 0)
1452                                 {
1453                                         long xVec = 0;
1454                                         long yVec = 0;
1455
1456                                         if (pFont->GetKerning(prevChar, *pText, xVec, yVec))
1457                                         {
1458                                                 curX += xVec;
1459                                         }
1460                                 }
1461
1462                                 int prevX = curX;
1463
1464                                 curX += pFontGlyphData->xAdvance.ToInt() + addingSpace;
1465                                 curY += pFontGlyphData->yAdvance.ToInt();
1466
1467                                 pFont->UnloadGlyph(&pFontGlyphData);
1468
1469                                 prevChar = *pText;
1470                                 outList.Push(_Util::MakePair(prevX, curX));
1471
1472                                 continue;
1473                         }
1474                 }
1475
1476                 // Cannot determine a glyph extent
1477                 prevChar = 0;
1478                 outList.Push(_Util::MakePair(curX, curX));
1479         }
1480
1481         return E_SUCCESS;
1482 }
1483
1484 result
1485 _Font::__GetTextExtentList(_TextBidiPropertyWithReorder& bidiProperty, _Util::AccumList<_Util::Pair<int, int> >& outList) const
1486 {
1487         if (bidiProperty.length <= 0)
1488         {
1489                 outList.Clear();
1490
1491                 return E_SUCCESS;
1492         }
1493
1494         _Util::AccumList<_Util::Pair<int, int> > tempList;
1495
1496         {
1497                 int xDest = 0;
1498                 int yDest = 0;
1499
1500                 int length = bidiProperty.length;
1501
1502                 _Font* pThis = const_cast <_Font*>(this);
1503
1504                 pThis->ApplyAttribute();
1505
1506                 const wchar_t* pReorderedText = bidiProperty.GetReorderedText();
1507
1508                 const wchar_t* pTextFragmentBegin = pReorderedText;
1509                 const wchar_t* pTextFragmentEnd = pTextFragmentBegin + length;
1510
1511                 const wchar_t* pTextSegment = pTextFragmentBegin;
1512
1513                 _IFont* pBaseFont = pThis->__GetFont(*pTextSegment);
1514
1515                 _Util::AccumList<_TextFragment> textFragmentList;
1516
1517                 while (pTextSegment < pTextFragmentEnd)
1518                 {
1519                         if (pBaseFont->CheckGlyph(*pTextSegment) == 0)
1520                         {
1521                                 _IFont* pFallbackFont = pThis->__GetFont(*pTextSegment);
1522
1523                                 if (pBaseFont != pFallbackFont)
1524                                 {
1525                                         textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1526
1527                                         pTextFragmentBegin = pTextSegment;
1528                                         pBaseFont = pFallbackFont;
1529                                 }
1530                         }
1531
1532                         ++pTextSegment;
1533                 }
1534
1535                 textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1536
1537                 /*
1538                  * - In case of LTR
1539                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1540                  *
1541                  * - In case of RTL
1542                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.End(); textFragment != textFragmentList.Begin(); )
1543                  * {
1544                  *     --textFragment;
1545                  *
1546                  */
1547
1548                 for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1549                 {
1550                         if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
1551                         {
1552                                 continue;
1553                         }
1554
1555                         if (textFragment->pUsingFont != __pNativeFont)
1556                         {
1557                                 _IFont::Attrib fontAttrib;
1558
1559                                 if (textFragment->pUsingFont->GetAttrib(fontAttrib))
1560                                 {
1561                                         fontAttrib.size = __fontAttrib.size;
1562                                         fontAttrib.style = _IFont::STYLE_NONE;
1563                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1564                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1565                                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1566
1567                                         textFragment->pUsingFont->SetAttrib(fontAttrib);
1568                                 }
1569                         }
1570
1571                         Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
1572
1573                         const wchar_t firstChar = *textFragment->textFragment.pStart;
1574
1575                         GUnicodeScript script = _TextBidiUtil::GetUnicodeScript(firstChar);
1576                         // need to check if (script < 0 || script >= _sampleLanguageCount) ?
1577
1578                         textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, script);
1579
1580                         int count = glyphList.GetCount();
1581
1582                         for (int i = 0; i < count; i++)
1583                         {
1584                                 _IFont::Glyph *pGlyph = 0;
1585
1586                                 glyphList.GetAt(i, pGlyph);
1587
1588                                 // bug fixed in test case of L"\x9a8\x20\x981\x9a0\x635"
1589                                 //if (pGlyph->xAdvance == 0 && pGlyph->image.width == 0)
1590                                 //{
1591                                 //      continue;
1592                                 //}
1593
1594                                 int prevX = xDest;
1595
1596                                 xDest += pGlyph->xAdvance.ToInt();
1597                                 yDest += pGlyph->yAdvance.ToInt();
1598
1599                                 tempList.Push(_Util::MakePair(prevX, xDest));
1600                                 outList.Push(_Util::MakePair(-1, -1));
1601                         }
1602
1603                         IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
1604
1605                         if (pEnum)
1606                         {
1607                                 while (pEnum->MoveNext() == E_SUCCESS)
1608                                 {
1609                                         _IFont::Glyph* pGlyph;
1610
1611                                         pEnum->GetCurrent(pGlyph);
1612                                         pBaseFont->UnloadGlyph(&pGlyph);
1613                                 }
1614
1615                                 delete pEnum;
1616                         }
1617                 }
1618         }
1619
1620         if (bidiProperty.pBidiIndex)
1621         {
1622                 // Reorder list by using BIDI index
1623                 typedef _Util::Pair<int, int> Gap;
1624                 typedef _Util::AccumList<Gap> GapList;
1625
1626                 GapList::Iterator dstBegin = outList.Begin();
1627
1628                 int index = 0;
1629
1630                 if (bidiProperty.length == int(tempList.Size()))
1631                 {
1632                         for (GapList::ConstIterator src = tempList.Begin(); src != tempList.End(); ++src)
1633                         {
1634                                 *(dstBegin + bidiProperty.pBidiIndex[index++]) = *src;
1635                         }
1636                 }
1637                 else if (bidiProperty.length > int(tempList.Size()))
1638                 {
1639                         _TextBidiUtil::GetReorderedIndexList(bidiProperty, tempList, outList);
1640                 }
1641                 else // if (bidiProperty.length < tempList.Size())
1642                 {
1643                         // under development
1644                         for (GapList::ConstIterator src = tempList.Begin(); src != tempList.End() && index < bidiProperty.length; ++src)
1645                         {
1646                                 *(dstBegin + bidiProperty.pBidiIndex[index++]) = *src;
1647                         }
1648                 }
1649         }
1650         else
1651         {
1652                 typedef _Util::Pair<int, int> Gap;
1653                 typedef _Util::AccumList<Gap> GapList;
1654
1655                 GapList::Iterator dst = outList.Begin();
1656                 GapList::Iterator dstEnd = outList.End();
1657
1658                 GapList::ConstIterator src = tempList.Begin();
1659                 GapList::ConstIterator srcEnd = tempList.End();
1660
1661                 for (; (src != srcEnd) && (dst != dstEnd); ++src, ++dst)
1662                 {
1663                         *dst = *src;
1664                 }
1665         }
1666
1667         return E_SUCCESS;
1668 }
1669
1670 result
1671 _Font::GetTextExtentList(const _Util::String& text, _Util::AccumList<_Util::Pair<int, int> >& outList) const
1672 {
1673         if (text.pStart == null || text.length <= 0)
1674         {
1675                 outList.Clear();
1676                 return E_SUCCESS;
1677         }
1678
1679         _TextBidiPropertyWithReorder bidiProperty(text.pStart, text.length, _Util::Convert<TextBidiHint, _TextBidiProperty::BidiHint>(_GetTextBidiHint()));
1680
1681         if (bidiProperty.HasComplexText())
1682         {
1683                 return this->__GetTextExtentList(bidiProperty, outList);
1684         }
1685         else
1686         {
1687                 return this->__GetTextExtentList(text, outList);
1688         }
1689
1690         return E_SUCCESS;
1691 }
1692
1693 result
1694 _Font::SetSize(_Util::FixedPoint26_6 pcSize)
1695 {
1696         __UpdateFontAttribute(__fontAttrib.style, pcSize);
1697
1698         return E_SUCCESS;
1699 }
1700
1701 result
1702 _Font::SetStyle(int style)
1703 {
1704         __fontAttrib.style = style;
1705
1706         return E_SUCCESS;
1707 }
1708
1709 int
1710 _Font::GetStyle(void) const
1711 {
1712         return __fontAttrib.style;
1713 }
1714
1715 _Util::FixedPoint26_6
1716 _Font::GetLeading(void) const
1717 {
1718         return __fontAttrib.maxHeight;
1719 }
1720
1721 result
1722 _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
1723 {
1724         SysTryReturnResult(NID_GRP, canvas.__pScratchPad != null, E_INVALID_ARG, "A canvas is invalid");
1725
1726         const wchar_t* pText = text.GetPointer() + startIndex;
1727
1728         bool rtn = this->ApplyAttribute();
1729         SysTryReturn(NID_GRP, rtn, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fails to apply font attribute.");
1730
1731         _Util::ScratchPad <SystemPixel>& scratchPad = *canvas.__pScratchPad;
1732         scratchPad.RegisterFillRect(_RasterOp::FnFillRectFont32Bit);
1733
1734         Rectangle clipBounds;
1735         canvas.__GetClipBounds(clipBounds);
1736
1737         int xDest = point.x;
1738         int yDest = point.y;
1739         int startX = point.x;
1740         int charHeight = 0;
1741         int italicSpace = 0;
1742         int boldSpace = 0;
1743         int clipX1 = clipBounds.x;
1744         int clipY1 = clipBounds.y;
1745         int clipX2 = clipX1 + clipBounds.width;
1746         int clipY2 = clipY1 + clipBounds.height;
1747         long xVec = 0;
1748         long yVec = 0;
1749         int left = 0;
1750         wchar_t leftChar = 0;
1751         _IFont::Glyph* pFontGlyphData = 0;
1752
1753         _IFont::SizeProperty sizeProperty;
1754         rtn = this->GetFontSizeProperty(sizeProperty);
1755         SysTryReturn(NID_GRP, rtn, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get font sizeProperty.");
1756
1757         // need to revise y value, because _IFont is based on the baseline
1758         {
1759                 if (canvas.__textOrigin == TEXT_ORIGIN_LEFT_TOP)
1760                 {
1761                         yDest += sizeProperty.ascender.ToInt();
1762                 }
1763
1764                 charHeight = sizeProperty.ascender.ToInt() - sizeProperty.descender.ToInt();
1765
1766                 if (this->GetStyle() & FONT_STYLE_ITALIC)
1767                 {
1768                         italicSpace = (sizeProperty.ascender.ToInt() * 2) >> 4;
1769                 }
1770         }
1771
1772         _IFont::Property property;
1773         GET_FONT_PROPERTY(property, false);
1774
1775         if (__fontAttrib.style & FONT_STYLE_BOLD && property.weightClass < _MEDIUM_FONT_BOLD_WEIGHT)
1776         {
1777                 _IFont::Attrib attr;
1778                 this->GetAttrib(attr);
1779                 boldSpace = static_cast<int>(attr.boldWeight.ToFloat() + 0.5f);
1780         }
1781
1782         unsigned long canvasFgColor = canvas.__fgColor;
1783
1784         _TextBidiPropertyWithReorder bidiProperty(pText, length, _Util::Convert<TextBidiHint, _TextBidiProperty::BidiHint>(_GetTextBidiHint()));
1785
1786         if (bidiProperty.HasComplexText())
1787         {
1788                 const wchar_t* pReorderedText = bidiProperty.GetReorderedText();
1789
1790                 const wchar_t* pTextFragmentBegin = pReorderedText;
1791                 const wchar_t* pTextFragmentEnd = pTextFragmentBegin + length;
1792
1793                 const wchar_t* pTextSegment = pTextFragmentBegin;
1794
1795                 _IFont* pBaseFont = this->__GetFont(*pTextSegment);
1796
1797                 _Util::AccumList<_TextFragment> textFragmentList;
1798
1799                 while (pTextSegment < pTextFragmentEnd)
1800                 {
1801                         if (pBaseFont->CheckGlyph(*pTextSegment) == 0)
1802                         {
1803                                 _IFont* pFallbackFont = this->__GetFont(*pTextSegment);
1804
1805                                 if (pBaseFont != pFallbackFont)
1806                                 {
1807                                         textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1808
1809                                         pTextFragmentBegin = pTextSegment;
1810                                         pBaseFont = pFallbackFont;
1811                                 }
1812                         }
1813
1814                         ++pTextSegment;
1815                 }
1816
1817                 textFragmentList.Push(_TextFragment(_Util::String(pTextFragmentBegin, pTextSegment - pTextFragmentBegin), pBaseFont));
1818
1819                 /*
1820                  * - In case of LTR
1821                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1822                  *
1823                  * - In case of RTL
1824                  * for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.End(); textFragment != textFragmentList.Begin(); )
1825                  * {
1826                  *     --textFragment;
1827                  *
1828                  */
1829
1830                 for (_Util::AccumList<_TextFragment>::Iterator textFragment = textFragmentList.Begin(); textFragment != textFragmentList.End(); ++textFragment)
1831                 {
1832                         if (textFragment->pUsingFont == null || textFragment->textFragment.length <= 0)
1833                         {
1834                                 continue;
1835                         }
1836
1837                         if (textFragment->pUsingFont != __pNativeFont)
1838                         {
1839                                 _IFont::Attrib fontAttrib;
1840
1841                                 if (textFragment->pUsingFont->GetAttrib(fontAttrib))
1842                                 {
1843                                         fontAttrib.size = __fontAttrib.size;
1844                                         fontAttrib.style = _IFont::STYLE_NONE;
1845                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1846                                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1847                                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1848
1849                                         textFragment->pUsingFont->SetAttrib(fontAttrib);
1850                                 }
1851                         }
1852
1853                         Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
1854
1855                         const wchar_t firstChar = *textFragment->textFragment.pStart;
1856
1857                         GUnicodeScript script = _TextBidiUtil::GetUnicodeScript(firstChar);
1858
1859                         textFragment->pUsingFont->GetGlyphList(textFragment->textFragment, glyphList, script);
1860                         // need to check if (script < 0 || script >= _sampleLanguageCount) ?
1861
1862                         int count = glyphList.GetCount();
1863
1864                         for (int i = 0; i < count; i++)
1865                         {
1866                                 /* for debugging
1867                                 static int s_index = 0;
1868                                 const unsigned long COLOR[6] =
1869                                 {
1870                                         0xFFFFFFFF,
1871                                         0xFF40FF40,
1872                                         0xFF40FFFF,
1873                                         0xFFFF4040,
1874                                         0xFFFF40FF,
1875                                         0xFFFFFF40
1876                                 };
1877                                 unsigned long canvasFgColor = COLOR[s_index++ % 6];
1878                                 */
1879
1880                                 typedef unsigned long TPixel;
1881                                 _IFont::Glyph *pGlyph = 0;
1882
1883                                 TPixel srcR, srcG, srcB, srcA;
1884                                 TPixel dstR, dstG, dstB, dstA;
1885
1886                                 srcA = (canvasFgColor >> 24) & 0xFF;
1887                                 srcA += (srcA >> 7);
1888                                 srcR = (canvasFgColor >> 16) & 0xFF;
1889                                 srcG = (canvasFgColor >> 8) & 0xFF;
1890                                 srcB = (canvasFgColor) & 0xFF;
1891
1892                                 SystemPixel* pBufferStartAddr = null;
1893                                 int bufferPitch;
1894
1895                                 scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
1896
1897                                 glyphList.GetAt(i, pGlyph);
1898
1899                                 if (!_TextBidiUtil::IsTextBidiBaseLtr())
1900                                 {
1901                                         xDest -= pGlyph->xAdvance.ToInt();
1902                                         yDest -= pGlyph->yAdvance.ToInt();
1903                                 }
1904
1905                                 for (int h = 0; h < pGlyph->image.height; h++)
1906                                 {
1907                                         int y = yDest - pGlyph->yOffset.ToInt() + h;
1908
1909                                         if (y < clipY1)
1910                                         {
1911                                                 continue;
1912                                         }
1913
1914                                         if (y >= clipY2)
1915                                         {
1916                                                 break;
1917                                         }
1918
1919                                         TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pGlyph->xOffset.ToInt();
1920
1921                                         for (int w = 0; w < pGlyph->image.width; w++)
1922                                         {
1923                                                 int x = xDest + pGlyph->xOffset.ToInt() + w;
1924
1925                                                 if (x < clipX1)
1926                                                 {
1927                                                         ++pDest32;
1928                                                         continue;
1929                                                 }
1930
1931                                                 if (x >= clipX2)
1932                                                 {
1933                                                         break;
1934                                                 }
1935
1936                                                 unsigned long alpha = (unsigned long) (pGlyph->image.pBitmap[h * pGlyph->image.bytesPerLine + w]);
1937
1938                                                 if (alpha > 0)
1939                                                 {
1940                                                         // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
1941                                                         alpha = (alpha * srcA) >> 8;
1942                                                         alpha += (alpha >> 7);
1943
1944                                                         dstA = (*pDest32 >> 24) & 0xFF;
1945                                                         dstR = (*pDest32 >> 16) & 0xFF;
1946                                                         dstG = (*pDest32 >> 8) & 0xFF;
1947                                                         dstB = (*pDest32) & 0xFF;
1948
1949                                                         dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
1950                                                         dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
1951                                                         dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
1952                                                         dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
1953
1954                                                         *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
1955
1956                                                 }
1957                                                 ++pDest32;
1958                                         }
1959                                 }
1960
1961                                 if (_TextBidiUtil::IsTextBidiBaseLtr())
1962                                 {
1963                                         xDest += pGlyph->xAdvance.ToInt();
1964                                         yDest += pGlyph->yAdvance.ToInt();
1965                                 }
1966                         }
1967
1968                         IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
1969
1970                         if (pEnum)
1971                         {
1972                                 while (pEnum->MoveNext() == E_SUCCESS)
1973                                 {
1974                                         _IFont::Glyph* pGlyph;
1975
1976                                         pEnum->GetCurrent(pGlyph);
1977                                         pBaseFont->UnloadGlyph(&pGlyph);
1978                                 }
1979
1980                                 delete pEnum;
1981                         }
1982                 }
1983         }
1984         else
1985         {
1986                 while (*pText && --length >= 0)
1987                 {
1988                         // find out proper native font
1989                         _IFont* pFont = this->__GetFont(*pText);
1990
1991                         if (pFont == null)
1992                         {
1993                                 continue;
1994                         }
1995
1996                         if (pFont != __pNativeFont)
1997                         {
1998                                 _IFont::Attrib fontAttrib;
1999                                 bool rtn = pFont->GetAttrib(fontAttrib);
2000                                 //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
2001
2002                                 fontAttrib.size = __fontAttrib.size;
2003                                 fontAttrib.style = _IFont::STYLE_NONE;
2004                                 fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
2005                                 fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
2006                                 fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
2007
2008                                 rtn = pFont->SetAttrib(fontAttrib);
2009                                 //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
2010                         }
2011
2012                         _IFont::Property property;
2013                         pFont->GetFontProperty(property);
2014
2015                         unsigned long fgColor = (canvas.__applyEmoji && pFont->IsEmoji()) ? GetPredefinedColor(*pText, canvasFgColor) : canvasFgColor;
2016
2017                         if (left > 0)
2018                         {
2019                                 if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
2020                                 {
2021                                         xDest += xVec;
2022                                 }
2023                         }
2024
2025                         bool rtn = pFont->LoadGlyph(*pText++, &pFontGlyphData);
2026
2027                         if (!rtn)
2028                         {
2029                                 continue;
2030                         }
2031
2032                         typedef unsigned long TPixel;
2033
2034                         TPixel srcA = (fgColor >> 24) & 0xFF;
2035                         srcA += (srcA >> 7);
2036
2037                         TPixel srcR = (fgColor >> 16) & 0xFF;
2038                         TPixel srcG = (fgColor >> 8) & 0xFF;
2039                         TPixel srcB = (fgColor) & 0xFF;
2040
2041                         SystemPixel* pBufferStartAddr = null;
2042                         int bufferPitch = 0;
2043
2044                         scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
2045
2046                         for (int h = 0; h < pFontGlyphData->image.height; h++)
2047                         {
2048                                 int y = yDest - pFontGlyphData->yOffset.ToInt() + h;
2049
2050                                 if (y < clipY1)
2051                                 {
2052                                         continue;
2053                                 }
2054
2055                                 if (y >= clipY2)
2056                                 {
2057                                         break;
2058                                 }
2059
2060                                 TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pFontGlyphData->xOffset.ToInt();
2061
2062                                 for (int w = 0; w < pFontGlyphData->image.width; w++)
2063                                 {
2064                                         int x = xDest + pFontGlyphData->xOffset.ToInt() + w;
2065
2066                                         if (x < clipX1)
2067                                         {
2068                                                 ++pDest32;
2069                                                 continue;
2070                                         }
2071
2072                                         if (x >= clipX2)
2073                                         {
2074                                                 break;
2075                                         }
2076
2077                                         unsigned long alpha = (unsigned long) (pFontGlyphData->image.pBitmap[h * pFontGlyphData->image.bytesPerLine + w]);
2078
2079                                         if (alpha > 0)
2080                                         {
2081                                                 // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
2082                                                 alpha = (alpha * srcA) >> 8;
2083                                                 alpha += (alpha >> 7);
2084
2085                                                 TPixel dstA = (*pDest32 >> 24) & 0xFF;
2086                                                 TPixel dstR = (*pDest32 >> 16) & 0xFF;
2087                                                 TPixel dstG = (*pDest32 >> 8) & 0xFF;
2088                                                 TPixel dstB = (*pDest32) & 0xFF;
2089
2090                                                 dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
2091                                                 dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
2092                                                 dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
2093                                                 dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
2094
2095                                                 *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
2096
2097                                         }
2098                                         ++pDest32;
2099                                 }
2100                         }
2101
2102                         xDest += pFontGlyphData->xAdvance.ToInt() + __fontAttrib.charSpace + italicSpace + boldSpace;
2103                         yDest += pFontGlyphData->yAdvance.ToInt();
2104                         left++;
2105                         leftChar = *(pText - 1);
2106
2107                         pFont->UnloadGlyph(&pFontGlyphData);
2108
2109                 }
2110         }
2111
2112         if (this->IsUnderlined() || this->IsStrikeOut())
2113         {
2114                 int y = 0;
2115                 int thick = this->GetLineThickness();
2116
2117                 if (canvas.__textOrigin == TEXT_ORIGIN_LEFT_TOP)
2118                 {
2119                         y = point.y + charHeight - 1;
2120                 }
2121                 else
2122                 {
2123                         y = point.y - sizeProperty.descender.ToInt() - 1;
2124                 }
2125
2126                 xDest -= this->GetCharSpace();
2127
2128                 if (this->IsUnderlined())
2129                 {
2130                         canvas.FillRectangle(canvasFgColor, Rectangle(startX, y - thick, xDest - startX, thick));
2131                 }
2132
2133                 if (this->IsStrikeOut())
2134                 {
2135                         y -= charHeight / 2;
2136                         canvas.FillRectangle(canvasFgColor, Rectangle(startX, y - thick, xDest - startX, thick));
2137                 }
2138         }
2139
2140         scratchPad.RegisterFillRect(null);
2141
2142
2143         return E_SUCCESS;
2144 }
2145
2146 #undef BLEND_ALPHA_COMPONEMT
2147
2148 result
2149 _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
2150 {
2151         unsigned long textColor = canvas.__fgColor;
2152         bool applyEmoji = canvas.__applyEmoji;
2153
2154         //sunmi557.shin: draw border of font
2155         canvas.__fgColor = outlineColor.GetRGB32();
2156         canvas.__applyEmoji = false;
2157
2158         this->__DrawText(canvas, Point(point.x - 1, point.y), text, startIndex, length);
2159         this->__DrawText(canvas, Point(point.x + 1, point.y), text, startIndex, length);
2160         this->__DrawText(canvas, Point(point.x, point.y - 1), text, startIndex, length);
2161         this->__DrawText(canvas, Point(point.x, point.y + 1), text, startIndex, length);
2162
2163         //sunmi557.shin: draw original shape of font
2164         canvas.__applyEmoji = applyEmoji;
2165         canvas.__fgColor = textColor;
2166
2167         this->__DrawText(canvas, point, text, startIndex, length);
2168
2169         return E_SUCCESS;
2170 }
2171
2172 bool
2173 _Font::SetAttrib(const _IFont::Attrib& fontAttrib)
2174 {
2175         return __pNativeFont->SetAttrib(fontAttrib);
2176 }
2177
2178 bool
2179 _Font::GetAttrib(_IFont::Attrib& fontAttrib) const
2180 {
2181         return __pNativeFont->GetAttrib(fontAttrib);
2182 }
2183
2184 bool
2185 _Font::GetKerning(unsigned long character1, unsigned long character2, long& xVector, long& yVector) const
2186 {
2187         return __pNativeFont->GetKerning(character1, character2, xVector, yVector);
2188 }
2189
2190 bool
2191 _Font::GetFontSizeProperty(_IFont::SizeProperty& sizeProperty) const
2192 {
2193         return __pNativeFont->GetFontSizeProperty(sizeProperty);
2194 }
2195
2196 bool
2197 _Font::LoadGlyph(unsigned long character, _IFont::Glyph** ppFontGlyphData)
2198 {
2199         // note! we assume that the font attribute has been already applied on _IFont
2200         bool rtn = false;
2201
2202         // if not, loading glyph (character/size/style) and caching it
2203         rtn = __pNativeFont->LoadGlyph(character, ppFontGlyphData);
2204         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to load glyph data");
2205
2206         // return cached glyph
2207         return true;
2208 }
2209
2210 bool
2211 _Font::UnloadGlyph(_IFont::Glyph** ppFontGlyphData)
2212 {
2213         return __pNativeFont->UnloadGlyph(ppFontGlyphData);
2214 }
2215
2216 unsigned long
2217 _Font::CheckGlyph(unsigned long character)
2218 {
2219         return __pNativeFont->CheckGlyph(character);
2220 }
2221
2222 void
2223 _Font::__UpdateFontAttribute(int style, _Util::FixedPoint26_6 pcSize)
2224 {
2225         __fontAttrib.style = style;
2226         __fontAttrib.size = pcSize;
2227         __fontAttrib.lineThickness = pcSize.ToInt() > 0 ? (pcSize.ToInt() / 24) + 1 : 1;
2228
2229         _IFont::SizeProperty sizeProperty;
2230         bool getProperty = false;
2231
2232         if (this->ApplyAttribute())
2233         {
2234                 getProperty = __pNativeFont->GetFontSizeProperty(sizeProperty);
2235         }
2236
2237         if (getProperty)
2238         {
2239                 __fontAttrib.maxWidth = sizeProperty.maxWidth;
2240                 __fontAttrib.maxHeight = sizeProperty.maxHeight;
2241                 __fontAttrib.ascender = sizeProperty.ascender;
2242                 __fontAttrib.descender = sizeProperty.descender;
2243         }
2244         else
2245         {
2246                 // if failed to get property above, each property should be remained as default: -1
2247                 SysLog(NID_GRP, "[] Failed to get font attribute from native font");
2248
2249                 __fontAttrib.maxWidth.Reset(0);
2250                 __fontAttrib.maxHeight.Reset(0);
2251                 __fontAttrib.ascender.Reset(0);
2252                 __fontAttrib.descender.Reset(0);
2253         }
2254 }
2255
2256 result
2257 _Font::__DrawTextLastFallback(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
2258 {
2259         return E_SUCCESS;
2260 }
2261
2262 result
2263 _Font::__DrawTextDefault(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
2264 {
2265         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2266         result r = mgr.GetDefaultSystemFont().__DrawText(canvas, point, text, startIndex, length);
2267         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to draw default system font", GetErrorMessage(r));
2268
2269         return E_SUCCESS;
2270
2271 CATCH:
2272         _Font::__DrawTextLastFallback(canvas, point, text, startIndex, length);
2273         return r;
2274 }
2275
2276 result
2277 _Font::__DrawTextDefault(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
2278 {
2279         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2280         result r = mgr.GetDefaultSystemFont().__DrawText(canvas, point, text, startIndex, length, outlineColor);
2281         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to draw default system font", GetErrorMessage(r));
2282
2283         return E_SUCCESS;
2284
2285 CATCH:
2286         _Font::__DrawTextLastFallback(canvas, point, text, startIndex, length);
2287         return r;
2288 }
2289
2290
2291 result
2292 _Font::DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
2293 {
2294         if (canvas.__pPriorityFont)
2295         {
2296                 return canvas.__pPriorityFont->__DrawText(canvas, point, text, startIndex, length);
2297         }
2298         else if (canvas.__pFont)
2299         {
2300                 return canvas.__pFont->__DrawText(canvas, point, text, startIndex, length);
2301         }
2302         else
2303         {
2304                 return _Font::__DrawTextDefault(canvas, point, text, startIndex, length);
2305         }
2306 }
2307
2308 result
2309 _Font::DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
2310 {
2311         if (canvas.__pPriorityFont)
2312         {
2313                 return canvas.__pPriorityFont->__DrawText(canvas, point, text, startIndex, length, outlineColor);
2314         }
2315         else if (canvas.__pFont)
2316         {
2317                 return canvas.__pFont->__DrawText(canvas, point, text, startIndex, length, outlineColor);
2318         }
2319         else
2320         {
2321                 return _Font::__DrawTextDefault(canvas, point, text, startIndex, length, outlineColor);
2322         }
2323
2324         return E_SUCCESS;
2325 }
2326
2327 _Font*
2328 _Font::GetInstance(_FontImpl& font)
2329 {
2330         return (&font != null) ? font._pNativeFont : null;
2331 }
2332
2333 const _Font*
2334 _Font::GetInstance(const _FontImpl& font)
2335 {
2336         return (&font != null) ? font._pNativeFont : null;
2337 }
2338
2339 _IFont*
2340 _Font::__GetFont(wchar_t character)
2341 {
2342         //------------------------------------------------------
2343         //
2344         // 1. check if this font has a requested glyph
2345         //
2346         //------------------------------------------------------
2347         unsigned long idx = __pNativeFont->CheckGlyph(character);
2348
2349         if (idx > 0)
2350         {
2351                 return __pNativeFont;
2352         }
2353
2354         //------------------------------------------------------
2355         //
2356         // 1-2. check if this glyph is in the fallback list.
2357         //
2358         //------------------------------------------------------
2359         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2360         _IFont::FontMapT* pFallbackFontMap = __pNativeFont->GetFallbackMap();
2361
2362 #ifdef USE_HASHMAP_FOR_FONT
2363         std::auto_ptr<IMapEnumeratorT<_Util::WString, _FontRsrcManager::SharedFontResource> > enumerator(pFallbackFontMap->GetMapEnumeratorN());
2364
2365         while (enumerator->MoveNext() == E_SUCCESS)
2366         {
2367                 _FontRsrcManager::SharedFontResource pTempFont;
2368
2369                 if (enumerator->GetValue(pTempFont) == E_SUCCESS)
2370                 {
2371                         _Util::WString key(L"");
2372                         result r = enumerator->GetKey(key);
2373
2374                         if (r == E_SUCCESS)
2375                         {
2376                                 if (mgr.SearchFont(key))
2377                                 {
2378                                         if (pTempFont.get()->CheckGlyph(character) > 0)
2379                                         {
2380                                                 return  pTempFont.get();
2381                                         }
2382                                 }
2383                                 else
2384                                 {
2385                                         pFallbackFontMap->Remove(key);
2386                                 }
2387                         }
2388                 }
2389         }
2390 #else
2391         for (_FontRsrcManager::FontMapT::const_iterator fontIterator = pFallbackFontMap->begin(); fontIterator != pFallbackFontMap->end(); ++fontIterator)
2392         {
2393                 if (fontIterator->second != null)
2394                 {
2395                         if (fontIterator->second->CheckGlyph(character) > 0)
2396                         {
2397                                 return fontIterator->second.get();
2398                         }
2399                 }
2400         }
2401 #endif
2402
2403         //------------------------------------------------------
2404         //
2405         // 2. Get fallback font list via fontconfig
2406         //
2407         //------------------------------------------------------
2408         Tizen::Base::Collection::ArrayListT<String> fileList;
2409         bool rtn = __GetFallbackFontFileList(character, fileList);
2410
2411         if (!rtn)
2412         {
2413                 // if failed find out fallback font,
2414                 // just use this instance for drawing something for unknown glyph
2415                 return __pNativeFont;
2416         }
2417
2418         //------------------------------------------------------
2419         //
2420         // 3. try to find a font having a requested glyph
2421         //
2422         //------------------------------------------------------
2423         String fontName;
2424         _IFont* pFallbackFont = null;
2425
2426         _FontRsrcManager::SharedFontResource out;
2427
2428         int count = fileList.GetCount();
2429         result r = E_FAILURE;
2430
2431         for (int i = 0; i < count; i++)
2432         {
2433                 fileList.GetAt(i, fontName);
2434
2435                 if (fontName.IsEmpty())
2436                 {
2437                         continue;
2438                 }
2439
2440                 r = mgr.GetTempFont(fontName, __fontAttrib.style, __fontAttrib.size, out);
2441
2442                 if (r == E_SUCCESS)
2443                 {
2444                         unsigned long idx = out.get()->CheckGlyph(character);
2445
2446                         if (idx > 0)
2447                         {
2448                                 _Util::WString fontNameTemp(fontName.GetPointer());
2449
2450                                 // keep it
2451 #ifdef USE_HASHMAP_FOR_FONT
2452                                 r = pFallbackFontMap->Add(fontNameTemp, out);
2453
2454                                 if (r == E_OBJ_ALREADY_EXIST)
2455                                 {
2456                                         pFallbackFont = out.get();
2457                                         break;
2458                                 }
2459
2460                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
2461 #else
2462                                 pFallbackFontMap->push_back(std::make_pair(fontNameTemp, out));
2463 #endif
2464                                 r = mgr.AddFont(fontNameTemp, out);
2465                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
2466
2467                                 pFallbackFont = out.get();
2468                                 break;
2469                         }
2470                 }
2471         }
2472
2473         return (pFallbackFont != null) ? pFallbackFont : __pNativeFont;
2474
2475 CATCH:
2476         // if failed find out fallback font,
2477         //      just use this instance for drawing something for unknown glyph
2478         return __pNativeFont;
2479 }
2480
2481 bool
2482 _Font::__GetFallbackFontFileList(wchar_t character, Tizen::Base::Collection::IListT<String>& out)
2483 {
2484         GUnicodeScript script = g_unichar_get_script(character);
2485         if (script < 0 || script >= _sampleLanguageCount)
2486         {
2487                 return false;
2488         }
2489
2490         FcPattern* pPattern = null;
2491         FcFontSet* pSet = null;
2492         FcChar8* pName = null;
2493         FcResult res = FcResultNoMatch;
2494         const int fcWeight = (__fontAttrib.style & FONT_STYLE_BOLD) ? FC_WEIGHT_MEDIUM : FC_WEIGHT_REGULAR;
2495
2496         // getting fallback font list
2497         pPattern = FcPatternBuild(NULL, FC_WEIGHT, FcTypeInteger, fcWeight, NULL);
2498         SysTryCatch(NID_GRP, pPattern, , E_SYSTEM, "[E_SYSTEM] Failed to FcPatternBuild()");
2499
2500         FcPatternAddString(pPattern, FC_FAMILY, (FcChar8*)"Tizen");
2501
2502         if (strncmp(SAMPLE_LANGUAGE_EMPTY, _SampleLanguages[script], strlen(SAMPLE_LANGUAGE_EMPTY) + 1) != 0)
2503         {
2504                 FcPatternAddString(pPattern, FC_LANG, (FcChar8*)_SampleLanguages[script]);
2505         }
2506
2507         FcConfigSubstitute(NULL, pPattern, FcMatchPattern);
2508         FcDefaultSubstitute(pPattern);
2509
2510         // do matching
2511         pSet = FcFontSort(NULL, pPattern, FcTrue, NULL, &res);
2512         SysTryCatch(NID_GRP, pSet, , E_SYSTEM, "[E_SYSTEM] Failed to FcFontSort()");
2513
2514         out.RemoveAll();
2515
2516         for (int i = 0; i < pSet->nfont; i++)
2517         {
2518                 if (FcPatternGetString(pSet->fonts[i], FC_FILE, 0, &pName) == FcResultMatch)
2519                 {
2520                                 out.Add(String((char*)pName));
2521                 }
2522         }
2523
2524         // destroy
2525         FcFontSetDestroy(pSet);
2526         FcPatternDestroy(pPattern);
2527
2528         return (out.GetCount() > 0) ? true : false;
2529 CATCH:
2530         if (pSet != null)
2531         {
2532                 FcFontSetDestroy(pSet);
2533         }
2534
2535         if (pPattern != null)
2536         {
2537                 FcPatternDestroy(pPattern);
2538         }
2539
2540         return false;
2541 }
2542
2543 bool
2544 _Font::UpdateDefaultFont(const String& key)
2545 {
2546         if (!key.IsEmpty())
2547         {
2548                 SysLog(NID_GRP, "Request to change the default font");
2549
2550                 _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
2551
2552                 return mgr.ReloadDefaultSystemFont();
2553         }
2554
2555         return false;
2556 }
2557
2558 }} // Tizen::Graphics