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