1 /** @file lvfontglyphcache.cpp
2     @brief font glyph cache implementation
3 
4     CoolReader Engine
5 
6 
7     (c) Vadim Lopatin, 2000-2006
8     This source code is distributed under the terms of
9     GNU General Public License.
10 
11     See LICENSE file for details.
12 
13 */
14 
15 // This file contains copy of class LVFontLocalGlyphCacheA from cr3.2.31
16 
17 #include "lvfontglyphcache_a.h"
18 #include "../../include/crlocks.h"
19 
20 
clear()21 void LVFontLocalGlyphCacheA::clear() {
22     FONT_LOCAL_GLYPH_CACHE_GUARD
23     while (head) {
24         LVFontGlyphCacheItemA *ptr = head;
25         remove(ptr);
26         global_cache->remove(ptr);
27         LVFontGlyphCacheItemA::freeItem(ptr);
28     }
29 }
30 
getByChar(lChar32 ch)31 LVFontGlyphCacheItemA *LVFontLocalGlyphCacheA::getByChar(lChar32 ch) {
32     FONT_LOCAL_GLYPH_CACHE_GUARD
33     LVFontGlyphCacheItemA *ptr = head;
34     for (; ptr; ptr = ptr->next_local) {
35         if (ptr->data.ch == ch) {
36             global_cache->refresh(ptr);
37             return ptr;
38         }
39     }
40     return NULL;
41 }
42 
43 #if USE_HARFBUZZ==1
getByIndex(lUInt32 index)44 LVFontGlyphCacheItemA* LVFontLocalGlyphCacheA::getByIndex(lUInt32 index)
45 {
46     FONT_LOCAL_GLYPH_CACHE_GUARD
47     LVFontGlyphCacheItemA *ptr = head;
48     for (; ptr; ptr = ptr->next_local) {
49         if (ptr->data.gindex == index) {
50             global_cache->refresh(ptr);
51             return ptr;
52         }
53     }
54     return NULL;
55 }
56 #endif
57 
put(LVFontGlyphCacheItemA * item)58 void LVFontLocalGlyphCacheA::put(LVFontGlyphCacheItemA *item) {
59     FONT_LOCAL_GLYPH_CACHE_GUARD
60     global_cache->put(item);
61     item->next_local = head;
62     if (head)
63         head->prev_local = item;
64     if (!tail)
65         tail = item;
66     head = item;
67 }
68 
69 /// remove from list, but don't delete
remove(LVFontGlyphCacheItemA * item)70 void LVFontLocalGlyphCacheA::remove(LVFontGlyphCacheItemA *item) {
71     FONT_LOCAL_GLYPH_CACHE_GUARD
72     if (item == head)
73         head = item->next_local;
74     if (item == tail)
75         tail = item->prev_local;
76     if (!head || !tail)
77         return;
78     if (item->prev_local)
79         item->prev_local->next_local = item->next_local;
80     if (item->next_local)
81         item->next_local->prev_local = item->prev_local;
82     item->next_local = NULL;
83     item->prev_local = NULL;
84 }
85 
refresh(LVFontGlyphCacheItemA * item)86 void LVFontGlobalGlyphCacheA::refresh(LVFontGlyphCacheItemA *item) {
87     FONT_GLYPH_CACHE_GUARD
88     if (tail != item) {
89         //move to head
90         removeNoLock(item);
91         putNoLock(item);
92     }
93 }
94 
put(LVFontGlyphCacheItemA * item)95 void LVFontGlobalGlyphCacheA::put(LVFontGlyphCacheItemA *item) {
96     FONT_GLYPH_CACHE_GUARD
97     putNoLock(item);
98 }
99 
putNoLock(LVFontGlyphCacheItemA * item)100 void LVFontGlobalGlyphCacheA::putNoLock(LVFontGlyphCacheItemA *item) {
101     int sz = item->getSize();
102     // remove extra items from tail
103     while (sz + size > max_size) {
104         LVFontGlyphCacheItemA *removed_item = tail;
105         if (!removed_item)
106             break;
107         removeNoLock(removed_item);
108         removed_item->local_cache->remove(removed_item);
109         LVFontGlyphCacheItemA::freeItem(removed_item);
110     }
111     // add new item to head
112     item->next_global = head;
113     if (head)
114         head->prev_global = item;
115     head = item;
116     if (!tail)
117         tail = item;
118     size += sz;
119 }
120 
remove(LVFontGlyphCacheItemA * item)121 void LVFontGlobalGlyphCacheA::remove(LVFontGlyphCacheItemA *item) {
122     FONT_GLYPH_CACHE_GUARD
123     removeNoLock(item);
124 }
125 
removeNoLock(LVFontGlyphCacheItemA * item)126 void LVFontGlobalGlyphCacheA::removeNoLock(LVFontGlyphCacheItemA *item) {
127     if (item == head)
128         head = item->next_global;
129     if (item == tail)
130         tail = item->prev_global;
131     if (!head || !tail)
132         return;
133     if (item->prev_global)
134         item->prev_global->next_global = item->next_global;
135     if (item->next_global)
136         item->next_global->prev_global = item->prev_global;
137     item->next_global = NULL;
138     item->prev_global = NULL;
139     size -= item->getSize();
140 }
141 
clear()142 void LVFontGlobalGlyphCacheA::clear() {
143     FONT_GLYPH_CACHE_GUARD
144     while (head) {
145         LVFontGlyphCacheItemA *ptr = head;
146         remove(ptr);
147         ptr->local_cache->remove(ptr);
148         LVFontGlyphCacheItemA::freeItem(ptr);
149     }
150 }
151 
newItem(LVFontLocalGlyphCacheA * local_cache,lChar32 ch,int w,int h)152 LVFontGlyphCacheItemA *LVFontGlyphCacheItemA::newItem(LVFontLocalGlyphCacheA *local_cache, lChar32 ch, int w, int h) {
153     LVFontGlyphCacheItemA *item = (LVFontGlyphCacheItemA *) malloc(sizeof(LVFontGlyphCacheItemA)
154                                                                  + (w * h - 1) * sizeof(lUInt8));
155     if (item) {
156         item->data.ch = ch;
157         item->bmp_width = (lUInt16) w;
158         item->bmp_height = (lUInt16) h;
159         item->origin_x = 0;
160         item->origin_y = 0;
161         item->advance = 0;
162         item->prev_global = NULL;
163         item->next_global = NULL;
164         item->prev_local = NULL;
165         item->next_local = NULL;
166         item->local_cache = local_cache;
167     }
168     return item;
169 }
170 
171 #if USE_HARFBUZZ==1
newItem(LVFontLocalGlyphCacheA * local_cache,lUInt32 glyph_index,int w,int h)172 LVFontGlyphCacheItemA *LVFontGlyphCacheItemA::newItem(LVFontLocalGlyphCacheA* local_cache, lUInt32 glyph_index, int w, int h)
173 {
174     LVFontGlyphCacheItemA *item = (LVFontGlyphCacheItemA *) malloc(sizeof(LVFontGlyphCacheItemA)
175                                                                  + (w * h - 1) * sizeof(lUInt8));
176     if (item) {
177         item->data.gindex = glyph_index;
178         item->bmp_width = (lUInt16) w;
179         item->bmp_height = (lUInt16) h;
180         item->origin_x = 0;
181         item->origin_y = 0;
182         item->advance = 0;
183         item->prev_global = NULL;
184         item->next_global = NULL;
185         item->prev_local = NULL;
186         item->next_local = NULL;
187         item->local_cache = local_cache;
188     }
189     return item;
190 }
191 #endif // USE_HARFBUZZ==1
192 
freeItem(LVFontGlyphCacheItemA * item)193 void LVFontGlyphCacheItemA::freeItem(LVFontGlyphCacheItemA *item) {
194     if (item)
195         ::free(item);
196 }
197