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