summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/drawing.c
diff options
context:
space:
mode:
authorFranklin Wei <franklin@rockbox.org>2024-08-11 23:34:57 -0400
committerFranklin Wei <franklin@rockbox.org>2024-08-16 16:31:28 -0400
commitea0e3704a8aacf87f20ba87e3b33bc4b3966c731 (patch)
tree8db0a329800cffd661f6a80767ce2f956eb57ab8 /apps/plugins/puzzles/src/drawing.c
parent903e8c5b32285e50907e6525388162bd459cbef8 (diff)
downloadrockbox-ea0e3704a8aacf87f20ba87e3b33bc4b3966c731.tar.gz
rockbox-ea0e3704a8aacf87f20ba87e3b33bc4b3966c731.zip
puzzles: resync with upstream 262f709.
This is the first resync with a fully unmodified upstream repo. This includes a new scanline polygon renderer in the upstream puzzles distribution. This allows us to get rid of the monstrosity of a polygon renderer we had been shipping in rockbox.c. Change-Id: I23628c74bb5ff7a9e7932bf16d68a1c867c49969
Diffstat (limited to 'apps/plugins/puzzles/src/drawing.c')
-rw-r--r--apps/plugins/puzzles/src/drawing.c196
1 files changed, 120 insertions, 76 deletions
diff --git a/apps/plugins/puzzles/src/drawing.c b/apps/plugins/puzzles/src/drawing.c
index 2c8816c31a..a754b068f3 100644
--- a/apps/plugins/puzzles/src/drawing.c
+++ b/apps/plugins/puzzles/src/drawing.c
@@ -42,9 +42,12 @@ struct print_colour {
42 float grey; 42 float grey;
43}; 43};
44 44
45struct drawing { 45typedef struct drawing_internal {
46 const drawing_api *api; 46 /* we implement data hiding by casting `struct drawing*` pointers
47 void *handle; 47 * to `struct drawing_internal*` */
48 struct drawing pub;
49
50 /* private data */
48 struct print_colour *colours; 51 struct print_colour *colours;
49 int ncolours, coloursize; 52 int ncolours, coloursize;
50 float scale; 53 float scale;
@@ -52,53 +55,70 @@ struct drawing {
52 * this may set it to NULL. */ 55 * this may set it to NULL. */
53 midend *me; 56 midend *me;
54 char *laststatus; 57 char *laststatus;
55}; 58} drawing_internal;
59
60#define PRIVATE_CAST(dr) ((drawing_internal*)(dr))
61#define PUBLIC_CAST(dri) ((drawing*)(dri))
62
63/* See puzzles.h for a description of the version number. */
64#define DRAWING_API_VERSION 1
56 65
57drawing *drawing_new(const drawing_api *api, midend *me, void *handle) 66drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
58{ 67{
59 drawing *dr = snew(drawing); 68 if(api->version != DRAWING_API_VERSION) {
60 dr->api = api; 69 fatal("Drawing API version mismatch: expected: %d, actual: %d\n", DRAWING_API_VERSION, api->version);
61 dr->handle = handle; 70 /* shouldn't get here */
62 dr->colours = NULL; 71 return NULL;
63 dr->ncolours = dr->coloursize = 0; 72 }
64 dr->scale = 1.0F; 73
65 dr->me = me; 74 drawing_internal *dri = snew(drawing_internal);
66 dr->laststatus = NULL; 75 dri->pub.api = api;
67 return dr; 76 dri->pub.handle = handle;
77 dri->colours = NULL;
78 dri->ncolours = dri->coloursize = 0;
79 dri->scale = 1.0F;
80 dri->me = me;
81 dri->laststatus = NULL;
82 return PUBLIC_CAST(dri);
68} 83}
69 84
70void drawing_free(drawing *dr) 85void drawing_free(drawing *dr)
71{ 86{
72 sfree(dr->laststatus); 87 drawing_internal *dri = PRIVATE_CAST(dr);
73 sfree(dr->colours); 88 sfree(dri->laststatus);
74 sfree(dr); 89 sfree(dri->colours);
90 sfree(dri);
75} 91}
76 92
77void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize, 93void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
78 int align, int colour, const char *text) 94 int align, int colour, const char *text)
79{ 95{
80 dr->api->draw_text(dr->handle, x, y, fonttype, fontsize, align, 96 drawing_internal *dri = PRIVATE_CAST(dr);
81 colour, text); 97 dri->pub.api->draw_text(dr, x, y, fonttype, fontsize, align,
98 colour, text);
82} 99}
83 100
84void draw_rect(drawing *dr, int x, int y, int w, int h, int colour) 101void draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
85{ 102{
86 dr->api->draw_rect(dr->handle, x, y, w, h, colour); 103 drawing_internal *dri = PRIVATE_CAST(dr);
104 dri->pub.api->draw_rect(dr, x, y, w, h, colour);
87} 105}
88 106
89void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) 107void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
90{ 108{
91 dr->api->draw_line(dr->handle, x1, y1, x2, y2, colour); 109 drawing_internal *dri = PRIVATE_CAST(dr);
110 dri->pub.api->draw_line(dr, x1, y1, x2, y2, colour);
92} 111}
93 112
94void draw_thick_line(drawing *dr, float thickness, 113void draw_thick_line(drawing *dr, float thickness,
95 float x1, float y1, float x2, float y2, int colour) 114 float x1, float y1, float x2, float y2, int colour)
96{ 115{
116 drawing_internal *dri = PRIVATE_CAST(dr);
97 if (thickness < 1.0F) 117 if (thickness < 1.0F)
98 thickness = 1.0F; 118 thickness = 1.0F;
99 if (dr->api->draw_thick_line) { 119 if (dri->pub.api->draw_thick_line) {
100 dr->api->draw_thick_line(dr->handle, thickness, 120 dri->pub.api->draw_thick_line(dr, thickness,
101 x1, y1, x2, y2, colour); 121 x1, y1, x2, y2, colour);
102 } else { 122 } else {
103 /* We'll fake it up with a filled polygon. The tweak to the 123 /* We'll fake it up with a filled polygon. The tweak to the
104 * thickness empirically compensates for rounding errors, because 124 * thickness empirically compensates for rounding errors, because
@@ -117,59 +137,67 @@ void draw_thick_line(drawing *dr, float thickness,
117 p[5] = y2 - tvhatx; 137 p[5] = y2 - tvhatx;
118 p[6] = x1 + tvhaty; 138 p[6] = x1 + tvhaty;
119 p[7] = y1 - tvhatx; 139 p[7] = y1 - tvhatx;
120 dr->api->draw_polygon(dr->handle, p, 4, colour, colour); 140 dri->pub.api->draw_polygon(dr, p, 4, colour, colour);
121 } 141 }
122} 142}
123 143
124void draw_polygon(drawing *dr, const int *coords, int npoints, 144void draw_polygon(drawing *dr, const int *coords, int npoints,
125 int fillcolour, int outlinecolour) 145 int fillcolour, int outlinecolour)
126{ 146{
127 dr->api->draw_polygon(dr->handle, coords, npoints, fillcolour, 147 drawing_internal *dri = PRIVATE_CAST(dr);
128 outlinecolour); 148 dri->pub.api->draw_polygon(dr, coords, npoints, fillcolour,
149 outlinecolour);
129} 150}
130 151
131void draw_circle(drawing *dr, int cx, int cy, int radius, 152void draw_circle(drawing *dr, int cx, int cy, int radius,
132 int fillcolour, int outlinecolour) 153 int fillcolour, int outlinecolour)
133{ 154{
134 dr->api->draw_circle(dr->handle, cx, cy, radius, fillcolour, 155 drawing_internal *dri = PRIVATE_CAST(dr);
135 outlinecolour); 156 dri->pub.api->draw_circle(dr, cx, cy, radius, fillcolour,
157 outlinecolour);
136} 158}
137 159
138void draw_update(drawing *dr, int x, int y, int w, int h) 160void draw_update(drawing *dr, int x, int y, int w, int h)
139{ 161{
140 if (dr->api->draw_update) 162 drawing_internal *dri = PRIVATE_CAST(dr);
141 dr->api->draw_update(dr->handle, x, y, w, h); 163 if (dri->pub.api->draw_update)
164 dri->pub.api->draw_update(dr, x, y, w, h);
142} 165}
143 166
144void clip(drawing *dr, int x, int y, int w, int h) 167void clip(drawing *dr, int x, int y, int w, int h)
145{ 168{
146 dr->api->clip(dr->handle, x, y, w, h); 169 drawing_internal *dri = PRIVATE_CAST(dr);
170 dri->pub.api->clip(dr, x, y, w, h);
147} 171}
148 172
149void unclip(drawing *dr) 173void unclip(drawing *dr)
150{ 174{
151 dr->api->unclip(dr->handle); 175 drawing_internal *dri = PRIVATE_CAST(dr);
176 dri->pub.api->unclip(dr);
152} 177}
153 178
154void start_draw(drawing *dr) 179void start_draw(drawing *dr)
155{ 180{
156 dr->api->start_draw(dr->handle); 181 drawing_internal *dri = PRIVATE_CAST(dr);
182 dri->pub.api->start_draw(dr);
157} 183}
158 184
159void end_draw(drawing *dr) 185void end_draw(drawing *dr)
160{ 186{
161 dr->api->end_draw(dr->handle); 187 drawing_internal *dri = PRIVATE_CAST(dr);
188 dri->pub.api->end_draw(dr);
162} 189}
163 190
164char *text_fallback(drawing *dr, const char *const *strings, int nstrings) 191char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
165{ 192{
193 drawing_internal *dri = PRIVATE_CAST(dr);
166 int i; 194 int i;
167 195
168 /* 196 /*
169 * If the drawing implementation provides one of these, use it. 197 * If the drawing implementation provides one of these, use it.
170 */ 198 */
171 if (dr && dr->api->text_fallback) 199 if (dr && dri->pub.api->text_fallback)
172 return dr->api->text_fallback(dr->handle, strings, nstrings); 200 return dri->pub.api->text_fallback(dr, strings, nstrings);
173 201
174 /* 202 /*
175 * Otherwise, do the simple thing and just pick the first string 203 * Otherwise, do the simple thing and just pick the first string
@@ -196,18 +224,19 @@ char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
196 224
197void status_bar(drawing *dr, const char *text) 225void status_bar(drawing *dr, const char *text)
198{ 226{
227 drawing_internal *dri = PRIVATE_CAST(dr);
199 char *rewritten; 228 char *rewritten;
200 229
201 if (!dr->api->status_bar) 230 if (!dri->pub.api->status_bar)
202 return; 231 return;
203 232
204 assert(dr->me); 233 assert(dri->me);
205 234
206 rewritten = midend_rewrite_statusbar(dr->me, text); 235 rewritten = midend_rewrite_statusbar(dri->me, text);
207 if (!dr->laststatus || strcmp(rewritten, dr->laststatus)) { 236 if (!dri->laststatus || strcmp(rewritten, dri->laststatus)) {
208 dr->api->status_bar(dr->handle, rewritten); 237 dri->pub.api->status_bar(dr, rewritten);
209 sfree(dr->laststatus); 238 sfree(dri->laststatus);
210 dr->laststatus = rewritten; 239 dri->laststatus = rewritten;
211 } else { 240 } else {
212 sfree(rewritten); 241 sfree(rewritten);
213 } 242 }
@@ -215,74 +244,85 @@ void status_bar(drawing *dr, const char *text)
215 244
216blitter *blitter_new(drawing *dr, int w, int h) 245blitter *blitter_new(drawing *dr, int w, int h)
217{ 246{
218 return dr->api->blitter_new(dr->handle, w, h); 247 drawing_internal *dri = PRIVATE_CAST(dr);
248 return dri->pub.api->blitter_new(dr, w, h);
219} 249}
220 250
221void blitter_free(drawing *dr, blitter *bl) 251void blitter_free(drawing *dr, blitter *bl)
222{ 252{
223 dr->api->blitter_free(dr->handle, bl); 253 drawing_internal *dri = PRIVATE_CAST(dr);
254 dri->pub.api->blitter_free(dr, bl);
224} 255}
225 256
226void blitter_save(drawing *dr, blitter *bl, int x, int y) 257void blitter_save(drawing *dr, blitter *bl, int x, int y)
227{ 258{
228 dr->api->blitter_save(dr->handle, bl, x, y); 259 drawing_internal *dri = PRIVATE_CAST(dr);
260 dri->pub.api->blitter_save(dr, bl, x, y);
229} 261}
230 262
231void blitter_load(drawing *dr, blitter *bl, int x, int y) 263void blitter_load(drawing *dr, blitter *bl, int x, int y)
232{ 264{
233 dr->api->blitter_load(dr->handle, bl, x, y); 265 drawing_internal *dri = PRIVATE_CAST(dr);
266 dri->pub.api->blitter_load(dr, bl, x, y);
234} 267}
235 268
236void print_begin_doc(drawing *dr, int pages) 269void print_begin_doc(drawing *dr, int pages)
237{ 270{
238 dr->api->begin_doc(dr->handle, pages); 271 drawing_internal *dri = PRIVATE_CAST(dr);
272 dri->pub.api->begin_doc(dr, pages);
239} 273}
240 274
241void print_begin_page(drawing *dr, int number) 275void print_begin_page(drawing *dr, int number)
242{ 276{
243 dr->api->begin_page(dr->handle, number); 277 drawing_internal *dri = PRIVATE_CAST(dr);
278 dri->pub.api->begin_page(dr, number);
244} 279}
245 280
246void print_begin_puzzle(drawing *dr, float xm, float xc, 281void print_begin_puzzle(drawing *dr, float xm, float xc,
247 float ym, float yc, int pw, int ph, float wmm, 282 float ym, float yc, int pw, int ph, float wmm,
248 float scale) 283 float scale)
249{ 284{
250 dr->scale = scale; 285 drawing_internal *dri = PRIVATE_CAST(dr);
251 dr->ncolours = 0; 286 dri->scale = scale;
252 dr->api->begin_puzzle(dr->handle, xm, xc, ym, yc, pw, ph, wmm); 287 dri->ncolours = 0;
288 dri->pub.api->begin_puzzle(dr, xm, xc, ym, yc, pw, ph, wmm);
253} 289}
254 290
255void print_end_puzzle(drawing *dr) 291void print_end_puzzle(drawing *dr)
256{ 292{
257 dr->api->end_puzzle(dr->handle); 293 drawing_internal *dri = PRIVATE_CAST(dr);
258 dr->scale = 1.0F; 294 dri->pub.api->end_puzzle(dr);
295 dri->scale = 1.0F;
259} 296}
260 297
261void print_end_page(drawing *dr, int number) 298void print_end_page(drawing *dr, int number)
262{ 299{
263 dr->api->end_page(dr->handle, number); 300 drawing_internal *dri = PRIVATE_CAST(dr);
301 dri->pub.api->end_page(dr, number);
264} 302}
265 303
266void print_end_doc(drawing *dr) 304void print_end_doc(drawing *dr)
267{ 305{
268 dr->api->end_doc(dr->handle); 306 drawing_internal *dri = PRIVATE_CAST(dr);
307 dri->pub.api->end_doc(dr);
269} 308}
270 309
271void print_get_colour(drawing *dr, int colour, bool printing_in_colour, 310void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
272 int *hatch, float *r, float *g, float *b) 311 int *hatch, float *r, float *g, float *b)
273{ 312{
274 assert(colour >= 0 && colour < dr->ncolours); 313 drawing_internal *dri = PRIVATE_CAST(dr);
275 if (dr->colours[colour].hatch_when == 2 || 314 assert(colour >= 0 && colour < dri->ncolours);
276 (dr->colours[colour].hatch_when == 1 && !printing_in_colour)) { 315 if (dri->colours[colour].hatch_when == 2 ||
277 *hatch = dr->colours[colour].hatch; 316 (dri->colours[colour].hatch_when == 1 && !printing_in_colour)) {
317 *hatch = dri->colours[colour].hatch;
278 } else { 318 } else {
279 *hatch = -1; 319 *hatch = -1;
280 if (printing_in_colour) { 320 if (printing_in_colour) {
281 *r = dr->colours[colour].r; 321 *r = dri->colours[colour].r;
282 *g = dr->colours[colour].g; 322 *g = dri->colours[colour].g;
283 *b = dr->colours[colour].b; 323 *b = dri->colours[colour].b;
284 } else { 324 } else {
285 *r = *g = *b = dr->colours[colour].grey; 325 *r = *g = *b = dri->colours[colour].grey;
286 } 326 }
287 } 327 }
288} 328}
@@ -290,18 +330,19 @@ void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
290static int print_generic_colour(drawing *dr, float r, float g, float b, 330static int print_generic_colour(drawing *dr, float r, float g, float b,
291 float grey, int hatch, int hatch_when) 331 float grey, int hatch, int hatch_when)
292{ 332{
293 if (dr->ncolours >= dr->coloursize) { 333 drawing_internal *dri = PRIVATE_CAST(dr);
294 dr->coloursize = dr->ncolours + 16; 334 if (dri->ncolours >= dri->coloursize) {
295 dr->colours = sresize(dr->colours, dr->coloursize, 335 dri->coloursize = dri->ncolours + 16;
336 dri->colours = sresize(dri->colours, dri->coloursize,
296 struct print_colour); 337 struct print_colour);
297 } 338 }
298 dr->colours[dr->ncolours].hatch = hatch; 339 dri->colours[dri->ncolours].hatch = hatch;
299 dr->colours[dr->ncolours].hatch_when = hatch_when; 340 dri->colours[dri->ncolours].hatch_when = hatch_when;
300 dr->colours[dr->ncolours].r = r; 341 dri->colours[dri->ncolours].r = r;
301 dr->colours[dr->ncolours].g = g; 342 dri->colours[dri->ncolours].g = g;
302 dr->colours[dr->ncolours].b = b; 343 dri->colours[dri->ncolours].b = b;
303 dr->colours[dr->ncolours].grey = grey; 344 dri->colours[dri->ncolours].grey = grey;
304 return dr->ncolours++; 345 return dri->ncolours++;
305} 346}
306 347
307int print_mono_colour(drawing *dr, int grey) 348int print_mono_colour(drawing *dr, int grey)
@@ -336,6 +377,8 @@ int print_rgb_hatched_colour(drawing *dr, float r, float g, float b, int hatch)
336 377
337void print_line_width(drawing *dr, int width) 378void print_line_width(drawing *dr, int width)
338{ 379{
380 drawing_internal *dri = PRIVATE_CAST(dr);
381
339 /* 382 /*
340 * I don't think it's entirely sensible to have line widths be 383 * I don't think it's entirely sensible to have line widths be
341 * entirely relative to the puzzle size; there is a point 384 * entirely relative to the puzzle size; there is a point
@@ -348,10 +391,11 @@ void print_line_width(drawing *dr, int width)
348 * _square root_ of the main puzzle scale. Double the puzzle 391 * _square root_ of the main puzzle scale. Double the puzzle
349 * size, and the line width multiplies by 1.4. 392 * size, and the line width multiplies by 1.4.
350 */ 393 */
351 dr->api->line_width(dr->handle, (float)sqrt(dr->scale) * width); 394 dri->pub.api->line_width(dr, (float)sqrt(dri->scale) * width);
352} 395}
353 396
354void print_line_dotted(drawing *dr, bool dotted) 397void print_line_dotted(drawing *dr, bool dotted)
355{ 398{
356 dr->api->line_dotted(dr->handle, dotted); 399 drawing_internal *dri = PRIVATE_CAST(dr);
400 dri->pub.api->line_dotted(dr, dotted);
357} 401}