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