diff options
author | Franklin Wei <git@fwei.tk> | 2017-10-29 12:42:34 -0400 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2017-10-29 12:49:39 -0400 |
commit | 47ebf623cbfa46bd37456cce28a192471b46ddd5 (patch) | |
tree | 9678921e3f66278bd7298ccbf38d85e7af5daf76 /apps | |
parent | b2c470719a79f301ff4e9a6adcc5307ef47cfacf (diff) | |
download | rockbox-47ebf623cbfa46bd37456cce28a192471b46ddd5.tar.gz rockbox-47ebf623cbfa46bd37456cce28a192471b46ddd5.zip |
puzzles: improve zoom rendering
This adds colored font rendering, as well as a workaround for font
loading while zoomed. Additionally, the frontend has been modified to
match the new upstream API.
Change-Id: I8c3fe57e6854f176485bf792cf4778cd54a21674
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/puzzles/rbmalloc.c | 24 | ||||
-rw-r--r-- | apps/plugins/puzzles/rockbox.c | 117 |
2 files changed, 86 insertions, 55 deletions
diff --git a/apps/plugins/puzzles/rbmalloc.c b/apps/plugins/puzzles/rbmalloc.c index 5bf914ff87..1cb903ef4f 100644 --- a/apps/plugins/puzzles/rbmalloc.c +++ b/apps/plugins/puzzles/rbmalloc.c | |||
@@ -14,12 +14,9 @@ | |||
14 | int allocs = 0; | 14 | int allocs = 0; |
15 | int frees = 0; | 15 | int frees = 0; |
16 | 16 | ||
17 | bool audiobuf_available = | 17 | /* We don't load as an overlay anymore, so the audiobuf should always |
18 | #ifndef COMBINED | 18 | * be available. */ |
19 | true; | 19 | bool audiobuf_available = true; |
20 | #else | ||
21 | false; | ||
22 | #endif | ||
23 | 20 | ||
24 | static bool grab_audiobuf(void) | 21 | static bool grab_audiobuf(void) |
25 | { | 22 | { |
@@ -29,10 +26,23 @@ static bool grab_audiobuf(void) | |||
29 | if(rb->audio_status()) | 26 | if(rb->audio_status()) |
30 | rb->audio_stop(); | 27 | rb->audio_stop(); |
31 | 28 | ||
32 | size_t sz, junk; | 29 | size_t sz; |
30 | |||
33 | void *audiobuf = rb->plugin_get_audio_buffer(&sz); | 31 | void *audiobuf = rb->plugin_get_audio_buffer(&sz); |
34 | extern char *giant_buffer; | 32 | extern char *giant_buffer; |
35 | 33 | ||
34 | #if 0 | ||
35 | /* Try aligning if tlsf crashes in add_new_area(). This is | ||
36 | * disabled now since things seem to work without it. */ | ||
37 | void *old = audiobuf; | ||
38 | |||
39 | /* I'm sorry. */ | ||
40 | audiobuf = (void*)((int) audiobuf & ~0xff); | ||
41 | audiobuf += 0x100; | ||
42 | |||
43 | sz -= audiobuf - old; | ||
44 | #endif | ||
45 | |||
36 | add_new_area(audiobuf, sz, giant_buffer); | 46 | add_new_area(audiobuf, sz, giant_buffer); |
37 | audiobuf_available = false; | 47 | audiobuf_available = false; |
38 | return true; | 48 | return true; |
diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c index 59984a7891..b79070cba8 100644 --- a/apps/plugins/puzzles/rockbox.c +++ b/apps/plugins/puzzles/rockbox.c | |||
@@ -64,8 +64,8 @@ | |||
64 | #define midend_colors midend_colours | 64 | #define midend_colors midend_colours |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | #define PAN_X LCD_WIDTH / 4 | 67 | #define PAN_X (MIN(LCD_HEIGHT, LCD_WIDTH) / 4) |
68 | #define PAN_Y LCD_WIDTH / 4 /* not a typo */ | 68 | #define PAN_Y (MIN(LCD_HEIGHT, LCD_WIDTH) / 4) |
69 | 69 | ||
70 | #define ZOOM_FACTOR 3 | 70 | #define ZOOM_FACTOR 3 |
71 | 71 | ||
@@ -84,7 +84,9 @@ static int help_times = 0; | |||
84 | static void fix_size(void); | 84 | static void fix_size(void); |
85 | 85 | ||
86 | static struct viewport clip_rect; | 86 | static struct viewport clip_rect; |
87 | static bool clipped = false, audiobuf_available, zoom_enabled = false; | 87 | static bool clipped = false, zoom_enabled = false; |
88 | |||
89 | extern bool audiobuf_available; | ||
88 | 90 | ||
89 | static fb_data *zoom_fb; | 91 | static fb_data *zoom_fb; |
90 | static int zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr; | 92 | static int zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr; |
@@ -209,6 +211,7 @@ static void zoom_drawcircle(int cx, int cy, int radius) | |||
209 | * efficiency? */ | 211 | * efficiency? */ |
210 | static void zoom_mono_bitmap(const unsigned char *bits, int x, int y, int w, int h) | 212 | static void zoom_mono_bitmap(const unsigned char *bits, int x, int y, int w, int h) |
211 | { | 213 | { |
214 | unsigned int pix = rb->lcd_get_foreground(); | ||
212 | for(int i = 0; i < h / 8 + 1; ++i) | 215 | for(int i = 0; i < h / 8 + 1; ++i) |
213 | { | 216 | { |
214 | for(int j = 0; j < w; ++j) | 217 | for(int j = 0; j < w; ++j) |
@@ -219,11 +222,11 @@ static void zoom_mono_bitmap(const unsigned char *bits, int x, int y, int w, int | |||
219 | if(column & 1) | 222 | if(column & 1) |
220 | { | 223 | { |
221 | #if LCD_DEPTH == 24 | 224 | #if LCD_DEPTH == 24 |
222 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].b = RGB_UNPACK_BLUE(LCD_BLACK); | 225 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].b = RGB_UNPACK_BLUE(pix); |
223 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].g = RGB_UNPACK_GREEN(LCD_BLACK); | 226 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].g = RGB_UNPACK_GREEN(pix); |
224 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].r = RGB_UNPACK_RED(LCD_BLACK); | 227 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].r = RGB_UNPACK_RED(pix); |
225 | #else | 228 | #else |
226 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j] = LCD_BLACK; | 229 | zoom_fb[(y + i * 8 + dy) * zoom_w + x + j] = pix; |
227 | #endif | 230 | #endif |
228 | } | 231 | } |
229 | column >>= 1; | 232 | column >>= 1; |
@@ -240,6 +243,10 @@ static void zoom_alpha_bitmap(const unsigned char *bits, int x, int y, int w, in | |||
240 | const unsigned char *ptr = bits; | 243 | const unsigned char *ptr = bits; |
241 | unsigned char buf; | 244 | unsigned char buf; |
242 | int n_read = 0; /* how many 4-bit nibbles we've read (read new when even) */ | 245 | int n_read = 0; /* how many 4-bit nibbles we've read (read new when even) */ |
246 | |||
247 | unsigned int pix = rb->lcd_get_foreground(); | ||
248 | unsigned int r = RGB_UNPACK_RED(pix), g = RGB_UNPACK_GREEN(pix), b = RGB_UNPACK_BLUE(pix); | ||
249 | |||
243 | for(int i = 0; i < h; ++i) | 250 | for(int i = 0; i < h; ++i) |
244 | { | 251 | { |
245 | for(int j = 0; j < w; ++j) | 252 | for(int j = 0; j < w; ++j) |
@@ -254,7 +261,7 @@ static void zoom_alpha_bitmap(const unsigned char *bits, int x, int y, int w, in | |||
254 | 261 | ||
255 | int plot_alpha = (pix_alpha << 4) | pix_alpha; /* so 0xF -> 0xFF, 0x1 -> 0x11, etc. */ | 262 | int plot_alpha = (pix_alpha << 4) | pix_alpha; /* so 0xF -> 0xFF, 0x1 -> 0x11, etc. */ |
256 | 263 | ||
257 | plot(zoom_fb, zoom_w, zoom_h, x + j, y + i, plot_alpha, 0, 0, 0, | 264 | plot(zoom_fb, zoom_w, zoom_h, x + j, y + i, plot_alpha, r, g, b, |
258 | 0, zoom_w, 0, zoom_h); | 265 | 0, zoom_w, 0, zoom_h); |
259 | } | 266 | } |
260 | } | 267 | } |
@@ -394,8 +401,9 @@ static void rb_setfont(int type, int size) | |||
394 | { | 401 | { |
395 | /* out of range (besides, no puzzle should ever need this large | 402 | /* out of range (besides, no puzzle should ever need this large |
396 | of a font, anyways) */ | 403 | of a font, anyways) */ |
397 | if(BUNDLE_MAX < size) | 404 | if(size > BUNDLE_MAX) |
398 | size = BUNDLE_MAX; | 405 | size = BUNDLE_MAX; |
406 | |||
399 | if(size < 10) | 407 | if(size < 10) |
400 | { | 408 | { |
401 | if(size < 7) /* no teeny-tiny fonts */ | 409 | if(size < 7) /* no teeny-tiny fonts */ |
@@ -459,7 +467,7 @@ fallback: | |||
459 | } | 467 | } |
460 | 468 | ||
461 | static void rb_draw_text(void *handle, int x, int y, int fonttype, | 469 | static void rb_draw_text(void *handle, int x, int y, int fonttype, |
462 | int fontsize, int align, int color, char *text) | 470 | int fontsize, int align, int color, const char *text) |
463 | { | 471 | { |
464 | (void) fontsize; | 472 | (void) fontsize; |
465 | if(!zoom_enabled) | 473 | if(!zoom_enabled) |
@@ -490,6 +498,7 @@ static void rb_draw_text(void *handle, int x, int y, int fonttype, | |||
490 | } | 498 | } |
491 | else | 499 | else |
492 | { | 500 | { |
501 | rb_color(color); | ||
493 | rb_setfont(fonttype, fontsize); /* size will be clamped if too large */ | 502 | rb_setfont(fonttype, fontsize); /* size will be clamped if too large */ |
494 | 503 | ||
495 | int w, h; | 504 | int w, h; |
@@ -1252,7 +1261,7 @@ static void rb_end_draw(void *handle) | |||
1252 | 1261 | ||
1253 | static char *titlebar = NULL; | 1262 | static char *titlebar = NULL; |
1254 | 1263 | ||
1255 | static void rb_status_bar(void *handle, char *text) | 1264 | static void rb_status_bar(void *handle, const char *text) |
1256 | { | 1265 | { |
1257 | if(titlebar) | 1266 | if(titlebar) |
1258 | sfree(titlebar); | 1267 | sfree(titlebar); |
@@ -1320,6 +1329,7 @@ const drawing_api rb_drawing = { | |||
1320 | /* render to a virtual framebuffer and let the user pan (but not make any moves) */ | 1329 | /* render to a virtual framebuffer and let the user pan (but not make any moves) */ |
1321 | static void zoom(void) | 1330 | static void zoom(void) |
1322 | { | 1331 | { |
1332 | rb->splash(0, "Please wait..."); | ||
1323 | zoom_w = LCD_WIDTH * ZOOM_FACTOR, zoom_h = LCD_HEIGHT * ZOOM_FACTOR; | 1333 | zoom_w = LCD_WIDTH * ZOOM_FACTOR, zoom_h = LCD_HEIGHT * ZOOM_FACTOR; |
1324 | 1334 | ||
1325 | zoom_clipu = 0; | 1335 | zoom_clipu = 0; |
@@ -1329,8 +1339,21 @@ static void zoom(void) | |||
1329 | 1339 | ||
1330 | midend_size(me, &zoom_w, &zoom_h, TRUE); | 1340 | midend_size(me, &zoom_w, &zoom_h, TRUE); |
1331 | 1341 | ||
1332 | /* allocate a framebuffer */ | 1342 | /* Allocating the framebuffer will mostly likely grab the |
1343 | * audiobuffer, which will make impossible to load new fonts, and | ||
1344 | * lead to zoomed puzzles being drawn with the default fallback | ||
1345 | * fonts. As a semi-workaround, we go ahead and load the biggest available | ||
1346 | * monospace and proportional fonts. */ | ||
1347 | rb_setfont(FONT_FIXED, BUNDLE_MAX); | ||
1348 | rb_setfont(FONT_VARIABLE, BUNDLE_MAX); | ||
1349 | |||
1333 | zoom_fb = smalloc(zoom_w * zoom_h * sizeof(fb_data)); | 1350 | zoom_fb = smalloc(zoom_w * zoom_h * sizeof(fb_data)); |
1351 | if(!zoom_fb) | ||
1352 | { | ||
1353 | rb->splashf(HZ * 2, "Not enough memory to allocate %d KB framebuffer!", zoom_w * zoom_h * sizeof(fb_data) / 1024); | ||
1354 | return; | ||
1355 | } | ||
1356 | |||
1334 | zoom_enabled = true; | 1357 | zoom_enabled = true; |
1335 | 1358 | ||
1336 | /* draws go to the enlarged framebuffer */ | 1359 | /* draws go to the enlarged framebuffer */ |
@@ -1530,7 +1553,7 @@ static void int_chooser(config_item *cfgs, int idx, int val) | |||
1530 | * a workaround for Unruly): */ | 1553 | * a workaround for Unruly): */ |
1531 | #define CHOOSER_MAX_INCR 2 | 1554 | #define CHOOSER_MAX_INCR 2 |
1532 | 1555 | ||
1533 | char *ret; | 1556 | const char *ret; |
1534 | for(int i = 0; i < CHOOSER_MAX_INCR; ++i) | 1557 | for(int i = 0; i < CHOOSER_MAX_INCR; ++i) |
1535 | { | 1558 | { |
1536 | val += d; | 1559 | val += d; |
@@ -1694,7 +1717,7 @@ static bool config_menu(void) | |||
1694 | old_str = dupstr(old.u.string.sval); | 1717 | old_str = dupstr(old.u.string.sval); |
1695 | 1718 | ||
1696 | bool freed_str = do_configure_item(config, pos); | 1719 | bool freed_str = do_configure_item(config, pos); |
1697 | char *err = midend_set_config(me, CFG_SETTINGS, config); | 1720 | const char *err = midend_set_config(me, CFG_SETTINGS, config); |
1698 | 1721 | ||
1699 | if(err) | 1722 | if(err) |
1700 | { | 1723 | { |
@@ -1971,12 +1994,12 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item) | |||
1971 | break; | 1994 | break; |
1972 | case 7: | 1995 | case 7: |
1973 | break; | 1996 | break; |
1974 | case 8: | 1997 | case 9: |
1975 | if(audiobuf_available) | 1998 | if(audiobuf_available) |
1976 | break; | 1999 | break; |
1977 | else | 2000 | else |
1978 | return ACTION_EXIT_MENUITEM; | 2001 | return ACTION_EXIT_MENUITEM; |
1979 | case 9: | 2002 | case 10: |
1980 | if(!midend_get_presets(me, NULL)->n_entries) | 2003 | if(!midend_get_presets(me, NULL)->n_entries) |
1981 | return ACTION_EXIT_MENUITEM; | 2004 | return ACTION_EXIT_MENUITEM; |
1982 | break; | 2005 | break; |
@@ -2021,21 +2044,21 @@ static int pause_menu(void) | |||
2021 | #define static auto | 2044 | #define static auto |
2022 | #define const | 2045 | #define const |
2023 | MENUITEM_STRINGLIST(menu, NULL, pausemenu_cb, | 2046 | MENUITEM_STRINGLIST(menu, NULL, pausemenu_cb, |
2024 | "Resume Game", | 2047 | "Resume Game", // 0 |
2025 | "New Game", | 2048 | "New Game", // 1 |
2026 | "Restart Game", | 2049 | "Restart Game", // 2 |
2027 | "Undo", | 2050 | "Undo", // 3 |
2028 | "Redo", | 2051 | "Redo", // 4 |
2029 | "Solve", | 2052 | "Solve", // 5 |
2030 | "Zoom In", | 2053 | "Zoom In", // 6 |
2031 | "Quick Help", | 2054 | "Quick Help", // 7 |
2032 | "Extensive Help", | 2055 | "Extensive Help", // 8 |
2033 | "Playback Control", | 2056 | "Playback Control", // 9 |
2034 | "Game Type", | 2057 | "Game Type", // 10 |
2035 | "Debug Menu", | 2058 | "Debug Menu", // 11 |
2036 | "Configure Game", | 2059 | "Configure Game", // 12 |
2037 | "Quit without Saving", | 2060 | "Quit without Saving", // 13 |
2038 | "Quit"); | 2061 | "Quit"); // 14 |
2039 | #undef static | 2062 | #undef static |
2040 | #undef const | 2063 | #undef const |
2041 | /* HACK ALERT */ | 2064 | /* HACK ALERT */ |
@@ -2082,7 +2105,7 @@ static int pause_menu(void) | |||
2082 | break; | 2105 | break; |
2083 | case 5: | 2106 | case 5: |
2084 | { | 2107 | { |
2085 | char *msg = midend_solve(me); | 2108 | const char *msg = midend_solve(me); |
2086 | if(msg) | 2109 | if(msg) |
2087 | rb->splash(HZ, msg); | 2110 | rb->splash(HZ, msg); |
2088 | quit = true; | 2111 | quit = true; |
@@ -2391,7 +2414,7 @@ static int read_wrapper(void *ptr, void *buf, int len) | |||
2391 | return rb->read(fd, buf, len); | 2414 | return rb->read(fd, buf, len); |
2392 | } | 2415 | } |
2393 | 2416 | ||
2394 | static void write_wrapper(void *ptr, void *buf, int len) | 2417 | static void write_wrapper(void *ptr, const void *buf, int len) |
2395 | { | 2418 | { |
2396 | int fd = (int) ptr; | 2419 | int fd = (int) ptr; |
2397 | rb->write(fd, buf, len); | 2420 | rb->write(fd, buf, len); |
@@ -2416,7 +2439,7 @@ static void init_colors(void) | |||
2416 | sfree(floatcolors); | 2439 | sfree(floatcolors); |
2417 | } | 2440 | } |
2418 | 2441 | ||
2419 | static char *init_for_game(const game *gm, int load_fd, bool draw) | 2442 | static const char *init_for_game(const game *gm, int load_fd, bool draw) |
2420 | { | 2443 | { |
2421 | me = midend_new(NULL, gm, &rb_drawing, NULL); | 2444 | me = midend_new(NULL, gm, &rb_drawing, NULL); |
2422 | 2445 | ||
@@ -2424,7 +2447,7 @@ static char *init_for_game(const game *gm, int load_fd, bool draw) | |||
2424 | midend_new_game(me); | 2447 | midend_new_game(me); |
2425 | else | 2448 | else |
2426 | { | 2449 | { |
2427 | char *ret = midend_deserialize(me, read_wrapper, (void*) load_fd); | 2450 | const char *ret = midend_deserialize(me, read_wrapper, (void*) load_fd); |
2428 | if(ret) | 2451 | if(ret) |
2429 | return ret; | 2452 | return ret; |
2430 | } | 2453 | } |
@@ -2584,7 +2607,7 @@ static void save_fonts(void) | |||
2584 | final |= oldmask; | 2607 | final |= oldmask; |
2585 | uint32_t left = final >> 31; | 2608 | uint32_t left = final >> 31; |
2586 | uint32_t right = final & 0x7fffffff; | 2609 | uint32_t right = final & 0x7fffffff; |
2587 | rb->fdprintf(outfd, "%s:%u:%u\n", midend_which_game(me)->name, left, right); | 2610 | rb->fdprintf(outfd, "%s:%lu:%lu\n", midend_which_game(me)->name, left, right); |
2588 | rb->close(outfd); | 2611 | rb->close(outfd); |
2589 | rb->rename(FONT_TABLE ".tmp", FONT_TABLE); | 2612 | rb->rename(FONT_TABLE ".tmp", FONT_TABLE); |
2590 | } | 2613 | } |
@@ -2609,7 +2632,7 @@ static bool load_game(void) | |||
2609 | rb->splash(0, "Loading..."); | 2632 | rb->splash(0, "Loading..."); |
2610 | 2633 | ||
2611 | char *game; | 2634 | char *game; |
2612 | char *ret = identify_game(&game, read_wrapper, (void*)fd); | 2635 | const char *ret = identify_game(&game, read_wrapper, (void*)fd); |
2613 | 2636 | ||
2614 | if(!*game && ret) | 2637 | if(!*game && ret) |
2615 | { | 2638 | { |
@@ -2625,12 +2648,10 @@ static bool load_game(void) | |||
2625 | 2648 | ||
2626 | if(!strcmp(game, thegame.name)) | 2649 | if(!strcmp(game, thegame.name)) |
2627 | { | 2650 | { |
2628 | sfree(ret); | ||
2629 | ret = init_for_game(&thegame, fd, false); | 2651 | ret = init_for_game(&thegame, fd, false); |
2630 | if(ret) | 2652 | if(ret) |
2631 | { | 2653 | { |
2632 | rb->splash(HZ, ret); | 2654 | rb->splash(HZ, ret); |
2633 | sfree(ret); | ||
2634 | rb->close(fd); | 2655 | rb->close(fd); |
2635 | rb->remove(fname); | 2656 | rb->remove(fname); |
2636 | return false; | 2657 | return false; |
@@ -2755,15 +2776,15 @@ enum plugin_status plugin_start(const void *param) | |||
2755 | #define static auto | 2776 | #define static auto |
2756 | #define const | 2777 | #define const |
2757 | MENUITEM_STRINGLIST(menu, NULL, mainmenu_cb, | 2778 | MENUITEM_STRINGLIST(menu, NULL, mainmenu_cb, |
2758 | "Resume Game", | 2779 | "Resume Game", // 0 |
2759 | "New Game", | 2780 | "New Game", // 1 |
2760 | "Quick Help", | 2781 | "Quick Help", // 2 |
2761 | "Extensive Help", | 2782 | "Extensive Help", // 3 |
2762 | "Playback Control", | 2783 | "Playback Control", // 4 |
2763 | "Game Type", | 2784 | "Game Type", // 5 |
2764 | "Configure Game", | 2785 | "Configure Game", // 6 |
2765 | "Quit without Saving", | 2786 | "Quit without Saving", // 7 |
2766 | "Quit"); | 2787 | "Quit"); // 8 |
2767 | #undef static | 2788 | #undef static |
2768 | #undef const | 2789 | #undef const |
2769 | 2790 | ||