ref: 58511aa009c672cc2ade783d537a5830806fd02c
parent: 76da6ec140cbbdac6136469ce50aab40e218f398
author: Ben Harris <bjh21@bjh21.me.uk>
date: Sun Jul 30 07:30:19 EDT 2023
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.
--- a/samegame.c
+++ b/samegame.c
@@ -1471,6 +1471,7 @@
int tile, int bgcolour)
{
int outer = bgcolour, inner = outer, col = tile & TILE_COLMASK;
+ int tile_w, tile_h, outer_w, outer_h;
if (col) {
if (tile & TILE_IMPOSSIBLE) {
@@ -1483,19 +1484,25 @@
outer = inner = col;
}
}
- draw_rect(dr, COORD(x), COORD(y), TILE_INNER, TILE_INNER, outer);
- draw_rect(dr, COORD(x)+TILE_INNER/4, COORD(y)+TILE_INNER/4,
- TILE_INNER/2, TILE_INNER/2, inner);
-
- if (dright)
- draw_rect(dr, COORD(x)+TILE_INNER, COORD(y), TILE_GAP, TILE_INNER,
- (tile & TILE_JOINRIGHT) ? outer : bgcolour);
- if (dbelow)
- draw_rect(dr, COORD(x), COORD(y)+TILE_INNER, TILE_INNER, TILE_GAP,
- (tile & TILE_JOINDOWN) ? outer : bgcolour);
- if (dright && dbelow)
- draw_rect(dr, COORD(x)+TILE_INNER, COORD(y)+TILE_INNER, TILE_GAP, TILE_GAP,
- (tile & TILE_JOINDIAG) ? outer : bgcolour);
+ tile_w = dright ? TILE_SIZE : TILE_INNER;
+ tile_h = dbelow ? TILE_SIZE : TILE_INNER;
+ outer_w = (tile & TILE_JOINRIGHT) ? tile_w : TILE_INNER;
+ outer_h = (tile & TILE_JOINDOWN) ? tile_h : TILE_INNER;
+ /* Draw the background if any of it will be visible. */
+ if (outer_w != tile_w || outer_h != tile_h || outer == bgcolour)
+ draw_rect(dr, COORD(x), COORD(y), tile_w, tile_h, bgcolour);
+ /* Draw the piece. */
+ if (outer != bgcolour)
+ draw_rect(dr, COORD(x), COORD(y), outer_w, outer_h, outer);
+ if (inner != outer)
+ draw_rect(dr, COORD(x)+TILE_INNER/4, COORD(y)+TILE_INNER/4,
+ 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) {
int sx = COORD(x)+2, sy = COORD(y)+2, ssz = TILE_INNER-5;