1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2003 Tat Tang
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
22 #include "font_cache.h"
25 /*******************************************************************************
27 ******************************************************************************/
28 static void font_cache_lru_init(void* data
)
30 struct font_cache_entry
* p
= data
;
31 p
->_char_code
= 0xffff; /* assume invalid char */
34 /*******************************************************************************
36 ******************************************************************************/
37 void font_cache_create(
38 struct font_cache
* fcache
,
41 int bitmap_bytes_size
)
43 int font_cache_entry_size
=
44 sizeof(struct font_cache_entry
) + bitmap_bytes_size
;
46 /* make sure font cache entries are a multiple of 16 bits */
47 if (font_cache_entry_size
% 2 != 0)
48 font_cache_entry_size
++;
50 int cache_size
= buf_size
/
51 (font_cache_entry_size
+ LRU_SLOT_OVERHEAD
+ sizeof(short));
54 fcache
->_capacity
= cache_size
;
60 unsigned char* lru_buf
= buf
;
61 lru_buf
+= sizeof(short) * cache_size
;
62 lru_create(&fcache
->_lru
, lru_buf
, cache_size
, font_cache_entry_size
);
64 /* initialise cache */
65 lru_traverse(&fcache
->_lru
, font_cache_lru_init
);
67 for (i
= 0; i
< cache_size
; i
++)
68 fcache
->_index
[i
] = i
; /* small cheat here */
71 /*******************************************************************************
73 ******************************************************************************/
74 static int font_cache_index_of(
75 struct font_cache
* fcache
,
76 unsigned short char_code
)
78 struct font_cache_entry
* p
;
79 int left
, right
, mid
, c
;
81 right
= fcache
->_size
- 1;
85 mid
= (left
+ right
) / 2;
87 p
= lru_data(&fcache
->_lru
, fcache
->_index
[mid
]);
88 c
= p
->_char_code
- char_code
;
98 while (left
<= right
);
103 /*******************************************************************************
104 * font_cache_insertion_point
105 ******************************************************************************/
106 static int font_cache_insertion_point(
107 struct font_cache
* fcache
,
108 unsigned short char_code
)
110 struct font_cache_entry
* p
;
111 short *index
= fcache
->_index
;
113 p
= lru_data(&fcache
->_lru
, index
[0]);
114 if (char_code
< p
->_char_code
)
117 p
= lru_data(&fcache
->_lru
, index
[fcache
->_capacity
- 1]);
118 if (char_code
> p
->_char_code
)
119 return fcache
->_capacity
- 1;
121 int left
, right
, mid
, c
;
124 right
= fcache
->_capacity
- 1;
128 mid
= (left
+ right
) / 2;
130 p
= lru_data(&fcache
->_lru
, index
[mid
]);
131 c
= char_code
- p
->_char_code
;
135 p
= lru_data(&fcache
->_lru
, index
[mid
+1]);
136 int z
= char_code
- p
->_char_code
;
151 while (left
<= right
);
157 /*******************************************************************************
159 ******************************************************************************/
160 struct font_cache_entry
* font_cache_get(
161 struct font_cache
* fcache
,
162 unsigned short char_code
,
163 void (*callback
) (struct font_cache_entry
* p
, void *callback_data
),
166 int insertion_point
= font_cache_insertion_point(fcache
, char_code
);
167 if (insertion_point
>= 0)
169 short lru_handle
= fcache
->_index
[insertion_point
];
170 struct font_cache_entry
* p
= lru_data(&fcache
->_lru
, lru_handle
);
171 if (p
->_char_code
== char_code
)
173 lru_touch(&fcache
->_lru
, lru_handle
);
174 return lru_data(&fcache
->_lru
, lru_handle
);
179 short lru_handle_to_replace
= fcache
->_lru
._head
;
180 struct font_cache_entry
* p
=
181 lru_data(&fcache
->_lru
, lru_handle_to_replace
);
182 int index_to_replace
= font_cache_index_of(fcache
, p
->_char_code
);
184 if (insertion_point
< index_to_replace
)
186 /* shift memory up */
187 memmove(fcache
->_index
+ insertion_point
+ 2,
188 fcache
->_index
+ insertion_point
+ 1,
189 (index_to_replace
- insertion_point
- 1) * sizeof(short));
192 fcache
->_index
[insertion_point
+ 1] = lru_handle_to_replace
;
194 else if (insertion_point
> index_to_replace
)
196 /* shift memory down */
197 memmove(fcache
->_index
+ index_to_replace
,
198 fcache
->_index
+ index_to_replace
+ 1,
199 (insertion_point
- index_to_replace
) * sizeof(short));
202 fcache
->_index
[insertion_point
] = lru_handle_to_replace
;
205 /* load new entry into cache */
206 lru_touch(&fcache
->_lru
, lru_handle_to_replace
);
208 if (fcache
->_size
< fcache
->_capacity
)
211 p
->_char_code
= char_code
;
212 callback(p
, callback_data
);