]> git.draconx.ca Git - rrace.git/blob - src/icon.c
Performance improvements for runtime icon generation.
[rrace.git] / src / icon.c
1 /*
2  * Icon generation helpers for slide puzzle game
3  * Copyright © 2022-2023 Nick Bowler
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18
19 #include <config.h>
20 #include <string.h>
21
22 #include "colour.h"
23 #include "icon.h"
24
25 #define MIN(a, b) ((a) < (b) ? (a) : (b))
26
27 #define primary(c) (((c) >> 8*COLOUR_PRIMARY) & 0xff)
28 #define dark(c)    (((c) >> 8*COLOUR_DARK) & 0xff)
29 #define light(c)   (((c) >> 8*COLOUR_LIGHT) & 0xff)
30
31 static void format_row(unsigned char *row, unsigned long c, unsigned s,
32                        unsigned y, unsigned w, unsigned h)
33 {
34         memset(row, dark(c), w);
35         memset(row, primary(c), y+s < h ? w-s : 0);
36         memset(row, light(c), y >= s ? MIN(s, h-y) : w-y);
37 }
38
39 static void format_row2(unsigned char *row, unsigned long c, unsigned s,
40                         unsigned y, unsigned w, unsigned h, unsigned stride)
41 {
42         row += stride*y;
43         if (y > s && y+s < h) {
44                 if (stride)
45                         memcpy(row, row-stride, w);
46         } else {
47                 format_row(row, c, s, y, w, h);
48         }
49 }
50
51 /*
52  * The 16x16 icon is drawn with 1px shadow, 6x6 tiles, with 1 pixel cropped
53  * off all the edge tiles.
54  */
55 void icon_tile16(unsigned char *icon, unsigned long c, int tile_x, int tile_y)
56 {
57         unsigned char row[6];
58         unsigned y, w;
59
60         icon += 16*(11u*tile_y / 2) + (11u*tile_x / 2);
61
62         w = 5+(tile_x&1u);
63         for (y = !tile_y; y < 6-(tile_y==2); y++) {
64                 format_row2(row, c, 1, y, 6, 6, 0);
65                 memcpy(&icon[16*(y-!tile_y)], &row[!tile_x], w);
66         }
67 }
68
69 /*
70  * The 24x24 icon is drawn with 1px shadow and 8x8 tiles.
71  */
72 void icon_tile24(unsigned char *icon, unsigned long c, int tile_x, int tile_y)
73 {
74         unsigned y;
75
76         icon += 8*(24u*tile_y + tile_x);
77
78         for (y = 0; y < 8; y++) {
79                 format_row2(icon, c, 1, y, 8, 8, 24);
80         }
81 }
82
83 /*
84  * The 32x32 icon is drawn with 1px shadow with slightly uneven tiles on
85  * an 11-10-11 pixel grid.
86  */
87 void icon_tile32(unsigned char *icon, unsigned long c, int tile_x, int tile_y)
88 {
89         unsigned y, w, h;
90
91         icon += 32*(10u*tile_y + !!tile_y) + (10u*tile_x + !!tile_x);
92
93         w = 10u + (tile_x != 1);
94         h = 10u + (tile_y != 1);
95         for (y = 0; y < h; y++) {
96                 format_row2(icon, c, 1, y, w, h, 32);
97         }
98 }
99
100 /*
101  * The 48x48 icon is drawn with 2px shadow and 16x16 tiles.
102  */
103 void icon_tile48(unsigned char *icon, unsigned long c, int tile_x, int tile_y)
104 {
105         unsigned y;
106
107         icon += 16*(48u*tile_y + tile_x);
108
109         for (y = 0; y < 16; y++) {
110                 format_row2(icon, c, 2, y, 16, 16, 48);
111         }
112 }