mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 10:37:38 -04:00
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
This commit is contained in:
parent
b2c470719a
commit
47ebf623cb
2 changed files with 86 additions and 55 deletions
|
@ -14,12 +14,9 @@
|
|||
int allocs = 0;
|
||||
int frees = 0;
|
||||
|
||||
bool audiobuf_available =
|
||||
#ifndef COMBINED
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
/* We don't load as an overlay anymore, so the audiobuf should always
|
||||
* be available. */
|
||||
bool audiobuf_available = true;
|
||||
|
||||
static bool grab_audiobuf(void)
|
||||
{
|
||||
|
@ -29,10 +26,23 @@ static bool grab_audiobuf(void)
|
|||
if(rb->audio_status())
|
||||
rb->audio_stop();
|
||||
|
||||
size_t sz, junk;
|
||||
size_t sz;
|
||||
|
||||
void *audiobuf = rb->plugin_get_audio_buffer(&sz);
|
||||
extern char *giant_buffer;
|
||||
|
||||
#if 0
|
||||
/* Try aligning if tlsf crashes in add_new_area(). This is
|
||||
* disabled now since things seem to work without it. */
|
||||
void *old = audiobuf;
|
||||
|
||||
/* I'm sorry. */
|
||||
audiobuf = (void*)((int) audiobuf & ~0xff);
|
||||
audiobuf += 0x100;
|
||||
|
||||
sz -= audiobuf - old;
|
||||
#endif
|
||||
|
||||
add_new_area(audiobuf, sz, giant_buffer);
|
||||
audiobuf_available = false;
|
||||
return true;
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
#define midend_colors midend_colours
|
||||
#endif
|
||||
|
||||
#define PAN_X LCD_WIDTH / 4
|
||||
#define PAN_Y LCD_WIDTH / 4 /* not a typo */
|
||||
#define PAN_X (MIN(LCD_HEIGHT, LCD_WIDTH) / 4)
|
||||
#define PAN_Y (MIN(LCD_HEIGHT, LCD_WIDTH) / 4)
|
||||
|
||||
#define ZOOM_FACTOR 3
|
||||
|
||||
|
@ -84,7 +84,9 @@ static int help_times = 0;
|
|||
static void fix_size(void);
|
||||
|
||||
static struct viewport clip_rect;
|
||||
static bool clipped = false, audiobuf_available, zoom_enabled = false;
|
||||
static bool clipped = false, zoom_enabled = false;
|
||||
|
||||
extern bool audiobuf_available;
|
||||
|
||||
static fb_data *zoom_fb;
|
||||
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)
|
|||
* efficiency? */
|
||||
static void zoom_mono_bitmap(const unsigned char *bits, int x, int y, int w, int h)
|
||||
{
|
||||
unsigned int pix = rb->lcd_get_foreground();
|
||||
for(int i = 0; i < h / 8 + 1; ++i)
|
||||
{
|
||||
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
|
|||
if(column & 1)
|
||||
{
|
||||
#if LCD_DEPTH == 24
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].b = RGB_UNPACK_BLUE(LCD_BLACK);
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].g = RGB_UNPACK_GREEN(LCD_BLACK);
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].r = RGB_UNPACK_RED(LCD_BLACK);
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].b = RGB_UNPACK_BLUE(pix);
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].g = RGB_UNPACK_GREEN(pix);
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j].r = RGB_UNPACK_RED(pix);
|
||||
#else
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j] = LCD_BLACK;
|
||||
zoom_fb[(y + i * 8 + dy) * zoom_w + x + j] = pix;
|
||||
#endif
|
||||
}
|
||||
column >>= 1;
|
||||
|
@ -240,6 +243,10 @@ static void zoom_alpha_bitmap(const unsigned char *bits, int x, int y, int w, in
|
|||
const unsigned char *ptr = bits;
|
||||
unsigned char buf;
|
||||
int n_read = 0; /* how many 4-bit nibbles we've read (read new when even) */
|
||||
|
||||
unsigned int pix = rb->lcd_get_foreground();
|
||||
unsigned int r = RGB_UNPACK_RED(pix), g = RGB_UNPACK_GREEN(pix), b = RGB_UNPACK_BLUE(pix);
|
||||
|
||||
for(int i = 0; i < h; ++i)
|
||||
{
|
||||
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
|
|||
|
||||
int plot_alpha = (pix_alpha << 4) | pix_alpha; /* so 0xF -> 0xFF, 0x1 -> 0x11, etc. */
|
||||
|
||||
plot(zoom_fb, zoom_w, zoom_h, x + j, y + i, plot_alpha, 0, 0, 0,
|
||||
plot(zoom_fb, zoom_w, zoom_h, x + j, y + i, plot_alpha, r, g, b,
|
||||
0, zoom_w, 0, zoom_h);
|
||||
}
|
||||
}
|
||||
|
@ -394,8 +401,9 @@ static void rb_setfont(int type, int size)
|
|||
{
|
||||
/* out of range (besides, no puzzle should ever need this large
|
||||
of a font, anyways) */
|
||||
if(BUNDLE_MAX < size)
|
||||
if(size > BUNDLE_MAX)
|
||||
size = BUNDLE_MAX;
|
||||
|
||||
if(size < 10)
|
||||
{
|
||||
if(size < 7) /* no teeny-tiny fonts */
|
||||
|
@ -459,7 +467,7 @@ fallback:
|
|||
}
|
||||
|
||||
static void rb_draw_text(void *handle, int x, int y, int fonttype,
|
||||
int fontsize, int align, int color, char *text)
|
||||
int fontsize, int align, int color, const char *text)
|
||||
{
|
||||
(void) fontsize;
|
||||
if(!zoom_enabled)
|
||||
|
@ -490,6 +498,7 @@ static void rb_draw_text(void *handle, int x, int y, int fonttype,
|
|||
}
|
||||
else
|
||||
{
|
||||
rb_color(color);
|
||||
rb_setfont(fonttype, fontsize); /* size will be clamped if too large */
|
||||
|
||||
int w, h;
|
||||
|
@ -1252,7 +1261,7 @@ static void rb_end_draw(void *handle)
|
|||
|
||||
static char *titlebar = NULL;
|
||||
|
||||
static void rb_status_bar(void *handle, char *text)
|
||||
static void rb_status_bar(void *handle, const char *text)
|
||||
{
|
||||
if(titlebar)
|
||||
sfree(titlebar);
|
||||
|
@ -1320,6 +1329,7 @@ const drawing_api rb_drawing = {
|
|||
/* render to a virtual framebuffer and let the user pan (but not make any moves) */
|
||||
static void zoom(void)
|
||||
{
|
||||
rb->splash(0, "Please wait...");
|
||||
zoom_w = LCD_WIDTH * ZOOM_FACTOR, zoom_h = LCD_HEIGHT * ZOOM_FACTOR;
|
||||
|
||||
zoom_clipu = 0;
|
||||
|
@ -1329,8 +1339,21 @@ static void zoom(void)
|
|||
|
||||
midend_size(me, &zoom_w, &zoom_h, TRUE);
|
||||
|
||||
/* allocate a framebuffer */
|
||||
/* Allocating the framebuffer will mostly likely grab the
|
||||
* audiobuffer, which will make impossible to load new fonts, and
|
||||
* lead to zoomed puzzles being drawn with the default fallback
|
||||
* fonts. As a semi-workaround, we go ahead and load the biggest available
|
||||
* monospace and proportional fonts. */
|
||||
rb_setfont(FONT_FIXED, BUNDLE_MAX);
|
||||
rb_setfont(FONT_VARIABLE, BUNDLE_MAX);
|
||||
|
||||
zoom_fb = smalloc(zoom_w * zoom_h * sizeof(fb_data));
|
||||
if(!zoom_fb)
|
||||
{
|
||||
rb->splashf(HZ * 2, "Not enough memory to allocate %d KB framebuffer!", zoom_w * zoom_h * sizeof(fb_data) / 1024);
|
||||
return;
|
||||
}
|
||||
|
||||
zoom_enabled = true;
|
||||
|
||||
/* draws go to the enlarged framebuffer */
|
||||
|
@ -1530,7 +1553,7 @@ static void int_chooser(config_item *cfgs, int idx, int val)
|
|||
* a workaround for Unruly): */
|
||||
#define CHOOSER_MAX_INCR 2
|
||||
|
||||
char *ret;
|
||||
const char *ret;
|
||||
for(int i = 0; i < CHOOSER_MAX_INCR; ++i)
|
||||
{
|
||||
val += d;
|
||||
|
@ -1694,7 +1717,7 @@ static bool config_menu(void)
|
|||
old_str = dupstr(old.u.string.sval);
|
||||
|
||||
bool freed_str = do_configure_item(config, pos);
|
||||
char *err = midend_set_config(me, CFG_SETTINGS, config);
|
||||
const char *err = midend_set_config(me, CFG_SETTINGS, config);
|
||||
|
||||
if(err)
|
||||
{
|
||||
|
@ -1971,12 +1994,12 @@ static int pausemenu_cb(int action, const struct menu_item_ex *this_item)
|
|||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
if(audiobuf_available)
|
||||
break;
|
||||
else
|
||||
return ACTION_EXIT_MENUITEM;
|
||||
case 9:
|
||||
case 10:
|
||||
if(!midend_get_presets(me, NULL)->n_entries)
|
||||
return ACTION_EXIT_MENUITEM;
|
||||
break;
|
||||
|
@ -2021,21 +2044,21 @@ static int pause_menu(void)
|
|||
#define static auto
|
||||
#define const
|
||||
MENUITEM_STRINGLIST(menu, NULL, pausemenu_cb,
|
||||
"Resume Game",
|
||||
"New Game",
|
||||
"Restart Game",
|
||||
"Undo",
|
||||
"Redo",
|
||||
"Solve",
|
||||
"Zoom In",
|
||||
"Quick Help",
|
||||
"Extensive Help",
|
||||
"Playback Control",
|
||||
"Game Type",
|
||||
"Debug Menu",
|
||||
"Configure Game",
|
||||
"Quit without Saving",
|
||||
"Quit");
|
||||
"Resume Game", // 0
|
||||
"New Game", // 1
|
||||
"Restart Game", // 2
|
||||
"Undo", // 3
|
||||
"Redo", // 4
|
||||
"Solve", // 5
|
||||
"Zoom In", // 6
|
||||
"Quick Help", // 7
|
||||
"Extensive Help", // 8
|
||||
"Playback Control", // 9
|
||||
"Game Type", // 10
|
||||
"Debug Menu", // 11
|
||||
"Configure Game", // 12
|
||||
"Quit without Saving", // 13
|
||||
"Quit"); // 14
|
||||
#undef static
|
||||
#undef const
|
||||
/* HACK ALERT */
|
||||
|
@ -2082,7 +2105,7 @@ static int pause_menu(void)
|
|||
break;
|
||||
case 5:
|
||||
{
|
||||
char *msg = midend_solve(me);
|
||||
const char *msg = midend_solve(me);
|
||||
if(msg)
|
||||
rb->splash(HZ, msg);
|
||||
quit = true;
|
||||
|
@ -2391,7 +2414,7 @@ static int read_wrapper(void *ptr, void *buf, int len)
|
|||
return rb->read(fd, buf, len);
|
||||
}
|
||||
|
||||
static void write_wrapper(void *ptr, void *buf, int len)
|
||||
static void write_wrapper(void *ptr, const void *buf, int len)
|
||||
{
|
||||
int fd = (int) ptr;
|
||||
rb->write(fd, buf, len);
|
||||
|
@ -2416,7 +2439,7 @@ static void init_colors(void)
|
|||
sfree(floatcolors);
|
||||
}
|
||||
|
||||
static char *init_for_game(const game *gm, int load_fd, bool draw)
|
||||
static const char *init_for_game(const game *gm, int load_fd, bool draw)
|
||||
{
|
||||
me = midend_new(NULL, gm, &rb_drawing, NULL);
|
||||
|
||||
|
@ -2424,7 +2447,7 @@ static char *init_for_game(const game *gm, int load_fd, bool draw)
|
|||
midend_new_game(me);
|
||||
else
|
||||
{
|
||||
char *ret = midend_deserialize(me, read_wrapper, (void*) load_fd);
|
||||
const char *ret = midend_deserialize(me, read_wrapper, (void*) load_fd);
|
||||
if(ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -2584,7 +2607,7 @@ static void save_fonts(void)
|
|||
final |= oldmask;
|
||||
uint32_t left = final >> 31;
|
||||
uint32_t right = final & 0x7fffffff;
|
||||
rb->fdprintf(outfd, "%s:%u:%u\n", midend_which_game(me)->name, left, right);
|
||||
rb->fdprintf(outfd, "%s:%lu:%lu\n", midend_which_game(me)->name, left, right);
|
||||
rb->close(outfd);
|
||||
rb->rename(FONT_TABLE ".tmp", FONT_TABLE);
|
||||
}
|
||||
|
@ -2609,7 +2632,7 @@ static bool load_game(void)
|
|||
rb->splash(0, "Loading...");
|
||||
|
||||
char *game;
|
||||
char *ret = identify_game(&game, read_wrapper, (void*)fd);
|
||||
const char *ret = identify_game(&game, read_wrapper, (void*)fd);
|
||||
|
||||
if(!*game && ret)
|
||||
{
|
||||
|
@ -2625,12 +2648,10 @@ static bool load_game(void)
|
|||
|
||||
if(!strcmp(game, thegame.name))
|
||||
{
|
||||
sfree(ret);
|
||||
ret = init_for_game(&thegame, fd, false);
|
||||
if(ret)
|
||||
{
|
||||
rb->splash(HZ, ret);
|
||||
sfree(ret);
|
||||
rb->close(fd);
|
||||
rb->remove(fname);
|
||||
return false;
|
||||
|
@ -2755,15 +2776,15 @@ enum plugin_status plugin_start(const void *param)
|
|||
#define static auto
|
||||
#define const
|
||||
MENUITEM_STRINGLIST(menu, NULL, mainmenu_cb,
|
||||
"Resume Game",
|
||||
"New Game",
|
||||
"Quick Help",
|
||||
"Extensive Help",
|
||||
"Playback Control",
|
||||
"Game Type",
|
||||
"Configure Game",
|
||||
"Quit without Saving",
|
||||
"Quit");
|
||||
"Resume Game", // 0
|
||||
"New Game", // 1
|
||||
"Quick Help", // 2
|
||||
"Extensive Help", // 3
|
||||
"Playback Control", // 4
|
||||
"Game Type", // 5
|
||||
"Configure Game", // 6
|
||||
"Quit without Saving", // 7
|
||||
"Quit"); // 8
|
||||
#undef static
|
||||
#undef const
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue