Tizen 2.1 base
[framework/osp/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 Flora License, Version 1.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://floralicense.org/license/
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 <new>
28 #include <memory>
29
30 #include <unique_ptr.h>
31 #include <dirent.h>
32
33 #include <fontconfig/fontconfig.h>
34 #include <pango/pangocairo.h>
35 #include <unicode/uloc.h>
36
37 #include <FApp_AppInfo.h>
38
39 #include <FBaseByteBuffer.h>
40 #include <FBaseColArrayList.h>
41 #include <FBaseColIList.h>
42 #include <FBaseUtilStringUtil.h>
43 #include <FGrpDimension.h>
44 #include <FGrpPoint.h>
45 #include <FGrpRectangle.h>
46
47 #include <FBaseSysLog.h>
48 #include <FSys_EnvironmentImpl.h>
49
50 #include "FGrp_FontImpl.h"
51
52 #include "FGrp_CanvasRasterOp.h"
53 #include "FGrp_FontRsrcManager.h"
54 #include "FGrp_FontBidiManager.h"
55
56 #include "FGrp_Canvas.h"
57
58 #include "util/FGrp_UtilTemplate.h"
59
60 #define USE_EMOJI
61 #define SYNCHRONIZATION_2_0
62 #define __pNativeFont __sharedFont.get()
63 #define CONVERT_INTEGER_TO_26_6_FIXED_POINT(value) (value * 64)
64 #define CONVERT_26_6_FIXED_POINT_TO_INTEGER(value) (value / 64)
65 #define IF_NOT_INITIALIZED(code) \
66         if (__pNativeFont == null) \
67         { \
68                 code; \
69         }
70 #define GET_FONT_PROPERTY(prop, rtnValue) \
71         { \
72                 bool rtn = __pNativeFont->GetFontProperty(prop); \
73                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to get font property"); \
74         }
75 #define LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, rtnValue) \
76         { \
77                 _Font* pThis = const_cast <_Font*>(this); \
78                 bool rtn = pThis->LoadGlyph(character, &pFontGlyphData); \
79                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to load glyph data"); \
80         }
81 #define UNLOAD_GLYPH_DATA_CONST(pFontGlyphData) \
82         { \
83                 _Font* pThis = const_cast <_Font*>(this); \
84                 pThis->UnloadGlyph(&pFontGlyphData); \
85         }
86 #define APPLY_ATTRIBUTE(rtnValue) \
87         { \
88                 _Font* pFont = const_cast <_Font*>(this); \
89                 bool rtn = pFont->ApplyAttribute(); \
90                 SysTryReturn(NID_GRP, rtn, rtnValue, E_SYSTEM, "[E_SYSTEM] Failed to apply font attribute"); \
91         }
92 #define SAMPLE_LANGUAGE_EMPTY ""
93
94
95 using namespace Tizen::Base;
96 using namespace Tizen::Base::Collection;
97 using namespace Tizen::Base::Utility;
98 using namespace Tizen::Graphics;
99 using namespace Tizen::Io;
100 using namespace Tizen::System;
101
102 namespace // unnamed
103 {
104
105 const int _SYSTEM_DEFAULT_FONT_SIZE = CONVERT_INTEGER_TO_26_6_FIXED_POINT(16);
106
107 template<typename Type>
108 inline void
109 _ExpandBounds(Type curX, Type curY, Type& x1, Type& y1, Type& x2, Type& y2)
110 {
111         if (curX > x2)
112         {
113                 x2 = curX;
114         }
115
116         if (curX < x1)
117         {
118                 x1 = curX;
119         }
120
121         if (curY > y2)
122         {
123                 y2 = curY;
124         }
125
126         if (curY < y1)
127         {
128                 y1 = curY;
129         }
130 }
131
132 result
133 _GetSystemFontList(Tizen::Base::Collection::IList& list)
134 {
135         FcPattern* pPattern = null;
136         FcFontSet* pSet = null;
137         FcObjectSet* pObjectSet = null;
138         const char* pLang = null;
139         const char* fcStyle = "Regular";
140
141         // initialize fontconfig library
142         FcBool rtn = FcInit();
143         SysTryCatch(NID_GRP, rtn, , E_SYSTEM, "[E_SYSTEM] Failed to init fontconfig");
144
145         pPattern = FcPatternCreate();
146         SysTryCatch(NID_GRP, pPattern, , E_SYSTEM, "[E_SYSTEM] Failed to FcPatternCreate()");
147
148         // language and style
149         FcPatternAddString(pPattern, FC_STYLE, (FcChar8*)fcStyle);
150
151         // RFC3066 formatted 2-level language identifier will be returned.
152         // e.g., en-NR, ar-SD, byn, tig etc.
153         // but, fontconfig only need 1-level language identifier having maximum 3 letters.
154         pLang = uloc_getDefault();
155
156         if (pLang != null)
157         {
158                         char lang3Letters[4] = {0,};
159                         strncpy(lang3Letters, pLang, 3);
160
161                         for (int i = 0; i < 3; i++)
162                         {
163                                 if (lang3Letters[i] == '-' || lang3Letters[i] == '_')
164                                 {
165                                         lang3Letters[i] = 0;
166                                         break;
167                                 }
168                         }
169
170                         FcPatternAddString(pPattern, FC_LANG, (FcChar8*)lang3Letters);
171         }
172
173         pObjectSet = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FILE, NULL);
174         SysTryCatch(NID_GRP, pObjectSet, , E_SYSTEM, "[E_SYSTEM] Failed to FcObjectSetBuild()");
175
176         pSet = FcFontList(NULL, pPattern, pObjectSet);
177         SysTryCatch(NID_GRP, pSet, , E_SYSTEM, "[E_SYSTEM] Failed to init fontconfig");
178
179         {
180                 _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
181                 String defaultFontFaceName(mgr.GetDefaultSystemFont().GetFaceName());
182
183                 bool defaultFontExists = false;
184
185                 list.RemoveAll(true);
186                 FcChar8* pName = null;
187
188                 for (int i = 0; i < pSet->nfont; i++)
189                 {
190                         if (FcPatternGetString(pSet->fonts[i], FC_FILE, 0, &pName) == FcResultMatch)
191                         {
192                                 String* pFamilyName = new (std::nothrow) String(Tizen::Graphics::_Font::GetFaceName(String((char*)pName)));
193                                 SysTryCatch(NID_GRP, pFamilyName, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
194
195                                 list.Add(*pFamilyName);
196
197                                 if (*pFamilyName == defaultFontFaceName)
198                                 {
199                                         defaultFontExists = true;
200                                 }
201                         }
202                 }
203
204                 if (defaultFontExists == false)
205                 {
206                         String* pDefaultFontName = new (std::nothrow) String(defaultFontFaceName);
207                         SysTryCatch(NID_GRP, pDefaultFontName, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
208
209                         list.InsertAt(*pDefaultFontName, 0);
210                 }
211         }
212
213         // destroy
214         FcFontSetDestroy(pSet);
215         FcObjectSetDestroy(pObjectSet);
216         FcPatternDestroy(pPattern);
217         FcFini();
218
219         return E_SUCCESS;
220
221 CATCH:
222         list.RemoveAll(true);
223
224         // destroy, but before doing that check if those value has been created or not.
225         if (pSet)
226         {
227                 FcFontSetDestroy(pSet);
228         }
229
230         if (pObjectSet)
231         {
232                 FcObjectSetDestroy(pObjectSet);
233         }
234
235         if (pPattern)
236         {
237                 FcPatternDestroy(pPattern);
238         }
239
240         FcFini();
241
242         return GetLastResult();
243 }
244
245 typedef Tizen::Graphics::_Font::SystemPixel _SystemPixel;
246 typedef Tizen::Graphics::_Util::ScratchPad<_SystemPixel> _ScratchPad32;
247
248
249 unsigned long
250 _ComposeColor(unsigned long color32, int opacity)
251 {
252         unsigned char alpha = (unsigned char) (((color32) >> 24));
253         unsigned char red = (unsigned char) (((color32) >> 16));
254         unsigned char green = (unsigned char) (((color32) >> 8));
255         unsigned char blue = (unsigned char) ((color32));
256
257         alpha = (unsigned char) ((alpha * opacity + 255) >> 8);
258         red = (unsigned char) ((red * opacity + 255) >> 8);
259         green = (unsigned char) ((green * opacity + 255) >> 8);
260         blue = (unsigned char) ((blue * opacity + 255) >> 8);
261
262         return (unsigned long) (((unsigned long) (alpha) << 24) | ((unsigned long) (red) << 16) | ((unsigned long) (green) << 8) | (unsigned long) (blue));
263 }
264
265 void
266 _SetColor(cairo_t* pCairo, unsigned long composedColor)
267 {
268         double a = ((composedColor >> 24) & 0xFF) * 1.0 / 255.0;
269         double r = ((composedColor >> 16) & 0xFF) * 1.0 / 255.0;
270         double g = ((composedColor >> 8) & 0xFF) * 1.0 / 255.0;
271         double b = ((composedColor >> 0) & 0xFF) * 1.0 / 255.0;
272
273         cairo_set_source_rgba(pCairo, r, g, b, a);
274 }
275
276 template<typename T>
277 inline T
278 _TempMin(T a, T b)
279 {
280         return (a < b) ? a : b;
281 }
282 #define BLEND_ALPHA_COMPONEMT(srcA, dstA) (_TempMin <unsigned long>((srcA) + (dstA) - (((srcA) * (dstA)) >> 8), 0xFF));
283
284 struct _NativeGfxEngine
285 {
286         cairo_t* pCairo;
287         cairo_surface_t* pCairoSurface;
288
289         _NativeGfxEngine()
290                 : pCairo(0)
291                 , pCairoSurface(0)
292         {
293         }
294         ~_NativeGfxEngine()
295         {
296                 if (pCairo)
297                 {
298                         cairo_destroy(pCairo);
299                 }
300
301                 if (pCairoSurface)
302                 {
303                         cairo_surface_destroy(pCairoSurface);
304                 }
305
306         }
307 };
308
309 // ISO 15924
310 const char* _SampleLanguages[] =
311 {
312         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_COMMON
313         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_INHERITED
314         "ar",                                                                                                   // G_UNICODE_SCRIPT_ARABIC
315         "hy",                                                                                                   // G_UNICODE_SCRIPT_ARMENIAN
316         "bn",                                                                                                   // G_UNICODE_SCRIPT_BENGALI
317         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_BOPOMOFO
318         "chr",                                                                                                  // G_UNICODE_SCRIPT_CHEROKEE
319         "cop",                                                                                                  // G_UNICODE_SCRIPT_COPTIC
320         "ru",                                                                                                   // G_UNICODE_SCRIPT_CYRILLIC
321         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_DESERET
322         "hi",                                                                                                   // G_UNICODE_SCRIPT_DEVANAGARI
323         "am",                                                                                                   // G_UNICODE_SCRIPT_ETHIOPIC
324         "ka",                                                                                                   // G_UNICODE_SCRIPT_GEORGIAN
325         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_GOTHIC
326         "el",                                                                                                   // G_UNICODE_SCRIPT_GREEK
327         "gu",                                                                                                   // G_UNICODE_SCRIPT_GUJARATI
328         "pa",                                                                                                   // G_UNICODE_SCRIPT_GURMUKHI
329         "zh",                                                                                                   // G_UNICODE_SCRIPT_HAN
330         "ko",                                                                                                   // G_UNICODE_SCRIPT_HANGUL
331         "he",                                                                                                   // G_UNICODE_SCRIPT_HEBREW
332         "ja",                                                                                                   // G_UNICODE_SCRIPT_HIRAGANA
333         "kn",                                                                                                   // G_UNICODE_SCRIPT_KANNADA
334         "ja",                                                                                                   // G_UNICODE_SCRIPT_KATAKANA
335         "km",                                                                                                   // G_UNICODE_SCRIPT_KHMER
336         "lo",                                                                                                   // G_UNICODE_SCRIPT_LAO
337         "en",                                                                                                   // G_UNICODE_SCRIPT_LATIN
338         "ml",                                                                                                   // G_UNICODE_SCRIPT_MALAYALAM
339         "mn",                                                                                                   // G_UNICODE_SCRIPT_MONGOLIAN
340         "my",                                                                                                   // G_UNICODE_SCRIPT_MYANMAR
341         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_OGHAM
342         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_OLD_ITALIC
343         "or",                                                                                                   // G_UNICODE_SCRIPT_ORIYA
344         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_RUNIC
345         "si",                                                                                                   // G_UNICODE_SCRIPT_SINHALA
346         "syr",                                                                                                  // G_UNICODE_SCRIPT_SYRIAC
347         "ta",                                                                                                   // G_UNICODE_SCRIPT_TAMIL
348         "te",                                                                                                   // G_UNICODE_SCRIPT_TELUGU
349         "dv",                                                                                                   // G_UNICODE_SCRIPT_THAANA
350         "th",                                                                                                   // G_UNICODE_SCRIPT_THAI
351         "bo",                                                                                                   // G_UNICODE_SCRIPT_TIBETAN
352         "iu",                                                                                                   // G_UNICODE_SCRIPT_CANADIAN_ABORIGINAL
353         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_YI
354         "tl",                                                                                                   // G_UNICODE_SCRIPT_TAGALOG
355         "hnn",                                                                                                  // G_UNICODE_SCRIPT_HANUNOO
356         "bku",                                                                                                  // G_UNICODE_SCRIPT_BUHID
357         "tbw",                                                                                                  // G_UNICODE_SCRIPT_TAGBANWA
358         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_BRAILLE
359         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_CYPRIOT
360         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_LIMBU
361         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_OSMANYA
362         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_SHAVIAN
363         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_LINEAR_B
364         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_TAI_LE
365         "uga",                                                                                          // G_UNICODE_SCRIPT_UGARITIC
366         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_NEW_TAI_LUE
367         "bug",                                                                                                  // G_UNICODE_SCRIPT_BUGINESE
368         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_GLAGOLITIC
369         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_TIFINAGH
370         "syl",                                                                                                  // G_UNICODE_SCRIPT_SYLOTI_NAGRI
371         "peo",                                                                                                  // G_UNICODE_SCRIPT_OLD_PERSIAN
372         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_KHAROSHTHI
373         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_UNKNOWN
374         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_BALINESE
375         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_CUNEIFORM
376         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_PHOENICIAN
377         SAMPLE_LANGUAGE_EMPTY,          // G_UNICODE_SCRIPT_PHAGS_PA
378         "nqo"                                                                                                   // G_UNICODE_SCRIPT_NKO
379 };
380
381 const int _sampleLanguageCount = sizeof(_SampleLanguages) / sizeof(_SampleLanguages[0]);
382
383 unsigned long
384 GetPredefinedColor(const wchar_t unicode, unsigned long fgColor)
385 {
386 #ifdef USE_EMOJI
387         //
388         // Emoji Unicode List 176 + 76
389         //
390                 static const unsigned long _EMOJI_BLACK = 0xFF000000;
391                 static const unsigned long _EMOJI_BLUE = 0xFF0000FF;
392                 static const unsigned long _EMOJI_GREEN = 0xFF00FF00;
393                 static const unsigned long _EMOJI_RED = 0xFFFF0000;
394                 static const unsigned long _EMOJI_ORANGE = 0xFFFF6600;
395                 static const unsigned long _EMOJI_PURPLE = 0xFF9370DB;
396                 static const unsigned long _EMOJI_DEEP_PURPLE = 0xFF800080;
397                 static const unsigned long _EMOJI_DARK_BLUE = 0xFF00008B;
398                 static const unsigned long _EMOJI_BROWN = 0xFFA52A2A;
399                 static const unsigned long _NOT_EMOJI = 0;
400
401                 static const long _MAX_EMOJI_UNICODE = 0xE757;
402                 static const long _MIN_EMOJI_UNICODE = 0xE63E;
403
404         static const unsigned long _emojiTable[] =
405         {
406                 _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_ORANGE,
407                 _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_GREEN, _EMOJI_BLUE,
408                 _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_GREEN, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_PURPLE, _EMOJI_GREEN,
409                 _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_RED,
410                 _EMOJI_BLACK, _EMOJI_PURPLE, _EMOJI_RED, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_PURPLE, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK,
411                 _EMOJI_GREEN, _EMOJI_PURPLE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE,
412                 _EMOJI_BLUE, _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_ORANGE,
413                 _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_RED,
414                 _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_BLACK,
415                 _EMOJI_ORANGE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE,
416                 _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_GREEN, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI,
417                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI,
418                 _NOT_EMOJI, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI,
419                 _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI,
420                 _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _NOT_EMOJI, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BLACK,
421                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_RED,
422                 _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK,
423                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_RED,
424                 _EMOJI_BLUE, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_RED, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_ORANGE,
425                 _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_RED, _EMOJI_RED,
426                 _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BLUE, _EMOJI_BLACK,
427                 _EMOJI_RED, _EMOJI_DARK_BLUE, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_BROWN, _EMOJI_BROWN, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_GREEN,
428                 _EMOJI_ORANGE, _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_PURPLE, _EMOJI_BLUE, _EMOJI_BLUE,
429                 _EMOJI_RED, _EMOJI_DEEP_PURPLE, _EMOJI_PURPLE, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_PURPLE, _EMOJI_DARK_BLUE, _EMOJI_ORANGE, _EMOJI_BLUE,
430                 _EMOJI_BLUE, _EMOJI_RED, _EMOJI_BLUE, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_GREEN, _EMOJI_BLACK, _EMOJI_ORANGE,
431                 _EMOJI_RED, _EMOJI_BLUE, _EMOJI_RED, _EMOJI_RED, _EMOJI_BLACK, _EMOJI_BLACK, _EMOJI_GREEN, _EMOJI_BLUE, _EMOJI_BLUE, _EMOJI_GREEN,
432                 _EMOJI_RED, _EMOJI_RED, _EMOJI_ORANGE, _EMOJI_RED, _EMOJI_GREEN, _EMOJI_RED, _EMOJI_PURPLE, _EMOJI_BLACK, _EMOJI_RED, _EMOJI_BROWN,
433                 _EMOJI_ORANGE, _EMOJI_BROWN, _EMOJI_BROWN, _EMOJI_ORANGE, _EMOJI_DARK_BLUE, _EMOJI_BLUE, _EMOJI_ORANGE, _EMOJI_ORANGE, _EMOJI_BROWN, _EMOJI_ORANGE,
434                 _EMOJI_DEEP_PURPLE, _EMOJI_DEEP_PURPLE
435         };
436
437         if (unicode >= _MIN_EMOJI_UNICODE && unicode <= _MAX_EMOJI_UNICODE)
438         {
439                 if (_emojiTable[unicode - _MIN_EMOJI_UNICODE] != _NOT_EMOJI)
440                 {
441                         fgColor = _emojiTable[unicode - _MIN_EMOJI_UNICODE];
442                 }
443         }
444 #endif
445
446         return fgColor;
447 }
448
449 }
450
451
452 namespace Tizen { namespace Graphics
453 {
454
455 _Font::_Font()
456 {
457         __fontAttrib.Init();
458         //__fallbackFontMap.Construct(1, 0, _fontHashCodeProvider, _fontComparer);
459 }
460
461 _Font::_Font(const _Font& obj)
462 {
463         this->__fontAttrib = obj.__fontAttrib;
464         this->__sharedFont = obj.__sharedFont;
465
466         return;
467 }
468
469 _Font::~_Font(void)
470 {
471 }
472
473 result
474 _Font::Construct(int style, int pcSize)
475 {
476         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
477
478         // use default system font
479         _FontRsrcManager::SharedFontResource out;
480         result r = mgr.GetFont(style, pcSize, out);
481         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system default font", GetErrorMessage(r));
482
483         // assign it
484         __sharedFont = out;
485         __UpdateFontAttribute(style, pcSize);
486
487         return E_SUCCESS;
488 }
489
490 result
491 _Font::Construct(const Tizen::Base::String& fontName, int style, int pcSize, bool isPathEnabled)
492 {
493         result r = E_SUCCESS;
494
495         if (fontName.Compare(fontName, "TizenSans") == 0)
496         {
497                 r = Construct(style,pcSize);
498
499                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
500
501                 return E_SUCCESS;
502         }
503
504         bool systemFont = false;
505         String appFontPath = L"";
506
507         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
508         _FontRsrcManager::SharedFontResource out;
509
510         if (!Tizen::App::_AppInfo::IsOspCompat())
511         {
512                 appFontPath = mgr.FindAppFontName(fontName);
513         }
514
515         // check if user want to use a app font
516         if (!appFontPath.IsEmpty())
517         {
518                 r = mgr.GetFont(appFontPath, style, pcSize, out);
519                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get app font", GetErrorMessage(r));
520         }
521         else
522         {
523                 IList* pList = GetSystemFontListN();
524                 int idx = 0;
525
526                 if (pList)
527                 {
528                         for (idx = 0; idx < pList->GetCount(); idx++)
529                         {
530                                 String* pName = static_cast <String*>(pList->GetAt(idx));
531
532                                 if (pName == null)
533                                 {
534                                         continue;
535                                 }
536
537                                 if (*pName == fontName)
538                                 {
539                                         systemFont = true;
540                                         break;
541                                 }
542                         }
543
544                         pList->RemoveAll(true);
545                         delete pList;
546                 }
547
548                 if (systemFont)
549                 {
550                         r = mgr.GetSystemFont(fontName, style, pcSize, out);
551                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
552                 }
553                 else if (isPathEnabled)
554                 {
555                         r = mgr.GetFont(fontName, style, pcSize, out);
556                         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get font", GetErrorMessage(r));
557                 }
558         }
559
560         // assign it
561         __sharedFont = out;
562         __UpdateFontAttribute(style, pcSize);
563
564         return E_SUCCESS;
565 }
566
567 result
568 _Font::Construct(const Tizen::Base::ByteBuffer& fontData, int style, int pcSize)
569 {
570         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
571
572         const byte* pBuffer = fontData.GetPointer();
573         int buffSize = fontData.GetLimit();
574
575         _FontRsrcManager::SharedFontResource out;
576         result r = mgr.GetFont(pBuffer, buffSize, style, pcSize, out);
577         SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to get system font", GetErrorMessage(r));
578
579         // assign it
580         __sharedFont = out;
581         __UpdateFontAttribute(style, pcSize);
582
583         return E_SUCCESS;
584 }
585
586 bool
587 _Font::IsConstructed(void) const
588 {
589         return (__sharedFont.get() != null);
590 }
591
592 int
593 _Font::GetMaxHeight(void) const
594 {
595         IF_NOT_INITIALIZED(return -1);
596
597         return __fontAttrib.maxHeight;
598 }
599
600 int
601 _Font::GetMaxWidth(void) const
602 {
603         IF_NOT_INITIALIZED(return -1);
604
605         return __fontAttrib.maxWidth;
606 }
607
608 int
609 _Font::GetAscender(void) const
610 {
611         IF_NOT_INITIALIZED(return -1);
612
613         return __fontAttrib.ascender;
614 }
615
616 int
617 _Font::GetDescender(void) const
618 {
619         IF_NOT_INITIALIZED(return -1);
620
621         return __fontAttrib.descender;
622 }
623
624 result
625 _Font::GetLeftBear(wchar_t character, int& leftBear) const
626 {
627         IF_NOT_INITIALIZED(return E_OPERATION_FAILED);
628
629         APPLY_ATTRIBUTE(-1);
630
631         _IFont::Glyph* pFontGlyphData = null;
632         LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, E_SYSTEM);
633
634         // left bear is Glyph::xOffset, set it
635         leftBear = pFontGlyphData->xOffset;
636
637         UNLOAD_GLYPH_DATA_CONST(pFontGlyphData);
638
639         return E_SUCCESS;
640 }
641
642 result
643 _Font::GetRightBear(wchar_t character, int& rightBear) const
644 {
645         IF_NOT_INITIALIZED(return E_OPERATION_FAILED);
646
647         APPLY_ATTRIBUTE(-1);
648
649         _IFont::Glyph* pFontGlyphData = null;
650         LOAD_GLYPH_DATA_CONST(character, pFontGlyphData, E_SYSTEM);
651
652         // right bear is Glyph::xOffset + GlyphBitmap::width, set it
653         rightBear = pFontGlyphData->xOffset + pFontGlyphData->image.width;
654
655         UNLOAD_GLYPH_DATA_CONST(pFontGlyphData);
656
657         return E_SUCCESS;
658 }
659
660 result
661 _Font::GetTextExtent(const Tizen::Base::String& text, int length, Dimension& pcDim) const
662 {
663         int x1 = 0x7FFFFFFF;
664         int y1 = 0x7FFFFFFF;
665         int x2 = -0x7FFFFFFF;
666         int y2 = -0x7FFFFFFF;
667
668         int curX = 0;
669         int curY = 0;
670
671         int italicSpace = 0;
672         int boldSpace = 0;
673
674         long xVec = 0;
675         long yVec = 0;
676         int left = 0;
677         wchar_t leftChar = 0;
678
679         _IFont::Glyph* pFontGlyphData = 0;
680
681         IF_NOT_INITIALIZED(return E_OPERATION_FAILED);
682
683         _Font* pThis = const_cast <_Font*>(this);
684
685         const wchar_t* pText = text.GetPointer();
686         SysTryCatch(NID_GRP, pText, pcDim.SetSize(0, 0), E_SYSTEM, "[E_SYSTEM] Failed to get string pointer");
687
688         APPLY_ATTRIBUTE(E_SYSTEM);
689
690         {
691                 _IFont::Property prop;
692                 GET_FONT_PROPERTY(prop, E_SYSTEM);
693
694                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
695                 {
696                         italicSpace = (prop.ascender * 2) >> 4;
697                 }
698         }
699
700         if (__fontAttrib.style & FONT_STYLE_BOLD)
701         {
702                 _IFont::Attrib attr;
703                 pThis->GetAttrib(attr);
704                 boldSpace = (attr.boldWeight + 32) >> 6;
705         }
706
707         while (*pText && --length >= 0)
708         {
709                 _IFont* pFont = pThis->__GetFont(*pText);
710
711                 if (pFont != __pNativeFont)
712                 {
713                         _IFont::Attrib fontAttrib;
714                         bool rtn = pFont->GetAttrib(fontAttrib);
715
716                         fontAttrib.size = __fontAttrib.size;
717                         fontAttrib.style = _IFont::STYLE_NONE;
718                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
719                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
720                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
721                         rtn = pFont->SetAttrib(fontAttrib);
722                 }
723
724                 if (left > 0)
725                 {
726                         if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
727                         {
728                                 curX += xVec;
729                         }
730                 }
731
732                 if (pFont->LoadGlyph(*pText++, &pFontGlyphData))
733                 {
734                         int glyphBoundX1 = curX;
735                         int glyphBoundY1 = curY - (pFontGlyphData->yOffset >> 10);
736                         int glyphBoundX2 = glyphBoundX1 + (pFontGlyphData->xOffset >> 10) + pFontGlyphData->image.width;
737                         int glyphBoundY2 = glyphBoundY1 + pFontGlyphData->image.height;
738
739 #ifdef SYNCHRONIZATION_2_0
740                         // adjusting x bounds for synchronizing this operation with 2.0
741                         if (length == 0)
742                         {
743                                 glyphBoundX2 = glyphBoundX1 + (pFontGlyphData->xAdvance >> 10) + italicSpace + boldSpace;
744                         }
745 #endif // 2_0_SYNCHROMIZATION
746
747                         _ExpandBounds(glyphBoundX1, glyphBoundY1, x1, y1, x2, y2);
748                         _ExpandBounds(glyphBoundX2, glyphBoundY1, x1, y1, x2, y2);
749                         _ExpandBounds(glyphBoundX1, glyphBoundY2, x1, y1, x2, y2);
750                         _ExpandBounds(glyphBoundX2, glyphBoundY2, x1, y1, x2, y2);
751
752 #ifdef SYNCHRONIZATION_2_0
753                         curX += (pFontGlyphData->xAdvance >> 10) + __fontAttrib.charSpace + italicSpace + boldSpace;
754 #else
755                         curX += (pFontGlyphData->xAdvance >> 10) + __fontAttrib.charSpace + boldSpace;
756 #endif
757                         curY += (pFontGlyphData->yAdvance >> 10);
758                         left++;
759                         leftChar = *(pText - 1);
760
761                         pFont->UnloadGlyph(&pFontGlyphData);
762                 }
763         }
764
765         SysTryCatch(NID_GRP, x1 <= x2 && y1 <= y2, pcDim.SetSize(0, 0), E_SYSTEM, "[E_SYSTEM] Failed to calculate text extent");
766
767         pcDim.width = x2 - x1;
768 #ifdef SYNCHRONIZATION_2_0
769         pcDim.height = CONVERT_26_6_FIXED_POINT_TO_INTEGER(__fontAttrib.size);
770 #else
771         pcDim.height = y2 - y1;
772 #endif // 2_0_SYNCHROMIZATION
773
774         return E_SUCCESS;
775
776 CATCH:
777         return E_SYSTEM;
778 }
779
780 bool
781 _Font::IsBold(void) const
782 {
783         IF_NOT_INITIALIZED(return false);
784
785         return ((__fontAttrib.style & FONT_STYLE_BOLD) ? true : false);
786 }
787
788 bool
789 _Font::IsItalic(void) const
790 {
791         IF_NOT_INITIALIZED(return false);
792
793         return ((__fontAttrib.style & FONT_STYLE_ITALIC) ? true : false);
794 }
795
796 bool
797 _Font::IsPlain(void) const
798 {
799         IF_NOT_INITIALIZED(return false);
800
801         return ((__fontAttrib.style & FONT_STYLE_PLAIN) ? true : false);
802 }
803
804 bool
805 _Font::IsStrikeOut(void) const
806 {
807         IF_NOT_INITIALIZED(return false);
808
809         return __fontAttrib.strikeout;
810 }
811
812 bool
813 _Font::IsUnderlined(void) const
814 {
815         IF_NOT_INITIALIZED(return false);
816
817         return __fontAttrib.underline;
818 }
819
820 bool
821 _Font::IsEmoji(void) const
822 {
823         IF_NOT_INITIALIZED(return false);
824
825         return (this->GetFaceName() == L"keitaiemoji");
826 }
827
828 int
829 _Font::GetSize(void) const
830 {
831         IF_NOT_INITIALIZED(return -1);
832
833         return CONVERT_26_6_FIXED_POINT_TO_INTEGER(__fontAttrib.size);
834 }
835
836 void
837 _Font::SetStrikeOut(bool strikeout)
838 {
839         IF_NOT_INITIALIZED(return);
840
841         __fontAttrib.strikeout = strikeout;
842 }
843
844 void
845 _Font::SetUnderline(bool underline)
846 {
847         IF_NOT_INITIALIZED(return);
848
849         __fontAttrib.underline = underline;
850 }
851
852 void
853 _Font::SetCharSpace(int pc_space)
854 {
855         IF_NOT_INITIALIZED(return);
856
857         __fontAttrib.charSpace = pc_space;
858 }
859
860 int
861 _Font::GetCharSpace(void) const
862 {
863         IF_NOT_INITIALIZED(return -1);
864
865         return __fontAttrib.charSpace;
866 }
867
868 int
869 _Font::GetLineThickness(void) const
870 {
871         IF_NOT_INITIALIZED(return -1);
872
873         return __fontAttrib.lineThickness;
874 }
875
876 Tizen::Base::String
877 _Font::GetFaceName(void) const
878 {
879         IF_NOT_INITIALIZED(return String());
880
881         _IFont::Property prop;
882         GET_FONT_PROPERTY(prop, String());
883
884         return ((prop.pFamilyName) ? String(prop.pFamilyName) : String());
885 }
886
887 Tizen::Base::Collection::IList*
888 _Font::GetSystemFontListN(void)
889 {
890         std::auto_ptr<ArrayList> pList(new (std::nothrow) Tizen::Base::Collection::ArrayList);
891         SysTryReturn(NID_GRP, pList.get(), null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Fails to allocate memory");
892
893         result r = _GetSystemFontList(*pList);
894         SysTryReturn(NID_GRP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
895
896         return pList.release();
897
898 }
899
900 Tizen::Base::String
901 _Font::GetFaceName(const Tizen::Base::String& filePath)
902 {
903         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
904         _FontRsrcManager::SharedFontResource out;
905         String faceName;
906
907         result r = mgr.GetTempFont(filePath, FONT_STYLE_PLAIN, _SYSTEM_DEFAULT_FONT_SIZE, out);
908         SysTryReturn(NID_GRP, r == E_SUCCESS, faceName, r, "[%s] Failed to get font", GetErrorMessage(r));
909
910         if (r == E_SUCCESS)
911         {
912                 _IFont* pTempFont = out.get();
913
914                 _IFont::Property prop;
915                 pTempFont->GetFontProperty(prop);
916                 faceName = String(prop.pFamilyName);
917         }
918
919         return faceName;
920 }
921
922 _IFont*
923 _Font::GetNativeFont(void) const
924 {
925         IF_NOT_INITIALIZED(return null);
926
927         return __pNativeFont;
928 }
929
930 _Font*
931 _Font::CloneN()
932 {
933         // if it's not initialized, return null.
934         IF_NOT_INITIALIZED(return null);
935
936         // make the clone
937         _Font* pNativeFont = new (std::nothrow) _Font(*this);
938         SysTryReturn(NID_GRP, pNativeFont, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocated memory");
939
940         // done
941         return pNativeFont;
942 }
943
944 bool
945 _Font::ApplyAttribute()
946 {
947         IF_NOT_INITIALIZED(return false);
948
949         _IFont::Attrib fontAttrib;
950         bool rtn = __pNativeFont->GetAttrib(fontAttrib);
951         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
952
953         fontAttrib.size = __fontAttrib.size;
954         fontAttrib.style = _IFont::STYLE_NONE;
955         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
956         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
957         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
958         rtn = __pNativeFont->SetAttrib(fontAttrib);
959         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
960
961         return true;
962 }
963
964
965 result
966 _Font::GetTextExtent(int width, const Tizen::Base::String& text, int startIndex, int length, bool outline, int& count, Dimension& pcDim) const
967 {
968         int preX1 = 0x7FFFFFFF;
969         int preY1 = 0x7FFFFFFF;
970         int preX2 = -0x7FFFFFFF;
971         int preY2 = -0x7FFFFFFF;
972
973         int x1 = 0x7FFFFFFF;
974         int y1 = 0x7FFFFFFF;
975         int x2 = -0x7FFFFFFF;
976         int y2 = -0x7FFFFFFF;
977
978         int curX = 0;
979         int curY = 0;
980
981         int characters = 0;
982         int italicSpace = 0;
983         int boldSpace = 0;
984
985         long xVec = 0;
986         long yVec = 0;
987         int left = 0;
988         wchar_t leftChar = 0;
989
990         _IFont::Glyph* pFontGlyphData = 0;
991
992         IF_NOT_INITIALIZED(return E_SYSTEM);
993
994         if (length == 0)
995         {
996                 count = 0;
997                 pcDim.SetSize(0, 0);
998                 return E_SUCCESS;
999         }
1000
1001         _Font* pThis = const_cast <_Font*>(this);
1002
1003         const wchar_t* pText = text.GetPointer() + startIndex;
1004         SysTryCatch(NID_GRP, pText, pcDim.SetSize(0, 0), E_SYSTEM, "[E_SYSTEM] Failed to get string pointer");
1005
1006         APPLY_ATTRIBUTE(E_SYSTEM);
1007
1008         {
1009                 _IFont::Property prop;
1010                 GET_FONT_PROPERTY(prop, E_SYSTEM);
1011
1012                 if (__fontAttrib.style & FONT_STYLE_ITALIC)
1013                 {
1014                         italicSpace = (prop.ascender * 2) >> 4;
1015                 }
1016         }
1017
1018         if (__fontAttrib.style & FONT_STYLE_BOLD)
1019         {
1020                 _IFont::Attrib attr;
1021                 pThis->GetAttrib(attr);
1022                 boldSpace = (attr.boldWeight + 32) >> 6;
1023         }
1024
1025         while (*pText && --length >= 0)
1026         {
1027                 // getting proper _Font instance for the specified text
1028                 _IFont* pFont = pThis->__GetFont(*pText);
1029
1030                 if (pFont != __pNativeFont)
1031                 {
1032                         _IFont::Attrib fontAttrib;
1033                         bool rtn = pFont->GetAttrib(fontAttrib);
1034                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
1035
1036                         fontAttrib.size = __fontAttrib.size;
1037                         fontAttrib.style = _IFont::STYLE_NONE;
1038                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1039                         fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1040                         fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1041                         rtn = pFont->SetAttrib(fontAttrib);
1042                         //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
1043                 }
1044
1045                 if (left > 0)
1046                 {
1047                         if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
1048                         {
1049                                 curX += xVec;
1050                         }
1051                 }
1052
1053                 if (pFont->LoadGlyph(*pText++, &pFontGlyphData))
1054                 {
1055                         int glyphBoundX1 = curX;
1056                         int glyphBoundY1 = curY - (pFontGlyphData->yOffset >> 10);
1057                         int glyphBoundX2 = glyphBoundX1 +
1058                                                         ((pFontGlyphData->image.width <= 0) ? (pFontGlyphData->xAdvance >>
1059                                                                                                                                         10) : ((pFontGlyphData->xOffset >>
1060                                                                                                                                                         10) + pFontGlyphData->image.width));
1061                         int glyphBoundY2 = glyphBoundY1 + pFontGlyphData->image.height;
1062
1063 #ifdef SYNCHRONIZATION_2_0
1064                         // adjusting x2 bounds for synchronizing fuctionality with 2.0
1065                         glyphBoundX2 = glyphBoundX1 + (pFontGlyphData->xAdvance >> 10) + italicSpace + boldSpace;
1066 #endif
1067
1068
1069                         if (outline)
1070                         {
1071                                 glyphBoundX1 -= 1;
1072                                 glyphBoundY1 -= 1;
1073                                 glyphBoundX2 += 1;
1074                                 glyphBoundY2 += 1;
1075                         }
1076
1077                         _ExpandBounds(glyphBoundX1, glyphBoundY1, x1, y1, x2, y2);
1078                         _ExpandBounds(glyphBoundX2, glyphBoundY1, x1, y1, x2, y2);
1079                         _ExpandBounds(glyphBoundX1, glyphBoundY2, x1, y1, x2, y2);
1080                         _ExpandBounds(glyphBoundX2, glyphBoundY2, x1, y1, x2, y2);
1081
1082 #ifdef SYNCHRONIZATION_2_0
1083                         curX += (pFontGlyphData->xAdvance >> 10) + __fontAttrib.charSpace + italicSpace + boldSpace;
1084 #else
1085                         curX += (pFontGlyphData->xAdvance >> 10) + __fontAttrib.charSpace + boldSpace;
1086 #endif
1087                         curY += (pFontGlyphData->yAdvance >> 10);
1088
1089                         pFont->UnloadGlyph(&pFontGlyphData);
1090
1091                         // check end condition
1092                         // TODO, shkim, BIDI need to be cared
1093                         if ((x2 - x1) > width)
1094                         {
1095                                 break;
1096                         }
1097
1098                         preX1 = x1;
1099                         preY1 = y1;
1100                         preX2 = x2;
1101                         preY2 = y2;
1102                         characters++;
1103                         left++;
1104                         leftChar = *(pText - 1);
1105                 }
1106         }
1107
1108         if (characters == 0)
1109         {
1110                 pcDim.SetSize(0, 0);
1111                 count = 0;
1112                 return E_SUCCESS;
1113         }
1114
1115         SysTryCatch(NID_GRP, preX1 <= preX2 && preY1 <= preY2, pcDim.SetSize(0, 0); count = 0, E_SYSTEM, "[E_SYSTEM] Failed to calculate text extent");
1116
1117         count = characters;
1118         pcDim.width = preX2 - preX1;
1119 #ifdef SYNCHRONIZATION_2_0
1120         pcDim.height = CONVERT_26_6_FIXED_POINT_TO_INTEGER(__fontAttrib.size);
1121 #else
1122         pcDim.height = preY2 - preY1;
1123 #endif // SYNCHRONIZATION_2_0
1124
1125         return E_SUCCESS;
1126
1127 CATCH:
1128         return E_SYSTEM;
1129 }
1130
1131 result
1132 _Font::GetTextExtent(int width, const Tizen::Base::String& text, int startIndex, int length, bool outline, const Tizen::Base::String& delimiter, int& count, Dimension& dim) const
1133 {
1134         IF_NOT_INITIALIZED(return E_OPERATION_FAILED);
1135
1136         SysTryReturn(NID_GRP, startIndex >= 0 && length >= 0, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
1137
1138         const wchar_t* pBaseStringBegin = text.GetPointer();
1139         const wchar_t* pBaseStringEnd = pBaseStringBegin + text.GetLength();
1140
1141         const wchar_t* pTextBegin = pBaseStringBegin + startIndex;
1142         const wchar_t* pTextEnd = pTextBegin + length;
1143
1144         pTextEnd = (pTextEnd < pBaseStringEnd) ? pTextEnd : pBaseStringEnd;
1145
1146         const wchar_t* pText = pTextBegin;
1147
1148         while (pText < pTextEnd)
1149         {
1150                 if (*pText == 0x0D || *pText == 0x0A)
1151                 {
1152                         pTextEnd = pText;
1153                         break;
1154                 }
1155
1156                 ++pText;
1157         }
1158
1159         return this->GetTextExtent(width, text, startIndex, pTextEnd - pTextBegin, outline, count, dim);
1160 }
1161
1162 result
1163 _Font::SetSize(int pcSize)
1164 {
1165         IF_NOT_INITIALIZED(return E_OPERATION_FAILED);
1166
1167         __UpdateFontAttribute(__fontAttrib.style, pcSize);
1168
1169         return E_SUCCESS;
1170 }
1171
1172 result
1173 _Font::SetStyle(int style)
1174 {
1175         IF_NOT_INITIALIZED(return E_OPERATION_FAILED);
1176
1177         __fontAttrib.style = style;
1178
1179         return E_SUCCESS;
1180 }
1181
1182 int
1183 _Font::GetStyle(void) const
1184 {
1185         IF_NOT_INITIALIZED(return FONT_STYLE_PLAIN);
1186
1187         return __fontAttrib.style;
1188 }
1189
1190 int
1191 _Font::GetLeading(void) const
1192 {
1193         IF_NOT_INITIALIZED(return -1);
1194
1195         return __fontAttrib.maxHeight;
1196 }
1197
1198 result
1199 _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
1200 {
1201         SysTryReturnResult(NID_GRP, canvas.__pScratchPad != null, E_INVALID_ARG, "A canvas is invalid");
1202
1203         const wchar_t* pText = text.GetPointer() + startIndex;
1204
1205         bool rtn = this->ApplyAttribute();
1206         SysTryReturn(NID_GRP, rtn, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Fails to apply font attribute.");
1207
1208         _Util::ScratchPad <SystemPixel>& scratchPad = *canvas.__pScratchPad;
1209         scratchPad.RegisterFillRect(_RasterOp::FnFillRectFont32Bit);
1210
1211         Rectangle clipBounds;
1212         canvas.__GetClipBounds(clipBounds);
1213
1214         int xDest = point.x;
1215         int yDest = point.y;
1216         int startX = point.x;
1217         int charHeight = 0;
1218         int italicSpace = 0;
1219         int boldSpace = 0;
1220         int clipX1 = clipBounds.x;
1221         int clipY1 = clipBounds.y;
1222         int clipX2 = clipX1 + clipBounds.width;
1223         int clipY2 = clipY1 + clipBounds.height;
1224         long xVec = 0;
1225         long yVec = 0;
1226         int left = 0;
1227         wchar_t leftChar = 0;
1228         _IFont::Glyph* pFontGlyphData = 0;
1229
1230         // need to revise y value, because _IFont is based on the baseline
1231         {
1232                 _IFont::Property prop;
1233                 bool rtn = this->GetFontProperty(prop);
1234                 SysTryReturn(NID_GRP, rtn, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to get font property.");
1235
1236                 if (canvas.__textOrigin == TEXT_ORIGIN_LEFT_TOP)
1237                 {
1238                         yDest += prop.maxHeight + prop.descender;
1239                 }
1240
1241                 charHeight = prop.ascender - prop.descender;
1242
1243                 if (this->GetStyle() & FONT_STYLE_ITALIC)
1244                 {
1245                         italicSpace = (prop.ascender * 2) >> 4;
1246                 }
1247         }
1248
1249         if (this->GetStyle() & FONT_STYLE_BOLD)
1250         {
1251                 _IFont::Attrib attr;
1252                 this->GetAttrib(attr);
1253                 boldSpace = (attr.boldWeight + 32) >> 6;
1254         }
1255
1256         unsigned long canvasFgColor = canvas.__fgColor;
1257
1258         GUnicodeScript script = g_unichar_get_script(*pText);
1259         // need to check if (script < 0 || script >= _sampleLanguageCount) ?
1260
1261         // Temporary code for testing Arabic
1262         if (script == G_UNICODE_SCRIPT_ARABIC)
1263         {
1264                 _FontBidiProps bidiProps(pText, length);
1265
1266                 _IFont* pFont = this->__GetFont(*pText);
1267
1268                 if (pFont == null)
1269                 {
1270                         return E_SYSTEM;
1271                 }
1272
1273                 Tizen::Base::Collection::ArrayListT<_IFont::Glyph *> glyphList;
1274
1275                 pFont->GetGlyphList(_Util::String(text.GetPointer(), text.GetLength(), startIndex, length), glyphList, bidiProps.isRtl, script);
1276
1277                 int count = glyphList.GetCount();
1278
1279                 for (int i = 0; i < count; i++)
1280                 {
1281                         typedef unsigned long TPixel;
1282                         _IFont::Glyph *pGlyph = 0;
1283
1284                         TPixel srcR, srcG, srcB, srcA;
1285                         TPixel dstR, dstG, dstB, dstA;
1286
1287                         srcA = (canvasFgColor >> 24) & 0xFF;
1288                         srcA += (srcA >> 7);
1289                         srcR = (canvasFgColor >> 16) & 0xFF;
1290                         srcG = (canvasFgColor >> 8) & 0xFF;
1291                         srcB = (canvasFgColor) & 0xFF;
1292
1293                         SystemPixel* pBufferStartAddr = null;
1294                         int bufferPitch;
1295
1296                         scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
1297
1298                         glyphList.GetAt(i, pGlyph);
1299
1300                         for (int h = 0; h < pGlyph->image.height; h++)
1301                         {
1302                                 int y = yDest - pGlyph->yOffset + h;
1303
1304                                 if (y < 0)
1305                                 {
1306                                         continue;
1307                                 }
1308
1309                                 if (y >= scratchPad.GetHeight())
1310                                 {
1311                                         break;
1312                                 }
1313
1314                                 TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + pGlyph->xOffset;
1315
1316                                 for (int w = 0; w < pGlyph->image.width; w++)
1317                                 {
1318                                         int x = xDest + pGlyph->xOffset + w;
1319
1320                                         if (x < 0)
1321                                         {
1322                                                 ++pDest32;
1323                                                 continue;
1324                                         }
1325
1326                                         if (x >= scratchPad.GetWidth())
1327                                         {
1328                                                 break;
1329                                         }
1330
1331                                         unsigned long alpha = (unsigned long) (pGlyph->image.pBitmap[h * pGlyph->image.bytesPerLine + w]);
1332
1333                                         if (alpha > 0)
1334                                         {
1335                                                 // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
1336                                                 alpha = (alpha * srcA) >> 8;
1337                                                 alpha += (alpha >> 7);
1338
1339                                                 dstA = (*pDest32 >> 24) & 0xFF;
1340                                                 dstR = (*pDest32 >> 16) & 0xFF;
1341                                                 dstG = (*pDest32 >> 8) & 0xFF;
1342                                                 dstB = (*pDest32) & 0xFF;
1343
1344                                                 dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
1345                                                 dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
1346                                                 dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
1347                                                 dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
1348
1349                                                 *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
1350
1351                                         }
1352                                         ++pDest32;
1353                                 }
1354                         }
1355
1356                         xDest += (pGlyph->xAdvance >> 10);
1357                         yDest += (pGlyph->yAdvance >> 10);
1358                 }
1359
1360                 scratchPad.RegisterFillRect(null);
1361
1362                 IEnumeratorT<_IFont::Glyph*>* pEnum = glyphList.GetEnumeratorN();
1363
1364                 if (pEnum)
1365                 {
1366                         while (pEnum->MoveNext() == E_SUCCESS)
1367                         {
1368                                 _IFont::Glyph* pGlyph;
1369
1370                                 pEnum->GetCurrent(pGlyph);
1371                                 delete pGlyph;
1372                         }
1373
1374                         delete pEnum;
1375                 }
1376         }
1377         else
1378         {
1379                 while (*pText && --length >= 0)
1380                 {
1381                         // find out proper native font
1382                         _IFont* pFont = this->__GetFont(*pText);
1383
1384                         if (pFont == null)
1385                         {
1386                                 continue;
1387                         }
1388
1389                         if (pFont != __pNativeFont)
1390                         {
1391                                 _IFont::Attrib fontAttrib;
1392                                 bool rtn = pFont->GetAttrib(fontAttrib);
1393                                 //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to get font attribute");
1394
1395                                 fontAttrib.size = __fontAttrib.size;
1396                                 fontAttrib.style = _IFont::STYLE_NONE;
1397                                 fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
1398                                 fontAttrib.style |= (__fontAttrib.style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
1399                                 fontAttrib.style |= (__fontAttrib.underline) ? _IFont::STYLE_UNDERLINE : 0;
1400                                 rtn = pFont->SetAttrib(fontAttrib);
1401                                 //SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to set font attribute");
1402                         }
1403
1404                         _IFont::Property prop;
1405                         pFont->GetFontProperty(prop);
1406
1407                         unsigned long fgColor = (canvas.__applyEmoji && (String(prop.pFamilyName) == L"keitaiemoji")) ? GetPredefinedColor(*pText, canvasFgColor) : canvasFgColor;
1408
1409                         if (left > 0)
1410                         {
1411                                 if (pFont->GetKerning(leftChar, *pText, xVec, yVec))
1412                                 {
1413                                         xDest += xVec;
1414                                 }
1415                         }
1416
1417                         bool rtn = pFont->LoadGlyph(*pText++, &pFontGlyphData);
1418
1419                         if (!rtn)
1420                         {
1421                                 continue;
1422                         }
1423
1424                         typedef unsigned long TPixel;
1425
1426                         TPixel srcA = (fgColor >> 24) & 0xFF;
1427                         srcA += (srcA >> 7);
1428
1429                         TPixel srcR = (fgColor >> 16) & 0xFF;
1430                         TPixel srcG = (fgColor >> 8) & 0xFF;
1431                         TPixel srcB = (fgColor) & 0xFF;
1432
1433                         SystemPixel* pBufferStartAddr = null;
1434                         int bufferPitch = 0;
1435
1436                         scratchPad.GetBuffer(pBufferStartAddr, bufferPitch);
1437
1438                         for (int h = 0; h < pFontGlyphData->image.height; h++)
1439                         {
1440                                 int y = yDest - (pFontGlyphData->yOffset >> 10) + h;
1441
1442                                 if (y < clipY1)
1443                                 {
1444                                         continue;
1445                                 }
1446
1447                                 if (y >= clipY2)
1448                                 {
1449                                         break;
1450                                 }
1451
1452                                 TPixel* pDest32 = pBufferStartAddr + y * bufferPitch + xDest + (pFontGlyphData->xOffset >> 10);
1453
1454                                 for (int w = 0; w < pFontGlyphData->image.width; w++)
1455                                 {
1456                                         int x = xDest + (pFontGlyphData->xOffset >> 10) + w;
1457
1458                                         if (x < clipX1)
1459                                         {
1460                                                 ++pDest32;
1461                                                 continue;
1462                                         }
1463
1464                                         if (x >= clipX2)
1465                                         {
1466                                                 break;
1467                                         }
1468
1469                                         unsigned long alpha = (unsigned long) (pFontGlyphData->image.pBitmap[h * pFontGlyphData->image.bytesPerLine + w]);
1470
1471                                         if (alpha > 0)
1472                                         {
1473                                                 // equivalent to scratchPad.FillRect(x, y, 1, 1, fgColor, alpha);
1474                                                 alpha = (alpha * srcA) >> 8;
1475                                                 alpha += (alpha >> 7);
1476
1477                                                 TPixel dstA = (*pDest32 >> 24) & 0xFF;
1478                                                 TPixel dstR = (*pDest32 >> 16) & 0xFF;
1479                                                 TPixel dstG = (*pDest32 >> 8) & 0xFF;
1480                                                 TPixel dstB = (*pDest32) & 0xFF;
1481
1482                                                 dstA = BLEND_ALPHA_COMPONEMT(alpha, dstA);
1483                                                 dstR = (dstR + (((srcR - dstR) * alpha) >> 8)) & 0xFF;
1484                                                 dstG = (dstG + (((srcG - dstG) * alpha) >> 8)) & 0xFF;
1485                                                 dstB = (dstB + (((srcB - dstB) * alpha) >> 8)) & 0xFF;
1486
1487                                                 *pDest32 = (dstA << 24) | (dstR << 16) | (dstG << 8) | dstB;
1488
1489                                         }
1490                                         ++pDest32;
1491                                 }
1492                         }
1493
1494                         xDest += (pFontGlyphData->xAdvance >> 10) + __fontAttrib.charSpace + italicSpace + boldSpace;
1495                         yDest += (pFontGlyphData->yAdvance >> 10);
1496                         left++;
1497                         leftChar = *(pText - 1);
1498
1499                         pFont->UnloadGlyph(&pFontGlyphData);
1500
1501                 }
1502
1503                 if (this->IsUnderlined() || this->IsStrikeOut())
1504                 {
1505                         int y = point.y + charHeight - 1;
1506                         int thick = this->GetLineThickness();
1507
1508                         xDest -= this->GetCharSpace();
1509
1510                         if (this->IsUnderlined())
1511                         {
1512                                 canvas.FillRectangle(canvasFgColor, Rectangle(startX, y - thick, xDest - startX, thick));
1513                         }
1514
1515                         if (this->IsStrikeOut())
1516                         {
1517                                 y -= charHeight / 2;
1518                                 canvas.FillRectangle(canvasFgColor, Rectangle(startX, y - thick, xDest - startX, thick));
1519                         }
1520                 }
1521
1522                 scratchPad.RegisterFillRect(null);
1523         }
1524
1525         return E_SUCCESS;
1526 }
1527
1528 #undef BLEND_ALPHA_COMPONEMT
1529
1530 result
1531 _Font::__DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
1532 {
1533         unsigned long textColor = canvas.__fgColor;
1534         bool applyEmoji = canvas.__applyEmoji;
1535
1536         //sunmi557.shin: draw border of font
1537         canvas.__fgColor = outlineColor.GetRGB32();
1538         canvas.__applyEmoji = false;
1539
1540         this->__DrawText(canvas, Point(point.x - 1, point.y), text, startIndex, length);
1541         this->__DrawText(canvas, Point(point.x + 1, point.y), text, startIndex, length);
1542         this->__DrawText(canvas, Point(point.x, point.y - 1), text, startIndex, length);
1543         this->__DrawText(canvas, Point(point.x, point.y + 1), text, startIndex, length);
1544
1545         //sunmi557.shin: draw original shape of font
1546         canvas.__applyEmoji = applyEmoji;
1547         canvas.__fgColor = textColor;
1548
1549         this->__DrawText(canvas, point, text, startIndex, length);
1550
1551         return E_SUCCESS;
1552 }
1553
1554 bool
1555 _Font::SetAttrib(const _IFont::Attrib& fontAttrib)
1556 {
1557         IF_NOT_INITIALIZED(return false);
1558
1559         return __pNativeFont->SetAttrib(fontAttrib);
1560 }
1561
1562 bool
1563 _Font::GetAttrib(_IFont::Attrib& fontAttrib) const
1564 {
1565         IF_NOT_INITIALIZED(return false);
1566
1567         return __pNativeFont->GetAttrib(fontAttrib);
1568 }
1569
1570 bool
1571 _Font::GetKerning(unsigned long character1, unsigned long character2, long& xVector, long& yVector) const
1572 {
1573         IF_NOT_INITIALIZED(return false);
1574
1575         return __pNativeFont->GetKerning(character1, character2, xVector, yVector);
1576 }
1577
1578 bool
1579 _Font::GetFontProperty(_IFont::Property& property) const
1580 {
1581         IF_NOT_INITIALIZED(return false);
1582
1583         return __pNativeFont->GetFontProperty(property);
1584 }
1585
1586 bool
1587 _Font::LoadGlyph(unsigned long character, _IFont::Glyph** ppFontGlyphData)
1588 {
1589         IF_NOT_INITIALIZED(return false);
1590
1591         // note! we assume that the font attribute has been already applied on _IFont
1592         bool rtn = false;
1593
1594         // if not, loading glyph (character/size/style) and caching it
1595         rtn = __pNativeFont->LoadGlyph(character, ppFontGlyphData);
1596         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to load glyph data");
1597
1598         // return cached glyph
1599         return true;
1600 }
1601
1602 bool
1603 _Font::UnloadGlyph(_IFont::Glyph** ppFontGlyphData)
1604 {
1605         IF_NOT_INITIALIZED(return false);
1606
1607         return __pNativeFont->UnloadGlyph(ppFontGlyphData);
1608 }
1609
1610 unsigned long
1611 _Font::CheckGlyph(unsigned long character)
1612 {
1613         IF_NOT_INITIALIZED(return false);
1614
1615         return __pNativeFont->CheckGlyph(character);
1616 }
1617
1618 void
1619 _Font::__UpdateFontAttribute(int style, int pcSize)
1620 {
1621         IF_NOT_INITIALIZED(return);
1622
1623         __fontAttrib.style = style;
1624         __fontAttrib.size = pcSize;
1625         __fontAttrib.lineThickness = ((CONVERT_26_6_FIXED_POINT_TO_INTEGER(pcSize) < 24) ? 1 : ((CONVERT_26_6_FIXED_POINT_TO_INTEGER(pcSize) < 48) ? 2 : 3));
1626
1627         _IFont::Property prop;
1628         bool getProperty = false;
1629
1630         if (this->ApplyAttribute())
1631         {
1632                 getProperty = __pNativeFont->GetFontProperty(prop);
1633         }
1634
1635         if (getProperty)
1636         {
1637                 __fontAttrib.maxWidth = prop.maxWidth;
1638                 __fontAttrib.maxHeight = prop.maxHeight;
1639                 __fontAttrib.ascender = prop.ascender;
1640                 __fontAttrib.descender = prop.descender;
1641         }
1642         else
1643         {
1644                 // if failed to get property above, each property should be remained as default: -1
1645                 SysLog(NID_GRP, "[] Failed to get font attribute from native font");
1646
1647                 __fontAttrib.maxWidth = -1;
1648                 __fontAttrib.maxHeight = -1;
1649                 __fontAttrib.ascender = -1;
1650                 __fontAttrib.descender = -1;
1651         }
1652 }
1653
1654 result
1655 _Font::__DrawTextLastFallback(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
1656 {
1657         return E_SUCCESS;
1658 }
1659
1660 result
1661 _Font::__DrawTextDefault(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
1662 {
1663         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
1664         result r = mgr.GetDefaultSystemFont().__DrawText(canvas, point, text, startIndex, length);
1665         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to draw default system font", GetErrorMessage(r));
1666
1667         return E_SUCCESS;
1668
1669 CATCH:
1670         _Font::__DrawTextLastFallback(canvas, point, text, startIndex, length);
1671         return r;
1672 }
1673
1674 result
1675 _Font::__DrawTextDefault(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
1676 {
1677         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
1678         result r = mgr.GetDefaultSystemFont().__DrawText(canvas, point, text, startIndex, length, outlineColor);
1679         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to draw default system font", GetErrorMessage(r));
1680
1681         return E_SUCCESS;
1682
1683 CATCH:
1684         _Font::__DrawTextLastFallback(canvas, point, text, startIndex, length);
1685         return r;
1686 }
1687
1688
1689 result
1690 _Font::DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length)
1691 {
1692         if (canvas.__pPriorityFont)
1693         {
1694                 return canvas.__pPriorityFont->__DrawText(canvas, point, text, startIndex, length);
1695         }
1696         else if (canvas.__pFont)
1697         {
1698                 return canvas.__pFont->__DrawText(canvas, point, text, startIndex, length);
1699         }
1700         else
1701         {
1702                 return _Font::__DrawTextDefault(canvas, point, text, startIndex, length);
1703         }
1704 }
1705
1706 result
1707 _Font::DrawText(_Canvas& canvas, const Point& point, const Tizen::Base::String& text, int startIndex, int length, const Color& outlineColor)
1708 {
1709         if (canvas.__pPriorityFont)
1710         {
1711                 return canvas.__pPriorityFont->__DrawText(canvas, point, text, startIndex, length, outlineColor);
1712         }
1713         else if (canvas.__pFont)
1714         {
1715                 return canvas.__pFont->__DrawText(canvas, point, text, startIndex, length, outlineColor);
1716         }
1717         else
1718         {
1719                 return _Font::__DrawTextDefault(canvas, point, text, startIndex, length, outlineColor);
1720         }
1721
1722         return E_SUCCESS;
1723 }
1724
1725 _Font*
1726 _Font::GetInstance(_FontImpl& font)
1727 {
1728         return (&font != null) ? font._pNativeFont : null;
1729 }
1730
1731 const _Font*
1732 _Font::GetInstance(const _FontImpl& font)
1733 {
1734         return (&font != null) ? font._pNativeFont : null;
1735 }
1736
1737 _IFont*
1738 _Font::__GetFont(wchar_t character)
1739 {
1740         IF_NOT_INITIALIZED(return null);
1741
1742         //------------------------------------------------------
1743         //
1744         // 1. check if this font has a requested glyph
1745         //
1746         //------------------------------------------------------
1747         unsigned long idx = __pNativeFont->CheckGlyph(character);
1748
1749         if (idx > 0)
1750         {
1751                 return __pNativeFont;
1752         }
1753
1754         //------------------------------------------------------
1755         //
1756         // 1-2. check if this glyph is in the fallback list.
1757         //
1758         //------------------------------------------------------
1759         _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
1760         Tizen::Base::Collection::HashMapT<String, _FontRsrcManager::SharedFontResource>* fallbackFontMap = __pNativeFont->GetFallbackMap();
1761         std::auto_ptr<IMapEnumeratorT<String, _FontRsrcManager::SharedFontResource> > enumerator(fallbackFontMap->GetMapEnumeratorN());
1762
1763         while (enumerator->MoveNext() == E_SUCCESS)
1764         {
1765                 _FontRsrcManager::SharedFontResource pTempFont;
1766
1767                 if (enumerator->GetValue(pTempFont) == E_SUCCESS)
1768                 {
1769                         String key;
1770                         result r = enumerator->GetKey(key);
1771
1772                         if (r == E_SUCCESS)
1773                         {
1774                                 if (mgr.SearchFont(key))
1775                                 {
1776                                         if (pTempFont.get()->CheckGlyph(character) > 0)
1777                                         {
1778                                                 return  pTempFont.get();
1779                                         }
1780                                 }
1781                                 else
1782                                 {
1783                                         fallbackFontMap->Remove(key);
1784                                 }
1785                         }
1786                 }
1787         }
1788
1789         //------------------------------------------------------
1790         //
1791         // 2. Get fallback font list via fontconfig
1792         //
1793         //------------------------------------------------------
1794         Tizen::Base::Collection::ArrayListT<String> fileList;
1795         bool rtn = __GetFallbackFontFileList(character, fileList);
1796         if (!rtn)
1797         {
1798                 // if failed find out fallback font,
1799                 // just use this instance for drawing something for unknown glyph
1800                 return __pNativeFont;
1801         }
1802
1803         //------------------------------------------------------
1804         //
1805         // 3. try to find a font having a requested glyph
1806         //
1807         //------------------------------------------------------
1808         String fontName;
1809         _IFont* pFallbackFont = null;
1810
1811         _FontRsrcManager::SharedFontResource out;
1812
1813         int count = fileList.GetCount();
1814         result r = E_FAILURE;
1815
1816         for (int i = 0; i < count; i++)
1817         {
1818                 fileList.GetAt(i, fontName);
1819
1820                 if (fontName.IsEmpty())
1821                 {
1822                         continue;
1823                 }
1824
1825                 r = mgr.GetTempFont(fontName, __fontAttrib.style, __fontAttrib.size, out);
1826
1827                 if (r == E_SUCCESS)
1828                 {
1829                         unsigned long idx = out.get()->CheckGlyph(character);
1830
1831                         if (idx > 0)
1832                         {
1833                                 // keep it
1834                                 r = fallbackFontMap->Add(fontName, out);
1835                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1836
1837                                 r = mgr.AddFont(fontName, out);
1838                                 SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
1839
1840                                 pFallbackFont = out.get();
1841                                 break;
1842                         }
1843                 }
1844         }
1845
1846         return (pFallbackFont != null) ? pFallbackFont : __pNativeFont;
1847
1848 CATCH:
1849         // if failed find out fallback font,
1850         //      just use this instance for drawing something for unknown glyph
1851         return __pNativeFont;
1852 }
1853
1854 bool
1855 _Font::__GetFallbackFontFileList(wchar_t character, Tizen::Base::Collection::IListT<String>& out)
1856 {
1857         GUnicodeScript script = g_unichar_get_script(character);
1858         if (script < 0 || script >= _sampleLanguageCount)
1859         {
1860                 return false;
1861         }
1862
1863         _IFont::Property prop;
1864         const char* pFamilyName = null;
1865         GET_FONT_PROPERTY(prop, false);
1866
1867         pFamilyName = prop.pFamilyName;
1868
1869         FcPattern* pPattern = null;
1870         FcFontSet* pSet = null;
1871         FcChar8* pName = null;
1872         FcResult res = FcResultNoMatch;
1873         const char* fcStyle = (__fontAttrib.style & FONT_STYLE_BOLD) ? "Bold" : "Regular";
1874
1875         // initialize fontconfig library
1876         FcBool rtn = FcInit();
1877         SysTryCatch(NID_GRP, rtn, , E_SYSTEM, "[E_SYSTEM] Failed to init fontconfig");
1878
1879         // getting fallback font list
1880         pPattern = FcPatternBuild(NULL, FC_STYLE, FcTypeString, (FcChar8*)fcStyle, NULL);
1881         SysTryCatch(NID_GRP, pPattern, , E_SYSTEM, "[E_SYSTEM] Failed to FcPatternBuild()");
1882
1883         FcPatternAddString(pPattern, FC_FAMILY, (FcChar8*) pFamilyName);
1884
1885         if (strncmp(SAMPLE_LANGUAGE_EMPTY, _SampleLanguages[script], strlen(SAMPLE_LANGUAGE_EMPTY) + 1) != 0)
1886         {
1887                 FcPatternAddString(pPattern, FC_LANG, (FcChar8*)_SampleLanguages[script]);
1888         }
1889
1890         FcConfigSubstitute(NULL, pPattern, FcMatchPattern);
1891         FcDefaultSubstitute(pPattern);
1892
1893         // do matching
1894         pSet = FcFontSort(NULL, pPattern, FcTrue, NULL, &res);
1895         SysTryCatch(NID_GRP, pSet, , E_SYSTEM, "[E_SYSTEM] Failed to FcFontSort()");
1896
1897         out.RemoveAll();
1898
1899         for (int i = 0; i < pSet->nfont; i++)
1900         {
1901                 if (FcPatternGetString(pSet->fonts[i], FC_FILE, 0, &pName) == FcResultMatch)
1902                 {
1903                                 out.Add(String((char*)pName));
1904                 }
1905         }
1906
1907         // destroy
1908         FcFontSetDestroy(pSet);
1909         FcPatternDestroy(pPattern);
1910         FcFini();
1911
1912         return (out.GetCount() > 0) ? true : false;
1913
1914 CATCH:
1915         if (pSet != null)
1916         {
1917                 FcFontSetDestroy(pSet);
1918         }
1919
1920         if (pPattern != null)
1921         {
1922                 FcPatternDestroy(pPattern);
1923         }
1924
1925         FcFini();
1926
1927         return false;
1928 }
1929
1930 bool
1931 _Font::UpdateDefaultFont(const String& key)
1932 {
1933         if (!key.IsEmpty())
1934         {
1935                 SysLog(NID_GRP, "Request to change the default font");
1936
1937                 _FontRsrcManager& mgr = _FontRsrcManager::GetInstance();
1938
1939                 return mgr.ReloadDefaultSystemFont();
1940         }
1941
1942         return false;
1943 }
1944
1945 }} // Tizen::Graphics