summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/rockbox.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2017-07-12 12:19:09 -0400
committerFranklin Wei <git@fwei.tk>2017-07-17 16:58:13 -0400
commite7a35ba3833925043b1b3e4a164e06058500bcd8 (patch)
tree1c6c3b920195824cf08d79fda23e7b738d39c730 /apps/plugins/puzzles/rockbox.c
parent84e13d5749835234347c8f94f85ea2790980f44d (diff)
downloadrockbox-e7a35ba3833925043b1b3e4a164e06058500bcd8.tar.gz
rockbox-e7a35ba3833925043b1b3e4a164e06058500bcd8.zip
puzzles: dynamic text size via custom font pack
Up to now, we'd just ignore whatever font size the puzzle asked for, and instead just go with either the UI font or system font regardless of their size, which led to some horrible-looking puzzles. This patch adds the ability to automatically load fonts of the proper size when they are available, which makes text-based puzzles such as Pattern and Slant function correctly with any UI font. The font pack, which should be extracted to the system-wide fonts directory consists of 3 small bitmap fonts from 7px to 10px and then anti-aliased Deja Vu fonts from 10px to 36px. It is available in the source tree (apps/plugins/puzzles/fonts.zip), or from <http://download.rockbox.org/useful/sgt-fonts.zip>. Change-Id: I05c8fe7bd6d867e14de9b941deb91e8c642ee4a8
Diffstat (limited to 'apps/plugins/puzzles/rockbox.c')
-rw-r--r--apps/plugins/puzzles/rockbox.c150
1 files changed, 137 insertions, 13 deletions
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c
index 56bb83e3a6..18194dad36 100644
--- a/apps/plugins/puzzles/rockbox.c
+++ b/apps/plugins/puzzles/rockbox.c
@@ -30,7 +30,9 @@
30#ifndef COMBINED 30#ifndef COMBINED
31#include "lib/playback_control.h" 31#include "lib/playback_control.h"
32#endif 32#endif
33#include "lib/simple_viewer.h"
33#include "lib/xlcd.h" 34#include "lib/xlcd.h"
35
34#include "fixedpoint.h" 36#include "fixedpoint.h"
35 37
36/* how many ticks between timer callbacks */ 38/* how many ticks between timer callbacks */
@@ -131,28 +133,128 @@ static void rb_color(int n)
131 rb->lcd_set_foreground(colors[n]); 133 rb->lcd_set_foreground(colors[n]);
132} 134}
133 135
134static void rb_draw_text(void *handle, int x, int y, int fonttype, 136/* font bundle size range */
135 int fontsize, int align, int color, char *text) 137#define BUNDLE_MIN 7
138#define BUNDLE_MAX 36
139#define BUNDLE_COUNT (BUNDLE_MAX - BUNDLE_MIN + 1)
140
141static struct bundled_font {
142 int status; /* -3 = never tried loading, or unloaded, -2 = failed to load, >= -1: loaded successfully */
143 int last_use;
144} loaded_fonts[2*BUNDLE_COUNT]; /* monospace are first, then proportional */
145
146static int n_fonts, access_counter = -1;
147
148static void unload_fonts(void)
136{ 149{
137 (void) fontsize; 150 for(int i = 0; i < 2 * BUNDLE_COUNT; ++i)
138 LOGF("rb_draw_text(%d %d %s)", x, y, text); 151 if(loaded_fonts[i].status > 0) /* don't unload FONT_UI */
152 {
153 rb->font_unload(loaded_fonts[i].status);
154 loaded_fonts[i].status = -3;
155 }
156 access_counter = -1;
157 rb->lcd_setfont(FONT_UI);
158}
139 159
140 offset_coords(&x, &y); 160static void rb_setfont(int type, int size)
161{
162 if(access_counter < 0)
163 {
164 for(int i = 0; i < 2 * BUNDLE_COUNT; ++i)
165 loaded_fonts[i].status = -3;
166 access_counter = 0;
167 n_fonts = 0;
168 }
169
170 /* out of range */
171 if(BUNDLE_MAX < size)
172 size = BUNDLE_MAX;
141 173
142 /* TODO: variable font size */ 174 int font_idx = (type == FONT_FIXED ? 0 : BUNDLE_COUNT) + size - BUNDLE_MIN;
143 switch(fonttype) 175 switch(loaded_fonts[font_idx].status)
144 { 176 {
145 case FONT_FIXED: 177 case -3:
146 rb->lcd_setfont(FONT_SYSFIXED); 178 {
147 break; 179 /* never loaded */
148 case FONT_VARIABLE: 180 char buf[MAX_PATH];
149 rb->lcd_setfont(FONT_UI); 181 if(size < 10) /* Deja Vu only goes down to 10px, below that it's a giant blob */
182 {
183 if(size < 7)
184 size = 7; /* we're not going to force anyone to read 05-Tiny :P */
185 /* we also don't care about monospace/proportional at this point */
186 switch(size)
187 {
188 case 7:
189 rb->snprintf(buf, sizeof(buf), FONT_DIR "/07-Fixed.fnt");
190 break;
191 case 8:
192 rb->snprintf(buf, sizeof(buf), FONT_DIR "/08-Rockfont.fnt");
193 break;
194 case 9:
195 rb->snprintf(buf, sizeof(buf), FONT_DIR "/09-Fixed.fnt");
196 break;
197 default:
198 assert(false);
199 }
200 }
201 else
202 rb->snprintf(buf, sizeof(buf), FONT_DIR "/%02d-%s.fnt", size, type == FONT_FIXED ? "DejaVuSansMono" : "DejaVuSans");
203
204 if(n_fonts >= MAXUSERFONTS - 3) /* safety margin, FIXME */
205 {
206 /* unload an old font */
207 int oldest_use = -1, oldest_idx = -1;
208 for(int i = 0; i < 2 * BUNDLE_COUNT; ++i)
209 {
210 if((loaded_fonts[i].status >= 0 && loaded_fonts[i].last_use < oldest_use) || oldest_use < 0)
211 {
212 oldest_use = loaded_fonts[i].last_use;
213 oldest_idx = i;
214 }
215 }
216 assert(oldest_idx >= 0);
217 rb->font_unload(loaded_fonts[oldest_idx].status);
218 loaded_fonts[oldest_idx].status = -3;
219 n_fonts--;
220 }
221
222 loaded_fonts[font_idx].status = rb->font_load(buf);
223 if(loaded_fonts[font_idx].status < 0)
224 goto fallback;
225 loaded_fonts[font_idx].last_use = access_counter++;
226 n_fonts++;
227 rb->lcd_setfont(loaded_fonts[font_idx].status);
150 break; 228 break;
229 }
230 case -2:
231 case -1:
232 goto fallback;
151 default: 233 default:
152 fatal("bad font"); 234 loaded_fonts[font_idx].last_use = access_counter++;
235 rb->lcd_setfont(loaded_fonts[font_idx].status);
153 break; 236 break;
154 } 237 }
155 238
239 return;
240
241fallback:
242
243 rb->lcd_setfont(type == FONT_FIXED ? FONT_SYSFIXED : FONT_UI);
244
245 return;
246}
247
248static void rb_draw_text(void *handle, int x, int y, int fonttype,
249 int fontsize, int align, int color, char *text)
250{
251 (void) fontsize;
252 LOGF("rb_draw_text(%d %d %s)", x, y, text);
253
254 offset_coords(&x, &y);
255
256 rb_setfont(fonttype, fontsize);
257
156 int w, h; 258 int w, h;
157 rb->lcd_getstringsize(text, &w, &h); 259 rb->lcd_getstringsize(text, &w, &h);
158 260
@@ -1053,6 +1155,27 @@ static void quick_help(void)
1053 return; 1155 return;
1054} 1156}
1055 1157
1158static void full_help(const char *name)
1159{
1160 unsigned old_bg = rb->lcd_get_background();
1161
1162 bool orig_clipped = clipped;
1163 if(orig_clipped)
1164 rb_unclip(NULL);
1165
1166 rb->lcd_set_foreground(LCD_WHITE);
1167 rb->lcd_set_background(LCD_BLACK);
1168 unload_fonts();
1169 rb->lcd_setfont(FONT_UI);
1170
1171 view_text(name, help_text);
1172
1173 rb->lcd_set_background(old_bg);
1174
1175 if(orig_clipped)
1176 rb_clip(NULL, clip_rect.x, clip_rect.y, clip_rect.width, clip_rect.height);
1177}
1178
1056static void init_default_settings(void) 1179static void init_default_settings(void)
1057{ 1180{
1058 settings.slowmo_factor = 1; 1181 settings.slowmo_factor = 1;
@@ -1663,6 +1786,7 @@ static char *init_for_game(const game *gm, int load_fd, bool draw)
1663 1786
1664static void exit_handler(void) 1787static void exit_handler(void)
1665{ 1788{
1789 unload_fonts();
1666#ifdef HAVE_ADJUSTABLE_CPU_FREQ 1790#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1667 rb->cpu_boost(false); 1791 rb->cpu_boost(false);
1668#endif 1792#endif