xref: /freebsd-src/stand/liblua/gfx_utils.c (revision 6faf55c86d9b86f40de8d19970e42cb42a892c47)
1061b68a7SWarner Losh /*-
2061b68a7SWarner Losh  * Copyright (c) 2024 Netflix, Inc.
3061b68a7SWarner Losh  *
4061b68a7SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
5061b68a7SWarner Losh  */
6061b68a7SWarner Losh 
7061b68a7SWarner Losh /* Copied from a file that likely shoulve have had this at the top */
8061b68a7SWarner Losh /*-
9061b68a7SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
10061b68a7SWarner Losh  *
11061b68a7SWarner Losh  * Copyright 2020 Toomas Soome
12061b68a7SWarner Losh  * Copyright 2020 RackTop Systems, Inc.
13061b68a7SWarner Losh  *
14061b68a7SWarner Losh  * Redistribution and use in source and binary forms, with or without
15061b68a7SWarner Losh  * modification, are permitted provided that the following conditions
16061b68a7SWarner Losh  * are met:
17061b68a7SWarner Losh  * 1. Redistributions of source code must retain the above copyright
18061b68a7SWarner Losh  *    notice, this list of conditions and the following disclaimer.
19061b68a7SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
20061b68a7SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
21061b68a7SWarner Losh  *    documentation and/or other materials provided with the distribution.
22061b68a7SWarner Losh  *
23061b68a7SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24061b68a7SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25061b68a7SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26061b68a7SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27061b68a7SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28061b68a7SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29061b68a7SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30061b68a7SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31061b68a7SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32061b68a7SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33061b68a7SWarner Losh  * SUCH DAMAGE.
34061b68a7SWarner Losh  */
35061b68a7SWarner Losh 
36061b68a7SWarner Losh #include "lua.h"
37061b68a7SWarner Losh #include "lauxlib.h"
38061b68a7SWarner Losh #include "lutils.h"
39061b68a7SWarner Losh #include <gfx_fb.h>
40061b68a7SWarner Losh #include <pnglite.h>
41061b68a7SWarner Losh 
42061b68a7SWarner Losh /*
43061b68a7SWarner Losh  * put image using terminal coordinates.
44061b68a7SWarner Losh  */
45061b68a7SWarner Losh static int
lua_term_putimage(lua_State * L)46061b68a7SWarner Losh lua_term_putimage(lua_State *L)
47061b68a7SWarner Losh {
48061b68a7SWarner Losh 	const char *name;
49061b68a7SWarner Losh 	png_t png;
50061b68a7SWarner Losh 	uint32_t x1, y1, x2, y2, f;
51061b68a7SWarner Losh 	int nargs, ret = 0, error;
52061b68a7SWarner Losh 
53061b68a7SWarner Losh 	nargs = lua_gettop(L);
54061b68a7SWarner Losh 	if (nargs != 6) {
55061b68a7SWarner Losh 		lua_pushboolean(L, 0);
56061b68a7SWarner Losh 		return 1;
57061b68a7SWarner Losh 	}
58061b68a7SWarner Losh 
59061b68a7SWarner Losh 	name = luaL_checkstring(L, 1);
60061b68a7SWarner Losh 	x1 = luaL_checknumber(L, 2);
61061b68a7SWarner Losh 	y1 = luaL_checknumber(L, 3);
62061b68a7SWarner Losh 	x2 = luaL_checknumber(L, 4);
63061b68a7SWarner Losh 	y2 = luaL_checknumber(L, 5);
64061b68a7SWarner Losh 	f = luaL_checknumber(L, 6);
65061b68a7SWarner Losh 
66061b68a7SWarner Losh 	x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
67061b68a7SWarner Losh 	y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
68061b68a7SWarner Losh 	if (x2 != 0) {
69061b68a7SWarner Losh 		x2 = gfx_state.tg_origin.tp_col +
70061b68a7SWarner Losh 		    x2 * gfx_state.tg_font.vf_width;
71061b68a7SWarner Losh 	}
72061b68a7SWarner Losh 	if (y2 != 0) {
73061b68a7SWarner Losh 		y2 = gfx_state.tg_origin.tp_row +
74061b68a7SWarner Losh 		    y2 * gfx_state.tg_font.vf_height;
75061b68a7SWarner Losh 	}
76061b68a7SWarner Losh 
77061b68a7SWarner Losh 	if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
78061b68a7SWarner Losh 		if (f & FL_PUTIMAGE_DEBUG)
79061b68a7SWarner Losh 			printf("%s\n", png_error_string(error));
80061b68a7SWarner Losh 	} else {
81061b68a7SWarner Losh 		if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
82061b68a7SWarner Losh 			ret = 1;
83061b68a7SWarner Losh 		(void) png_close(&png);
84061b68a7SWarner Losh 	}
85061b68a7SWarner Losh 	lua_pushboolean(L, ret);
86061b68a7SWarner Losh 	return 1;
87061b68a7SWarner Losh }
88061b68a7SWarner Losh 
89061b68a7SWarner Losh static int
lua_fb_putimage(lua_State * L)90061b68a7SWarner Losh lua_fb_putimage(lua_State *L)
91061b68a7SWarner Losh {
92061b68a7SWarner Losh 	const char *name;
93061b68a7SWarner Losh 	png_t png;
94061b68a7SWarner Losh 	uint32_t x1, y1, x2, y2, f;
95061b68a7SWarner Losh 	int nargs, ret = 0, error;
96061b68a7SWarner Losh 
97061b68a7SWarner Losh 	nargs = lua_gettop(L);
98061b68a7SWarner Losh 	if (nargs != 6) {
99061b68a7SWarner Losh 		lua_pushboolean(L, 0);
100061b68a7SWarner Losh 		return 1;
101061b68a7SWarner Losh 	}
102061b68a7SWarner Losh 
103061b68a7SWarner Losh 	name = luaL_checkstring(L, 1);
104061b68a7SWarner Losh 	x1 = luaL_checknumber(L, 2);
105061b68a7SWarner Losh 	y1 = luaL_checknumber(L, 3);
106061b68a7SWarner Losh 	x2 = luaL_checknumber(L, 4);
107061b68a7SWarner Losh 	y2 = luaL_checknumber(L, 5);
108061b68a7SWarner Losh 	f = luaL_checknumber(L, 6);
109061b68a7SWarner Losh 
110061b68a7SWarner Losh 	if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
111061b68a7SWarner Losh 		if (f & FL_PUTIMAGE_DEBUG)
112061b68a7SWarner Losh 			printf("%s\n", png_error_string(error));
113061b68a7SWarner Losh 	} else {
114061b68a7SWarner Losh 		if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
115061b68a7SWarner Losh 			ret = 1;
116061b68a7SWarner Losh 		(void) png_close(&png);
117061b68a7SWarner Losh 	}
118061b68a7SWarner Losh 	lua_pushboolean(L, ret);
119061b68a7SWarner Losh 	return 1;
120061b68a7SWarner Losh }
121061b68a7SWarner Losh 
122061b68a7SWarner Losh static int
lua_fb_setpixel(lua_State * L)123061b68a7SWarner Losh lua_fb_setpixel(lua_State *L)
124061b68a7SWarner Losh {
125061b68a7SWarner Losh 	uint32_t x, y;
126061b68a7SWarner Losh 	int nargs;
127061b68a7SWarner Losh 
128061b68a7SWarner Losh 	nargs = lua_gettop(L);
129061b68a7SWarner Losh 	if (nargs != 2) {
130061b68a7SWarner Losh 		lua_pushnil(L);
131061b68a7SWarner Losh 		return 1;
132061b68a7SWarner Losh 	}
133061b68a7SWarner Losh 
134061b68a7SWarner Losh 	x = luaL_checknumber(L, 1);
135061b68a7SWarner Losh 	y = luaL_checknumber(L, 2);
136061b68a7SWarner Losh         gfx_fb_setpixel(x, y);
137061b68a7SWarner Losh 	return 0;
138061b68a7SWarner Losh }
139061b68a7SWarner Losh 
140061b68a7SWarner Losh static int
lua_fb_line(lua_State * L)141061b68a7SWarner Losh lua_fb_line(lua_State *L)
142061b68a7SWarner Losh {
143061b68a7SWarner Losh 	uint32_t x0, y0, x1, y1, wd;
144061b68a7SWarner Losh 	int nargs;
145061b68a7SWarner Losh 
146061b68a7SWarner Losh 	nargs = lua_gettop(L);
147061b68a7SWarner Losh 	if (nargs != 5) {
148061b68a7SWarner Losh 		lua_pushnil(L);
149061b68a7SWarner Losh 		return 1;
150061b68a7SWarner Losh 	}
151061b68a7SWarner Losh 
152061b68a7SWarner Losh 	x0 = luaL_checknumber(L, 1);
153061b68a7SWarner Losh 	y0 = luaL_checknumber(L, 2);
154061b68a7SWarner Losh 	x1 = luaL_checknumber(L, 3);
155061b68a7SWarner Losh 	y1 = luaL_checknumber(L, 4);
156061b68a7SWarner Losh 	wd = luaL_checknumber(L, 5);
157061b68a7SWarner Losh         gfx_fb_line(x0, y0, x1, y1, wd);
158061b68a7SWarner Losh 	return 0;
159061b68a7SWarner Losh }
160061b68a7SWarner Losh 
161061b68a7SWarner Losh static int
lua_fb_bezier(lua_State * L)162061b68a7SWarner Losh lua_fb_bezier(lua_State *L)
163061b68a7SWarner Losh {
164061b68a7SWarner Losh 	uint32_t x0, y0, x1, y1, x2, y2, width;
165061b68a7SWarner Losh 	int nargs;
166061b68a7SWarner Losh 
167061b68a7SWarner Losh 	nargs = lua_gettop(L);
168061b68a7SWarner Losh 	if (nargs != 7) {
169061b68a7SWarner Losh 		lua_pushnil(L);
170061b68a7SWarner Losh 		return 1;
171061b68a7SWarner Losh 	}
172061b68a7SWarner Losh 
173061b68a7SWarner Losh 	x0 = luaL_checknumber(L, 1);
174061b68a7SWarner Losh 	y0 = luaL_checknumber(L, 2);
175061b68a7SWarner Losh 	x1 = luaL_checknumber(L, 3);
176061b68a7SWarner Losh 	y1 = luaL_checknumber(L, 4);
177061b68a7SWarner Losh 	x2 = luaL_checknumber(L, 5);
178061b68a7SWarner Losh 	y2 = luaL_checknumber(L, 6);
179061b68a7SWarner Losh 	width = luaL_checknumber(L, 7);
180061b68a7SWarner Losh         gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
181061b68a7SWarner Losh 	return 0;
182061b68a7SWarner Losh }
183061b68a7SWarner Losh 
184061b68a7SWarner Losh static int
lua_fb_drawrect(lua_State * L)185061b68a7SWarner Losh lua_fb_drawrect(lua_State *L)
186061b68a7SWarner Losh {
187061b68a7SWarner Losh 	uint32_t x0, y0, x1, y1, fill;
188061b68a7SWarner Losh 	int nargs;
189061b68a7SWarner Losh 
190061b68a7SWarner Losh 	nargs = lua_gettop(L);
191061b68a7SWarner Losh 	if (nargs != 5) {
192061b68a7SWarner Losh 		lua_pushnil(L);
193061b68a7SWarner Losh 		return 1;
194061b68a7SWarner Losh 	}
195061b68a7SWarner Losh 
196061b68a7SWarner Losh 	x0 = luaL_checknumber(L, 1);
197061b68a7SWarner Losh 	y0 = luaL_checknumber(L, 2);
198061b68a7SWarner Losh 	x1 = luaL_checknumber(L, 3);
199061b68a7SWarner Losh 	y1 = luaL_checknumber(L, 4);
200061b68a7SWarner Losh 	fill = luaL_checknumber(L, 5);
201061b68a7SWarner Losh         gfx_fb_drawrect(x0, y0, x1, y1, fill);
202061b68a7SWarner Losh 	return 0;
203061b68a7SWarner Losh }
204061b68a7SWarner Losh 
205061b68a7SWarner Losh static int
lua_term_drawrect(lua_State * L)206061b68a7SWarner Losh lua_term_drawrect(lua_State *L)
207061b68a7SWarner Losh {
208061b68a7SWarner Losh 	uint32_t x0, y0, x1, y1;
209061b68a7SWarner Losh 	int nargs;
210061b68a7SWarner Losh 
211061b68a7SWarner Losh 	nargs = lua_gettop(L);
212061b68a7SWarner Losh 	if (nargs != 4) {
213061b68a7SWarner Losh 		lua_pushnil(L);
214061b68a7SWarner Losh 		return 1;
215061b68a7SWarner Losh 	}
216061b68a7SWarner Losh 
217061b68a7SWarner Losh 	x0 = luaL_checknumber(L, 1);
218061b68a7SWarner Losh 	y0 = luaL_checknumber(L, 2);
219061b68a7SWarner Losh 	x1 = luaL_checknumber(L, 3);
220061b68a7SWarner Losh 	y1 = luaL_checknumber(L, 4);
221061b68a7SWarner Losh         gfx_term_drawrect(x0, y0, x1, y1);
222061b68a7SWarner Losh 	return 0;
223061b68a7SWarner Losh }
224061b68a7SWarner Losh 
225061b68a7SWarner Losh #define REG_SIMPLE(n)	{ #n, lua_ ## n }
226061b68a7SWarner Losh static const struct luaL_Reg gfxlib[] = {
227061b68a7SWarner Losh 	REG_SIMPLE(fb_bezier),
228061b68a7SWarner Losh 	REG_SIMPLE(fb_drawrect),
229061b68a7SWarner Losh 	REG_SIMPLE(fb_line),
230061b68a7SWarner Losh 	REG_SIMPLE(fb_putimage),
231061b68a7SWarner Losh 	REG_SIMPLE(fb_setpixel),
232061b68a7SWarner Losh 	REG_SIMPLE(term_drawrect),
233061b68a7SWarner Losh 	REG_SIMPLE(term_putimage),
234061b68a7SWarner Losh 	{ NULL, NULL },
235061b68a7SWarner Losh };
236061b68a7SWarner Losh 
237061b68a7SWarner Losh int
luaopen_gfx(lua_State * L)238061b68a7SWarner Losh luaopen_gfx(lua_State *L)
239061b68a7SWarner Losh {
240061b68a7SWarner Losh 	luaL_newlib(L, gfxlib);
241061b68a7SWarner Losh 	return 1;
242061b68a7SWarner Losh }
24360e199d9SWarner Losh 
24460e199d9SWarner Losh void
gfx_interp_ref(void)245*6faf55c8SWarner Losh gfx_interp_ref(void)
24660e199d9SWarner Losh {
24760e199d9SWarner Losh }
2480921a771SWarner Losh 
2490921a771SWarner Losh static void
gfx_init_md(lua_State * L)2500921a771SWarner Losh gfx_init_md(lua_State *L)
2510921a771SWarner Losh {
2520921a771SWarner Losh 	luaL_requiref(L, "gfx", luaopen_gfx, 1);
2530921a771SWarner Losh 	lua_pop(L, 1);	/* Remove lib */
2540921a771SWarner Losh 
2550921a771SWarner Losh 	/*
2560921a771SWarner Losh 	 * Add in the compatibility references in the loader table.  Doing it with
2570921a771SWarner Losh 	 * a pseudo-embedded script is easier than the raw calls.
2580921a771SWarner Losh 	 */
2590921a771SWarner Losh 	if (luaL_dostring(L,
2600921a771SWarner Losh 		"loader.fb_bezier = gfx.fb_bezier\n"
2610921a771SWarner Losh 		"loader.fb_drawrect = gfx.fb_drawrect\n"
2620921a771SWarner Losh 		"loader.fb_line = gfx.fb_line\n"
2630921a771SWarner Losh 		"loader.fb_putimage = gfx.fb_putimage\n"
2640921a771SWarner Losh 		"loader.fb_setpixel = gfx.fb_setpixel\n"
2650921a771SWarner Losh 		"loader.term_drawrect = gfx.term_drawrect\n"
2660921a771SWarner Losh 		"loader.term_putimage = gfx.term_putimage") != 0) {
2670921a771SWarner Losh 		lua_pop(L, 1);
2680921a771SWarner Losh 		const char *errstr = lua_tostring(L, -1);
2690921a771SWarner Losh 		errstr = errstr == NULL ? "unknown" : errstr;
2700921a771SWarner Losh 		printf("Error adding compat loader bindings: %s.\n", errstr);
2710921a771SWarner Losh 	}
2720921a771SWarner Losh }
2730921a771SWarner Losh 
2740921a771SWarner Losh LUA_COMPILE_SET(gfx_init_md);
275