Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / FGrp_FontRsrcManager.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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_FontRsrcManager.cpp
20  * @brief       This is the cpp file for _FontRsrcManager class.
21  *
22  */
23
24 #include <new>
25 #include <memory>
26
27 #include <unique_ptr.h>
28 #include <pthread.h>
29
30 #include <fontconfig/fontconfig.h>
31
32 #include <FAppApp.h>
33 #include <FBaseColIHashCodeProviderT.h>
34 #include <FBaseUtilStringUtil.h>
35 #include <FIoFile.h>
36 #include <FGrpFontCommon.h>
37 #include <FIoDirectory.h>
38 #include <FBaseUtilStringTokenizer.h>
39
40 #include <FBaseSysLog.h>
41
42 #include "FGrp_Font.h"
43 #include "FGrp_FontRsrcManager.h"
44 #include "FGrp_FontMemoryManager.h"
45 #include "FGrp_FontFt2.h"
46
47 #define USE_REMOVE_ALL_CACHE
48 #define USE_MMAP
49
50 #include "util/FGrp_UtilTemplate.h"
51
52
53 #define IF_NOT_INITIALIZED(code) if (_pImpl == null) \
54         { \
55                 code; \
56         }
57
58 using namespace Tizen::App;
59 using namespace Tizen::Io;
60 using namespace Tizen::Base;
61 using namespace Tizen::Base::Collection;
62 using namespace Tizen::Base::Utility;
63 using namespace Tizen::Graphics;
64 using namespace Tizen::System;
65
66
67 namespace // unnamed
68 {
69
70 const int _DEFAULT_FONT_ENGINE = 0;
71 const int _DEFAULT_FONT_FACE = 0;
72 const char* _DEFAULT_SYSTEM_FONT = "DefaultSystemFont";
73 const char* _DEFAULT_SYSTEM_BOLD_FONT = "DefaultSystemBoldFont";
74 const int _SYSTEM_DEFAULT_FONT_SIZE = 16 * 64;
75
76 class _FontNull
77         : public Tizen::Graphics::_IFont
78 {
79 public:
80         virtual bool SetAttrib(const Attrib& fontAttrib)
81         {
82                 return false;
83         }
84
85         virtual bool GetAttrib(Attrib& fontAttrib) const
86         {
87                 return false;
88         }
89
90         virtual bool GetKerning(unsigned long character1, unsigned long character2, long& xVector, long& yVector) const
91         {
92                 return false;
93         }
94
95         virtual bool LoadGlyph(unsigned long character, Glyph** pFontGlyphData)
96         {
97                 return false;
98         }
99
100         virtual bool UnloadGlyph(Glyph** pFontGlyphData)
101         {
102                 return false;
103         }
104
105         virtual unsigned long CheckGlyph(unsigned long character)
106         {
107                 return 0;
108         }
109
110         virtual bool GetGlyphList(const _Util::String& text, Tizen::Base::Collection::IListT<_IFont::Glyph *>& out, bool isRtl, int script) const
111         {
112                 return false;
113         }
114
115         virtual bool GetFontProperty(Property& property) const
116         {
117                 return false;
118         }
119
120         virtual Tizen::Base::Collection::HashMapT<Tizen::Base::String, SharedFontResource>* GetFallbackMap(void)
121         {
122                 return null;
123         }
124
125 protected:
126         virtual bool Create(const void* pBuffer, long bufSize, long face = 0)
127         {
128                 return false;
129         }
130
131         virtual bool Create(const char* pFilePath, long face = 0)
132         {
133                 return false;
134         }
135
136         virtual bool CreateStatic(const void* pBuffer, long bufSize, long face = 0)
137         {
138                 return false;
139         }
140
141         virtual bool Reload(const void* pBuffer, long bufSize, long face = 0)
142         {
143                 return false;
144         }
145
146         virtual bool Reload(const char* filePath, long face = 0)
147         {
148                 return false;
149         }
150
151         virtual void Destroy(void) {}
152
153         virtual bool FindCache(unsigned long character, int size, int style, Glyph** pOut)
154         {
155                 return false;
156         }
157
158         virtual bool AddCache(unsigned long character, int size, int style, Glyph* pGlyph)
159         {
160                 return false;
161         }
162
163         virtual bool CleanCache(void)
164         {
165                 return false;
166         }
167 }; // _FontNull
168
169 template<class T>
170 class _FontHashCodeProvider
171         : public IHashCodeProviderT <T>
172 {
173 public:
174         virtual int GetHashCode(const T& obj) const
175         {
176                 return obj.GetHashCode();
177         }
178 }; // _FontHashCodeProvider
179
180 template<class T>
181 class _FontComparer
182         : public IComparerT <T>
183 {
184 public:
185         virtual result Compare(const T& obj1, const T& obj2, int& cmp) const
186         {
187                 String& objString1 = static_cast <String&>(const_cast <T&>(obj1));
188                 String& objString2 = static_cast <String&>(const_cast <T&>(obj2));
189
190                 cmp = objString1.CompareTo(objString2);
191
192                 return E_SUCCESS;
193         }
194 }; // _FontComparer
195
196 }
197
198
199 namespace Tizen { namespace Graphics
200 {
201
202 _FontRsrcManager* _FontRsrcManager::__pTheInstance = null;
203
204 _FontRsrcManager::_FontRsrcManager()
205         : __isAppFontListInitialized(false)
206 {
207         static _FontHashCodeProvider <String> fontHashCodeProvider;
208         static _FontComparer <String> fontComparer;
209
210         // are you worry about failing to construct?
211         // but, HashMapT only can give E_SUCCESS/E_INVALID_ARG/E_OUT_OF_MEMORY.
212         // it means, if you have already verified input param, don't need to concern yourself.
213         // even though you have E_OUT_OF_MEMORY, it's already out of our control,
214         // and surely the other member function can give a error message.
215         __fontRsrcMap.Construct(0, 0, fontHashCodeProvider, fontComparer);
216         __appFontMap.Construct(0, 0, fontHashCodeProvider, fontComparer);
217
218         __defaultSystemFontPath.Clear();
219         __defaultSystemBoldFontPath.Clear();
220         __pDefaultSystemFont = null;
221
222         FcInit();
223
224         const unsigned long cacheMemorySize = 1 * 1024 * 1024;
225         std::unique_ptr<_FontMemoryManager> pMemoryMgr(new (std::nothrow) _FontMemoryManager(_FontMemoryManager::TYPE_SIZE, cacheMemorySize));
226
227         if (pMemoryMgr != null && pMemoryMgr->IsValid())
228         {
229                 __pFontMemoryManager = pMemoryMgr.release();
230         }
231
232         SysAssert(__pFontMemoryManager != null);
233 }
234
235 _FontRsrcManager::~_FontRsrcManager()
236 {
237         __fontRsrcMap.RemoveAll();
238         __appFontMap.RemoveAll();
239
240         delete __pDefaultSystemFont;
241         delete __pFontMemoryManager;
242
243         FcFini();
244 }
245
246 result
247 _FontRsrcManager::GetFont(const Tizen::Base::String& fontPath, int style, int size, SharedFontResource& out)
248 {
249         SharedFontResource sharedFont;
250         _IFont* pFont = null;
251
252         bool rtn = false;
253
254         //--------------------------------------------------------------------------
255         // validation check of input param
256         //
257         // in case input fontPath is indicating folder,
258         // we should return 'E_UNSUPPORTED_FORMAT' as bads 2.0 did.
259         //--------------------------------------------------------------------------
260         {
261                 FileAttributes attr;
262                 result r = File::GetAttributes(fontPath, attr);
263                 if (IsFailed(r))
264                 {
265                         return E_FILE_NOT_FOUND;
266                 }
267                 else if (attr.IsDirectory())
268                 {
269                         return E_UNSUPPORTED_FORMAT;
270                 }
271         }
272
273         //--------------------------------------------------------------------------
274         // step 1
275         //
276         // if we already have specified resoruce,
277         // return it with increasing reference count
278         //--------------------------------------------------------------------------
279         rtn = __SearchFont(fontPath, sharedFont);
280
281         if (rtn)
282         {
283                 out = sharedFont;
284
285                 return E_SUCCESS;
286         }
287
288         //--------------------------------------------------------------------------
289         // step 2
290         //
291         // create new font
292         //--------------------------------------------------------------------------
293         {
294 #ifdef USE_MMAP
295                 ByteBuffer* pBuffer = StringUtil::StringToUtf8N(fontPath);
296                 if (pBuffer == null)
297                 {
298                         return false;
299                 }
300                 std::auto_ptr<ByteBuffer> pathString(pBuffer);
301
302                 rtn = __CreateFont(_DEFAULT_FONT_ENGINE, (char*)pathString->GetPointer(), _DEFAULT_FONT_FACE, &pFont);
303 #else
304                 int fileLength = 0;
305                 int readLength = 0;
306                 File file;
307
308                 result r = file.Construct(fontPath, L"rb");
309                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, E_SYSTEM, "Failed to open file");
310
311                 r = file.Seek(FILESEEKPOSITION_END, 0);
312                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, E_SYSTEM, "Failed to seek file");
313
314                 fileLength = file.Tell();
315                 SysTryReturnResult(NID_GRP, fileLength > 0, E_SYSTEM, "The length of the file is not positive");
316
317                 r = file.Seek(FILESEEKPOSITION_BEGIN, 0);
318                 SysTryReturnResult(NID_GRP, r == E_SUCCESS, E_SYSTEM, "Failed to seek file");
319
320                 std::unique_ptr<unsigned char[]> buffer(new (std::nothrow) unsigned char[fileLength]);
321                 SysTryReturnResult(NID_GRP, buffer, E_OUT_OF_MEMORY, "Failed to create font instance");
322
323                 readLength = file.Read(buffer.get(), fileLength);
324                 SysTryReturnResult(NID_GRP, readLength == fileLength, E_SYSTEM, "Failed to read file");
325
326                 // create font
327                 rtn = __CreateFont(_DEFAULT_FONT_ENGINE, buffer.get(), fileLength, _DEFAULT_FONT_FACE, &pFont);
328 #endif
329                 std::auto_ptr<_IFont> autoPtrFont(pFont);
330                 SysTryReturnResult(NID_GRP, rtn && autoPtrFont.get() != null, E_UNSUPPORTED_FORMAT, "Failed to create _IFont instance");
331
332                 // make shared resource
333                 sharedFont.reset(autoPtrFont.release());
334
335                 _IFont::Attrib fontAttrib;
336                 rtn = pFont->GetAttrib(fontAttrib);
337                 SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to get font attribute");
338
339                 fontAttrib.size = size;
340                 fontAttrib.style = 0;
341                 fontAttrib.style |= (style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
342                 fontAttrib.style |= (style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
343
344                 rtn = pFont->SetAttrib(fontAttrib);
345                 SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to set font attribute");
346         }
347
348         //--------------------------------------------------------------------------
349         // step 3
350         //
351         // add newly created font resource to rsrc manager
352         //--------------------------------------------------------------------------
353         rtn = __AddFont(fontPath, sharedFont);
354         SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to add font resource into the shared container.");
355
356         // set
357         out = sharedFont;
358
359         //--------------------------------------------------------------------------
360         // step 4
361         //
362         // remove unused font
363         //--------------------------------------------------------------------------
364         __RemoveUnusedFont();
365
366         return E_SUCCESS;
367 }
368
369 result
370 _FontRsrcManager::GetTempFont(const Tizen::Base::String& fontPath, int style, int size, SharedFontResource& out)
371 {
372         SharedFontResource sharedFont;
373         _IFont* pFont = null;
374         //_FontCache* pFontCache = null;
375         bool rtn = false;
376         //unsigned char* pBuffer = null;
377
378         //--------------------------------------------------------------------------
379         // validation check of input param
380         //
381         // in case input fontPath is indicating folder,
382         // we should return 'E_UNSUPPORTED_FORMAT' as bads 2.0 did.
383         //--------------------------------------------------------------------------
384         {
385                 FileAttributes attr;
386                 result r = File::GetAttributes(fontPath, attr);
387                 if (IsFailed(r))
388                 {
389                         return E_FILE_NOT_FOUND;
390                 }
391                 else if (attr.IsDirectory())
392                 {
393                         return E_UNSUPPORTED_FORMAT;
394                 }
395         }
396
397         //--------------------------------------------------------------------------
398         // step 1
399         //
400         // if we already have specified resoruce,
401         // return it with increasing reference count
402         //--------------------------------------------------------------------------
403         rtn = __SearchFont(fontPath, sharedFont);
404
405         if (rtn)
406         {
407                 out = sharedFont;
408
409                 return E_SUCCESS;
410         }
411
412         //--------------------------------------------------------------------------
413         // step 2
414         //
415         // create new font
416         //--------------------------------------------------------------------------
417         {
418                 ByteBuffer* pBuffer = StringUtil::StringToUtf8N(fontPath);
419                 if (pBuffer == null)
420                 {
421                         return false;
422                 }
423                 std::auto_ptr<ByteBuffer> pathString(pBuffer);
424
425                 rtn = __CreateFont(_DEFAULT_FONT_ENGINE, (char*)pathString->GetPointer(), _DEFAULT_FONT_FACE, &pFont);
426
427                 std::auto_ptr<_IFont> autoPtrFont(pFont);
428                 SysTryReturnResult(NID_GRP, rtn && autoPtrFont.get() != null, E_UNSUPPORTED_FORMAT, "Failed to create _IFont instance");
429
430                 // make shared resource
431                 sharedFont.reset(autoPtrFont.release());
432
433                 _IFont::Attrib fontAttrib;
434                 rtn = pFont->GetAttrib(fontAttrib);
435                 SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to get font attribute");
436
437                 fontAttrib.size = size;
438                 fontAttrib.style = 0;
439                 fontAttrib.style |= (style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
440                 fontAttrib.style |= (style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
441
442                 rtn = pFont->SetAttrib(fontAttrib);
443                 SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to set font attribute");
444         }
445
446         // set
447         out = sharedFont;
448
449         return E_SUCCESS;
450 }
451
452 result
453 _FontRsrcManager::AddFont(const Tizen::Base::String& fontPath, SharedFontResource& out)
454 {
455         bool rtn = false;
456
457         rtn = __AddFont(fontPath, out);
458         SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to add font resource into the shared container.");
459
460         return E_SUCCESS;
461 }
462
463
464 bool
465 _FontRsrcManager::SearchFont(const Tizen::Base::String& fontName)
466 {
467         SharedFontResource sharedFont;
468
469         return (__SearchFont(fontName, sharedFont) == true);
470 }
471
472 result
473 _FontRsrcManager::GetFont(const byte* pFontData, int fontDataSize, int style, int size, SharedFontResource& out)
474 {
475         const char* pUserMemoryFont = "UserMemoryFont";
476         SharedFontResource sharedFont;
477         _IFont* pFont = null;
478
479         //--------------------------------------------------------------------------
480         // step 1
481         //
482         // create new font with user resource.
483         //--------------------------------------------------------------------------
484         bool rtn = __CreateFont(_DEFAULT_FONT_ENGINE, pFontData, fontDataSize, _DEFAULT_FONT_FACE, &pFont);
485         std::auto_ptr<_IFont> autoPtrFont(pFont);
486         SysTryReturnResult(NID_GRP, rtn && autoPtrFont.get() != null, E_UNSUPPORTED_FORMAT, "Failed to create _IFont");
487
488         // make shared resource
489         sharedFont.reset(autoPtrFont.release());
490
491         _IFont::Attrib fontAttrib;
492         rtn = pFont->GetAttrib(fontAttrib);
493         SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to get font attribute");
494
495         fontAttrib.size = size;
496         fontAttrib.style = 0;
497         fontAttrib.style |= (style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
498         fontAttrib.style |= (style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
499
500         rtn = pFont->SetAttrib(fontAttrib);
501         SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to set font attribute");
502
503         //--------------------------------------------------------------------------
504         // step 2
505         //
506         // add newly created font resource to rsrc manager
507         //--------------------------------------------------------------------------
508         static long long idx = 0;
509         String fontName(pUserMemoryFont);
510         fontName.Append(idx++);
511         rtn = __AddFont(fontName, sharedFont);
512         SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to add font resrouce into the shared container.");
513
514         // set
515         out = sharedFont;
516
517         //--------------------------------------------------------------------------
518         // step 3
519         //
520         // remove unused font
521         //--------------------------------------------------------------------------
522         __RemoveUnusedFont();
523
524         return E_SUCCESS;
525 }
526
527 result
528 _FontRsrcManager::GetFont(int style, int size, SharedFontResource& out)
529 {
530         SharedFontResource sharedFont;
531         bool isBold = (style & FONT_STYLE_BOLD) ? true : false;
532
533         String systemFontName = isBold ? _DEFAULT_SYSTEM_BOLD_FONT : _DEFAULT_SYSTEM_FONT;
534
535         _IFont* pFont = null;
536         bool rtn = false;
537
538         //--------------------------------------------------------------------------
539         // step 1
540         //
541         // if we already have specified resoruce,
542         // return it with increasing reference count
543         //--------------------------------------------------------------------------
544         rtn = __SearchFont(systemFontName, sharedFont);
545
546         if (rtn)
547         {
548                 out = sharedFont;
549
550                 return E_SUCCESS;
551         }
552
553         //--------------------------------------------------------------------------
554         // step 2
555         //
556         // create new font with default font resource.
557         //--------------------------------------------------------------------------
558
559         isBold ? __defaultSystemBoldFontPath.Clear() : __defaultSystemFontPath.Clear();
560
561         const String& defaultSystemFontPath = __GetDefaultSystemFontPath(isBold);
562         SysTryReturnResult(NID_GRP, defaultSystemFontPath.IsEmpty() == false, E_SYSTEM, "Failed to get default system font path");
563
564         {
565 #ifdef USE_MMAP
566                 ByteBuffer* pBuffer = StringUtil::StringToUtf8N(defaultSystemFontPath);
567                 if (pBuffer == null)
568                 {
569                         return false;
570                 }
571                 std::auto_ptr<ByteBuffer> pathString(pBuffer);
572
573                 rtn = __CreateFont(_DEFAULT_FONT_ENGINE, (char*)pathString->GetPointer(), _DEFAULT_FONT_FACE, &pFont);
574 #else
575                 int fileLength = 0;
576                 File file;
577
578                 result r = file.Construct(defaultSystemFontPath, L"rb");
579                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to open file", GetErrorMessage(r));
580
581                 r = file.Seek(FILESEEKPOSITION_END, 0);
582                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to seek file", GetErrorMessage(r));
583
584                 fileLength = file.Tell();
585                 SysTryReturn(NID_GRP, fileLength > 0, r, r, "[%s] The length of the file is not positive", GetErrorMessage(r));
586
587                 r = file.Seek(FILESEEKPOSITION_BEGIN, 0);
588                 SysTryReturn(NID_GRP, r == E_SUCCESS, r, r, "[%s] Failed to seek file", GetErrorMessage(r));
589
590                 std::unique_ptr<unsigned char[]> autoPtrBuffer(new (std::nothrow) unsigned char[fileLength]);
591                 SysTryReturn(NID_GRP, autoPtrBuffer, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to create buffer of the file length");
592
593                 file.Read(autoPtrBuffer.get(), fileLength);
594
595                 rtn = __CreateFont(_DEFAULT_FONT_ENGINE, autoPtrBuffer.get(), fileLength, _DEFAULT_FONT_FACE, &pFont);
596 #endif
597                 std::auto_ptr<_IFont> autoPtrFont(pFont);
598                 SysTryReturnResult(NID_GRP, rtn && autoPtrFont.get() != null, E_UNSUPPORTED_FORMAT, "Failed to create _IFont instance");
599
600                 // make shared resource
601                 sharedFont.reset(autoPtrFont.release());
602
603                 _IFont::Attrib fontAttrib;
604                 rtn = pFont->GetAttrib(fontAttrib);
605                 SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to get font attribute");
606
607                 fontAttrib.size = size;
608                 fontAttrib.style = 0;
609                 fontAttrib.style |= (style & FONT_STYLE_BOLD) ? _IFont::STYLE_BOLD : 0;
610                 fontAttrib.style |= (style & FONT_STYLE_ITALIC) ? _IFont::STYLE_ITALIC : 0;
611
612                 rtn = pFont->SetAttrib(fontAttrib);
613                 SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to set font attribute");
614         }
615
616         //--------------------------------------------------------------------------
617         // step 3
618         //
619         // add newly created font resource to rsrc manager
620         //--------------------------------------------------------------------------
621         rtn = __AddFont(systemFontName, sharedFont);
622         SysTryReturnResult(NID_GRP, rtn, E_SYSTEM, "Failed to add font resource into the shared container");
623
624         // set
625         out = sharedFont;
626
627         //--------------------------------------------------------------------------
628         // step 4
629         //
630         // remove unused font
631         //--------------------------------------------------------------------------
632         __RemoveUnusedFont();
633
634         return E_SUCCESS;
635 }
636
637 result
638 _FontRsrcManager::GetSystemFont(const Tizen::Base::String& fontName, int style, int size, SharedFontResource& out)
639 {
640         FcPattern *pFontPattern = null;
641         FcFontSet *pFontSet = null;
642         FcResult res = FcResultNoMatch;
643         FcChar8* pPath = null;
644         const char* fcStyle = (style & FONT_STYLE_BOLD) ? "Bold" : "Regular";
645         result r = E_SYSTEM;
646
647         ByteBuffer* pBuffer = StringUtil::StringToUtf8N(fontName);
648         if (pBuffer == null)
649         {
650                 return E_SYSTEM;
651         }
652         std::auto_ptr<ByteBuffer> utfString(pBuffer);
653
654         FcBool rtn = FcInitReinitialize();
655         SysTryCatch(NID_GRP, rtn != FcFalse, , r, "[E_SYSTEM] Failed to init fontconfig");
656
657         pFontPattern = FcPatternBuild(NULL, FC_STYLE, FcTypeString, (FcChar8*)fcStyle, NULL);
658         SysTryCatch(NID_GRP, pFontPattern, , r, "[E_SYSTEM] Failed to FcPatternBuild()");
659
660         FcPatternAddString(pFontPattern, FC_FAMILY, (FcChar8*)utfString->GetPointer());
661         FcConfigSubstitute(NULL, pFontPattern, FcMatchPattern);
662         FcDefaultSubstitute(pFontPattern);
663
664         pFontSet = FcFontSort(NULL, pFontPattern, FcTrue, NULL, &res);
665         SysTryCatch(NID_GRP, pFontSet, , r, "[E_SYSTEM] Failed to FcFontSort()");
666
667         res = FcPatternGetString(pFontSet->fonts[0], FC_FILE, 0, &pPath);
668         SysTryCatch(NID_GRP, res == FcResultMatch, , r, "[E_SYSTEM] Failed to get path of system font");
669
670         r = this->GetFont(String((char*)pPath), style, size, out);
671         SysTryCatch(NID_GRP, r == E_SUCCESS, , r, "[%s] Failed to get font", GetErrorMessage(r));
672
673         // destroy
674         FcPatternDestroy(pFontPattern);
675         FcFontSetDestroy(pFontSet);
676         //FcFini();
677
678         return E_SUCCESS;
679
680 CATCH:
681         if (pFontSet)
682         {
683                 FcFontSetDestroy(pFontSet);
684         }
685
686         if (pFontPattern)
687         {
688                 FcPatternDestroy(pFontPattern);
689         }
690
691         //FcFini();
692
693         return r;
694 }
695
696 void
697 _FontRsrcManager::__InitFontRsrcManager(void)
698 {
699         static _FontRsrcManager instance;
700         __pTheInstance = &instance;
701 }
702
703 _FontRsrcManager&
704 _FontRsrcManager::GetInstance(void)
705 {
706         static pthread_once_t once_block = PTHREAD_ONCE_INIT;
707
708         if (!__pTheInstance)
709         {
710                 pthread_once(&once_block, __InitFontRsrcManager);
711         }
712
713         return (*__pTheInstance);
714 }
715
716 bool
717 _FontRsrcManager::__CreateFont(int fontEngine, const void* pBuffer, long bufSize, long face, _IFont** ppOut)
718 {
719         // check input param
720         SysTryReturn(NID_GRP, ppOut, false, E_INVALID_ARG, "[E_INVALID_ARG] Invalid out param is given");
721
722         std::auto_ptr<_IFont> autoPtrFont;
723
724         switch (fontEngine)
725         {
726         case 0:
727                 autoPtrFont.reset(new (std::nothrow) _FontFt2);
728                 break;
729
730         default:
731                 autoPtrFont.reset(new (std::nothrow) _FontNull);
732                 break;
733         }
734
735         SysTryReturn(NID_GRP, autoPtrFont.get() != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory");
736
737         bool rtn = autoPtrFont->Create(pBuffer, bufSize, face);
738         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to create font resource");
739
740         // set out param
741         *ppOut = autoPtrFont.release();
742
743         return true;
744 }
745
746 bool
747 _FontRsrcManager::__CreateFont(int fontEngine, const char* filePath, const long face, _IFont** ppOut)
748 {
749         // check input param
750         SysTryReturn(NID_GRP, ppOut, false, E_INVALID_ARG, "[E_INVALID_ARG] Invalid out param is given");
751
752         std::auto_ptr<_IFont> autoPtrFont;
753
754         switch (fontEngine)
755         {
756         case 0:
757                 autoPtrFont.reset(new (std::nothrow) _FontFt2);
758                 break;
759
760         default:
761                 autoPtrFont.reset(new (std::nothrow) _FontNull);
762                 break;
763         }
764
765         SysTryReturn(NID_GRP, autoPtrFont.get() != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory");
766
767         bool rtn = autoPtrFont->Create(filePath, face);
768         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to create font resource");
769
770         // set out param
771         *ppOut = autoPtrFont.release();
772
773         return true;
774 }
775
776 bool
777 _FontRsrcManager::__CreateStaticFont(int fontEngine, const void* pBuffer, long bufSize, long face, _IFont** ppOut)
778 {
779         // check input param
780         SysTryReturn(NID_GRP, ppOut, false, E_INVALID_ARG, "[E_INVALID_ARG] Invalid out param is given");
781
782         std::auto_ptr<_IFont> autoPtrFont;
783
784         switch (fontEngine)
785         {
786         case 0:
787                 autoPtrFont.reset(new (std::nothrow) _FontFt2);
788                 break;
789
790         default:
791                 autoPtrFont.reset(new (std::nothrow) _FontNull);
792                 break;
793         }
794
795         SysTryReturn(NID_GRP, autoPtrFont.get() != null, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to allocate memory");
796
797         bool rtn = autoPtrFont->CreateStatic(pBuffer, bufSize, face);
798         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to create font resource");
799
800         // set out param
801         *ppOut = autoPtrFont.release();
802
803         return true;
804 }
805
806 bool
807 _FontRsrcManager::__SearchFont(const String& fontPath, SharedFontResource& out) const
808 {
809         // check input param
810         SysTryReturn(NID_GRP, out.get() == null, false, E_INVALID_ARG, "[E_INVALID_ARG] Invalid out param is given");
811
812         return (__fontRsrcMap.GetValue(const_cast <String&>(fontPath), out) == E_SUCCESS);
813 }
814
815 bool
816 _FontRsrcManager::__AddFont(const String& key, const SharedFontResource& font)
817 {
818         // check input param
819         SysTryReturn(NID_GRP, font.get() != null, false, E_INVALID_ARG, "[E_INVALID_ARG] Invalid input param is given");
820
821         result r = __fontRsrcMap.Add(key, font);
822         SysTryReturn(NID_GRP, r == E_SUCCESS, false, false, "[%s] Failed to add font into resource pool", GetErrorMessage(r));
823
824         return true;
825 }
826
827 void
828 _FontRsrcManager::__RemoveUnusedFont(void)
829 {
830         ArrayListT<String> keys;
831         String systemFontName(_DEFAULT_SYSTEM_FONT);
832         String systemBoldFontName(_DEFAULT_SYSTEM_BOLD_FONT);
833
834         // find out unused font
835         {
836                 std::auto_ptr<IMapEnumeratorT<String, SharedFontResource> > enumerator(__fontRsrcMap.GetMapEnumeratorN());
837                 result r = GetLastResult();
838                 SysTryReturnVoidResult(NID_GRP, enumerator.get() != null, r, "[%s] Propagating.", GetErrorMessage(r));
839
840                 while (enumerator->MoveNext() == E_SUCCESS)
841                 {
842                         SharedFontResource font;
843                         r = enumerator->GetValue(font);
844
845                         if (r == E_SUCCESS && font.use_count() == 2)
846                         {
847                                 String key;
848                                 r = enumerator->GetKey(key);
849
850                                 if (r == E_SUCCESS && (key != systemFontName && key != systemBoldFontName))
851                                 {
852                                         keys.Add(key);
853                                 }
854                         }
855                 }
856         }
857
858         // remove
859         if (keys.GetCount() > 0)
860         {
861                 std::auto_ptr<IEnumeratorT<String> > enumerator(keys.GetEnumeratorN());
862                 result r = GetLastResult();
863                 SysTryReturnVoidResult(NID_GRP, enumerator.get() != null, r, "[%s] Propagating.", GetErrorMessage(r));
864
865                 while (enumerator->MoveNext() == E_SUCCESS)
866                 {
867                         String key;
868                         r = enumerator->GetCurrent(key);
869
870                         if (r == E_SUCCESS)
871                         {
872                                 __fontRsrcMap.Remove(key);
873                         }
874                 }
875         }
876
877         return;
878 }
879
880 bool
881 _FontRsrcManager::__ReloadFont(String fontName, bool isBold)
882 {
883         SharedFontResource sharedFont;
884         String systemFontName(fontName);
885
886         _IFont* pFont = null;
887         bool rtn = false;
888
889         // Check if there is default system font in font resource manager
890         // If there isn't default system font, we can't reload font resource
891         rtn = __SearchFont(systemFontName, sharedFont);
892         SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to search default system font");
893
894         // Get default system font interface instance
895         pFont = sharedFont.get();
896
897         // Reload system font resource in font interface
898         {
899 #ifdef USE_MMAP
900                 isBold ? __defaultSystemBoldFontPath.Clear() : __defaultSystemFontPath.Clear();
901                 const String& fontPath = __GetDefaultSystemFontPath(isBold);
902
903                 ByteBuffer* pBuffer = StringUtil::StringToUtf8N(fontPath);
904                 if (pBuffer == null)
905                 {
906                         return false;
907                 }
908                 std::auto_ptr<ByteBuffer> pathString(pBuffer);
909
910                 rtn = pFont->Reload((char*)pathString->GetPointer(), _DEFAULT_FONT_FACE);
911                 SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to reload font");
912 #else
913                 int fileLength = 0;
914                 File file;
915
916                 isBold ? __defaultSystemBoldFontPath.Clear() : __defaultSystemFontPath.Clear();
917
918                 result r = file.Construct(__GetDefaultSystemFontPath(isBold), L"rb");
919                 SysTryReturn(NID_GRP, r == E_SUCCESS, false, r, "[%s] Failed to open file", GetErrorMessage(r));
920
921                 r = file.Seek(FILESEEKPOSITION_END, 0);
922                 SysTryReturn(NID_GRP, r == E_SUCCESS, false, r, "[%s] Failed to seek file", GetErrorMessage(r));
923
924                 fileLength = file.Tell();
925                 SysTryReturn(NID_GRP, fileLength > 0, false, r, "[%s] The length of the file is not positive", GetErrorMessage(r));
926
927                 r = file.Seek(FILESEEKPOSITION_BEGIN, 0);
928                 SysTryReturn(NID_GRP, r == E_SUCCESS, false, r, "[%s] Failed to seek file", GetErrorMessage(r));
929
930                 std::unique_ptr<unsigned char[]> autoPtrBuffer(new (std::nothrow) unsigned char[fileLength]);
931                 SysTryReturn(NID_GRP, autoPtrBuffer, false, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Failed to create buffer of the file length");
932
933                 file.Read(autoPtrBuffer.get(), fileLength);
934                 rtn = pFont->Reload(autoPtrBuffer.get(), fileLength, _DEFAULT_FONT_FACE);
935                 SysTryReturn(NID_GRP, rtn, false, E_SYSTEM, "[E_SYSTEM] Failed to reload font");
936 #endif
937
938                 pFont->CleanCache();
939         }
940
941         return true;
942 }
943
944 bool
945 _FontRsrcManager::ReloadDefaultSystemFont(void)
946 {
947         String systemFontName;
948
949         systemFontName = _DEFAULT_SYSTEM_FONT;
950         __ReloadFont(systemFontName, false);
951
952         systemFontName = _DEFAULT_SYSTEM_BOLD_FONT;
953         __ReloadFont(systemFontName, true);
954
955         return true;
956 }
957
958 _FontMemoryManager&
959 _FontRsrcManager::GetMemoryManager(void)
960 {
961         return *__pFontMemoryManager;
962 }
963
964
965 _Font&
966 _FontRsrcManager::GetDefaultSystemFont(void)
967 {
968         if (__pDefaultSystemFont == null)
969         {
970                 std::auto_ptr<_Font> font(new (std::nothrow) _Font);
971
972                 if (font.get())
973                 {
974                         result r = font->Construct(FONT_STYLE_PLAIN, _SYSTEM_DEFAULT_FONT_SIZE);
975
976                         if (r == E_SUCCESS)
977                         {
978                                 __pDefaultSystemFont = font.release();
979                         }
980                 }
981         }
982
983         SysAssert(__pDefaultSystemFont != null);
984
985         return *__pDefaultSystemFont;
986 }
987
988
989 long
990 _FontRsrcManager::__GetMaxFontEngine(void) const
991 {
992         return 1;
993 }
994
995 String
996 _FontRsrcManager::__GetFontPath(bool isBold)
997 {
998         String fontPath(L"");
999
1000         FcFontSet* pFontSet = null;
1001         FcPattern* pFontPattern = null;
1002         const char* fcStyle = isBold ? "Bold" : "Regular";
1003         // initialize fontconfig library
1004         FcBool rtn = FcInitReinitialize();
1005         SysTryCatch(NID_GRP, rtn != FcFalse, , E_SYSTEM, "[E_SYSTEM] Failed to init fontconfig");
1006
1007         // create pattern
1008         pFontPattern = FcPatternCreate();
1009         SysTryCatch(NID_GRP, pFontPattern, , E_SYSTEM, "[E_SYSTEM] Failed to create font pattern");
1010
1011         FcPatternAddString(pFontPattern, FC_FAMILY, (FcChar8*)"Tizen");
1012         FcPatternAddString(pFontPattern, FC_STYLE, (FcChar8*)fcStyle);
1013         FcConfigSubstitute(0, pFontPattern, FcMatchPattern);
1014         FcDefaultSubstitute(pFontPattern);
1015
1016         // create fontset
1017         pFontSet = FcFontSetCreate();
1018         SysTryCatch(NID_GRP, pFontSet, , E_SYSTEM, "[E_SYSTEM] Failed to create fontset");
1019
1020         {
1021                 FcPattern* pMatchedPattern = null;
1022                 FcResult result = FcResultNoMatch;
1023                 pMatchedPattern = FcFontMatch(NULL, pFontPattern, &result);
1024
1025                 if (/*result == FcResultMatch && */pMatchedPattern)
1026                 {
1027                         FcFontSetAdd(pFontSet, pMatchedPattern);
1028                 }
1029
1030                 // check if we have a system font info
1031                 SysTryCatch(NID_GRP, pFontSet->nfont >= 1, , E_SYSTEM, "[E_SYSTEM] Default system count is %d", pFontSet->nfont);
1032
1033                 FcChar8* pPath = null;
1034                 result = FcPatternGetString(pFontSet->fonts[0], FC_FILE, 0, &pPath);
1035                 SysTryCatch(NID_GRP, result == FcResultMatch, , E_SYSTEM, "[E_SYSTEM] Failed to create fontset");
1036                 fontPath.Clear();
1037                 fontPath.Append(String((char*)pPath));
1038         }
1039
1040         // destroy
1041         FcPatternDestroy(pFontPattern);
1042         FcFontSetDestroy(pFontSet);
1043         //FcFini();
1044
1045         return fontPath;
1046
1047 CATCH:
1048         if (pFontSet != null)
1049         {
1050                 FcFontSetDestroy(pFontSet);
1051         }
1052
1053         if (pFontPattern != null)
1054         {
1055                 FcPatternDestroy(pFontPattern);
1056         }
1057
1058         return fontPath;
1059 }
1060
1061 const String&
1062 _FontRsrcManager::__GetDefaultSystemFontPath(bool isBold)
1063 {
1064         String& defaultPath = (isBold) ? __defaultSystemBoldFontPath : __defaultSystemFontPath;
1065
1066         if (!defaultPath.IsEmpty())
1067         {
1068                 return defaultPath;
1069         }
1070         else
1071         {
1072                 String path = __GetFontPath(isBold);
1073
1074                 if (isBold)
1075                 {
1076                         if (path.IsEmpty())
1077                         {
1078                                 path = __GetFontPath(false);
1079                                 // [ykahn] Is 'path' always not NULL ?
1080                         }
1081
1082                         __defaultSystemBoldFontPath.Clear();
1083                         __defaultSystemBoldFontPath.Append(path);
1084
1085                         return __defaultSystemBoldFontPath;
1086                 }
1087                 else
1088                 {
1089                         __defaultSystemFontPath.Clear();
1090                         __defaultSystemFontPath.Append(path);
1091
1092                         return __defaultSystemFontPath;
1093                 }
1094         }
1095 }
1096
1097 bool
1098 _FontRsrcManager::RemoveMemory(unsigned long requestedSize)
1099 {
1100 #ifdef USE_REMOVE_ALL_CACHE
1101         result r = E_SUCCESS;
1102         std::auto_ptr<IMapEnumeratorT<String, SharedFontResource > > enumerator(__fontRsrcMap.GetMapEnumeratorN());
1103
1104         while (enumerator->MoveNext() == E_SUCCESS)
1105         {
1106                 SharedFontResource fontRsrc;
1107                 r = enumerator->GetValue(fontRsrc);
1108
1109                 fontRsrc.get()->CleanCache();
1110         }
1111
1112         return true;
1113 #else
1114         unsigned long remainedMemory = 0;
1115         result r = E_SUCCESS;
1116         bool isComplete = false;
1117
1118         ArrayListT<String> keys;
1119         String systemFontName(_DEFAULT_SYSTEM_FONT);
1120
1121         std::auto_ptr<IMapEnumeratorT<String, SharedFontResource > > enumerator(__fontRsrcMap.GetMapEnumeratorN());
1122
1123         while (enumerator->MoveNext() == E_SUCCESS)
1124         {
1125                 if (isComplete)
1126                 {
1127                         break;
1128                 }
1129
1130                 String key;
1131                 r = enumerator->GetKey(key);
1132                 if (r == E_SUCCESS/* && key != systemFontName*/)
1133                 {
1134                         SharedFontResource fontRsrc;
1135                         r = enumerator->GetValue(fontRsrc);
1136
1137                         while (!fontRsrc.get()->second->IsEmpty())
1138                         {
1139                                 fontRsrc.get()->second->RemoveFirst();
1140
1141                                 remainedMemory = __pFontMemoryManager->GetRemainedMemory();
1142
1143                                 if (remainedMemory > requestedSize)
1144                                 {
1145                                                 isComplete = true;
1146                                                 break;
1147                                 }
1148                         }
1149                 }
1150         }
1151
1152         return isComplete;
1153 #endif
1154 }
1155
1156 Tizen::Base::String
1157 _FontRsrcManager::FindAppFontName(const Tizen::Base::String& fontName)
1158 {
1159         Tizen::Base::String fontPath = L"";
1160
1161         if (__isAppFontListInitialized)
1162         {
1163                 __appFontMap.GetValue(const_cast <String&>(fontName), fontPath);
1164                 return fontPath;
1165         }
1166         else
1167         {
1168                 String dirName;
1169                 Directory dir;
1170                 DirEnumerator* pDirEnum;
1171
1172                 //dirName = L"/usr/share/app_font";
1173                 dirName = Tizen::App::App::GetInstance()->GetAppResourcePath() + L"font";
1174
1175                 // Open the directory
1176                 if (IsFailed(dir.Construct(dirName)))
1177                 {
1178                         return fontPath;
1179                 }
1180
1181                 // Reads all the directory entries
1182                 pDirEnum = dir.ReadN();
1183                 if (!pDirEnum)
1184                 {
1185                         return fontPath;
1186                 }
1187
1188                 // Loops through all the directory entries
1189                 while (pDirEnum->MoveNext() == E_SUCCESS)
1190                 {
1191                         SharedFontResource sharedFont;
1192                         String faceName;
1193                         String name;
1194                         String token;
1195                         DirEntry entry = pDirEnum->GetCurrentDirEntry();
1196                         Tizen::Base::Utility::StringTokenizer formatTok(entry.GetName(), ".");
1197                         while (formatTok.GetTokenCount())
1198                         {
1199                                 formatTok.GetNextToken(token);
1200                         }
1201                         if (entry.IsDirectory() == false)
1202                         {
1203                                 name.Append(dirName);
1204                                 name.Append(L"/");
1205                                 name.Append(entry.GetName());
1206
1207                                 faceName = _Font::GetFaceName(name);
1208
1209                                 __appFontMap.Add(faceName, name);
1210                         }
1211                 }
1212
1213                 delete pDirEnum;
1214                 pDirEnum = null;
1215
1216                 __isAppFontListInitialized = true;
1217
1218                 __appFontMap.GetValue(const_cast <String&>(fontName), fontPath);
1219                 return fontPath;
1220         }
1221 }
1222
1223 }} // Tizen::Graphics