Another forgotten file.
[Rockbox.git] / firmware / font_cache.c
blob0fe36fe8ebe537b17001c99146ef61610a2ad611
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2003 Tat Tang
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
19 #include <string.h>
20 #include "font_cache.h"
21 #include "debug.h"
23 /*******************************************************************************
24 * font_cache_lru_init
25 ******************************************************************************/
26 static void font_cache_lru_init(void* data)
28 struct font_cache_entry* p = data;
29 p->_char_code = 0xffff; /* assume invalid char */
32 /*******************************************************************************
33 * font_cache_create
34 ******************************************************************************/
35 void font_cache_create(
36 struct font_cache* fcache,
37 void *buf,
38 int buf_size,
39 int bitmap_bytes_size)
41 int font_cache_entry_size =
42 sizeof(struct font_cache_entry) + bitmap_bytes_size;
44 /* make sure font cache entries are a multiple of 16 bits */
45 if (font_cache_entry_size % 2 != 0)
46 font_cache_entry_size++;
48 int cache_size = buf_size /
49 (font_cache_entry_size + LRU_SLOT_OVERHEAD + sizeof(short));
51 fcache->_size = 1;
52 fcache->_capacity = cache_size;
54 /* set up index */
55 fcache->_index = buf;
57 /* set up lru list */
58 unsigned char* lru_buf = buf;
59 lru_buf += sizeof(short) * cache_size;
60 lru_create(&fcache->_lru, lru_buf, cache_size, font_cache_entry_size);
62 /* initialise cache */
63 lru_traverse(&fcache->_lru, font_cache_lru_init);
64 short i;
65 for (i = 0; i < cache_size; i++)
66 fcache->_index[i] = i; /* small cheat here */
69 /*******************************************************************************
70 * font_cache_index_of
71 ******************************************************************************/
72 static int font_cache_index_of(
73 struct font_cache* fcache,
74 unsigned short char_code)
76 struct font_cache_entry* p;
77 int left, right, mid, c;
78 left = 0;
79 right = fcache->_size - 1;
83 mid = (left + right) / 2;
85 p = lru_data(&fcache->_lru, fcache->_index[mid]);
86 c = p->_char_code - char_code;
88 if (c == 0)
89 return mid;
91 if (c < 0)
92 left = mid + 1;
93 else
94 right = mid - 1;
96 while (left <= right);
98 return -1;
101 /*******************************************************************************
102 * font_cache_insertion_point
103 ******************************************************************************/
104 static int font_cache_insertion_point(
105 struct font_cache* fcache,
106 unsigned short char_code)
108 struct font_cache_entry* p;
109 short *index = fcache->_index;
111 p = lru_data(&fcache->_lru, index[0]);
112 if (char_code < p->_char_code)
113 return -1;
115 p = lru_data(&fcache->_lru, index[fcache->_capacity - 1]);
116 if (char_code > p->_char_code)
117 return fcache->_capacity - 1;
119 int left, right, mid, c;
121 left = 0;
122 right = fcache->_capacity - 1;
126 mid = (left + right) / 2;
128 p = lru_data(&fcache->_lru, index[mid]);
129 c = char_code - p->_char_code;
131 if (c >= 0)
133 p = lru_data(&fcache->_lru, index[mid+1]);
134 int z = char_code - p->_char_code;
136 if (z < 0)
137 return mid;
139 if (z == 0)
140 return mid + 1;
144 if (c > 0)
145 left = mid + 1;
146 else
147 right = mid - 1;
149 while (left <= right);
151 /* not found */
152 return -2;
155 /*******************************************************************************
156 * font_cache_get
157 ******************************************************************************/
158 struct font_cache_entry* font_cache_get(
159 struct font_cache* fcache,
160 unsigned short char_code,
161 void (*callback) (struct font_cache_entry* p, void *callback_data),
162 void *callback_data)
164 int insertion_point = font_cache_insertion_point(fcache, char_code);
165 if (insertion_point >= 0)
167 short lru_handle = fcache->_index[insertion_point];
168 struct font_cache_entry* p = lru_data(&fcache->_lru, lru_handle);
169 if (p->_char_code == char_code)
171 lru_touch(&fcache->_lru, lru_handle);
172 return lru_data(&fcache->_lru, lru_handle);
176 /* not found */
177 short lru_handle_to_replace = fcache->_lru._head;
178 struct font_cache_entry* p =
179 lru_data(&fcache->_lru, lru_handle_to_replace);
180 int index_to_replace = font_cache_index_of(fcache, p->_char_code);
182 if (insertion_point < index_to_replace)
184 /* shift memory up */
185 memmove(fcache->_index + insertion_point + 2,
186 fcache->_index + insertion_point + 1,
187 (index_to_replace - insertion_point - 1) * sizeof(short));
189 /* add to index */
190 fcache->_index[insertion_point + 1] = lru_handle_to_replace;
192 else if (insertion_point > index_to_replace)
194 /* shift memory down */
195 memmove(fcache->_index + index_to_replace,
196 fcache->_index + index_to_replace + 1,
197 (insertion_point - index_to_replace) * sizeof(short));
199 /* add to index */
200 fcache->_index[insertion_point] = lru_handle_to_replace;
203 /* load new entry into cache */
204 lru_touch(&fcache->_lru, lru_handle_to_replace);
206 if (fcache->_size < fcache->_capacity)
207 fcache->_size++;
209 p->_char_code = char_code;
210 callback(p, callback_data);
212 return p;