1b0bd60fa76bbd3c2f597d4e2d3a16804b81c78f
[platform/framework/native/uifw.git] / src / graphics / FGrp_FontFt2.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_FontFt2.cpp
20  * @brief       This is the implementation file for _FontFt2 class.
21  *
22  */
23
24 #include <new>
25 #include <math.h>
26
27 #include <unique_ptr.h>
28
29 #include <ft2build.h>
30 #include <freetype/tttables.h>
31 #include FT_FREETYPE_H
32 #include FT_OUTLINE_H
33
34 #include <FBaseErrors.h>
35
36 #include <FBaseSysLog.h>
37 #include <FBaseUtilStringUtil.h>
38 #include <FBaseColIHashCodeProviderT.h>
39
40 #include "FGrp_FontFt2.h"
41 #include "FGrp_FontCache.h"
42 #include "FGrp_FontBidiUtil.h"
43 #include "util/FGrp_UtilTemplate.h"
44 #include "util/FGrp_UtilType.h"
45
46 #define CHECK_NULL_PARAM(data) if (data == null) \
47         { \
48                 return false; \
49         }
50
51 using namespace Tizen::Base;
52 using namespace Tizen::Base::Collection;
53 using namespace Tizen::Graphics;
54
55 namespace // unnamed
56 {
57 const double _M_PI = 3.14159265358979323846;
58 const double _ITALIC_ANGLE = 10.619655;
59 const _Util::FixedPoint26_6 _SYSTEM_DEFAULT_FONT_SIZE(16);
60 const long _DEFAULT_RES = 72;
61
62 const unsigned long _INDEX_FIRST = 32;       // in first resource, the first chracter(space)
63 const unsigned long _INDEX_COUNT = 95;       // first resource character count
64
65 const long _MEDIUM_FONT_BOLD_WEIGHT = 600;
66
67 bool
68 _CompareFamilyForTitling(const char* pFamilyName)
69 {
70         static const char* _compNames[] =
71         {
72                 "TitlingGothicFB Comp",
73                 "TitlingGothicFB Cond",
74                 "TitlingGothicFB Narrow",
75                 "TitlingGothicFB Skyline"
76         };
77
78         for (unsigned int i = 0; i < sizeof(_compNames) / sizeof(_compNames[0]); i++)
79         {
80                 if (strcmp(pFamilyName, _compNames[i]) == 0)
81                 {
82                         return true;
83                 }
84         }
85
86         return false;
87 }
88
89 #ifdef USE_HASHMAP_FOR_FONT
90 template<class T>
91 class _FontHashCodeProvider
92         : public IHashCodeProviderT <T>
93 {
94 public:
95         virtual int GetHashCode(const T& obj) const
96         {
97                 return obj.GetHashCode();
98         }
99 }; // _FontHashCodeProvider
100
101 template<class T>
102 class _FontComparer
103         : public IComparerT <T>
104 {
105 public:
106         virtual result Compare(const T& obj1, const T& obj2, int& cmp) const
107         {
108                 String& objString1 = static_cast <String&>(const_cast <T&>(obj1));
109                 String& objString2 = static_cast <String&>(const_cast <T&>(obj2));
110
111                 cmp = objString1.CompareTo(objString2);
112
113                 return E_SUCCESS;
114         }
115 }; // _FontComparer
116
117 template<class T>
118 class _FontHashCodeProviderEx
119         : public IHashCodeProviderT <T>
120 {
121 public:
122         virtual int GetHashCode(const T& obj) const
123         {
124                 const wchar_t* pText = obj.c_str();
125                 const wchar_t* pTextEnd = pText - 1;
126
127                 while (*(++pTextEnd))
128                         ;
129
130                 int stride = ((pTextEnd - pText + 1) << 16) / 9;
131                 int ix16 = 0;
132
133                 int ret1 = (pText[(ix16 += stride) >> 16] & 0xFF);
134                 ret1 |= ((pText[(ix16 += stride) >> 16] & 0xFF) << 8);
135                 ret1 |= ((pText[(ix16 += stride) >> 16] & 0xFF) << 16);
136                 ret1 |= ((pText[(ix16 += stride) >> 16] & 0xFF) << 24);
137
138                 int ret2 = (pText[(ix16 += stride) >> 16] & 0xFF);
139                 ret2 |= ((pText[(ix16 += stride) >> 16] & 0xFF) << 8);
140                 ret2 |= ((pText[(ix16 += stride) >> 16] & 0xFF) << 16);
141                 ret2 |= ((pText[(ix16 += stride) >> 16] & 0xFF) << 24);
142
143                 return ret1 ^ ret2;
144         }
145 }; // _FontHashCodeProviderEx
146
147 template<class T>
148 class _FontComparerEx
149         : public IComparerT <T>
150 {
151 public:
152         virtual result Compare(const T& obj1, const T& obj2, int& cmp) const
153         {
154                 cmp = wcscmp((wchar_t*)obj1.c_str(), (wchar_t*)obj2.c_str());
155
156                 return E_SUCCESS;
157         }
158 }; // _FontComparerEx
159
160 const _FontHashCodeProviderEx<_Util::WString> _fontHashCodeProviderEx;
161 const _FontComparerEx<_Util::WString> _fontComparerEx;
162 #endif
163 } // unnamed
164
165 namespace Tizen { namespace Graphics
166 {
167
168 inline bool
169 _IsEqual(float f1, float f2)
170 {
171         return (((f1 > f2) ? f1 - f2 : f2 - f1) < 0.00001f); // epsilon is assumed to be 0.0001, not 1.192092896e-07f
172 }
173
174 _FontFt2::_FontFt2()
175         : __isValid(false)
176         , __isLoadGlyph(false)
177         , __pFontEngine(null)
178         , __pFontFace(null)
179         , __pFontBuffer(null)
180         , __isStaticBuffer(false)
181         , __isEmoji(false)
182 {
183         __fontAttrib.size = _SYSTEM_DEFAULT_FONT_SIZE;
184         __fontAttrib.angle = 0.0f;
185         __fontAttrib.style = _IFont::STYLE_NONE;
186         __fontAttrib.quality = _IFont::QUALITY_HIGH;
187         __fontAttrib.xExpansion = 100;
188         __fontAttrib.boldWeight = _Util::FixedPoint26_6(1.0f);
189
190 #ifdef USE_HASHMAP_FOR_FONT
191         __fallbackFontMap.Construct(1, 0, _fontHashCodeProviderEx, _fontComparerEx);
192 #endif
193
194         //create cache
195         __fontCache.reset(new (std::nothrow) _FontCache());
196 }
197
198 _FontFt2::~_FontFt2()
199 {
200         if (!__isValid)
201         {
202                 return;
203         }
204
205         __CleanUp();
206         __isValid = false;
207
208 #ifdef USE_HASHMAP_FOR_FONT
209         __fallbackFontMap.RemoveAll();
210 #else
211         __fallbackFontMap.clear();
212 #endif
213 }
214
215 bool
216 _FontFt2::Create(const void* pBuffer, long bufSize, long face)
217 {
218         if (__isValid)
219         {
220                 return false;
221         }
222
223         int error = FT_Init_FreeType(static_cast<FT_Library*>((void*) &__pFontEngine));
224
225         if (error)
226         {
227                 __CleanUp();
228
229                 return false;
230         }
231
232         // should keep the buffer
233         __pFontBuffer = new (std::nothrow) byte[bufSize];
234
235         if (!__pFontBuffer)
236         {
237                 __CleanUp();
238
239                 return false;
240         }
241
242         memcpy(__pFontBuffer, pBuffer, bufSize);
243
244         error = FT_New_Memory_Face(FT_Library(__pFontEngine), (const byte*) __pFontBuffer, bufSize, face, static_cast<FT_Face*>((void*) &__pFontFace));
245
246         if (error)
247         {
248                 __CleanUp();
249
250                 return false;
251         }
252
253         FT_Face pFace = FT_Face(__pFontFace);
254
255         if ((pFace->charmap == null) && (pFace->num_charmaps > 0))
256         {
257                 FT_Set_Charmap(pFace, pFace->charmaps[0]);
258         }
259
260         __isValid = true;
261
262         __InitProperty();
263
264         return true;
265 }
266
267 bool
268 _FontFt2::Create(const char* pFilePath, long face)
269 {
270         if (__isValid)
271         {
272                 return false;
273         }
274
275         int error = FT_Init_FreeType(static_cast<FT_Library*>((void*) &__pFontEngine));
276
277         if (error)
278         {
279                 __CleanUp();
280
281                 return false;
282         }
283
284         error = FT_New_Face(FT_Library(__pFontEngine), pFilePath, face, static_cast<FT_Face*>((void*) &__pFontFace));
285
286         if (error)
287         {
288                 __CleanUp();
289
290                 return false;
291         }
292
293         FT_Face pFace = FT_Face(__pFontFace);
294
295         if ((pFace->charmap == null) && (pFace->num_charmaps > 0))
296         {
297                 FT_Set_Charmap(pFace, pFace->charmaps[0]);
298         }
299
300         __isValid = true;
301
302         __InitProperty();
303
304         return true;
305 }
306
307 bool
308 _FontFt2::CreateStatic(const void* pBuffer, long bufSize, long face)
309 {
310         if (__isValid)
311         {
312                 return false;
313         }
314
315         FT_Face pFace = null;
316
317         int error = FT_Init_FreeType(static_cast<FT_Library*>((void*) &__pFontEngine));
318
319         if (error)
320         {
321                 __CleanUp();
322
323                 return false;
324         }
325
326         __pFontBuffer = const_cast<void*>(pBuffer);
327         __isStaticBuffer = true;
328
329         error = FT_New_Memory_Face(FT_Library(__pFontEngine), (const byte*) __pFontBuffer, bufSize, face, static_cast<FT_Face*>((void*) &__pFontFace));
330
331         if (error)
332         {
333                 __CleanUp();
334
335                 return false;
336         }
337
338         pFace = FT_Face(__pFontFace);
339
340         if ((pFace->charmap == null) && (pFace->num_charmaps > 0))
341         {
342                 FT_Set_Charmap(pFace, pFace->charmaps[0]);
343         }
344
345         __isValid = true;
346
347         __InitProperty();
348
349         return true;
350 }
351
352 bool
353 _FontFt2::Reload(const void* pBuffer, long bufSize, long face)
354 {
355         if (!__isValid)
356         {
357                 return false;
358         }
359
360         std::unique_ptr<byte[]> pReloadBuffer(new (std::nothrow) byte[bufSize]);
361
362         if (pReloadBuffer == null)
363         {
364                 return false;
365         }
366
367         memcpy(pReloadBuffer.get(), pBuffer, bufSize);
368
369         void* pReloadFace = null;
370
371         int error = FT_New_Memory_Face(FT_Library(__pFontEngine), (const byte*) pReloadBuffer.get(), bufSize, face, static_cast<FT_Face*>((void*) &pReloadFace));
372
373         if (error)
374         {
375                 return false;
376         }
377
378         //clean resource
379         if (__pFontFace)
380         {
381                 FT_Done_Face(FT_Face(__pFontFace));
382                 __pFontFace = null;
383         }
384
385         if (__pFontBuffer && !__isStaticBuffer)
386         {
387                 delete[] static_cast<byte*>(__pFontBuffer);
388         }
389
390         // assign new resource
391         __pFontBuffer = pReloadBuffer.release();
392         __pFontFace = pReloadFace;
393         __isStaticBuffer = false;
394
395         FT_Face pFace = FT_Face(__pFontFace);
396
397         if ((pFace->charmap == null) && (pFace->num_charmaps > 0))
398         {
399                 FT_Set_Charmap(pFace, pFace->charmaps[0]);
400         }
401
402         __isValid = true;
403
404         __InitProperty();
405
406         return true;
407 }
408
409 bool
410 _FontFt2::Reload(const char* filePath, long face)
411 {
412         if (!__isValid)
413         {
414                 return false;
415         }
416
417         void* pReloadFace = null;
418
419         int error = FT_New_Face(FT_Library(__pFontEngine), filePath, face, static_cast<FT_Face*>((void*) &pReloadFace));
420
421         if (error)
422         {
423                 return false;
424         }
425
426         //clean resource
427         if (__pFontFace)
428         {
429                 FT_Done_Face(FT_Face(__pFontFace));
430                 __pFontFace = null;
431         }
432
433         // assign new resource
434         __pFontFace = pReloadFace;
435         __isStaticBuffer = false;
436
437         FT_Face pFace = FT_Face(__pFontFace);
438
439         if ((pFace->charmap == null) && (pFace->num_charmaps > 0))
440         {
441                 FT_Set_Charmap(pFace, pFace->charmaps[0]);
442         }
443
444         __isValid = true;
445
446         __InitProperty();
447
448         return true;
449 }
450
451 void
452 _FontFt2::Destroy(void)
453 {
454         if (!__isValid)
455         {
456                 return;
457         }
458
459         __CleanUp();
460         __isValid = false;
461 }
462
463 bool
464 _FontFt2::FindCache(unsigned long glyphIndex, _Util::FixedPoint26_6 size, int style, Glyph** pOut)
465 {
466         return (__fontCache.get()) ? __fontCache->Find(glyphIndex, __fontAttrib.size, __fontAttrib.style, pOut) : false;
467 }
468
469 bool
470 _FontFt2::AddCache(unsigned long glyphIndex, _Util::FixedPoint26_6 size, int style, Glyph* pGlyph)
471 {
472         return (__fontCache.get()) ? __fontCache->Add(glyphIndex, size, style, pGlyph) : false;
473 }
474
475 bool
476 _FontFt2::CleanCache()
477 {
478         return (__fontCache.get()) ? __fontCache->Cleanup() : false;
479 }
480
481 bool
482 _FontFt2::SetAttrib(const Attrib& fontAttrib)
483 {
484         if (!__isValid)
485         {
486                 return false;
487         }
488
489         if (!(fontAttrib.size >= 1) ||
490                 !(fontAttrib.quality >= 0 && fontAttrib.quality <= 3) ||
491                 !(fontAttrib.xExpansion >= 1) ||
492                 !(fontAttrib.size.ToInt() * fontAttrib.xExpansion >= _DEFAULT_RES) ||
493                 !(fontAttrib.boldWeight > 0))
494         {
495                 return false;
496         }
497
498         if (FT_IS_SCALABLE(FT_Face(__pFontFace)) == 0)
499         {
500                 return false;
501         }
502
503         if (__fontAttrib.size != fontAttrib.size)
504         {
505                 if (FT_Set_Char_Size(FT_Face(__pFontFace), fontAttrib.size.__fixedPoint * _DEFAULT_RES, fontAttrib.size.__fixedPoint * _DEFAULT_RES, 1, 1) > 0)
506                 {
507                         return false;
508                 }
509         }
510
511         // set
512         memcpy(&__fontAttrib, &fontAttrib, sizeof(fontAttrib));
513
514         return true;
515 }
516
517 bool
518 _FontFt2::GetAttrib(Attrib& fontAttrib) const
519 {
520         if (!__isValid)
521         {
522                 return false;
523         }
524
525         fontAttrib.angle = __fontAttrib.angle;
526         fontAttrib.quality = __fontAttrib.quality;
527         fontAttrib.size = __fontAttrib.size;
528         fontAttrib.style = __fontAttrib.style;
529         fontAttrib.xExpansion = __fontAttrib.xExpansion;
530         fontAttrib.boldWeight = __fontAttrib.boldWeight;
531
532         return true;
533 }
534
535 bool
536 _FontFt2::GetKerning(unsigned long character1, unsigned long character2, long& xVector, long& yVector) const
537 {
538         if (!__isValid)
539         {
540                 return false;
541         }
542
543         bool isCharacter1InEnglish = false;
544         bool isCharacter2InEnglish = false;
545         FT_Face pFace = null;
546         unsigned long index1 = 0;
547         unsigned long index2 = 0;
548
549         if (character1 >= _INDEX_FIRST && character1 < (_INDEX_FIRST + _INDEX_COUNT))
550         {
551                 isCharacter1InEnglish = true;
552         }
553
554         if (character2 >= _INDEX_FIRST && character2 < (_INDEX_FIRST + _INDEX_COUNT))
555         {
556                 isCharacter2InEnglish = true;
557         }
558
559         if (isCharacter1InEnglish != isCharacter2InEnglish)
560         {
561                 xVector = 0;
562                 yVector = 0;
563                 return true;
564         }
565
566         pFace = FT_Face(__pFontFace);
567         index1 = __GetGlyphIndex(character1);
568         index2 = __GetGlyphIndex(character2);
569
570         bool hasKerning = false;
571
572         hasKerning = (FT_HAS_KERNING(pFace) != 0);
573
574         if (hasKerning)
575         {
576                 FT_Vector delta;
577
578                 int isSuccess = FT_Get_Kerning(pFace, index1, index2, ft_kerning_default, &delta);
579
580                 if (isSuccess != 0)  //0 means success.
581                 {
582                         return false;
583                 }
584
585                 _Util::FixedPoint26_6 deltaX;
586                 _Util::FixedPoint26_6 deltaY;
587
588                 deltaX.Reset(delta.x);
589                 deltaY.Reset(delta.y);
590
591                 xVector = deltaX.ToInt();
592                 yVector = deltaY.ToInt();
593         }
594         else
595         {
596                 xVector = 0;
597                 yVector = 0;
598         }
599
600         return true;
601 }
602
603 bool
604 _FontFt2::LoadGlyph(unsigned long character, Glyph** ppFontGlyphData)
605 {
606         if (!__isValid)
607         {
608                 return false;
609         }
610
611         CHECK_NULL_PARAM(__pFontFace);
612         CHECK_NULL_PARAM(ppFontGlyphData);
613
614         FT_UInt glyphIndex = __GetGlyphIndex(character);
615
616         bool rtn = FindCache(glyphIndex, __fontAttrib.size, __fontAttrib.style, ppFontGlyphData);
617
618         if (rtn)
619         {
620                 return true;
621         }
622
623         *ppFontGlyphData = null;
624
625         FT_Face pFace = null;
626
627         pFace = FT_Face(__pFontFace);
628
629         if (!FT_IS_SCALABLE(pFace))
630         {
631                 SysLog(NID_GRP, "[] FT_IS_SCALABLE has been failed");
632         }
633
634         // set transformation
635         FT_Matrix matrix;
636         FT_Vector pen = {0, 0};
637         __SetTransMatrix(&matrix);
638         FT_Set_Transform(pFace, &matrix, &pen);
639
640         if (__fontAttrib.quality == _IFont::QUALITY_LOW ||
641                          __fontAttrib.quality == _IFont::QUALITY_MEDIUM ||
642                          __fontAttrib.quality == _IFont::QUALITY_HIGH)
643         {
644                 FT_Error errCode = 1;
645
646                 bool isSynthetic = (__fontAttrib.style & _IFont::STYLE_BOLD) && (__fontProperty.weightClass < _MEDIUM_FONT_BOLD_WEIGHT);
647
648                 if (isSynthetic)
649                 {
650                         errCode = FT_Load_Glyph(pFace, glyphIndex, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP);
651                 }
652                 else
653                 {
654                         //errCode = FT_Load_Glyph(pFace, glyphIndex, FT_LOAD_RENDER);
655                         errCode = FT_Load_Glyph(pFace, glyphIndex, FT_LOAD_DEFAULT);
656                 }
657
658                 if (errCode)  // 0: success
659                 {
660                         SysLogException(NID_GRP, E_SYSTEM, "[E_SYSTEM] FT_Load_Glyph_HighQuality(errCode = %#x)=", errCode);
661
662                         return false;
663                 }
664
665                 if (isSynthetic)
666                 {
667                         FT_Outline_Embolden(&pFace->glyph->outline, __fontAttrib.boldWeight.__fixedPoint);
668                 }
669
670                 FT_Render_Glyph(pFace->glyph, FT_RENDER_MODE_NORMAL);
671         }
672         else if (__fontAttrib.quality == _IFont::QUALITY_MONO)
673         {
674                 //TODO sunmi557.shin, will not support
675                 FT_Error errCode = 1;
676
677                 errCode = FT_Load_Glyph(pFace, glyphIndex, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
678
679                 if (errCode)
680                 {
681                         SysLogException(NID_GRP, E_SYSTEM, "[E_SYSTEM] FT_Load_Glyph_MONO(errCode = %#x)=", errCode);
682
683                         return false;
684                 }
685         }
686         else
687         {
688                 SysLogException(NID_GRP, E_SYSTEM, "[E_SYSTEM] The quality of the FontFT2 is invalid!");
689
690                 return false;
691         }
692
693         __isLoadGlyph = __ConvertPrivateToImage(pFace->glyph, ppFontGlyphData);
694
695         if (__isLoadGlyph)
696         {
697                 rtn = AddCache(glyphIndex, __fontAttrib.size, __fontAttrib.style, *ppFontGlyphData);
698         }
699
700         if (*ppFontGlyphData != null)
701         {
702                 (*ppFontGlyphData)->hasOwnerShip = (__isLoadGlyph) ? 1 : 0;
703         }
704
705         return __isLoadGlyph;
706 }
707
708 bool
709 _FontFt2::UnloadGlyph(Glyph** ppFontGlyphData)
710 {
711         if (!__isValid)
712         {
713                 return false;
714         }
715
716         CHECK_NULL_PARAM(ppFontGlyphData);
717
718         if ((*ppFontGlyphData) && ((*ppFontGlyphData)->hasOwnerShip == 0))
719         {
720                 return false;
721         }
722
723         delete[] (char*) (*ppFontGlyphData);
724
725         *ppFontGlyphData = null;
726         __isLoadGlyph = false;
727
728         return false;
729 }
730
731 unsigned long
732 _FontFt2::CheckGlyph(unsigned long character)
733 {
734         return __GetGlyphIndex(character);
735 }
736
737 bool
738 _FontFt2::GetFontSizeProperty(SizeProperty& sizeProperty) const
739 {
740         if (!__isValid)
741         {
742                 return false;
743         }
744
745         FT_Face pFace = (FT_Face) __pFontFace;
746
747         if (FT_IS_SCALABLE(pFace))
748         {
749                 // validation check
750                 if (pFace->size == null)
751                 {
752                         return false;
753                 }
754
755                 // fill out
756
757                 sizeProperty.maxWidth.Reset(pFace->size->metrics.max_advance);
758                 sizeProperty.maxHeight.Reset(pFace->size->metrics.height);
759                 sizeProperty.baseLine.Reset(pFace->size->metrics.height + pFace->size->metrics.descender);
760                 sizeProperty.ascender.Reset(pFace->size->metrics.ascender);
761                 sizeProperty.descender.Reset(pFace->size->metrics.descender); // (-)
762                 sizeProperty.leading.Reset(pFace->size->metrics.height - pFace->size->metrics.ascender + pFace->size->metrics.descender);
763
764
765                 if (_CompareFamilyForTitling(pFace->family_name))
766                 {
767                         _Util::FixedPoint26_6 min;
768                         _Util::FixedPoint26_6 max;
769
770                         min.Reset((pFace->bbox.yMin * pFace->size->metrics.y_ppem) / pFace->units_per_EM);
771                         max.Reset((pFace->bbox.yMax * pFace->size->metrics.y_ppem) / pFace->units_per_EM);
772
773                         if (sizeProperty.ascender < max)
774                         {
775                                 sizeProperty.ascender = max;
776                         }
777
778                         if (sizeProperty.descender > min)
779                         {
780                                 sizeProperty.descender = min;
781                         }
782
783                         sizeProperty.maxHeight = sizeProperty.ascender - sizeProperty.descender;
784                         sizeProperty.baseLine = sizeProperty.maxHeight + sizeProperty.descender;
785                         sizeProperty.leading = sizeProperty.maxHeight - sizeProperty.ascender + sizeProperty.descender;
786                 }
787
788                 // shkim, TODO
789                 // min/max size need to be verified
790
791                 sizeProperty.minSize = _Util::FixedPoint26_6(8);
792                 sizeProperty.maxSize = _Util::FixedPoint26_6(540);
793         }
794         else
795         {
796                 return false;
797         }
798
799         return true;
800 }
801
802 bool
803 _FontFt2::__InitProperty()
804 {
805         if (!__isValid)
806         {
807                 return false;
808         }
809
810         FT_Face pFace = (FT_Face) __pFontFace;
811
812         if (FT_IS_SCALABLE(pFace))
813         {
814                 // validation check
815                 if (pFace->size == null)
816                 {
817                         return false;
818                 }
819
820                 TT_OS2* pFontSpecTable = (TT_OS2*)FT_Get_Sfnt_Table(pFace, ft_sfnt_os2);
821
822                 // fill out
823                 __fontProperty.pFamilyName = pFace->family_name;
824                 __fontProperty.pStyleName = pFace->style_name;
825                 __fontProperty.weightClass = (pFontSpecTable != null) ? pFontSpecTable->usWeightClass : 400;
826                 __fontProperty.styleFlag = pFace->style_flags;
827                 // shkim, TODO
828                 // engine name and min/max size need to be verified
829                 __fontProperty.pEngineName = "FreeType2";
830                 __fontProperty.styleCaps = _IFont::STYLE_ITALIC | _IFont::STYLE_BOLD | _IFont::STYLE_BACKSLANT;
831                 __fontProperty.fontCaps = _IFont::CAPS_SCALABLE | _IFont::CAPS_ANGLE | _IFont::CAPS_X_EXPANSION | _IFont::CAPS_QUALITY_MONO |
832                                                         _IFont::CAPS_QUALITY_LOW | _IFont::CAPS_QUALITY_MEDIUM | _IFont::CAPS_QUALITY_HIGH;
833
834                 FT_Set_Char_Size(FT_Face(__pFontFace), __fontAttrib.size.__fixedPoint * _DEFAULT_RES, __fontAttrib.size.__fixedPoint * _DEFAULT_RES, 1, 1);
835
836                 static const char* emojiFaceNames[] =
837                 {
838                         "keitaiemoji"
839                 };
840
841                 __isEmoji = false;
842
843                 for (unsigned int i = 0; i < sizeof(emojiFaceNames) / sizeof(emojiFaceNames[0]); i++)
844                 {
845                         if (strcmp(__fontProperty.pFamilyName, emojiFaceNames[i]) == 0)
846                         {
847                                 __isEmoji = true;
848                                 break;
849                         }
850                 }
851         }
852         else
853         {
854                 return false;
855         }
856
857         return true;
858 }
859
860 bool
861 _FontFt2::IsEmoji(void) const
862 {
863         return __isEmoji;
864 }
865
866 bool
867 _FontFt2::GetFontProperty(Property& property) const
868 {
869         if (!__isValid)
870         {
871                 return false;
872         }
873
874         property.pFamilyName = __fontProperty.pFamilyName;
875         property.pStyleName = __fontProperty.pStyleName;
876         property.styleFlag = __fontProperty.styleFlag;
877         property.weightClass = __fontProperty.weightClass;
878         property.pEngineName = __fontProperty.pEngineName;
879         property.styleCaps = __fontProperty.styleCaps;
880         property.fontCaps = __fontProperty.fontCaps;
881
882         return true;
883 }
884
885 _IFont::FontMapT*
886 _FontFt2::GetFallbackMap()
887 {
888         return &__fallbackFontMap;
889 }
890
891 bool
892 _FontFt2::GetGlyphList(const _Util::String& reorderedText, Tizen::Base::Collection::IListT<_IFont::Glyph *>& out, int script)
893 {
894         FT_Face pFace = FT_Face(__pFontFace);
895
896         {
897                 FT_Matrix matrix;
898                 FT_Vector pen = {0, 0};
899
900                 __SetTransMatrix(&matrix);
901
902                 FT_Set_Transform(pFace, &matrix, &pen);
903         }
904
905         _FontGlyphList glyphList(reorderedText, pFace, script);
906
907         out.RemoveAll();
908
909         FT_Error error = 1;
910
911         bool isSynthetic = (__fontAttrib.style & _IFont::STYLE_BOLD) && (__fontProperty.weightClass < _MEDIUM_FONT_BOLD_WEIGHT);
912
913         for (unsigned int i = 0; i < glyphList.GetCount(); i++)
914         {
915                 const _FontGlyphList::GlyphAuxInfo& auxInfo = glyphList.GetGlyphAuxInfo(i);
916
917                 if (!auxInfo.isAvailable)
918                 {
919                         _IFont::Glyph* pFontGlyphData = (_IFont::Glyph*) new (std::nothrow) char[sizeof(_IFont::Glyph)];
920
921                         if (pFontGlyphData)
922                         {
923                                 memset(pFontGlyphData, 0, sizeof(_IFont::Glyph));
924                                 pFontGlyphData->hasOwnerShip = 1;
925                                 out.Add(pFontGlyphData);
926                         }
927
928                         continue;
929                 }
930
931                 FT_UInt glyphIndex = auxInfo.glyphIndex;
932
933                 // bidi cache underdevelop
934                 _IFont::Glyph* pFontGlyphData;
935
936                 bool rtn = FindCache(glyphIndex, __fontAttrib.size, __fontAttrib.style, &pFontGlyphData);
937
938                 if (rtn)
939                 {
940                         int bufferSize = sizeof(_IFont::Glyph) + (pFontGlyphData->image.bytesPerLine * pFontGlyphData->image.height);
941
942                         _IFont::Glyph* pTempGlyphData = (_IFont::Glyph*) new (std::nothrow) char[bufferSize];
943
944                         if (pTempGlyphData)
945                         {
946                                 memcpy(pTempGlyphData, pFontGlyphData, bufferSize);
947
948                                 _Util::FixedPoint22_10 xOffset;
949                                 _Util::FixedPoint22_10 yOffset;
950                                 _Util::FixedPoint22_10 xAdvance;
951                                 _Util::FixedPoint22_10 yAdvance;
952                                 xOffset.Reset(auxInfo.xOffset.__fixedPoint << 4);
953                                 yOffset.Reset(auxInfo.yOffset.__fixedPoint << 4);
954                                 xAdvance.Reset(auxInfo.xAdvance.__fixedPoint << 4);
955                                 yAdvance.Reset(-auxInfo.yAdvance.__fixedPoint << 4);
956
957                                 pTempGlyphData->xOffset = pTempGlyphData->xOffset + xOffset;
958                                 pTempGlyphData->yOffset = pTempGlyphData->yOffset + yOffset;
959                                 pTempGlyphData->xAdvance = xAdvance;
960                                 pTempGlyphData->yAdvance = yAdvance;
961
962                                 pTempGlyphData->image.pBitmap = (unsigned char*)(pTempGlyphData + 1);
963                                 pTempGlyphData->hasOwnerShip = 1;
964
965                                 out.Add(pTempGlyphData);
966                         }
967
968                         continue;
969                 }
970
971                 if (isSynthetic)
972                 {
973                         error = FT_Load_Glyph(pFace, glyphIndex, FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP);
974                 }
975                 else
976                 {
977                         error = FT_Load_Glyph(pFace, glyphIndex, /*FT_LOAD_RENDER*/FT_LOAD_DEFAULT/* | FT_LOAD_NO_BITMAP*/);
978                 }
979
980                 if (error)
981                 {
982                         continue;
983                 }
984
985                 if (isSynthetic)
986                 {
987                         FT_Outline_Embolden(&pFace->glyph->outline, __fontAttrib.boldWeight.__fixedPoint);
988                 }
989
990                 error = FT_Render_Glyph(pFace->glyph, FT_RENDER_MODE_NORMAL);
991
992                 if (error)
993                 {
994                         continue;
995                 }
996
997                 _IFont::GlyphBitmap image;
998
999                 FT_GlyphSlot pSlot = FT_GlyphSlot(pFace->glyph);
1000
1001                 switch (pSlot->bitmap.pixel_mode)
1002                 {
1003                 case ft_pixel_mode_mono:
1004                         image.depth = 1;
1005                         break;
1006                 case ft_pixel_mode_grays:
1007                         image.depth = 8;
1008                         break;
1009                 default:
1010                         continue;
1011                 }
1012
1013                 image.width = pSlot->bitmap.width;
1014                 image.height = pSlot->bitmap.rows;
1015                 image.bytesPerLine = pSlot->bitmap.pitch;
1016                 image.pBitmap = pSlot->bitmap.buffer;
1017
1018                 pFontGlyphData = (_IFont::Glyph*) new (std::nothrow) char[sizeof(_IFont::Glyph) + (image.bytesPerLine * image.height)];
1019
1020                 if (pFontGlyphData == null)
1021                 {
1022                         continue;
1023                 }
1024
1025                 _Util::FixedPoint22_10 xOffset;
1026                 _Util::FixedPoint22_10 yOffset;
1027                 _Util::FixedPoint22_10 xAdvance;
1028                 _Util::FixedPoint22_10 yAdvance;
1029                 xOffset.Reset(auxInfo.xOffset.__fixedPoint << 4);
1030                 yOffset.Reset(auxInfo.yOffset.__fixedPoint << 4);
1031                 xAdvance.Reset(auxInfo.xAdvance.__fixedPoint << 4);
1032                 yAdvance.Reset(-auxInfo.yAdvance.__fixedPoint << 4);
1033
1034                 pFontGlyphData->id = 0;
1035                 pFontGlyphData->xOffset = xOffset + _Util::FixedPoint22_10(pSlot->bitmap_left);
1036                 pFontGlyphData->yOffset = yOffset + _Util::FixedPoint22_10(pSlot->bitmap_top);
1037                 pFontGlyphData->xAdvance = xAdvance;
1038                 pFontGlyphData->yAdvance = yAdvance;
1039                 pFontGlyphData->hasOwnerShip = 0;
1040                 pFontGlyphData->image = image;
1041
1042                 pFontGlyphData->image.pBitmap = (unsigned char*)(pFontGlyphData + 1);
1043                 memcpy(pFontGlyphData->image.pBitmap, image.pBitmap, image.bytesPerLine * image.height);
1044
1045                 out.Add(pFontGlyphData);
1046
1047                 pFontGlyphData->xOffset = _Util::FixedPoint22_10(pSlot->bitmap_left);
1048                 pFontGlyphData->yOffset = _Util::FixedPoint22_10(pSlot->bitmap_top);
1049
1050                 AddCache(glyphIndex, __fontAttrib.size, __fontAttrib.style, pFontGlyphData);
1051
1052                 pFontGlyphData->hasOwnerShip = 1;
1053         }
1054
1055         return true;
1056 }
1057
1058 void
1059 _FontFt2::__CleanUp()
1060 {
1061         if (__pFontFace != null)
1062         {
1063                 FT_Done_Face(FT_Face(__pFontFace));
1064                 __pFontFace = null;
1065         }
1066
1067         if (__pFontEngine != null)
1068         {
1069                 FT_Done_FreeType(FT_Library(__pFontEngine));
1070                 __pFontEngine = null;
1071         }
1072
1073         if ((__pFontBuffer != null) && !__isStaticBuffer)
1074         {
1075                 delete[] static_cast<byte*>(__pFontBuffer);
1076         }
1077
1078         __pFontBuffer = null;
1079         __isStaticBuffer = false;
1080 }
1081
1082 unsigned long
1083 _FontFt2::__GetGlyphIndex(unsigned long character) const
1084 {
1085         if (!__isValid)
1086         {
1087                 return 0;
1088         }
1089
1090         FT_Face pFace = FT_Face(__pFontFace);
1091
1092         if (pFace == null)
1093         {
1094                 return false;
1095         }
1096
1097         if (pFace->charmap != null)
1098         {
1099                 unsigned long glyphIndex = FT_Get_Char_Index(pFace, character);
1100
1101                 return glyphIndex;
1102         }
1103
1104         return character;
1105 }
1106
1107 bool
1108 _FontFt2::__ConvertPrivateToImage(void* pData1, _IFont::Glyph** ppFontGlyphData)
1109 {
1110         if (!__isValid)
1111         {
1112                 return false;
1113         }
1114
1115         FT_GlyphSlot pSlot = FT_GlyphSlot(pData1);
1116
1117         _IFont::GlyphBitmap image;
1118
1119         switch (pSlot->bitmap.pixel_mode)
1120         {
1121         case ft_pixel_mode_mono:
1122                 image.depth = 1;
1123                 break;
1124         case ft_pixel_mode_grays:
1125                 image.depth = 8;
1126                 break;
1127         default:
1128                 return false;
1129         }
1130
1131         image.width = pSlot->bitmap.width;
1132         image.height = pSlot->bitmap.rows;
1133         image.bytesPerLine = pSlot->bitmap.pitch;
1134         image.pBitmap = pSlot->bitmap.buffer;
1135
1136         *ppFontGlyphData = (_IFont::Glyph*) new (std::nothrow) char[sizeof(_IFont::Glyph) + (image.bytesPerLine * image.height)];
1137
1138         if (*ppFontGlyphData == null)
1139         {
1140                 return false;
1141         }
1142
1143         _Util::FixedPoint22_10 xAdvance;
1144         _Util::FixedPoint22_10 yAdvance;
1145         xAdvance.Reset(pSlot->advance.x << 4);
1146         yAdvance.Reset(-(pSlot->advance.y << 4));
1147
1148         (*ppFontGlyphData)->id = 0;
1149         (*ppFontGlyphData)->xOffset = _Util::FixedPoint22_10(pSlot->bitmap_left);
1150         (*ppFontGlyphData)->yOffset = _Util::FixedPoint22_10(pSlot->bitmap_top);
1151         (*ppFontGlyphData)->xAdvance = xAdvance;
1152         (*ppFontGlyphData)->yAdvance = yAdvance;
1153         (*ppFontGlyphData)->hasOwnerShip = 0;
1154         (*ppFontGlyphData)->image = image;
1155
1156         // shkim, set the memory address of bitmap to the allocated by ourself above
1157         //(*pFontGlyphData)->image.bitmap = (unsigned char*)((*pFontGlyphData) + 1);
1158
1159         if (image.width == 0 || image.height == 0)
1160         {
1161                 return true;
1162         }
1163
1164         //memcpy((*ppFontGlyphData)->image.bitmap, image.bitmap, image.bytesPerLine * image.height);
1165
1166         return true;
1167 }
1168
1169 bool
1170 _FontFt2::__SetTransMatrix(void* pMatrix)
1171 {
1172         if (!__isValid)
1173         {
1174                 return false;
1175         }
1176
1177         if (pMatrix == null)
1178         {
1179                 return true;
1180         }
1181
1182         FT_Matrix* pTrans = (FT_Matrix*) pMatrix;
1183
1184         double radian = _M_PI / 180.0;
1185
1186         if (_IsEqual(0.0f, __fontAttrib.angle))
1187         {
1188                 // apply font size
1189                 pTrans->xx = (FT_Fixed) (0x10000 * (__fontAttrib.xExpansion)) / 100;
1190                 pTrans->xy = (FT_Fixed) 0;
1191                 pTrans->yx = (FT_Fixed) 0;
1192                 pTrans->yy = (FT_Fixed) 0x10000;
1193
1194                 // apply italic style
1195                 if (__fontAttrib.style & _IFont::STYLE_ITALIC)
1196                 {
1197                         pTrans->xy = (FT_Fixed) (sin(_ITALIC_ANGLE * radian) * 0x10000);
1198                 }
1199                 else if (__fontAttrib.style & _IFont::STYLE_BACKSLANT)
1200                 {
1201                         pTrans->xy = (FT_Fixed) (sin(-_ITALIC_ANGLE * radian) * 0x10000);
1202                 }
1203         }
1204         else
1205         {
1206                 double radAngle = __fontAttrib.angle * radian;
1207
1208                 pTrans->xx = (FT_Fixed) (cos(radAngle) * (__fontAttrib.xExpansion) * 0x10000) / 100;
1209                 pTrans->xy = (FT_Fixed) (-sin(radAngle) * 0x10000);
1210                 pTrans->yx = (FT_Fixed) (sin(radAngle) * (__fontAttrib.xExpansion) * 0x10000) / 100;
1211                 pTrans->yy = (FT_Fixed) (cos(radAngle) * 0x10000);
1212
1213                 // apply italic style
1214                 if (__fontAttrib.style & _IFont::STYLE_ITALIC)
1215                 {
1216                         pTrans->xy = (FT_Fixed) ((cos(radAngle) * tan(_ITALIC_ANGLE * radian) - sin(radAngle)) * 0x10000);
1217                         pTrans->yy = (FT_Fixed) ((sin(radAngle) * tan(_ITALIC_ANGLE * radian) + cos(radAngle)) * 0x10000);
1218                 }
1219                 else if (__fontAttrib.style & _IFont::STYLE_BACKSLANT)
1220                 {
1221                         pTrans->xy = (FT_Fixed) ((cos(radAngle) * tan(-_ITALIC_ANGLE * radian) - sin(radAngle)) * 0x10000);
1222                         pTrans->yy = (FT_Fixed) ((sin(radAngle) * tan(-_ITALIC_ANGLE * radian) + cos(radAngle)) * 0x10000);
1223                 }
1224         }
1225
1226         return true;
1227 }
1228
1229 }} // Tizen::Graphics