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