1 /*
2  * Copyright 2009-2021 Peter Kosyh <p.kosyh at gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 
25 #include "externals.h"
26 #include "internals.h"
27 #include "noise1234.h"
28 
29 static LIST_HEAD(sprites);
30 
31 static LIST_HEAD(fonts);
32 
33 #define FN_SCALED 1
34 
35 typedef struct {
36 	struct list_node list;
37 	char	*name;
38 	int	flags;
39 	fnt_t	fnt;
40 } _fnt_t;
41 
42 typedef struct {
43 	struct list_node list;
44 	char	*name;
45 	img_t	img;
46 } _spr_t;
47 
48 struct lua_pixels;
49 
50 static img_t pixels_img(struct lua_pixels *hdr);
51 
sprites_free(void)52 static void sprites_free(void)
53 {
54 /*	fprintf(stderr, "sprites free \n"); */
55 	while (!list_empty(&sprites)) {
56 		_spr_t *sp = list_top(&sprites, _spr_t, list);
57 		free(sp->name);
58 		cache_forget(gfx_image_cache(), sp->img);
59 		list_del(&sp->list);
60 		free(sp);
61 	}
62 	while (!list_empty(&fonts)) {
63 		_fnt_t *fn = list_top(&fonts, _fnt_t, list);
64 		fnt_free(fn->fnt);
65 		free(fn->name);
66 		list_del(&fn->list);
67 		free(fn);
68 	}
69 	game_pict_modify(NULL);
70 	cache_shrink(gfx_image_cache());
71 }
72 
sprite_lookup(const char * name)73 static _spr_t *sprite_lookup(const char *name)
74 {
75 	_spr_t *pos = NULL;
76 	_spr_t *sp;
77 	list_for_each(&sprites, pos, list) {
78 		sp = (_spr_t*)pos;
79 		if (!strcmp(name, sp->name)) {
80 			list_del(&sp->list);
81 			list_add(&sprites, &sp->list); /* move it on head */
82 			return sp;
83 		}
84 	}
85 	return NULL;
86 }
87 
font_lookup(const char * name)88 static _fnt_t *font_lookup(const char *name)
89 {
90 	_fnt_t *pos = NULL;
91 	_fnt_t *fn;
92 	list_for_each(&fonts, pos, list) {
93 		fn = (_fnt_t*)pos;
94 		if (!strcmp(name, fn->name)) {
95 			list_del(&fn->list);
96 			list_add(&fonts, &fn->list); /* move it on head */
97 			return fn;
98 		}
99 	}
100 	return NULL;
101 }
102 
sprite_new(const char * name,img_t img)103 static _spr_t *sprite_new(const char *name, img_t img)
104 {
105 	_spr_t *sp;
106 	sp = malloc(sizeof(_spr_t));
107 	if (!sp)
108 		return NULL;
109 /*	INIT_LIST_HEAD(&sp->list); */
110 	sp->name = strdup(name);
111 	if (!sp->name) {
112 		free(sp);
113 		return NULL;
114 	}
115 	sp->img = img;
116 	if (cache_add(gfx_image_cache(), name, img)) {
117 		free(sp->name);
118 		free(sp);
119 		return NULL;
120 	}
121 /*	fprintf(stderr, "added: %s\n", name); */
122 	list_add(&sprites, &sp->list);
123 	return sp;
124 }
125 
font_new(const char * name,fnt_t fnt)126 static _fnt_t *font_new(const char *name, fnt_t fnt)
127 {
128 	_fnt_t *fn;
129 	fn = malloc(sizeof(_fnt_t));
130 	if (!fn)
131 		return NULL;
132 /*	INIT_LIST_HEAD(&fn->list); */
133 	fn->name = strdup(name);
134 	if (!fn->name) {
135 		free(fn);
136 		return NULL;
137 	}
138 	fn->fnt = fnt;
139 	fn->flags = 0;
140 	list_add(&fonts, &fn->list);
141 	return fn;
142 }
143 
sprite_name(const char * name,char * sname,int size)144 static void sprite_name(const char *name, char *sname, int size)
145 {
146 	unsigned long h = 0;
147 	if (!sname || !size)
148 		return;
149 	h = hash_string(name);
150 	do { /* new uniq name */
151 		snprintf(sname, size, "spr:%lx", h);
152 		h ++;
153 	} while (sprite_lookup(sname) || cache_lookup(gfx_image_cache(), sname));
154 	sname[size - 1] = 0;
155 }
156 
font_name(const char * name,char * sname,int size)157 static void font_name(const char *name, char *sname, int size)
158 {
159 	unsigned long h = 0;
160 	if (!sname || !size)
161 		return;
162 	h = hash_string(name);
163 	do { /* new uniq name */
164 		snprintf(sname, size, "fnt:%lx", h);
165 		h ++;
166 	} while (font_lookup(sname));
167 	sname[size - 1] = 0;
168 }
169 
170 static int _free_sprite(const char *key);
171 
luaB_free_sprites(lua_State * L)172 static int luaB_free_sprites(lua_State *L) {
173 	sprites_free();
174 	return 0;
175 }
176 
177 #define PIXELS_MAGIC 0x1980
178 struct lua_pixels {
179 	int type;
180 	int w;
181 	int h;
182 	float scale;
183 	size_t size;
184 	img_t img;
185 	int dirty;
186 	int direct;
187 };
188 
luaB_load_sprite(lua_State * L)189 static int luaB_load_sprite(lua_State *L) {
190 	int convert = 0;
191 	img_t img = NULL;
192 	_spr_t *sp;
193 	const char *key;
194 	char sname[sizeof(unsigned long) * 2 + 16];
195 	struct lua_pixels *pixels = lua_touserdata(L, 1);
196 	const char *desc = NULL;
197 	const char *fname = NULL;
198 	char pixels_name[32];
199 	if (lua_isstring(L, 2))
200 		desc = luaL_optstring(L, 2, NULL);
201 	if (!pixels)
202 		fname = luaL_optstring(L, 1, NULL);
203 	else {
204 		snprintf(pixels_name, sizeof(pixels_name), "pxl:%p", pixels);
205 		pixels_name[sizeof(pixels_name) - 1] = 0;
206 		fname = pixels_name;
207 	}
208 
209 	if (!fname)
210 		return 0;
211 
212 	if (pixels) {
213 		if (lua_isboolean(L, 2)) {
214 			convert = lua_toboolean(L, 2);
215 			desc = luaL_optstring(L, 3, NULL);
216 		}
217 		if (convert) { /* slow path */
218 			img = gfx_new_from(pixels->w, pixels->h, (unsigned char*)(pixels + 1));
219 			if (img)
220 				theme_gfx_scale(&img, pixels->scale);
221 		} else {
222 			img = pixels_img(pixels);
223 			if (img)
224 				img = gfx_dup(img);
225 		}
226 	} else {
227 		img = gfx_load_image((char*)fname);
228 		if (img)
229 			theme_gfx_scale(&img, 1.0f);
230 	}
231 	if (img)
232 		img = gfx_display_alpha(img); /*speed up */
233 
234 	if (!img)
235 		goto err;
236 
237 	if (!desc || sprite_lookup(desc)) {
238 		key = sname;
239 		sprite_name(fname, sname, sizeof(sname));
240 	} else
241 		key = desc;
242 	sp = sprite_new(key, img);
243 	if (!sp)
244 		goto err;
245 
246 	lua_pushstring(L, key);
247 	return 1;
248 err:
249 	game_res_err_msg(fname, debug_sw);
250 	gfx_free_image(img);
251 	return 0;
252 }
253 
luaB_load_font(lua_State * L)254 static int luaB_load_font(lua_State *L) {
255 	int scaled = 0;
256 	fnt_t fnt = NULL;
257 	_fnt_t *fn;
258 	const char *key;
259 	char sname[sizeof(unsigned long) * 2 + 16];
260 	struct game_theme *t = &game_theme;
261 
262 	const char *fname = luaL_optstring(L, 1, NULL);
263 	int sz = luaL_optnumber(L, 2, t->font_size);
264 	const char *desc = luaL_optstring(L, 3, NULL);
265 	if (!fname || sz == 0)
266 		return 0;
267 	if (sz > 0) {
268 		sz *= game_theme.scale;
269 		scaled = 1;
270 	} else
271 		sz = - sz; /* sz < 0 is unscalable */
272 	fnt = fnt_load((char*)fname, sz);
273 
274 	if (!fnt)
275 		return 0;
276 
277 	if (!desc || font_lookup(desc)) {
278 		key = sname;
279 		font_name(fname, sname, sizeof(sname));
280 	} else
281 		key = desc;
282 
283 	fn = font_new(key, fnt);
284 	if (!fn)
285 		goto err;
286 
287 	if (scaled)
288 		fn->flags |= FN_SCALED;
289 
290 	lua_pushstring(L, key);
291 	return 1;
292 err:
293 	fnt_free(fnt);
294 	return 0;
295 }
296 
luaB_text_size(lua_State * L)297 static int luaB_text_size(lua_State *L) {
298 	_fnt_t *fn;
299 	int w = 0, h = 0;
300 
301 	const char *font = luaL_optstring(L, 1, NULL);
302 	const char *text = luaL_optstring(L, 2, NULL);
303 	int style = luaL_optnumber(L, 3, 0);
304 
305 	if (!font)
306 		return 0;
307 
308 	fn = font_lookup(font);
309 
310 	if (!fn)
311 		return 0;
312 	if (!text) {
313 		w = 0;
314 		if (fn->flags & FN_SCALED)
315 			h = ceil((float)fnt_height(fn->fnt) / game_theme.scale);
316 		else
317 			h = fnt_height(fn->fnt);
318 	} else {
319 		fnt_style(fn->fnt, style);
320 		txt_size(fn->fnt, text, &w, &h);
321 		if (fn->flags & FN_SCALED) {
322 			w = ceil((float)w / game_theme.scale);
323 			h = ceil((float)h / game_theme.scale);
324 		}
325 	}
326 	lua_pushinteger(L, w);
327 	lua_pushinteger(L, h);
328 	return 2;
329 }
330 
luaB_font_size_scaled(lua_State * L)331 static int luaB_font_size_scaled(lua_State *L) {
332 	int sz = luaL_optnumber(L, 1, game_theme.font_size);
333 	lua_pushinteger(L, FONT_SZ(sz));
334 	return 1;
335 }
336 
luaB_text_sprite(lua_State * L)337 static int luaB_text_sprite(lua_State *L) {
338 	img_t img = NULL;
339 	_spr_t *sp;
340 	_fnt_t *fn;
341 	const char *key;
342 	char sname[sizeof(unsigned long) * 2 + 16];
343 
344 	const char *font = luaL_optstring(L, 1, NULL);
345 	const char *text = luaL_optstring(L, 2, NULL);
346 	char txtkey[32];
347 	const char *color = luaL_optstring(L, 3, NULL);
348 	int style = luaL_optnumber(L, 4, 0);
349 	const char *desc = luaL_optstring(L, 5, NULL);
350 
351 	color_t col = { .r = game_theme.fgcol.r, .g = game_theme.fgcol.g, .b = game_theme.fgcol.b };
352 
353 	if (!font)
354 		return 0;
355 	if (color)
356 		gfx_parse_color (color, &col);
357 	if (!text)
358 		text = "";
359 
360 	fn = font_lookup(font);
361 
362 	if (!fn)
363 		return 0;
364 
365 	fnt_style(fn->fnt, style);
366 
367 	img = fnt_render(fn->fnt, text, col);
368 
369 	if (img)
370 		img = gfx_display_alpha(img); /*speed up */
371 
372 	if (!img)
373 		return 0;
374 
375 	if (!desc || sprite_lookup(desc)) {
376 		key = sname;
377 		strncpy(txtkey, text, sizeof(txtkey));
378 		txtkey[sizeof(txtkey) - 1] = 0;
379 		sprite_name(txtkey, sname, sizeof(sname));
380 	} else
381 		key = desc;
382 
383 	sp = sprite_new(key, img);
384 
385 	if (!sp)
386 		goto err;
387 
388 	lua_pushstring(L, key);
389 	return 1;
390 err:
391 	gfx_free_image(img);
392 	return 0;
393 }
394 
395 static int in_callback = 0;
396 
grab_sprite(const char * dst,int * xoff,int * yoff)397 static img_t grab_sprite(const char *dst, int *xoff, int *yoff)
398 {
399 	img_t oldscreen;
400 	img_t d;
401 	if (!dst)
402 		return NULL;
403 	if ((DIRECT_MODE || in_callback) && !strcmp(dst, "screen")) {
404 		d = gfx_screen(NULL);
405 		*xoff = game_theme.xoff;
406 		*yoff = game_theme.yoff;
407 	} else if (opt_owntheme && !strcmp(dst, "screen")) {
408 		if (!game_theme.bg) { /* create on the fly */
409 			game_theme.bg = gfx_new(game_theme.w, game_theme.h);
410 			oldscreen = gfx_screen(game_theme.bg);
411 			gfx_clear(0, 0, game_theme.w, game_theme.h);
412 			gfx_screen(oldscreen);
413 		}
414 		d = game_theme.bg;
415 		*xoff = game_theme.xoff;
416 		*yoff = game_theme.yoff;
417 	} else {
418 		*xoff = 0;
419 		*yoff = 0;
420 		d = cache_lookup(gfx_image_cache(), dst);
421 	}
422 	return d;
423 }
424 
425 
luaB_sprite_size(lua_State * L)426 static int luaB_sprite_size(lua_State *L) {
427 	img_t s = NULL;
428 	float v;
429 	int w, h;
430 	int xoff, yoff;
431 	const char *src = luaL_optstring(L, 1, NULL);
432 	if (!src)
433 		return 0;
434 	s = grab_sprite(src, &xoff, &yoff);
435 	if (!s)
436 		return 0;
437 
438 	v = game_theme.scale;
439 
440 	w = ceil ((float)(gfx_img_w(s) - xoff * 2) / v);
441 	h = ceil ((float)(gfx_img_h(s) - yoff * 2) / v);
442 
443 	lua_pushinteger(L, w);
444 	lua_pushinteger(L, h);
445 	return 2;
446 }
447 
448 #define BLIT_COPY 0
449 #define BLIT_DRAW 1
450 #define BLIT_COMPOSE 2
451 
luaB_blit_sprite(lua_State * L,int mode)452 static int luaB_blit_sprite(lua_State *L, int mode) {
453 	img_t s = NULL, d = NULL;
454 	float v;
455 	struct lua_pixels *pixels = lua_touserdata(L, 1);
456 	const char *src = NULL;
457 
458 	int x = luaL_optnumber(L, 2, 0);
459 	int y = luaL_optnumber(L, 3, 0);
460 	int w = luaL_optnumber(L, 4, -1);
461 	int h = luaL_optnumber(L, 5, -1);
462 	const char *dst = luaL_optstring(L, 6, NULL);
463 	int xx = luaL_optnumber(L, 7, 0);
464 	int yy = luaL_optnumber(L, 8, 0);
465 	int alpha = luaL_optnumber(L, 9, 255);
466 	int xoff = 0, yoff = 0;
467 	int xoff0 = 0, yoff0 = 0;
468 
469 	if (!pixels)
470 		src = luaL_optstring(L, 1, NULL);
471 
472 	if ((!src && !pixels) || !dst)
473 		return 0;
474 
475 	if (pixels)
476 		s = pixels_img(pixels);
477 	if (!s)
478 		s = grab_sprite(src, &xoff0, &yoff0);
479 
480 	d = grab_sprite(dst, &xoff, &yoff);
481 
482 	if (!s || !d)
483 		return 0;
484 
485 	v = game_theme.scale;
486 
487 	if (v != 1.0f) {
488 		x *= v;
489 		y *= v;
490 		if (w != -1)
491 			w = ceil(w * v);
492 		if (h != -1)
493 			h = ceil(h * v);
494 		xx *= v;
495 		yy *= v;
496 	}
497 
498 	if (w == -1)
499 		w = gfx_img_w(s) - 2 * xoff0;
500 	if (h == -1)
501 		h = gfx_img_h(s) - 2 * yoff0;
502 
503 	game_pict_modify(d);
504 
505 	game_gfx_clip();
506 
507 	switch (mode) {
508 	case BLIT_DRAW:
509 		if (alpha != 255)
510 			gfx_draw_from_alpha(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff, alpha);
511 		else
512 			gfx_draw_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff);
513 		break;
514 	case BLIT_COPY:
515 		gfx_copy_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff);
516 		break;
517 	case BLIT_COMPOSE:
518 		gfx_compose_from(s, x + xoff0, y + yoff0, w, h, d, xx + xoff, yy + yoff);
519 		break;
520 	default:
521 		break;
522 	}
523 
524 	game_gfx_noclip();
525 	lua_pushboolean(L, 1);
526 	return 1;
527 }
528 
529 
luaB_draw_sprite(lua_State * L)530 static int luaB_draw_sprite(lua_State *L)
531 {
532 	return luaB_blit_sprite(L, BLIT_DRAW);
533 }
534 
luaB_copy_sprite(lua_State * L)535 static int luaB_copy_sprite(lua_State *L)
536 {
537 	return luaB_blit_sprite(L, BLIT_COPY);
538 }
539 
luaB_compose_sprite(lua_State * L)540 static int luaB_compose_sprite(lua_State *L)
541 {
542 	return luaB_blit_sprite(L, BLIT_COMPOSE);
543 }
544 
luaB_alpha_sprite(lua_State * L)545 static int luaB_alpha_sprite(lua_State *L) {
546 	_spr_t *sp;
547 	img_t s;
548 	img_t img2 = NULL;
549 	const char *key;
550 	char sname[sizeof(unsigned long) * 2 + 16];
551 
552 	const char *src = luaL_optstring(L, 1, NULL);
553 	int alpha = luaL_optnumber(L, 2, 255);
554 	const char *desc = luaL_optstring(L, 3, NULL);
555 
556 	if (!src)
557 		return 0;
558 
559 	s = cache_lookup(gfx_image_cache(), src);
560 	if (!s)
561 		return 0;
562 
563 	img2 = gfx_alpha_img(s, alpha);
564 	if (!img2)
565 		return 0;
566 
567 	if (!desc || sprite_lookup(desc)) {
568 		key = sname;
569 		sprite_name(src, sname, sizeof(sname));
570 	} else
571 		key = desc;
572 
573 	sp = sprite_new(key, img2);
574 	if (!sp)
575 		goto err;
576 	lua_pushstring(L, sname);
577 	return 1;
578 err:
579 	gfx_free_image(img2);
580 	return 0;
581 }
582 
luaB_colorkey_sprite(lua_State * L)583 static int luaB_colorkey_sprite(lua_State *L) {
584 	img_t s;
585 	color_t  col;
586 
587 	const char *src = luaL_optstring(L, 1, NULL);
588 	const char *color = luaL_optstring(L, 2, NULL);
589 
590 	if (color)
591 		gfx_parse_color(color, &col);
592 
593 	if (!src)
594 		return 0;
595 	s = cache_lookup(gfx_image_cache(), src);
596 	if (!s)
597 		return 0;
598 	if (color)
599 		gfx_set_colorkey(s, col);
600 	else
601 		gfx_unset_colorkey(s);
602 	return 0;
603 }
604 
luaB_dup_sprite(lua_State * L)605 static int luaB_dup_sprite(lua_State *L) {
606 	_spr_t *sp;
607 	img_t s;
608 	img_t img2 = NULL;
609 	const char *key;
610 	char sname[sizeof(unsigned long) * 2 + 16];
611 	const char *src = luaL_optstring(L, 1, NULL);
612 	const char *desc = luaL_optstring(L, 2, NULL);
613 
614 	if (!src)
615 		return 0;
616 
617 	s = cache_lookup(gfx_image_cache(), src);
618 	if (!s)
619 		return 0;
620 
621 	img2 = gfx_dup(s);
622 
623 	if (!img2)
624 		return 0;
625 
626 	if (!desc || sprite_lookup(desc)) {
627 		key = sname;
628 		sprite_name(src, sname, sizeof(sname));
629 	} else
630 		key = desc;
631 
632 	sp = sprite_new(key, img2);
633 	if (!sp)
634 		goto err;
635 	lua_pushstring(L, sname);
636 	return 1;
637 err:
638 	gfx_free_image(img2);
639 	return 0;
640 }
641 
luaB_scale_sprite(lua_State * L)642 static int luaB_scale_sprite(lua_State *L) {
643 	_spr_t *sp;
644 	img_t s;
645 	img_t img2 = NULL;
646 	const char *key;
647 	char sname[sizeof(unsigned long) * 2 + 16];
648 
649 	const char *src = luaL_optstring(L, 1, NULL);
650 	float xs = luaL_optnumber(L, 2, 0);
651 	float ys = luaL_optnumber(L, 3, 0);
652 	int smooth = lua_toboolean(L, 4);
653 	const char *desc = luaL_optstring(L, 5, NULL);
654 
655 	if (!src)
656 		return 0;
657 
658 	s = cache_lookup(gfx_image_cache(), src);
659 	if (!s)
660 		return 0;
661 
662 	if (xs == 0)
663 		xs = 1.0f;
664 
665 	if (ys == 0)
666 		ys = xs;
667 
668 	img2 = gfx_scale(s, xs, ys, smooth);
669 
670 	if (!img2)
671 		return 0;
672 
673 	if (!desc || sprite_lookup(desc)) {
674 		key = sname;
675 		sprite_name(src, sname, sizeof(sname));
676 	} else
677 		key = desc;
678 
679 	sp = sprite_new(key, img2);
680 	if (!sp)
681 		goto err;
682 	lua_pushstring(L, sname);
683 	return 1;
684 err:
685 	gfx_free_image(img2);
686 	return 0;
687 }
688 
689 
luaB_rotate_sprite(lua_State * L)690 static int luaB_rotate_sprite(lua_State *L) {
691 	_spr_t *sp;
692 	img_t s;
693 	img_t img2 = NULL;
694 	const char *key;
695 	char sname[sizeof(unsigned long) * 2 + 16];
696 
697 	const char *src = luaL_optstring(L, 1, NULL);
698 	float angle = luaL_optnumber(L, 2, 1.0f);
699 	int smooth = lua_toboolean(L, 3);
700 	const char *desc = luaL_optstring(L, 4, NULL);
701 
702 	if (!src)
703 		return 0;
704 
705 	s = cache_lookup(gfx_image_cache(), src);
706 	if (!s)
707 		return 0;
708 	img2 = gfx_rotate(s, angle, smooth);
709 
710 	if (!img2)
711 		return 0;
712 
713 	if (!desc || sprite_lookup(desc)) {
714 		key = sname;
715 		sprite_name(src, sname, sizeof(sname));
716 	} else
717 		key = desc;
718 
719 	sp = sprite_new(key, img2);
720 	if (!sp)
721 		goto err;
722 	lua_pushstring(L, sname);
723 	return 1;
724 err:
725 	gfx_free_image(img2);
726 	return 0;
727 }
728 
luaB_fill_sprite(lua_State * L)729 static int luaB_fill_sprite(lua_State *L) {
730 	img_t d;
731 	float v;
732 	const char *dst = luaL_optstring(L, 1, NULL);
733 	int x = luaL_optnumber(L, 2, 0);
734 	int y = luaL_optnumber(L, 3, 0);
735 	int w = luaL_optnumber(L, 4, -1);
736 	int h = luaL_optnumber(L, 5, -1);
737 	const char *color = luaL_optstring(L, 6, NULL);
738 	int xoff = 0, yoff = 0;
739 	color_t  col = { .r = game_theme.bgcol.r, .g = game_theme.bgcol.g, .b = game_theme.bgcol.b };
740 	if (!dst)
741 		return 0;
742 
743 	d = grab_sprite(dst, &xoff, &yoff);
744 
745 	if (color)
746 		gfx_parse_color(color, &col);
747 
748 	if (!d)
749 		return 0;
750 
751 	v = game_theme.scale;
752 
753 	if (v != 1.0f) {
754 		x *= v;
755 		y *= v;
756 		if (w != -1)
757 			w = ceil(w * v);
758 		if (h != -1)
759 			h = ceil(h * v);
760 	}
761 	if (w == -1)
762 		w = gfx_img_w(d) - 2 * xoff;
763 	if (h == -1)
764 		h = gfx_img_h(d) - 2 * yoff;
765 	game_pict_modify(d);
766 	game_gfx_clip();
767 	gfx_img_fill(d, x + xoff, y + yoff, w, h, col);
768 	game_gfx_noclip();
769 	lua_pushboolean(L, 1);
770 	return 1;
771 }
772 
luaB_pixel_sprite(lua_State * L)773 static int luaB_pixel_sprite(lua_State *L) {
774 	img_t d;
775 	float v;
776 	int rc, w, h;
777 	color_t  col = { .r = game_theme.bgcol.r, .g = game_theme.bgcol.g, .b = game_theme.bgcol.b, .a = 255 };
778 	const char *dst = luaL_optstring(L, 1, NULL);
779 	int x = luaL_optnumber(L, 2, 0);
780 	int y = luaL_optnumber(L, 3, 0);
781 	const char *color = luaL_optstring(L, 4, NULL);
782 	int alpha = luaL_optnumber(L, 5, 255);
783 	int xoff = 0, yoff = 0;
784 
785 	if (!dst)
786 		return 0;
787 
788 	d = grab_sprite(dst, &xoff, &yoff);
789 
790 	if (color)
791 		gfx_parse_color(color, &col);
792 
793 	if (!d)
794 		return 0;
795 
796 	w = gfx_img_w(d) - 2 * xoff;
797 	h = gfx_img_h(d) - 2 * yoff;
798 
799 	v = game_theme.scale;
800 
801 	if (v != 1.0f) {
802 		x *= v;
803 		y *= v;
804 	}
805 
806 	if (color) {
807 		if (x < 0 || y < 0 || x >= w || y >= h)
808 			return 0;
809 		game_pict_modify(d);
810 		col.a = alpha;
811 		rc = gfx_set_pixel(d, x + xoff, y + yoff, col);
812 	} else {
813 		rc = gfx_get_pixel(d, x + xoff, y + yoff, &col);
814 	}
815 
816 	if (rc)
817 		return 0;
818 
819 	lua_pushinteger(L, col.r);
820 	lua_pushinteger(L, col.g);
821 	lua_pushinteger(L, col.b);
822 	lua_pushinteger(L, col.a);
823 	return 4;
824 }
825 
_free_sprite(const char * key)826 static int _free_sprite(const char *key)
827 {
828 	_spr_t *sp;
829 	if (!key)
830 		return -1;
831 	sp = sprite_lookup(key);
832 
833 	if (!sp)
834 		return -1;
835 
836 	cache_forget(gfx_image_cache(), sp->img);
837 	cache_shrink(gfx_image_cache());
838 
839 	list_del(&sp->list);
840 	free(sp->name); free(sp);
841 	return 0;
842 }
843 
luaB_free_sprite(lua_State * L)844 static int luaB_free_sprite(lua_State *L) {
845 	const char *key = luaL_optstring(L, 1, NULL);
846 	if (_free_sprite(key))
847 		return 0;
848 	lua_pushboolean(L, 1);
849 	return 1;
850 }
851 
luaB_free_font(lua_State * L)852 static int luaB_free_font(lua_State *L) {
853 	const char *key = luaL_optstring(L, 1, NULL);
854 	_fnt_t *fn;
855 	if (!key)
856 		return 0;
857 
858 	fn = font_lookup(key);
859 	if (!fn)
860 		return 0;
861 
862 	list_del(&fn->list);
863 	fnt_free(fn->fnt);
864 	free(fn->name); free(fn);
865 	lua_pushboolean(L, 1);
866 	return 1;
867 }
868 
869 extern int theme_setvar(char *name, char *val);
870 extern char *theme_getvar(const char *name);
871 
luaB_theme_var(lua_State * L)872 static int luaB_theme_var(lua_State *L) {
873 	const char *var = luaL_optstring(L, 1, NULL);
874 	const char *val = luaL_optstring(L, 2, NULL);
875 	if (var && !val) { /* get */
876 		char *p = theme_getvar(var);
877 		if (p) {
878 			lua_pushstring(L, p);
879 			free(p);
880 			return 1;
881 		}
882 		return 0;
883 	}
884 	if (!val || !var)
885 		return 0;
886 /*	if (!game_own_theme)
887 		return 0; */
888 	if (!opt_owntheme)
889 		return 0;
890 	if (!strcmp(var, "scr.w") ||
891 		!strcmp(var, "scr.h") ||
892 		!strcmp(var, "scr.scale_aware") ||
893 		!strcmp(var, "scr.dpi")) /* filter resolution */
894 		return 0;
895 	if (!theme_setvar((char*)var, (char*)val)) {
896 		if (strcmp(var, "win.scroll.mode")) /* let change scroll mode w/o theme reload */
897 			game_theme_changed = 1;
898 	}
899 	return 0;
900 }
901 
luaB_theme_name(lua_State * L)902 static int luaB_theme_name(lua_State *L) {
903 	char *name;
904 	if (game_own_theme && opt_owntheme) {
905 		if (game_own_theme == 2) {
906 			name = malloc(strlen(curtheme_dir[THEME_GAME]) + 2);
907 			if (!name)
908 				return 0;
909 			sprintf(name, ".%s", curtheme_dir[THEME_GAME]);
910 			lua_pushstring(L, name);
911 			free(name);
912 		} else {
913 			lua_pushstring(L, ".");
914 		}
915 	} else
916 		lua_pushstring(L, curtheme_dir[THEME_GLOBAL]);
917 	return 1;
918 }
919 
luaB_instead_direct(lua_State * L)920 static int luaB_instead_direct(lua_State *L) {
921 	int direct = -1;
922 	int old = DIRECT_MODE;
923 
924 	if (lua_isboolean(L, 1))
925 		direct = lua_toboolean(L, 1);
926 
927 	if (direct == -1) {
928 		lua_pushboolean(L, old);
929 		return 1;
930 	}
931 
932 	if (!opt_owntheme) {
933 		lua_pushboolean(L, 0);
934 		return 1;
935 	}
936 
937 	if (direct)
938 		game_theme.gfx_mode = GFX_DIRECT_SET(game_theme.gfx_mode);
939 	else {
940 		if (game_theme.gfx_mode != GFX_MODE_DIRECT) {
941 			game_theme.gfx_mode = GFX_DIRECT_CLR(game_theme.gfx_mode);
942 		}
943 	}
944 	lua_pushboolean(L, 1);
945 	return 1;
946 }
947 static unsigned long busy_time = 0;
948 
instead_ready(void)949 void instead_ready(void)
950 {
951 	if (menu_visible() == menu_wait) {
952 		menu_toggle(-1);
953 	}
954 	busy_time = 0;
955 }
956 
luaB_stead_busy(lua_State * L)957 static int luaB_stead_busy(lua_State *L) {
958 	int busy = lua_toboolean(L, 1);
959 	if (busy) {
960 		struct inp_event ev;
961 		int dirty = 0;
962 		memset(&ev, 0, sizeof(ev));
963 
964 		if (!game_freezed()) {
965 			if (game_bg_modify(NULL))
966 				game_redraw_all();
967 			game_flip();
968 		}
969 
970 		while (input(&ev, 0) == AGAIN);
971 		if (ev.type == MOUSE_MOTION) {
972 			game_cursor(CURSOR_ON); /* to make all happy */
973 			dirty = 1;
974 		}
975 		if (!busy_time)
976 			busy_time = gfx_ticks();
977 		if (gfx_ticks() - busy_time >= 750 && menu_visible() != menu_wait) {
978 			game_menu(menu_wait);
979 			dirty = 1;
980 		}
981 		if (dirty)
982 			game_gfx_commit(0);
983 		return 0;
984 	}
985 	instead_ready();
986 	game_gfx_commit(0);
987 	return 0;
988 }
989 
luaB_mouse_pos(lua_State * L)990 static int luaB_mouse_pos(lua_State *L) {
991 	int x = luaL_optnumber(L, 1, -1);
992 	int y = luaL_optnumber(L, 2, -1);
993 	int m;
994 	float v = game_theme.scale;
995 	if (x != -1 && y != -1) {
996 		x *= v;
997 		y *= v;
998 		gfx_warp_cursor(x + game_theme.xoff, y + game_theme.yoff);
999 		x = -1;
1000 		y = -1;
1001 	}
1002 	m = gfx_cursor(&x, &y);
1003 	x = (x - game_theme.xoff) / v;
1004 	y = (y - game_theme.yoff) / v;
1005 	lua_pushinteger(L, x);
1006 	lua_pushinteger(L, y);
1007 	lua_pushinteger(L, m);
1008 	return 3;
1009 }
1010 
luaB_finger_pos(lua_State * L)1011 static int luaB_finger_pos(lua_State *L) {
1012 	int x, y;
1013 	float pressure;
1014 	float v = game_theme.scale;
1015 	const char *finger = luaL_optstring(L, 1, NULL);
1016 	if (!finger)
1017 		return 0;
1018 	if (finger_pos(finger, &x, &y, &pressure)) /* no finger */
1019 		return 0;
1020 	x = (x - game_theme.xoff) / v;
1021 	y = (y - game_theme.yoff) / v;
1022 	lua_pushinteger(L, x);
1023 	lua_pushinteger(L, y);
1024 	lua_pushnumber(L, pressure);
1025 	return 3;
1026 }
1027 
1028 extern int mouse_filter_delay;
1029 
luaB_mouse_filter(lua_State * L)1030 static int luaB_mouse_filter(lua_State *L) {
1031 	int d = luaL_optnumber(L, 1, -1);
1032 	int ov = mouse_filter_delay;
1033 	if (d != -1)
1034 		mouse_filter_delay = d;
1035 	lua_pushinteger(L, ov);
1036 	return 1;
1037 }
1038 
luaB_mouse_show(lua_State * L)1039 static int luaB_mouse_show(lua_State *L) {
1040 	int show = lua_toboolean(L, 1);
1041 	int ov = game_cursor_show;
1042 	if (lua_isboolean(L, 1))
1043 		game_cursor_show = show;
1044 	lua_pushboolean(L, ov);
1045 	return 1;
1046 }
1047 
luaB_get_ticks(lua_State * L)1048 static int luaB_get_ticks(lua_State *L) {
1049 	lua_pushinteger(L, gfx_ticks());
1050 	return 1;
1051 }
1052 
luaB_get_themespath(lua_State * L)1053 static int luaB_get_themespath(lua_State *L) {
1054 	char themes_path[PATH_MAX];
1055 
1056 	if (THEMES_PATH[0] != '/') {
1057 		strcpy(themes_path, instead_cwd());
1058 		strcat(themes_path, "/");
1059 	} else
1060 		themes_path[0] = 0;
1061 	strcat(themes_path, THEMES_PATH);
1062 	unix_path(themes_path);
1063 	lua_pushstring(L, themes_path);
1064 	return 1;
1065 }
pixels_size(lua_State * L)1066 static int pixels_size(lua_State *L) {
1067 	struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1);
1068 	if (!hdr || hdr->type != PIXELS_MAGIC)
1069 		return 0;
1070 	lua_pushinteger(L, hdr->w);
1071 	lua_pushinteger(L, hdr->h);
1072 	lua_pushnumber(L, hdr->scale);
1073 	return 3;
1074 }
1075 
1076 #define PXL_BLEND_COPY 1
1077 #define PXL_BLEND_BLEND 2
blend(unsigned char * s,unsigned char * d)1078 static __inline void blend(unsigned char *s, unsigned char *d)
1079 {
1080 	unsigned int r, g, b, a;
1081 	unsigned int sa = s[3];
1082 	unsigned int da = d[3];
1083 	a = sa + (da * (255 - sa) >> 8);
1084 	r = ((unsigned int)s[0] * sa >> 8) +
1085 		((unsigned int)d[0] * da * (255 - sa) >> 16);
1086 	g = ((unsigned int)s[1] * sa >> 8) +
1087 		((unsigned int)d[1] * da * (255 - sa) >> 16);
1088 	b = ((unsigned int)s[2] * sa >> 8) +
1089 		((unsigned int)d[2] * da * (255 - sa) >> 16);
1090 	d[0] = r; d[1] = g; d[2] = b; d[3] = a;
1091 }
1092 
draw(unsigned char * s,unsigned char * d)1093 static __inline void draw(unsigned char *s, unsigned char *d)
1094 {
1095 	unsigned int r, g, b, a;
1096 	unsigned int sa = s[3];
1097 	a = 255;
1098 	r = ((unsigned int)s[0] * sa >> 8) +
1099 		((unsigned int)d[0] * (255 - sa) >> 8);
1100 	g = ((unsigned int)s[1] * sa >> 8) +
1101 		((unsigned int)d[1] * (255 - sa) >> 8);
1102 	b = ((unsigned int)s[2] * sa >> 8) +
1103 		((unsigned int)d[2] * (255 - sa) >> 8);
1104 	d[0] = r; d[1] = g; d[2] = b; d[3] = a;
1105 }
pixel(unsigned char * s,unsigned char * d)1106 static __inline void pixel(unsigned char *s, unsigned char *d)
1107 {
1108 	unsigned char a_src = s[3];
1109 	unsigned char a_dst = d[3];
1110 	if (a_src == 255 || a_dst == 0) {
1111 		memcpy(d, s, 4);
1112 	} else if (a_dst == 255) {
1113 		draw(s, d);
1114 	} else if (a_src == 0) {
1115 		/* nothing to do */
1116 	} else {
1117 		blend(s, d);
1118 	}
1119 }
line0(struct lua_pixels * hdr,int x1,int y1,int dx,int dy,int xd,unsigned char * col)1120 static __inline void line0(struct lua_pixels *hdr, int x1, int y1, int dx, int dy, int xd, unsigned char *col)
1121 {
1122 	int dy2 = dy * 2;
1123 	int dyx2 = dy2 - dx * 2;
1124 	int err = dy2 - dx;
1125 	unsigned char *ptr = NULL;
1126 	int w = hdr->w; int h = hdr->h;
1127 
1128 	int ly = w * 4;
1129 	int lx = xd * 4;
1130 
1131 	while ((x1 < 0 || y1 < 0 || x1 >= w) && dx --) {
1132 		if (err >= 0) {
1133 			y1 ++;
1134 			err += dyx2;
1135 		} else {
1136 			err += dy2;
1137 		}
1138 		x1 += xd;
1139 	}
1140 	if (dx < 0)
1141 		return;
1142 	ptr = (unsigned char*)(hdr + 1);
1143 	ptr += (y1 * w + x1) << 2;
1144 
1145 	pixel(col, ptr);
1146 	while (dx --) {
1147 		if (err >= 0) {
1148 			y1 ++;
1149 			if (y1 >= h)
1150 				break;
1151 			ptr += ly;
1152 			err += dyx2;
1153 		} else {
1154 			err += dy2;
1155 		}
1156 		x1 += xd;
1157 		if (x1 >= w || x1 < 0)
1158 			break;
1159 		ptr += lx;
1160 		pixel(col, ptr);
1161 	}
1162 	return;
1163 }
1164 
line1(struct lua_pixels * hdr,int x1,int y1,int dx,int dy,int xd,unsigned char * col)1165 static __inline void line1(struct lua_pixels *hdr, int x1, int y1, int dx, int dy, int xd, unsigned char *col)
1166 {
1167 	int dx2 = dx * 2;
1168 	int dxy2 = dx2 - dy * 2;
1169 	int err = dx2 - dy;
1170 	int w = hdr->w; int h = hdr->h;
1171 	unsigned char *ptr = NULL;
1172 	int ly = w * 4;
1173 	int lx = xd * 4;
1174 
1175 	while ((x1 < 0 || y1 < 0 || x1 >= w) && dy --) {
1176 		if (err >= 0) {
1177 		        x1 += xd;
1178 			err += dxy2;
1179 		} else {
1180 			err += dx2;
1181 		}
1182 		y1 ++;
1183 	}
1184 	if (dy < 0)
1185 		return;
1186 
1187 	ptr = (unsigned char*)(hdr + 1);
1188 	ptr += (y1 * w + x1) << 2;
1189 
1190 	pixel(col, ptr);
1191 
1192 	while (dy --) {
1193 		if (err >= 0) {
1194 			x1 += xd;
1195 			if (x1 < 0 || x1 >= w)
1196 				break;
1197 			ptr += lx;
1198 			err += dxy2;
1199 		} else {
1200 			err += dx2;
1201 		}
1202 		y1 ++;
1203 		if (y1 >= h)
1204 			break;
1205 		ptr += ly;
1206 		pixel(col, ptr);
1207 	}
1208 	return;
1209 }
1210 
lineAA(struct lua_pixels * src,int x0,int y0,int x1,int y1,int r,int g,int b,int a)1211 static void lineAA(struct lua_pixels *src, int x0, int y0, int x1, int y1,
1212 		 int r, int g, int b, int a)
1213 {
1214 	int dx, dy, err, e2, sx;
1215 	int w, h;
1216 	int syp, sxp, ed;
1217 	unsigned char *ptr;
1218 	unsigned char col[4];
1219 	col[0] = r; col[1] = g; col[2] = b; col[3] = a;
1220 	if (y0 > y1) {
1221 		int tmp;
1222 		tmp = x0; x0 = x1; x1 = tmp;
1223 		tmp = y0; y0 = y1; y1 = tmp;
1224 	}
1225 	w = src->w; h = src->h;
1226 	if (y1 < 0 || y0 >= h)
1227 		return;
1228 	if (x0 < x1) {
1229 		sx = 1;
1230 		if (x0 >= w || x1 < 0)
1231 			return;
1232 	} else {
1233 		sx = -1;
1234 		if (x1 >= w || x0 < 0)
1235 			return;
1236 	}
1237 	sxp = sx * 4;
1238 	syp = w * 4;
1239 
1240 	dx =  abs(x1 - x0);
1241 	dy = y1 - y0;
1242 
1243 	err = dx - dy;
1244 	ed = dx + dy == 0 ? 1: sqrt((float)dx * dx + (float)dy * dy);
1245 
1246 	while (y0 < 0 || x0 < 0 || x0 >= w) {
1247 		e2 = err;
1248 		if (2 * e2 >= -dx) {
1249 			if (x0 == x1)
1250 				break;
1251 			err -= dy;
1252 			x0 += sx;
1253 		}
1254 		if (2 * e2 <= dy) {
1255 			if (y0 == y1)
1256 				break;
1257 			err += dx;
1258 			y0 ++;
1259 		}
1260 	}
1261 
1262 	if (y0 < 0 || x0 < 0 || x0 >= w)
1263 		return;
1264 
1265 	ptr = (unsigned char*)(src + 1);
1266 	ptr += (y0 * w + x0) << 2;
1267 
1268 	while (1) {
1269 		unsigned char *optr = ptr;
1270 		col[3] = a - a * abs(err - dx + dy) / ed;
1271 		pixel(col, ptr);
1272 		e2 = err;
1273 		if (2 * e2 >= -dx) {
1274 			if (x0 == x1)
1275 				break;
1276 			if (e2 + dy < ed) {
1277 				col[3] = a - a * (e2 + dy) / ed;
1278 				pixel(col, ptr + syp);
1279 			}
1280 			err -= dy;
1281 			x0 += sx;
1282 			if (x0 < 0 || x0 >= w)
1283 				break;
1284 			ptr += sxp;
1285 		}
1286 		if (2 * e2 <= dy) {
1287 			if (y0 == y1)
1288 				break;
1289 			if (dx - e2 < ed) {
1290 				col[3] = a - a * (dx - e2) / ed;
1291 				pixel(col, optr + sxp);
1292 			}
1293 			err += dx;
1294 			y0 ++;
1295 			if (y0 >= h)
1296 				break;
1297 			ptr += syp;
1298 		}
1299 	}
1300 	src->dirty = 1;
1301 }
1302 
line(struct lua_pixels * src,int x1,int y1,int x2,int y2,int r,int g,int b,int a)1303 static void line(struct lua_pixels *src, int x1, int y1, int x2, int y2, int r, int g, int b, int a)
1304 {
1305 	int dx, dy, tmp;
1306 	unsigned char col[4];
1307 	if (y1 > y2) {
1308 		tmp = y1; y1 = y2; y2 = tmp;
1309 		tmp = x1; x1 = x2; x2 = tmp;
1310 	}
1311 	col[0] = r; col[1] = g; col[2] = b; col[3] = a;
1312 	if (y1 >= src->h)
1313 		return;
1314 	if (y2 < 0)
1315 		return;
1316 	if (x1 < x2) {
1317 		if (x2 < 0)
1318 			return;
1319 		if (x1 >= src->w)
1320 			return;
1321 	} else {
1322 		if (x1 < 0)
1323 			return;
1324 		if (x2 >= src->w)
1325 			return;
1326 	}
1327 	dx = x2 - x1;
1328 	dy = y2 - y1;
1329 	if (dx > 0) {
1330 		if (dx > dy) {
1331 			line0(src, x1, y1, dx, dy, 1, col);
1332 		} else {
1333 			line1(src, x1, y1, dx, dy, 1, col);
1334 		}
1335 	} else {
1336 		dx = -dx;
1337 		if (dx > dy) {
1338 			line0(src, x1, y1, dx, dy, -1, col);
1339 		} else {
1340 			line1(src, x1, y1, dx, dy, -1, col);
1341 		}
1342 	}
1343 	src->dirty = 1;
1344 }
1345 
_pixels_blend(struct lua_pixels * src,int x,int y,int w,int h,struct lua_pixels * dst,int xx,int yy,int mode)1346 static int _pixels_blend(struct lua_pixels *src, int x, int y, int w, int h,
1347 			struct lua_pixels *dst, int xx, int yy, int mode)
1348 
1349 {
1350 	unsigned char *ptr1, *ptr2;
1351 	int cy, cx, srcw, dstw;
1352 
1353 	if (!w)
1354 		w = src->w;
1355 	if (!h)
1356 		h = src->h;
1357 
1358 	if (x < 0 || x + w > src->w)
1359 		return 0;
1360 
1361 	if (y < 0 || y + h > src->h)
1362 		return 0;
1363 
1364 	if (w <= 0 || h <= 0)
1365 		return 0;
1366 
1367 	if (xx < 0) {
1368 		w += xx;
1369 		x -= xx;
1370 		xx = 0;
1371 	}
1372 	if (yy < 0) {
1373 		h += yy;
1374 		y -= yy;
1375 		yy = 0;
1376 	}
1377 	if (w <= 0 || h <= 0)
1378 		return 0;
1379 
1380 	if (xx >= dst->w || yy >= dst->h)
1381 		return 0;
1382 
1383 	if (xx + w > dst->w)
1384 		w = dst->w - xx;
1385 	if (yy + h > dst->h)
1386 		h = dst->h - yy;
1387 
1388 	ptr1 = (unsigned char *)(src + 1);
1389 	ptr2 = (unsigned char *)(dst + 1);
1390 	ptr1 += (y * src->w + x) << 2;
1391 	ptr2 += (yy * dst->w + xx) << 2;
1392 	srcw = src->w * 4; dstw = dst->w * 4;
1393 	dst->dirty = 1;
1394 	for (cy = 0; cy < h; cy ++) {
1395 		if (mode == PXL_BLEND_COPY)
1396 			memcpy(ptr2, ptr1, w << 2);
1397 		else {
1398 			unsigned char *p2 = ptr2;
1399 			unsigned char *p1 = ptr1;
1400 			for (cx = 0; cx < w; cx ++) {
1401 				pixel(p1, p2);
1402 				p1 += 4;
1403 				p2 += 4;
1404 			}
1405 		}
1406 		ptr2 += dstw;
1407 		ptr1 += srcw;
1408 	}
1409 	return 0;
1410 }
1411 
pixels_copy(lua_State * L)1412 static int pixels_copy(lua_State *L) {
1413 	int x = 0, y = 0, w = 0, h = 0, xx = 0, yy = 0;
1414 	struct lua_pixels *src, *dst;
1415 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1416 	dst = (struct lua_pixels*)lua_touserdata(L, 2);
1417 	if (!dst) {
1418 		x = luaL_optnumber(L, 2, 0);
1419 		y = luaL_optnumber(L, 3, 0);
1420 		w = luaL_optnumber(L, 4, 0);
1421 		h = luaL_optnumber(L, 5, 0);
1422 		dst = (struct lua_pixels*)lua_touserdata(L, 6);
1423 		xx = luaL_optnumber(L, 7, 0);
1424 		yy = luaL_optnumber(L, 8, 0);
1425 	} else {
1426 		xx = luaL_optnumber(L, 3, 0);
1427 		yy = luaL_optnumber(L, 4, 0);
1428 	}
1429 	if (!src || src->type != PIXELS_MAGIC)
1430 		return 0;
1431 	if (!dst || dst->type != PIXELS_MAGIC)
1432 		return 0;
1433 	return _pixels_blend(src, x, y, w, h, dst, xx, yy, PXL_BLEND_COPY);
1434 }
1435 
pixels_blend(lua_State * L)1436 static int pixels_blend(lua_State *L) {
1437 	int x = 0, y = 0, w = 0, h = 0, xx = 0, yy = 0;
1438 	struct lua_pixels *src, *dst;
1439 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1440 	dst = (struct lua_pixels*)lua_touserdata(L, 2);
1441 	if (!dst) {
1442 		x = luaL_optnumber(L, 2, 0);
1443 		y = luaL_optnumber(L, 3, 0);
1444 		w = luaL_optnumber(L, 4, 0);
1445 		h = luaL_optnumber(L, 5, 0);
1446 		dst = (struct lua_pixels*)lua_touserdata(L, 6);
1447 		xx = luaL_optnumber(L, 7, 0);
1448 		yy = luaL_optnumber(L, 8, 0);
1449 	} else {
1450 		xx = luaL_optnumber(L, 3, 0);
1451 		yy = luaL_optnumber(L, 4, 0);
1452 	}
1453 	if (!src || src->type != PIXELS_MAGIC)
1454 		return 0;
1455 	if (!dst || dst->type != PIXELS_MAGIC)
1456 		return 0;
1457 	return _pixels_blend(src, x, y, w, h, dst, xx, yy, PXL_BLEND_BLEND);
1458 }
1459 
_fill(struct lua_pixels * src,int x,int y,int w,int h,int r,int g,int b,int a,int mode)1460 static void _fill(struct lua_pixels *src, int x, int y, int w, int h,
1461 		  int r, int g, int b, int a, int mode) {
1462 	unsigned char col[4];
1463 	unsigned char *ptr1;
1464 	int cy, cx;
1465 	if (!src || src->type != PIXELS_MAGIC)
1466 		return;
1467 	col[0] = r; col[1] = g; col[2] = b; col[3] = a;
1468 	if (!w)
1469 		w = src->w;
1470 	if (!h)
1471 		h = src->h;
1472 
1473 	if (x < 0) {
1474 		w += x;
1475 		x = 0;
1476 	}
1477 	if (y < 0) {
1478 		h += y;
1479 		y = 0;
1480 	}
1481 
1482 	if (w <= 0 || h <= 0 || x >= src->w || y >= src->h)
1483 		return;
1484 
1485 	if (x + w > src->w)
1486 		w = src->w - x;
1487 	if (y + h > src->h)
1488 		h = src->h - y;
1489 
1490 	ptr1 = (unsigned char *)(src + 1);
1491 	ptr1 += (y * src->w + x) << 2;
1492 	src->dirty = 1;
1493 	for (cy = 0; cy < h; cy ++) {
1494 		unsigned char *p1 = ptr1;
1495 		for (cx = 0; cx < w; cx ++) {
1496 			if (mode == PXL_BLEND_COPY)
1497 				memcpy(p1, col, 4);
1498 			else
1499 				pixel(col, p1);
1500 			p1 += 4;
1501 		}
1502 		ptr1 += (src->w * 4);
1503 	}
1504 	return;
1505 }
1506 
orient2d(int ax,int ay,int bx,int by,int cx,int cy)1507 static __inline int orient2d(int ax, int ay, int bx, int by, int cx, int cy)
1508 {
1509 	return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);
1510 }
1511 
min3(int a,int b,int c)1512 static __inline int min3(int a, int b, int c)
1513 {
1514 	if (a < b) {
1515 		if (a < c)
1516 			return a;
1517 		return c;
1518 	} else {
1519 		if (b < c)
1520 			return b;
1521 		return c;
1522 	}
1523 }
1524 
max3(int a,int b,int c)1525 static __inline int max3(int a, int b, int c)
1526 {
1527 	if (a > b) {
1528 		if (a > c)
1529 			return a;
1530 		return c;
1531 	} else {
1532 		if (b > c)
1533 			return b;
1534 		return c;
1535 	}
1536 }
1537 
triangle(struct lua_pixels * src,int x0,int y0,int x1,int y1,int x2,int y2,int r,int g,int b,int a)1538 static void triangle(struct lua_pixels *src, int x0, int y0, int x1, int y1, int x2, int y2, int r, int g, int b, int a)
1539 {
1540 	int A01 = y0 - y1, B01 = x1 - x0;
1541 	int A12 = y1 - y2, B12 = x2 - x1;
1542 	int A20 = y2 - y0, B20 = x0 - x2;
1543 
1544 	int minx = min3(x0, x1, x2);
1545 	int miny = min3(y0, y1, y2);
1546 	int maxx = max3(x0, x1, x2);
1547 	int maxy = max3(y0, y1, y2);
1548 
1549 	int w0_row = orient2d(x1, y1, x2, y2, minx, miny);
1550 	int w1_row = orient2d(x2, y2, x0, y0, minx, miny);
1551 	int w2_row = orient2d(x0, y0, x1, y1, minx, miny);
1552 
1553 	int y, x, w, h;
1554 	int yd;
1555 	unsigned char col[4];
1556 	unsigned char *ptr;
1557 	w = src->w; h = src->h;
1558 	yd = 4 * w;
1559 	col[0] = r; col[1] = b; col[2] = g; col[3] = a;
1560 
1561 	if (minx >= w || miny >= h)
1562 		return;
1563 	if (minx < 0)
1564 		minx = 0;
1565 	if (miny < 0)
1566 		miny = 0;
1567 	if (maxy >= h)
1568 		maxy = h - 1;
1569 	if (maxx >= w)
1570 		maxx = w - 1;
1571 	ptr = (unsigned char *)(src + 1) + miny * yd + 4 * minx;
1572 
1573 	src->dirty = 1;
1574 
1575 	for (y = miny; y <= maxy; y ++) {
1576 		int w0 = w0_row;
1577 		int w1 = w1_row;
1578 		int w2 = w2_row;
1579 		unsigned char *p = ptr;
1580 		for (x = minx; x <= maxx; x++) {
1581 			if ((w0 | w1 | w2) >= 0)
1582 				pixel(col, p);
1583 			p += 4;
1584 			w0 += A12;
1585 			w1 += A20;
1586 			w2 += A01;
1587 		}
1588 		w0_row += B12;
1589 		w1_row += B20;
1590 		w2_row += B01;
1591 		ptr += yd;
1592 	}
1593 }
fill_circle(struct lua_pixels * src,int xc,int yc,int radius,int r,int g,int b,int a)1594 static void fill_circle(struct lua_pixels *src, int xc, int yc, int radius, int r, int g, int b, int a)
1595 {
1596 	int r2 = radius * radius;
1597 	int x, y, x1, x2, y1, y2;
1598 	unsigned char col[4] = { r, g, b, a };
1599 	int w = src->w, h = src->h;
1600 	unsigned char *ptr;
1601 
1602 	if (xc + radius < 0 || yc + radius < 0)
1603 		return;
1604 	if (xc - radius >= w || yc - radius >= h)
1605 		return;
1606 
1607 	if (radius <= 0)
1608 		return;
1609 
1610 	ptr = (unsigned char *)(src + 1);
1611 	src->dirty = 1;
1612 	ptr += (w * yc + xc) << 2;
1613 
1614 	if (radius == 1) {
1615 		pixel(col, ptr);
1616 		return;
1617 	}
1618 	y1 = -radius; y2 = radius;
1619 	x1 = -radius; x2 = radius;
1620 	if (yc - radius < 0)
1621 		y1 = -yc;
1622 	if (xc - radius < 0)
1623 		x1 = -xc;
1624 	if (xc + radius >= w)
1625 		x2 = w - xc - 1;
1626 	if (yc + radius >= h)
1627 		y2 = h - yc - 1;
1628 	for (y = y1; y <= y2; y ++) {
1629 		unsigned char *ptrl = ptr + ((y * w + x1) << 2);
1630 		for (x = x1; x <= x2; x++) {
1631 			if (x*x + y*y < r2 - 1)
1632 				pixel(col, ptrl);
1633 			ptrl += 4;
1634 		}
1635 	}
1636 }
1637 
circle(struct lua_pixels * src,int xc,int yc,int rr,int r,int g,int b,int a)1638 static void circle(struct lua_pixels *src, int xc, int yc, int rr, int r, int g, int b, int a)
1639 {
1640 	int x = -rr, y = 0, err = 2 - 2 * rr;
1641 	unsigned char *ptr = (unsigned char *)(src + 1);
1642 	unsigned char col[4] = { r, g, b, a };
1643 	int w = src->w, h = src->h;
1644 
1645 	if (rr <= 0)
1646 		return;
1647 	if (xc + rr < 0 || yc + rr < 0)
1648 		return;
1649 	if (xc - rr >= w || yc - rr >= h)
1650 		return;
1651 	src->dirty = 1;
1652 	ptr += (w * yc + xc) * 4;
1653 	if (xc - rr >= 0 && xc + rr < w &&
1654 	    yc - rr >=0 && yc + rr < h) {
1655 		do {
1656 			int xmy = (x - y * w) * 4;
1657 			int yax = (y + x * w) * 4;
1658 			pixel(col, ptr - xmy);
1659 			pixel(col, ptr - yax);
1660 			pixel(col, ptr + xmy);
1661 			pixel(col, ptr + yax);
1662 
1663 			rr = err;
1664 			if (rr <= y)
1665 				err += ++y * 2 + 1;
1666 			if (rr > x || err > y)
1667 				err += ++x * 2 + 1;
1668 		} while (x < 0);
1669 		return;
1670 	}
1671 	/* slow */
1672 	do {
1673 		int xmy = (x - y * w) * 4;
1674 		int yax = (y + x * w) * 4;
1675 		if (((xc - x) | (w - xc + x - 1) |
1676 		    (yc + y) | (h - yc - y - 1)) >= 0)
1677 			pixel(col, ptr - xmy);
1678 		if (((xc - y) | (w - xc + y - 1) |
1679 		     (yc - x) | (h - yc + x - 1)) >= 0)
1680 			pixel(col, ptr - yax);
1681 		if (((xc + x) | (w - xc - x - 1) |
1682 		     (yc - y) | (h - yc + y - 1)) >= 0)
1683 			pixel(col, ptr + xmy);
1684 		if (((xc + y) | (w - xc - y - 1) |
1685 		      (yc + x) | (h - yc - x - 1)) >= 0)
1686 			pixel(col, ptr + yax);
1687 		rr = err;
1688 		if (rr <= y)
1689 			err += ++y * 2 + 1;
1690 		if (rr > x || err > y)
1691 			err += ++x * 2 + 1;
1692 	} while (x < 0);
1693 
1694 }
circleAA(struct lua_pixels * src,int xc,int yc,int rr,int r,int g,int b,int a)1695 static void circleAA(struct lua_pixels *src, int xc, int yc, int rr, int r, int g, int b, int a)
1696 {
1697 	int p1, p2, p3, p4;
1698 	int x = -rr, y = 0, x2, e2, err = 2 - 2 * rr;
1699 	unsigned char *ptr = (unsigned char *)(src + 1);
1700 	unsigned char col[4] = { r, g, b, a };
1701 	int w = src->w, h = src->h;
1702 	if (rr <= 0)
1703 		return;
1704 	if (xc + rr < 0 || yc + rr < 0)
1705 		return;
1706 	if (xc - rr >= w || yc - rr >= h)
1707 		return;
1708 	src->dirty = 1;
1709 	rr = 1 - err;
1710 	ptr += (w * yc + xc) * 4;
1711 	do {
1712 		int i = 255 * abs(err - 2 *(x + y)-2) / rr;
1713 		int xmy = (x - y * w) * 4;
1714 		int yax = (y + x * w) * 4;
1715 		col[3] = ((255 - i) * a) >> 8;
1716 		p1 = 0; p2 = 0; p3 = 0; p4 = 0;
1717 		if (((xc - x) | (w - xc + x - 1) |
1718 		     (yc + y) | (h - yc - y - 1)) >= 0) {
1719 			pixel(col, ptr - xmy);
1720 			p1 = 1;
1721 		}
1722 		if (((xc - y) | (w - xc + y - 1) |
1723 		     (yc - x) | (h - yc + x - 1)) >= 0) {
1724 			pixel(col, ptr - yax);
1725 			p2 = 1;
1726 		}
1727 		if (((xc + x) | (w - xc - x - 1) |
1728 		     (yc - y) | (h - yc + y - 1)) >= 0) {
1729 			pixel(col, ptr + xmy);
1730 			p3 = 1;
1731 		}
1732 		if (((xc + y) | (w - xc - y - 1) |
1733 		     (yc + x) | (h - yc - x - 1)) >= 0) {
1734 			pixel(col, ptr + yax);
1735 			p4 = 1;
1736 		}
1737 		e2 = err;
1738 		x2 = x;
1739 		if (err + y > 0) {
1740 			i = 255 * (err - 2 * x - 1) / rr;
1741 			if (i < 256) {
1742 				col[3] = ((255 - i) * a) >> 8;
1743 				if (p1 && yc + y + 1 < h)
1744 					pixel(col, ptr - xmy + w * 4);
1745 				if (p2 && xc - y - 1 >= 0)
1746 					pixel(col, ptr - yax - 4);
1747 				if (p3 && yc - y - 1 >= 0)
1748 					pixel(col, ptr + xmy - w * 4);
1749 				if (p4 && xc + y < w)
1750 					pixel(col, ptr + yax + 4);
1751 			}
1752 			err += ++x * 2 + 1;
1753 		}
1754 		if (e2 + x <= 0) {
1755 			i = 255 * (2 * y + 3 - e2) / rr;
1756 			if (i < 256) {
1757 				col[3] = ((255 - i) * a) >> 8;
1758 				if (p1 && xc - x2 - 1 >= 0)
1759 					pixel(col, ptr - xmy - 4);
1760 				if (p2 && yc - x2 - 1 >= 0)
1761 					pixel(col, ptr - yax - w * 4);
1762 				if (p3 && xc + x2 + 1 < w)
1763 					pixel(col, ptr + xmy + 4);
1764 				if (p4 && yc + x2 + 1 < h)
1765 					pixel(col, ptr + yax + w * 4);
1766 			}
1767 			err += ++y * 2 + 1;
1768 		}
1769 	} while (x < 0);
1770 }
1771 
pixels_fill(lua_State * L)1772 static int pixels_fill(lua_State *L) {
1773 	int x = 0, y = 0, w = 0, h = 0, r = 0, g = 0, b = 0, a = 255;
1774 	struct lua_pixels *src;
1775 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1776 	if (!src || src->type != PIXELS_MAGIC)
1777 		return 0;
1778 	b = luaL_optnumber(L, 8, -1);
1779 	if (b < 0) {
1780 		r = luaL_optnumber(L, 2, 0);
1781 		g = luaL_optnumber(L, 3, 0);
1782 		b = luaL_optnumber(L, 4, 0);
1783 		a = luaL_optnumber(L, 5, 255);
1784 	} else {
1785 		x = luaL_optnumber(L, 2, 0);
1786 		y = luaL_optnumber(L, 3, 0);
1787 		w = luaL_optnumber(L, 4, 0);
1788 		h = luaL_optnumber(L, 5, 0);
1789 		r = luaL_optnumber(L, 6, 0);
1790 		g = luaL_optnumber(L, 7, 0);
1791 		b = luaL_optnumber(L, 8, 0);
1792 		a = luaL_optnumber(L, 9, 255);
1793 	}
1794 	_fill(src, x, y, w, h, r, g, b, a, (a == 255)?PXL_BLEND_COPY:PXL_BLEND_BLEND);
1795 	return 0;
1796 }
1797 
pixels_clear(lua_State * L)1798 static int pixels_clear(lua_State *L) {
1799 	int x = 0, y = 0, w = 0, h = 0, r = 0, g = 0, b = 0, a = 0;
1800 	struct lua_pixels *src;
1801 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1802 	if (!src || src->type != PIXELS_MAGIC)
1803 		return 0;
1804 	b = luaL_optnumber(L, 8, -1);
1805 	if (b < 0) {
1806 		r = luaL_optnumber(L, 2, 0);
1807 		g = luaL_optnumber(L, 3, 0);
1808 		b = luaL_optnumber(L, 4, 0);
1809 		a = luaL_optnumber(L, 5, 0);
1810 	} else {
1811 		x = luaL_optnumber(L, 2, 0);
1812 		y = luaL_optnumber(L, 3, 0);
1813 		w = luaL_optnumber(L, 4, 0);
1814 		h = luaL_optnumber(L, 5, 0);
1815 		r = luaL_optnumber(L, 6, 0);
1816 		g = luaL_optnumber(L, 7, 0);
1817 		b = luaL_optnumber(L, 8, 0);
1818 		a = luaL_optnumber(L, 9, 0);
1819 	}
1820 	_fill(src, x, y, w, h, r, g, b, a, PXL_BLEND_COPY);
1821 	return 0;
1822 }
1823 
1824 
pixels_triangle(lua_State * L)1825 static int pixels_triangle(lua_State *L) {
1826 	int x0 = 0, y0 = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0, r = 0, g = 0, b = 0, a = 0;
1827 	struct lua_pixels *src;
1828 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1829 	if (!src || src->type != PIXELS_MAGIC)
1830 		return 0;
1831 	x0 = luaL_optnumber(L, 2, 0);
1832 	y0 = luaL_optnumber(L, 3, 0);
1833 	x1 = luaL_optnumber(L, 4, 0);
1834 	y1 = luaL_optnumber(L, 5, 0);
1835 	x2 = luaL_optnumber(L, 6, 0);
1836 	y2 = luaL_optnumber(L, 7, 0);
1837 	#define XOR_SWAP(x,y) x=x^y; y=x^y; x=x^y;
1838 	if (orient2d(x0, y0, x1, y1, x2, y2) < 0) {
1839 		XOR_SWAP(x1, x2)
1840 		XOR_SWAP(y1, y2)
1841 	}
1842 	#undef XOR_SWAP
1843 	r = luaL_optnumber(L, 8, 0);
1844 	g = luaL_optnumber(L, 9, 0);
1845 	b = luaL_optnumber(L, 10, 0);
1846 	a = luaL_optnumber(L, 11, 255);
1847 	triangle(src, x0, y0, x1, y1, x2, y2, r, g, b, a);
1848 	return 0;
1849 }
1850 
pixels_line(lua_State * L)1851 static int pixels_line(lua_State *L) {
1852 	int x1 = 0, y1 = 0, x2 = 0, y2 = 0, r = 0, g = 0, b = 0, a = 255;
1853 	struct lua_pixels *src;
1854 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1855 	if (!src || src->type != PIXELS_MAGIC)
1856 		return 0;
1857 	x1 = luaL_optnumber(L, 2, 0);
1858 	y1 = luaL_optnumber(L, 3, 0);
1859 	x2 = luaL_optnumber(L, 4, 0);
1860 	y2 = luaL_optnumber(L, 5, 0);
1861 	r = luaL_optnumber(L, 6, 0);
1862 	g = luaL_optnumber(L, 7, 0);
1863 	b = luaL_optnumber(L, 8, 0);
1864 	a = luaL_optnumber(L, 9, 255);
1865 	line(src, x1, y1, x2, y2, r, g, b, a);
1866 	return 0;
1867 }
1868 
pixels_lineAA(lua_State * L)1869 static int pixels_lineAA(lua_State *L) {
1870 	int x1 = 0, y1 = 0, x2 = 0, y2 = 0, r = 0, g = 0, b = 0, a = 255;
1871 	struct lua_pixels *src;
1872 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1873 	if (!src || src->type != PIXELS_MAGIC)
1874 		return 0;
1875 	x1 = luaL_optnumber(L, 2, 0);
1876 	y1 = luaL_optnumber(L, 3, 0);
1877 	x2 = luaL_optnumber(L, 4, 0);
1878 	y2 = luaL_optnumber(L, 5, 0);
1879 	r = luaL_optnumber(L, 6, 0);
1880 	g = luaL_optnumber(L, 7, 0);
1881 	b = luaL_optnumber(L, 8, 0);
1882 	a = luaL_optnumber(L, 9, 255);
1883 	lineAA(src, x1, y1, x2, y2, r, g, b, a);
1884 	return 0;
1885 }
pixels_circle(lua_State * L)1886 static int pixels_circle(lua_State *L) {
1887 	int xc = 0, yc = 0, rr = 0, r = 0, g = 0, b = 0, a = 255;
1888 	struct lua_pixels *src;
1889 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1890 	if (!src || src->type != PIXELS_MAGIC)
1891 		return 0;
1892 	xc = luaL_optnumber(L, 2, 0);
1893 	yc = luaL_optnumber(L, 3, 0);
1894 	rr = luaL_optnumber(L, 4, 0);
1895 	r = luaL_optnumber(L, 5, 0);
1896 	g = luaL_optnumber(L, 6, 0);
1897 	b = luaL_optnumber(L, 7, 0);
1898 	a = luaL_optnumber(L, 8, 255);
1899 	circle(src, xc, yc, rr, r, g, b, a);
1900 	return 0;
1901 }
pixels_circleAA(lua_State * L)1902 static int pixels_circleAA(lua_State *L) {
1903 	int xc = 0, yc = 0, rr = 0, r = 0, g = 0, b = 0, a = 255;
1904 	struct lua_pixels *src;
1905 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1906 	if (!src || src->type != PIXELS_MAGIC)
1907 		return 0;
1908 	xc = luaL_optnumber(L, 2, 0);
1909 	yc = luaL_optnumber(L, 3, 0);
1910 	rr = luaL_optnumber(L, 4, 0);
1911 	r = luaL_optnumber(L, 5, 0);
1912 	g = luaL_optnumber(L, 6, 0);
1913 	b = luaL_optnumber(L, 7, 0);
1914 	a = luaL_optnumber(L, 8, 255);
1915 	circleAA(src, xc, yc, rr, r, g, b, a);
1916 	return 0;
1917 }
pixels_fill_circle(lua_State * L)1918 static int pixels_fill_circle(lua_State *L) {
1919 	int xc = 0, yc = 0, rr = 0, r = 0, g = 0, b = 0, a = 255;
1920 	struct lua_pixels *src;
1921 	src = (struct lua_pixels*)lua_touserdata(L, 1);
1922 	if (!src || src->type != PIXELS_MAGIC)
1923 		return 0;
1924 	xc = luaL_optnumber(L, 2, 0);
1925 	yc = luaL_optnumber(L, 3, 0);
1926 	rr = luaL_optnumber(L, 4, 0);
1927 	r = luaL_optnumber(L, 5, 0);
1928 	g = luaL_optnumber(L, 6, 0);
1929 	b = luaL_optnumber(L, 7, 0);
1930 	a = luaL_optnumber(L, 8, 255);
1931 	fill_circle(src, xc, yc, rr, r, g, b, a);
1932 	return 0;
1933 }
1934 struct lua_point {
1935 	int x;
1936 	int y;
1937 	int nodex;
1938 };
1939 
1940 /*
1941    http://alienryderflex.com/polygon_fill/
1942    public-domain code by Darel Rex Finley, 2007
1943 */
1944 
fill_poly(struct lua_pixels * src,struct lua_point * v,int nr,unsigned char * col)1945 static void fill_poly(struct lua_pixels *src, struct lua_point *v, int nr, unsigned char *col)
1946 {
1947 	unsigned char *ptr = (unsigned char *)(src + 1), *ptr1;
1948 	int y, x, xmin, xmax, ymin, ymax, swap, w;
1949 	int nodes = 0, j, i;
1950 	xmin = v[0].x; xmax = v[0].x;
1951 	ymin = v[0].y; ymax = v[0].y;
1952 
1953 	for (i = 0; i < nr; i++) {
1954 		if (v[i].x < xmin)
1955 			xmin = v[i].x;
1956 		if (v[i].x > xmax)
1957 			xmax = v[i].x;
1958 		if (v[i].y < ymin)
1959 			ymin = v[i].y;
1960 		if (v[i].y > ymax)
1961 			ymax = v[i].y;
1962 	}
1963 	if (ymin < 0)
1964 		ymin = 0;
1965 	if (xmin < 0)
1966 		xmin = 0;
1967 	if (xmax >= src->w)
1968 		xmax = src->w;
1969 	if (ymax >= src->h)
1970 		ymax = src->h;
1971 	ptr += (ymin * src->w) << 2;
1972 	for (y = ymin; y < ymax; y ++) {
1973 		nodes = 0; j = nr - 1;
1974 		for (i = 0; i < nr; i++) {
1975 			if ((v[i].y < y && v[j].y >= y) ||
1976 			    (v[j].y < y && v[i].y >= y)) {
1977 				v[nodes ++].nodex = v[i].x + ((y - v[i].y) * (v[j].x - v[i].x)) /
1978 					(v[j].y - v[i].y);
1979 			}
1980 			j = i;
1981 		}
1982 		if (nodes < 2)
1983 			goto skip;
1984 		i = 0;
1985 		while (i < nodes - 1) { /* sort */
1986 			if (v[i].nodex > v[i + 1].nodex) {
1987 				swap = v[i].nodex;
1988 				v[i].nodex = v[i + 1].nodex;
1989 				v[i + 1].nodex = swap;
1990 				if (i)
1991 					i --;
1992 			} else {
1993 				i ++;
1994 			}
1995 		}
1996 		for (i = 0; i < nodes; i += 2) {
1997 			if (v[i].nodex >= xmax)
1998 				break;
1999 			if (v[i + 1].nodex > xmin) {
2000 				if (v[i].nodex < xmin)
2001 					v[i].nodex = xmin;
2002 				if (v[i + 1].nodex > xmax)
2003 					v[i + 1].nodex = xmax;
2004 				// hline
2005 				src->dirty = 1;
2006 				w = (v[i + 1].nodex - v[i].nodex);
2007 				ptr1 = ptr + v[i].nodex * 4;
2008 				for (x = 0; x < w; x ++) {
2009 					pixel(col, ptr1);
2010 					ptr1 += 4;
2011 				}
2012 			}
2013 		}
2014 	skip:
2015 		ptr += src->w * 4;
2016 	}
2017 }
2018 
pixels_fill_poly(lua_State * L)2019 static int pixels_fill_poly(lua_State *L) {
2020 	int nr, i;
2021 	struct lua_pixels *src;
2022 	struct lua_point *v;
2023 	unsigned char col[4];
2024 	src = (struct lua_pixels*)lua_touserdata(L, 1);
2025 	if (!src || src->type != PIXELS_MAGIC)
2026 		return 0;
2027 	luaL_checktype(L, 2, LUA_TTABLE);
2028 #if LUA_VERSION_NUM >= 502
2029 	nr = lua_rawlen(L, 2);
2030 #else
2031 	nr = lua_objlen(L, 2);
2032 #endif
2033 	if (nr < 6)
2034 		return 0;
2035 	col[0] = luaL_optnumber(L, 3, 0);
2036 	col[1] = luaL_optnumber(L, 4, 0);
2037 	col[2] = luaL_optnumber(L, 5, 0);
2038 	col[3] = luaL_optnumber(L, 6, 255);
2039 
2040 	nr /= 2;
2041 	v = malloc(sizeof(*v) * nr);
2042 	if (!v)
2043 		return 0;
2044 	lua_pushvalue(L, 2);
2045 	for (i = 0; i < nr; i++) {
2046 		lua_pushinteger(L, (i * 2) + 1);
2047 		lua_gettable(L, -2);
2048 		v[i].x = lua_tonumber(L, -1);
2049 		lua_pop(L, 1);
2050 		lua_pushinteger(L, (i * 2) + 2);
2051 		lua_gettable(L, -2);
2052 		v[i].y = lua_tonumber(L, -1);
2053 		lua_pop(L, 1);
2054 	}
2055 	lua_pop(L, 1);
2056 	fill_poly(src, v, nr, col);
2057 	free(v);
2058 	return 0;
2059 }
2060 
pixels_value(lua_State * L)2061 static int pixels_value(lua_State *L) {
2062 	struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1);
2063 	int x = luaL_optnumber(L, 2, -1);
2064 	int y = luaL_optnumber(L, 3, -1);
2065 	int r = luaL_optnumber(L, 4, -1);
2066 	int g = 0, b = 0, a = 0;
2067 	unsigned char *ptr;
2068 	if (r != -1) {
2069 		g = luaL_optnumber(L, 5, 0);
2070 		b = luaL_optnumber(L, 6, 0);
2071 		a = luaL_optnumber(L, 7, 255);
2072 	}
2073 	if (x < 0 || y < 0)
2074 		return 0;
2075 
2076 	if (!hdr || hdr->type != PIXELS_MAGIC)
2077 		return 0;
2078 
2079 	if (x >= hdr->w || y >= hdr->h)
2080 		return 0;
2081 
2082 	ptr = (unsigned char*)(hdr + 1);
2083 	ptr += ((y * hdr->w + x) << 2);
2084 	if (r == -1) {
2085 		lua_pushinteger(L, *(ptr ++));
2086 		lua_pushinteger(L, *(ptr ++));
2087 		lua_pushinteger(L, *(ptr ++));
2088 		lua_pushinteger(L, *ptr);
2089 		return 4;
2090 	}
2091 	hdr->dirty = 1;
2092 	*(ptr ++) = r;
2093 	*(ptr ++) = g;
2094 	*(ptr ++) = b;
2095 	*(ptr) = a;
2096 	return 0;
2097 }
2098 
pixels_pixel(lua_State * L)2099 static int pixels_pixel(lua_State *L) {
2100 	struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1);
2101 	int x = luaL_optnumber(L, 2, -1);
2102 	int y = luaL_optnumber(L, 3, -1);
2103 	int r = luaL_optnumber(L, 4, -1);
2104 	int g, b, a;
2105 	unsigned char col[4];
2106 	unsigned char *ptr;
2107 	if (r == -1)
2108 		return 0;
2109 
2110 	g = luaL_optnumber(L, 5, 0);
2111 	b = luaL_optnumber(L, 6, 0);
2112 	a = luaL_optnumber(L, 7, 255);
2113 
2114 	if (x < 0 || y < 0)
2115 		return 0;
2116 
2117 	if (!hdr || hdr->type != PIXELS_MAGIC)
2118 		return 0;
2119 
2120 	if (x >= hdr->w || y >= hdr->h)
2121 		return 0;
2122 	hdr->dirty = 1;
2123 	ptr = (unsigned char*)(hdr + 1);
2124 	ptr += ((y * hdr->w + x) << 2);
2125 	col[0] = r; col[1] = g; col[2] = b; col[3] = a;
2126 	pixel(col, ptr);
2127 	return 0;
2128 }
2129 
pixels_img(struct lua_pixels * hdr)2130 static img_t pixels_img(struct lua_pixels *hdr) {
2131 	int w, h, ww, hh, xx, yy, dx, dy;
2132 	unsigned char *ptr, *optr = NULL;
2133 	unsigned char *p;
2134 	img_t img;
2135 	if (!hdr)
2136 		return NULL;
2137 	if (hdr->type != PIXELS_MAGIC)
2138 		return NULL;
2139 	img = hdr->img;
2140 	if (!img)
2141 		return NULL;
2142 
2143 	if (hdr->direct || !hdr->dirty)
2144 		return img;
2145 	hdr->dirty = 0;
2146 
2147 	ptr = (unsigned char*)(hdr + 1);
2148 	ww = gfx_img_w(img);
2149 	hh = gfx_img_h(img);
2150 	w = hdr->w;
2151 	h = hdr->h;
2152 
2153 
2154 	p = gfx_get_pixels(img);
2155 
2156 	if (!p)
2157 		return NULL;
2158 
2159 	dy = 0;
2160 
2161 	for (yy = 0; yy < hh; yy++) {
2162 		unsigned char *ptrl = ptr;
2163 
2164 		dx = 0;
2165 
2166 		if (optr) {
2167 			memcpy(p, optr, ww * 4);
2168 			p += ww * 4;
2169 		} else {
2170 			optr = p;
2171 			for (xx = 0; xx < ww; xx++) {
2172 				memcpy(p, ptrl, 4); p += 4;
2173 				dx += w;
2174 				while (dx >= ww) {
2175 					dx -= ww;
2176 					ptrl += 4;
2177 				}
2178 			}
2179 		}
2180 		dy += h;
2181 		while (dy >= hh) {
2182 			dy -= hh;
2183 			ptr += (w << 2);
2184 			optr = NULL;
2185 		}
2186 	}
2187 	gfx_put_pixels(img);
2188 	return img;
2189 }
2190 
pixels_destroy(lua_State * L)2191 static int pixels_destroy(lua_State *L) {
2192 	struct lua_pixels *hdr = (struct lua_pixels*)lua_touserdata(L, 1);
2193 	if (!hdr || hdr->type != PIXELS_MAGIC)
2194 		return 0;
2195 
2196 	if (hdr->img)
2197 		gfx_free_image(hdr->img);
2198 	return 0;
2199 }
2200 
pixels_new(lua_State * L,int w,int h,float scale,img_t src)2201 static int pixels_new(lua_State *L, int w, int h, float scale, img_t src) {
2202 	int ww, hh, direct = 0;
2203 	img_t img2 = NULL, img;
2204 	size_t size;
2205 	float v = game_theme.scale;
2206 	struct lua_pixels *hdr;
2207 
2208 	if (src) {
2209 		w = gfx_img_w(src);
2210 		h = gfx_img_h(src);
2211 		img2 = gfx_new_rgba(w, h);
2212 		if (!img2)
2213 			return 0;
2214 		gfx_copy_from(src, 0, 0, w, h, img2, 0, 0);
2215 	}
2216 	if (w <=0 || h <= 0)
2217 		return 0;
2218 	ww = w; hh = h;
2219 	if (v != 1.0f) {
2220 		ww = ceil((float)w * v);
2221 		hh = ceil((float)h * v);
2222 	}
2223 	ww = ceil((float)ww * scale);
2224 	hh = ceil((float)hh * scale);
2225 	size = w * h * 4;
2226 	hdr = lua_newuserdata(L, sizeof(*hdr) + size);
2227 	if (!hdr) {
2228 		if (img2)
2229 			gfx_free_image(img2);
2230 		return 0;
2231 	}
2232 
2233 	hdr->type = PIXELS_MAGIC;
2234 	hdr->img = NULL;
2235 	hdr->w = w;
2236 	hdr->h = h;
2237 	hdr->scale = scale;
2238 	hdr->size = size;
2239 	hdr->dirty = 0;
2240 
2241 	if (ww == w && hh == h) { /* direct map */
2242 		direct = 1;
2243 		img = gfx_new_from(ww, hh, (unsigned char*)(hdr + 1));
2244 	} else {
2245 		img = gfx_new_rgba(ww, hh);
2246 	}
2247 	hdr->direct = direct;
2248 	if (!img) {
2249 		fprintf(stderr, "Error: no free memory\n");
2250 		memset(hdr, 0, sizeof(*hdr) + size);
2251 		if (img2)
2252 			gfx_free_image(img2);
2253 		return 1;
2254 	}
2255 
2256 	hdr->img = img;
2257 	if (img2) {
2258 		unsigned char *ptr = gfx_get_pixels(img2);
2259 		if (ptr) {
2260 			memcpy(hdr + 1, ptr, size);
2261 			gfx_put_pixels(img2);
2262 		}
2263 		gfx_free_image(img2);
2264 	} else {
2265 		memset(hdr + 1, 0, size);
2266 	}
2267 	hdr->dirty = 1;
2268 	luaL_getmetatable(L, "pixels metatable");
2269 	lua_setmetatable(L, -2);
2270 	return 1;
2271 
2272 }
luaB_pixels_sprite(lua_State * L)2273 static int luaB_pixels_sprite(lua_State *L) {
2274 	const char *fname;
2275 	int w, h, rc;
2276 	float scale;
2277 	img_t img = NULL;
2278 
2279 	if (!lua_isnumber(L, 1)) {
2280 		fname = luaL_optstring(L, 1, NULL);
2281 		if (!fname)
2282 			return 0;
2283 		img = gfx_load_image((char*)fname);
2284 		if (!img)
2285 			return 0;
2286 //		if (!cache_have(gfx_image_cache(), img))
2287 //			v = 1.0f; /* do not scale sprites! */
2288 		w = 0; h = 0;
2289 		scale = luaL_optnumber(L, 2, 1.0f);
2290 	} else {
2291 		w = luaL_optnumber(L, 1, -1);
2292 		h = luaL_optnumber(L, 2, -1);
2293 		scale = luaL_optnumber(L, 3, 1.0f);
2294 	}
2295 	rc = pixels_new(L, w, h, scale, img);
2296 	if (img)
2297 		gfx_free_image(img);
2298 	return rc;
2299 }
2300 
pixels_scale(lua_State * L)2301 static int pixels_scale(lua_State *L) {
2302 	img_t img, img2;
2303 	int rc;
2304 	struct lua_pixels *src = (struct lua_pixels*)lua_touserdata(L, 1);
2305 	float xs = luaL_optnumber(L, 2, 0);
2306 	float ys = luaL_optnumber(L, 3, 0);
2307 	int smooth = lua_toboolean(L, 4);
2308 
2309 	if (!src || src->type != PIXELS_MAGIC)
2310 		return 0;
2311 	if (ys == 0)
2312 		ys = xs;
2313 	img = gfx_new_from(src->w, src->h, (unsigned char*)(src + 1));
2314 	if (!img)
2315 		return 0;
2316 	img2 = gfx_scale(img, xs, ys, smooth);
2317 	gfx_free_image(img);
2318 	rc = pixels_new(L, 0, 0, src->scale, img2);
2319 	gfx_free_image(img2);
2320 	return rc;
2321 }
2322 
pixels_rotate(lua_State * L)2323 static int pixels_rotate(lua_State *L) {
2324 	img_t img, img2;
2325 	int rc;
2326 	struct lua_pixels *src = (struct lua_pixels*)lua_touserdata(L, 1);
2327 	float angle = luaL_optnumber(L, 2, 0);
2328 	int smooth = lua_toboolean(L, 3);
2329 
2330 	if (!src || src->type != PIXELS_MAGIC)
2331 		return 0;
2332 	img = gfx_new_from(src->w, src->h, (unsigned char*)(src + 1));
2333 	if (!img)
2334 		return 0;
2335 	img2 = gfx_rotate(img, angle, smooth);
2336 	gfx_free_image(img);
2337 	rc = pixels_new(L, 0, 0, src->scale, img2);
2338 	gfx_free_image(img2);
2339 	return rc;
2340 }
2341 
2342 /*
2343 ** Creates pixels metatable.
2344 */
pixels_create_meta(lua_State * L)2345 static int pixels_create_meta (lua_State *L) {
2346 	luaL_newmetatable (L, "pixels metatable");
2347 	lua_pushstring (L, "__index");
2348 	lua_newtable(L);
2349 	lua_pushstring (L, "val");
2350 	lua_pushcfunction (L, pixels_value);
2351 	lua_settable(L, -3);
2352 	lua_pushstring (L, "pixel");
2353 	lua_pushcfunction (L, pixels_pixel);
2354 	lua_settable(L, -3);
2355 	lua_pushstring (L, "size");
2356 	lua_pushcfunction (L, pixels_size);
2357 	lua_settable(L, -3);
2358 	lua_pushstring(L, "copy");
2359 	lua_pushcfunction (L, pixels_copy);
2360 	lua_settable(L, -3);
2361 	lua_pushstring(L, "blend");
2362 	lua_pushcfunction (L, pixels_blend);
2363 	lua_settable(L, -3);
2364 	lua_pushstring(L, "clear");
2365 	lua_pushcfunction (L, pixels_clear);
2366 	lua_settable(L, -3);
2367 	lua_pushstring(L, "fill");
2368 	lua_pushcfunction (L, pixels_fill);
2369 	lua_settable(L, -3);
2370 	lua_pushstring(L, "line");
2371 	lua_pushcfunction (L, pixels_line);
2372 	lua_settable(L, -3);
2373 	lua_pushstring(L, "lineAA");
2374 	lua_pushcfunction (L, pixels_lineAA);
2375 	lua_settable(L, -3);
2376 	lua_pushstring(L, "circle");
2377 	lua_pushcfunction (L, pixels_circle);
2378 	lua_settable(L, -3);
2379 	lua_pushstring(L, "circleAA");
2380 	lua_pushcfunction (L, pixels_circleAA);
2381 	lua_settable(L, -3);
2382 	lua_pushstring(L, "fill_circle");
2383 	lua_pushcfunction (L, pixels_fill_circle);
2384 	lua_settable(L, -3);
2385 	lua_pushstring(L, "fill_triangle");
2386 	lua_pushcfunction (L, pixels_triangle);
2387 	lua_settable(L, -3);
2388 	lua_pushstring(L, "fill_poly");
2389 	lua_pushcfunction (L, pixels_fill_poly);
2390 	lua_settable(L, -3);
2391 	lua_pushstring(L, "new_scaled");
2392 	lua_pushcfunction (L, pixels_scale);
2393 	lua_settable(L, -3);
2394 	lua_pushstring(L, "new_rotated");
2395 	lua_pushcfunction (L, pixels_rotate);
2396 	lua_settable(L, -3);
2397 	lua_settable(L, -3);
2398 	lua_pushstring (L, "__gc");
2399 	lua_pushcfunction (L, pixels_destroy);
2400 	lua_settable (L, -3);
2401 	return 0;
2402 }
2403 
luaB_noise1(lua_State * L)2404 static int luaB_noise1(lua_State *L) {
2405 	float r;
2406 	int px;
2407 	float x = luaL_optnumber(L, 1, 0);
2408 	px = luaL_optnumber(L, 2, 0);
2409 	if (px > 0) {
2410 		r = pnoise1(x, px);
2411 	} else {
2412 		r = noise1(x);
2413 	}
2414 	lua_pushnumber(L, r);
2415 	return 1;
2416 }
2417 
luaB_noise2(lua_State * L)2418 static int luaB_noise2(lua_State *L) {
2419 	float r;
2420 	int px; int py;
2421 	float x = luaL_optnumber(L, 1, 0);
2422 	float y = luaL_optnumber(L, 2, 0);
2423 	px = luaL_optnumber(L, 3, 0);
2424 	py = luaL_optnumber(L, 4, 0);
2425 
2426 	if (px > 0 && py > 0) {
2427 		r = pnoise2(x, y, px, py);
2428 	} else {
2429 		r = noise2(x, y);
2430 	}
2431 	lua_pushnumber(L, r);
2432 	return 1;
2433 }
2434 
luaB_noise3(lua_State * L)2435 static int luaB_noise3(lua_State *L) {
2436 	float r;
2437 	int px; int py; int pz;
2438 	float x = luaL_optnumber(L, 1, 0);
2439 	float y = luaL_optnumber(L, 2, 0);
2440 	float z = luaL_optnumber(L, 3, 0);
2441 	px = luaL_optnumber(L, 4, 0);
2442 	py = luaL_optnumber(L, 5, 0);
2443 	pz = luaL_optnumber(L, 6, 0);
2444 
2445 	if (px > 0 && py > 0 && pz > 0) {
2446 		r = pnoise3(x, y, z, px, py, pz);
2447 	} else {
2448 		r = noise3(x, y, z);
2449 	}
2450 	lua_pushnumber(L, r);
2451 	return 1;
2452 }
2453 
luaB_noise4(lua_State * L)2454 static int luaB_noise4(lua_State *L) {
2455 	float r;
2456 	int px; int py; int pz; int pw;
2457 	float x = luaL_optnumber(L, 1, 0);
2458 	float y = luaL_optnumber(L, 2, 0);
2459 	float z = luaL_optnumber(L, 3, 0);
2460 	float w = luaL_optnumber(L, 4, 0);
2461 	px = luaL_optnumber(L, 5, 0);
2462 	py = luaL_optnumber(L, 6, 0);
2463 	pz = luaL_optnumber(L, 7, 0);
2464 	pw = luaL_optnumber(L, 8, 0);
2465 
2466 	if (px > 0 && py > 0 && pz > 0 && pw > 0) {
2467 		r = pnoise4(x, y, z, w, px, py, pz, pw);
2468 	} else {
2469 		r = noise4(x, y, z, w);
2470 	}
2471 	lua_pushnumber(L, r);
2472 	return 1;
2473 }
2474 
2475 static int callback_ref = 0;
2476 static int render_callback_dirty = 0;
2477 
instead_render_callback_dirty(int fl)2478 int instead_render_callback_dirty(int fl)
2479 {
2480 	int rc = render_callback_dirty;
2481 	if (!callback_ref || game_freezed())
2482 		return 0;
2483 	if (fl != -1)
2484 		render_callback_dirty = fl;
2485 	return rc;
2486 }
2487 
instead_render_callback(void)2488 void instead_render_callback(void)
2489 {
2490 	if (!callback_ref || game_freezed() || render_callback_dirty == -1)
2491 		return;
2492 
2493 	game_cursor(CURSOR_CLEAR);
2494 	instead_lock();
2495 	lua_rawgeti(instead_lua(), LUA_REGISTRYINDEX, callback_ref);
2496 	in_callback ++;
2497 	if (instead_pcall(instead_lua(), 0)) { /* on any error */
2498 		luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref);
2499 		callback_ref = 0;
2500 	}
2501 	in_callback --;
2502 	instead_clear();
2503 	instead_unlock();
2504 	if (game_pict_modify(NULL))
2505 		render_callback_dirty = -1;
2506 	game_cursor(CURSOR_DRAW);
2507 	return;
2508 }
2509 
luaB_after_callback(lua_State * L)2510 static int luaB_after_callback(lua_State *L) {
2511 	if (!opt_owntheme) {
2512 		lua_pushboolean(L, 0);
2513 		return 1;
2514 	}
2515 	if (callback_ref)
2516 		luaL_unref(L, LUA_REGISTRYINDEX, callback_ref);
2517 	callback_ref = 0;
2518 	if (lua_isfunction(L, 1))
2519 		callback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
2520 	lua_pushboolean(L, 0);
2521 	return 1;
2522 }
2523 
luaB_screen_size(lua_State * L)2524 static int luaB_screen_size(lua_State *L) {
2525 	int w = 0; int h = 0;
2526 	gfx_get_max_mode(&w, &h, MODE_ANY);
2527 	lua_pushinteger(L, w);
2528 	lua_pushinteger(L, h);
2529 	return 2;
2530 }
2531 
luaB_screen_dpi(lua_State * L)2532 static int luaB_screen_dpi(lua_State *L) {
2533 	lua_pushnumber(L, gfx_get_dpi());
2534 	return 1;
2535 }
2536 
2537 static const luaL_Reg sprites_funcs[] = {
2538 	{"instead_font_load", luaB_load_font},
2539 	{"instead_font_free", luaB_free_font},
2540 	{"instead_font_scaled_size", luaB_font_size_scaled},
2541 	{"instead_sprite_load", luaB_load_sprite},
2542 	{"instead_sprite_text", luaB_text_sprite},
2543 	{"instead_sprite_free", luaB_free_sprite},
2544 	{"instead_sprites_free", luaB_free_sprites},
2545 	{"instead_sprite_draw", luaB_draw_sprite},
2546 	{"instead_sprite_copy", luaB_copy_sprite},
2547 	{"instead_sprite_compose", luaB_compose_sprite},
2548 	{"instead_sprite_fill", luaB_fill_sprite},
2549 	{"instead_sprite_dup", luaB_dup_sprite},
2550 	{"instead_sprite_alpha", luaB_alpha_sprite},
2551 	{"instead_sprite_colorkey", luaB_colorkey_sprite},
2552 	{"instead_sprite_size", luaB_sprite_size},
2553 	{"instead_sprite_scale", luaB_scale_sprite},
2554 	{"instead_sprite_rotate", luaB_rotate_sprite},
2555 	{"instead_sprite_text_size", luaB_text_size},
2556 	{"instead_sprite_pixel", luaB_pixel_sprite},
2557 	{"instead_sprite_pixels", luaB_pixels_sprite},
2558 	{"instead_theme_var", luaB_theme_var},
2559 	{"instead_theme_name", luaB_theme_name},
2560 	{"instead_ticks", luaB_get_ticks},
2561 	{"instead_busy", luaB_stead_busy},
2562 	{"instead_direct", luaB_instead_direct},
2563 	{"instead_mouse_pos", luaB_mouse_pos},
2564 	{"instead_mouse_filter", luaB_mouse_filter},
2565 	{"instead_mouse_show", luaB_mouse_show},
2566 	{"instead_finger_pos", luaB_finger_pos},
2567 	{"instead_themespath", luaB_get_themespath},
2568 	{"instead_noise1", luaB_noise1},
2569 	{"instead_noise2", luaB_noise2},
2570 	{"instead_noise3", luaB_noise3},
2571 	{"instead_noise4", luaB_noise4},
2572 	{"instead_screen_size", luaB_screen_size},
2573 	{"instead_screen_dpi", luaB_screen_dpi},
2574 	{"instead_render_callback", luaB_after_callback},
2575 	{NULL, NULL}
2576 };
2577 
sprites_done(void)2578 static int sprites_done(void)
2579 {
2580 	if (callback_ref) {
2581 		luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref);
2582 		callback_ref = 0;
2583 		render_callback_dirty = 0;
2584 	}
2585 	sprites_free();
2586 	return 0;
2587 }
2588 
sprites_init(void)2589 static int sprites_init(void)
2590 {
2591 	char path[PATH_MAX];
2592 	if (pixels_create_meta(instead_lua()))
2593 		return -1;
2594 	instead_api_register(sprites_funcs);
2595 	snprintf(path, sizeof(path), "%s/%s", instead_stead_path(), "/ext/sprites.lua");
2596 	return instead_loadfile(dirpath(path));
2597 }
2598 
sprites_err(void)2599 static int sprites_err(void)
2600 {
2601 	if (callback_ref) {
2602 		luaL_unref(instead_lua(), LUA_REGISTRYINDEX, callback_ref);
2603 		callback_ref = 0;
2604 	}
2605 	return 0;
2606 }
2607 
2608 static struct instead_ext ext = {
2609 	.init = sprites_init,
2610 	.done = sprites_done,
2611 	.err = sprites_err,
2612 };
2613 
instead_sprites_init(void)2614 int instead_sprites_init(void)
2615 {
2616 	return instead_extension(&ext);
2617 }
2618