Same Game: more efficient tile_redraw

I've rewritten tile_redraw to reduce the number of calls to
draw_rect().  Before, it would generally make five calls to
draw_rect() when drawing a tile.  Now it makes at most three, and
usually two.  That's one draw_rect() for each colour that appears in
the tile, which is as good as it can get.  This reduces the time to
draw a large puzzle by about 35% on Firefox 102.

This is of significance to me because CanvasRenderingContext2D on my
test KaiOS device seems to have a limit on the number of fill() and
fillRect() calls that it will tolerate in a short time.  This means
that if you issue more than 1024 fillRect() calls in rapid succession,
the later ones are simply ignored.

Same Game's largest preset called draw_rect() so much that it hit this
limit.  That meant that the right-hand side of the grid didn't get
properly drawn when starting a new game.  Now that it is less
profligate with draw_rect() it fits comfortably within the limit and I
get to see the entire grid.
This commit is contained in:
Ben Harris
2023-07-30 11:30:19 +01:00
parent 76da6ec140
commit 58511aa009

View File

@ -1471,6 +1471,7 @@ static void tile_redraw(drawing *dr, game_drawstate *ds,
int tile, int bgcolour) int tile, int bgcolour)
{ {
int outer = bgcolour, inner = outer, col = tile & TILE_COLMASK; int outer = bgcolour, inner = outer, col = tile & TILE_COLMASK;
int tile_w, tile_h, outer_w, outer_h;
if (col) { if (col) {
if (tile & TILE_IMPOSSIBLE) { if (tile & TILE_IMPOSSIBLE) {
@ -1483,19 +1484,25 @@ static void tile_redraw(drawing *dr, game_drawstate *ds,
outer = inner = col; outer = inner = col;
} }
} }
draw_rect(dr, COORD(x), COORD(y), TILE_INNER, TILE_INNER, outer); tile_w = dright ? TILE_SIZE : TILE_INNER;
draw_rect(dr, COORD(x)+TILE_INNER/4, COORD(y)+TILE_INNER/4, tile_h = dbelow ? TILE_SIZE : TILE_INNER;
TILE_INNER/2, TILE_INNER/2, inner); outer_w = (tile & TILE_JOINRIGHT) ? tile_w : TILE_INNER;
outer_h = (tile & TILE_JOINDOWN) ? tile_h : TILE_INNER;
if (dright) /* Draw the background if any of it will be visible. */
draw_rect(dr, COORD(x)+TILE_INNER, COORD(y), TILE_GAP, TILE_INNER, if (outer_w != tile_w || outer_h != tile_h || outer == bgcolour)
(tile & TILE_JOINRIGHT) ? outer : bgcolour); draw_rect(dr, COORD(x), COORD(y), tile_w, tile_h, bgcolour);
if (dbelow) /* Draw the piece. */
draw_rect(dr, COORD(x), COORD(y)+TILE_INNER, TILE_INNER, TILE_GAP, if (outer != bgcolour)
(tile & TILE_JOINDOWN) ? outer : bgcolour); draw_rect(dr, COORD(x), COORD(y), outer_w, outer_h, outer);
if (dright && dbelow) if (inner != outer)
draw_rect(dr, COORD(x)+TILE_INNER, COORD(y)+TILE_INNER, TILE_GAP, TILE_GAP, draw_rect(dr, COORD(x)+TILE_INNER/4, COORD(y)+TILE_INNER/4,
(tile & TILE_JOINDIAG) ? outer : bgcolour); TILE_INNER/2, TILE_INNER/2, inner);
/* Reset bottom-right corner if necessary. */
if ((tile & (TILE_JOINRIGHT | TILE_JOINDOWN | TILE_JOINDIAG)) ==
(TILE_JOINRIGHT | TILE_JOINDOWN) && outer != bgcolour &&
TILE_GAP != 0)
draw_rect(dr, COORD(x)+TILE_INNER, COORD(y)+TILE_INNER,
TILE_GAP, TILE_GAP, bgcolour);
if (tile & TILE_HASSEL) { if (tile & TILE_HASSEL) {
int sx = COORD(x)+2, sy = COORD(y)+2, ssz = TILE_INNER-5; int sx = COORD(x)+2, sy = COORD(y)+2, ssz = TILE_INNER-5;