Tizen 2.1 base
[framework/osp/uifw.git] / src / graphics / FGrp_FontCache.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_FontCache.cpp
20  * @brief       This is the cpp file for _FontCache class.
21  *
22  */
23
24 #include <new>
25 #include <list>
26
27 #include <FBaseErrors.h>
28
29 #include <FBaseSysLog.h>
30
31 #include "FGrp_FontCache.h"
32 #include "FGrp_FontRsrcManager.h"
33
34
35 #define CONVERT_INTEGER_TO_26_6_FIXED_POINT(value) (value * 64)
36 #define __pBspCache ((_BspTree<unsigned long, void*>*)__pCache)
37
38
39 namespace // unnamed
40 {
41
42 const unsigned long _CACHE_MEMORY_SIZE = 3 * 1024 * 1024;
43 const unsigned long _MAX_CACHABLE_ITEM_SIZE = _CACHE_MEMORY_SIZE / 10;
44
45 inline bool
46 _MakeId(unsigned long character, int size, int style, unsigned long& out)
47 {
48         int fixedSize = size >> 5;
49
50         if (((character >> 22) > 0) || ((fixedSize >> 8) > 0) || ((style >> 2) > 0))
51         {
52                 return false;
53         }
54
55         out = (character << 10) | ((fixedSize & 0xFF) << 2) | (style & 0x3);
56
57         return true;
58 }
59
60 template <typename Type>
61 inline unsigned long _MakeIndex(Type id, int level);
62
63 template <>
64 inline unsigned long
65 _MakeIndex<unsigned long>(unsigned long id, int level)
66 {
67         typedef unsigned long TBase;
68
69         TBase index = (id & (0x80808080 >> level)) >> ((sizeof(TBase) * 2 - 1) - level);
70
71         index |= (index >> 7);
72         index |= (index >> 14);
73         index |= (index >> 21);
74
75         return (index & 0x0000000F);
76 }
77
78 template <typename TId, typename TData>
79 class _BspTree
80 {
81         enum
82         {
83                 MAX_CHILD = 16,
84                 MAX_LEVEL = sizeof(TId) * 2
85         };
86
87 public:
88         _BspTree(int level = 0)
89                 : __level(level)
90                 , __data(null)
91         {
92                 for (int i = 0; i < MAX_CHILD; i++)
93                 {
94                         __child[i] = null;
95                 }
96         }
97
98         ~_BspTree(void)
99         {
100                 __Destroy();
101         }
102
103         bool Add(TId id, TData data)
104         {
105                 if (__IsEdge())
106                 {
107                         // shkim, TODO.
108                         // collision should not be occured.
109                         __data = data;
110                         return true;
111                 }
112
113                 unsigned long index = __GetIndex(id);
114
115                 if (__child[index] == null)
116                 {
117                         __child[index] = new (std::nothrow) _BspTree<TId, TData>(__level + 1);
118                         if (__child[index] == null)
119                         {
120                                 return false;
121                         }
122                 }
123
124                 return __child[index]->Add(id, data);
125         }
126
127         TData Find(TId id) const
128         {
129                 if (__data != null)
130                 {
131                         return __data;
132                 }
133
134                 unsigned long index = __GetIndex(id);
135
136                 if (__child[index])
137                 {
138                         return __child[index]->Find(id);
139                 }
140
141                 return 0;
142         }
143
144         TData Remove(TId id)
145         {
146                 TData found = 0;
147                 __Remove(id, found);
148                 return found;
149         }
150
151 private:
152         void __Destroy(void)
153         {
154                 for (int i = 0; i < MAX_CHILD; i++)
155                 {
156                         delete __child[i];
157                         __child[i] = null;
158                 }
159
160                 Tizen::Graphics::_FontRsrcManager::GetInstance().GetMemoryManager().Free(__data);
161
162                 __data = null;
163         }
164
165         bool __IsEdge(void) const
166         {
167                 return (__level >= MAX_LEVEL);
168         }
169
170         inline unsigned long __GetIndex(TId id) const
171         {
172                 return _MakeIndex(id, __level);
173         }
174
175         bool __Remove(TId id, TData& found)
176         {
177                 if (__data != null)
178                 {
179                         found = __data;
180                         return true;
181                 }
182
183                 unsigned long index = __GetIndex(id);
184
185                 if (__child[index])
186                 {
187                         if (__child[index]->__Remove(id, found))
188                         {
189                                 delete __child[index];
190                                 __child[index] = null;
191
192                                 unsigned long check = 0;
193
194                                 for (int i = 0; i < MAX_CHILD; i++)
195                                 {
196                                         check |= (unsigned long)__child[i];
197                                 }
198
199                                 return (check == 0);
200                         }
201                 }
202
203                 return false;
204         }
205
206         int __level;
207         TData __data;
208         _BspTree<TId, TData>* __child[MAX_CHILD];
209 };
210
211 }
212
213 namespace Tizen { namespace Graphics
214 {
215
216 class _FontCacheImpl
217 {
218 public:
219         _FontCacheImpl(void)
220         {
221         }
222
223         virtual ~_FontCacheImpl(void)
224         {
225         }
226
227         void Add(unsigned long id)
228         {
229                 __leastRecentlyUsedKeyList.push_back(id);
230         }
231
232         void Remove(unsigned long id)
233         {
234                 __leastRecentlyUsedKeyList.remove(id);
235         }
236
237         void RemoveFirst(void)
238         {
239                 __leastRecentlyUsedKeyList.pop_front();
240         }
241
242         void RemoveAll(void)
243         {
244                 __leastRecentlyUsedKeyList.clear();
245         }
246
247         unsigned long GetFirst(void)
248         {
249                 return __leastRecentlyUsedKeyList.front();
250         }
251
252         bool IsEmpty(void)
253         {
254                 return __leastRecentlyUsedKeyList.empty();
255         }
256
257 private:
258         //_BspTree<unsigned long, void*> bspTree;
259         std::list<unsigned long> __leastRecentlyUsedKeyList;
260 };
261
262 _FontCache::_FontCache(void)
263         : __pCache((void*) new (std::nothrow) _BspTree<unsigned long, void*>())
264 {
265         __pFontCacheImpl = new (std::nothrow) _FontCacheImpl;
266 }
267
268 _FontCache::~_FontCache(void)
269 {
270         delete reinterpret_cast<_BspTree<unsigned long, void*>*>(__pCache);
271         __pCache = null;
272
273         delete __pFontCacheImpl;
274         __pFontCacheImpl = null;
275 }
276
277 bool
278 _FontCache::IsValid(void) const
279 {
280         return (this->__pCache && this->__pFontCacheImpl);
281 }
282
283 bool
284 _FontCache::Find(unsigned long character, int size, int style, _IFont::Glyph** pOut)
285 {
286         unsigned long id = 0;
287         bool rtn = _MakeId(character, size, style, id);
288
289         if (!rtn)
290         {
291                 return false;
292         }
293
294         _IFont::Glyph* p = (_IFont::Glyph*)__pBspCache->Find(id);
295
296         if (p != null)
297         {
298                 *pOut = p;
299                 return true;
300         }
301         else
302         {
303                 return false;
304         }
305 }
306
307 bool
308 _FontCache::Add(unsigned long character, int size, int style, _IFont::Glyph* pGlyph)
309 {
310         unsigned long bufferSize = 0;
311         unsigned long id = 0;
312         bool rtn = _MakeId(character, size, style, id);
313         if (!rtn)
314         {
315                 // Requested glyph is not cachable
316                 return false;
317         }
318
319         bufferSize = sizeof(_IFont::Glyph) + (pGlyph->image.bytesPerLine * pGlyph->image.height);
320         _IFont::Glyph* pGlyphCache = (_IFont::Glyph*) _FontRsrcManager::GetInstance().GetMemoryManager().Alloc(bufferSize);
321         if (pGlyphCache == null)
322         {
323                 // secure memory
324                 bool rtn = _FontRsrcManager::GetInstance().RemoveMemory(bufferSize);
325
326                 if (!rtn)
327                 {
328                         return false;
329                 }
330
331                 pGlyphCache = (_IFont::Glyph*) _FontRsrcManager::GetInstance().GetMemoryManager().Alloc(bufferSize);
332
333                 if (pGlyphCache == null)
334                 {
335                         return false;
336                 }
337         }
338
339         memcpy(pGlyphCache, pGlyph, sizeof(_IFont::Glyph));
340         pGlyphCache->image.pBitmap = (unsigned char*)((pGlyphCache) + 1);
341         memcpy(pGlyphCache->image.pBitmap, pGlyph->image.pBitmap, pGlyph->image.bytesPerLine * pGlyph->image.height);
342
343         if (__pBspCache->Add(id, pGlyphCache))
344         {
345                 __pFontCacheImpl->Add(id);
346                 return true;
347         }
348         else
349         {
350                 return false;
351         }
352 }
353
354 void
355 _FontCache::Remove(unsigned long character, int size, int style)
356 {
357         unsigned long id = 0;
358         bool rtn = _MakeId(character, size, style, id);
359         if (!rtn)
360         {
361                 return;
362         }
363
364         __pBspCache->Remove(id);
365         __pFontCacheImpl->Remove(id);
366 }
367
368 void
369 _FontCache::RemoveFirst(void)
370 {
371         unsigned long id = 0;
372
373         id = __pFontCacheImpl->GetFirst();
374
375         __pBspCache->Remove(id);
376         __pFontCacheImpl->RemoveFirst();
377 }
378
379 bool
380 _FontCache::IsEmpty(void)
381 {
382         return __pFontCacheImpl->IsEmpty();
383 }
384
385 bool
386 _FontCache::Cleanup(void)
387 {
388         _BspTree<unsigned long, void*>* p = reinterpret_cast<_BspTree<unsigned long, void*>*>(__pCache);
389
390         p->~_BspTree();
391         new (p) _BspTree<unsigned long, void*>();
392
393         __pFontCacheImpl->RemoveAll();
394
395         return true;
396 }
397
398 bool
399 _FontCache::__DiscardVictim(unsigned long requestedSize)
400 {
401         return true;
402 }
403
404 bool
405 _FontCache::__RemoveId(unsigned long id)
406 {
407         _IFont::Glyph* pCachedGlyph = null;
408
409         pCachedGlyph = (_IFont::Glyph*)__pBspCache->Find(id);
410
411         if (pCachedGlyph != null)
412         {
413                 __pBspCache->Remove(id);
414
415                 return true;
416         }
417         else
418         {
419                 return false;
420         }
421 }
422
423 }} // Tizen::Graphics