xref: /freebsd/stand/ficl/gfx_loader.c (revision 3fb2e045791eb6f003205902cdc4f74702770ec6)
1 /*-
2  * Copyright (c) 2024 Netflix, Inc
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 /* Copied from a file that likely shoulve have had this at the top */
8 /*-
9  * SPDX-License-Identifier: BSD-2-Clause
10  *
11  * Copyright 2020 Toomas Soome
12  * Copyright 2020 RackTop Systems, Inc.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 /*******************************************************************
37 ** g f x _ l o a d e r . c
38 ** Additional FICL words designed for FreeBSD's loader
39 ** for graphics
40 *******************************************************************/
41 
42 #include <stand.h>
43 #include "bootstrap.h"
44 #include <gfx_fb.h>
45 #include <pnglite.h>
46 #include "ficl.h"
47 
48 /*		FreeBSD's loader interaction words and extras
49  *		for graphics
50  *		fb-bezier	( x0 y0 x1 y1 x2 y2 wd -- )
51  *		fb-drawrect	( x1 y1 x2 y2 fill -- )
52  *		fb-line		( x0 y0 x1 y1 wd -- )
53  * 		fb-putimage	( flags x1 y1 x2 y2 -- flag )
54  *		fb-setpixel	( x y -- )
55  *		term-drawrect	( x1 y1 x2 y2 fill -- )
56  *		term-putimage	( flags x1 y1 x2 y2 -- flag )
57  */
58 
59 /* ( flags x1 y1 x2 y2 -- flag ) */
60 void
61 ficl_term_putimage(FICL_VM *pVM)
62 {
63         char *namep, *name;
64         int names;
65         unsigned long ret = FICL_FALSE;
66         uint32_t x1, y1, x2, y2, f;
67         png_t png;
68 	int error;
69 
70 #if FICL_ROBUST > 1
71 	vmCheckStack(pVM, 7, 1);
72 #endif
73         names = stackPopINT(pVM->pStack);
74         namep = (char *) stackPopPtr(pVM->pStack);
75         y2 = stackPopINT(pVM->pStack);
76         x2 = stackPopINT(pVM->pStack);
77         y1 = stackPopINT(pVM->pStack);
78         x1 = stackPopINT(pVM->pStack);
79         f = stackPopINT(pVM->pStack);
80 
81 	x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
82 	y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
83 	if (x2 != 0) {
84 		x2 = gfx_state.tg_origin.tp_col +
85 		    x2 * gfx_state.tg_font.vf_width;
86 	}
87 	if (y2 != 0) {
88 		y2 = gfx_state.tg_origin.tp_row +
89 		    y2 * gfx_state.tg_font.vf_height;
90 	}
91 
92         name = ficlMalloc(names + 1);
93         if (!name)
94 		vmThrowErr(pVM, "Error: out of memory");
95         (void) strncpy(name, namep, names);
96         name[names] = '\0';
97 
98         if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
99 		if (f & FL_PUTIMAGE_DEBUG)
100 			printf("%s\n", png_error_string(error));
101 	} else {
102                 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
103                         ret = FICL_TRUE;        /* success */
104                 (void) png_close(&png);
105 	}
106         ficlFree(name);
107 	stackPushUNS(pVM->pStack, ret);
108 }
109 
110 /* ( flags x1 y1 x2 y2 -- flag ) */
111 void
112 ficl_fb_putimage(FICL_VM *pVM)
113 {
114         char *namep, *name;
115         int names;
116         unsigned long ret = FICL_FALSE;
117         uint32_t x1, y1, x2, y2, f;
118         png_t png;
119 	int error;
120 
121 #if FICL_ROBUST > 1
122 	vmCheckStack(pVM, 7, 1);
123 #endif
124         names = stackPopINT(pVM->pStack);
125         namep = (char *) stackPopPtr(pVM->pStack);
126         y2 = stackPopINT(pVM->pStack);
127         x2 = stackPopINT(pVM->pStack);
128         y1 = stackPopINT(pVM->pStack);
129         x1 = stackPopINT(pVM->pStack);
130         f = stackPopINT(pVM->pStack);
131 
132         name = ficlMalloc(names + 1);
133         if (!name)
134 		vmThrowErr(pVM, "Error: out of memory");
135         (void) strncpy(name, namep, names);
136         name[names] = '\0';
137 
138         if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
139 		if (f & FL_PUTIMAGE_DEBUG)
140 			printf("%s\n", png_error_string(error));
141 	} else {
142                 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
143                         ret = FICL_TRUE;        /* success */
144                 (void) png_close(&png);
145 	}
146         ficlFree(name);
147 	stackPushUNS(pVM->pStack, ret);
148 }
149 
150 void
151 ficl_fb_setpixel(FICL_VM *pVM)
152 {
153         FICL_UNS x, y;
154 
155 #if FICL_ROBUST > 1
156 	vmCheckStack(pVM, 2, 0);
157 #endif
158 
159         y = stackPopUNS(pVM->pStack);
160         x = stackPopUNS(pVM->pStack);
161         gfx_fb_setpixel(x, y);
162 }
163 
164 void
165 ficl_fb_line(FICL_VM *pVM)
166 {
167 	FICL_UNS x0, y0, x1, y1, wd;
168 
169 #if FICL_ROBUST > 1
170 	vmCheckStack(pVM, 5, 0);
171 #endif
172 
173 	wd = stackPopUNS(pVM->pStack);
174 	y1 = stackPopUNS(pVM->pStack);
175 	x1 = stackPopUNS(pVM->pStack);
176 	y0 = stackPopUNS(pVM->pStack);
177 	x0 = stackPopUNS(pVM->pStack);
178 	gfx_fb_line(x0, y0, x1, y1, wd);
179 }
180 
181 void
182 ficl_fb_bezier(FICL_VM *pVM)
183 {
184 	FICL_UNS x0, y0, x1, y1, x2, y2, width;
185 
186 #if FICL_ROBUST > 1
187 	vmCheckStack(pVM, 7, 0);
188 #endif
189 
190 	width = stackPopUNS(pVM->pStack);
191 	y2 = stackPopUNS(pVM->pStack);
192 	x2 = stackPopUNS(pVM->pStack);
193 	y1 = stackPopUNS(pVM->pStack);
194 	x1 = stackPopUNS(pVM->pStack);
195 	y0 = stackPopUNS(pVM->pStack);
196 	x0 = stackPopUNS(pVM->pStack);
197 	gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
198 }
199 
200 void
201 ficl_fb_drawrect(FICL_VM *pVM)
202 {
203 	FICL_UNS x1, x2, y1, y2, fill;
204 
205 #if FICL_ROBUST > 1
206 	vmCheckStack(pVM, 5, 0);
207 #endif
208 
209 	fill = stackPopUNS(pVM->pStack);
210 	y2 = stackPopUNS(pVM->pStack);
211 	x2 = stackPopUNS(pVM->pStack);
212 	y1 = stackPopUNS(pVM->pStack);
213 	x1 = stackPopUNS(pVM->pStack);
214 	gfx_fb_drawrect(x1, y1, x2, y2, fill);
215 }
216 
217 void
218 ficl_term_drawrect(FICL_VM *pVM)
219 {
220 	FICL_UNS x1, x2, y1, y2;
221 
222 #if FICL_ROBUST > 1
223 	vmCheckStack(pVM, 4, 0);
224 #endif
225 
226 	y2 = stackPopUNS(pVM->pStack);
227 	x2 = stackPopUNS(pVM->pStack);
228 	y1 = stackPopUNS(pVM->pStack);
229 	x1 = stackPopUNS(pVM->pStack);
230 	gfx_term_drawrect(x1, y1, x2, y2);
231 }
232 
233 /**************************************************************************
234                         f i c l C o m p i l e G f x
235 ** Build FreeBSD platform extensions into the system dictionary
236 ** for gfx
237 **************************************************************************/
238 static void ficlCompileGfx(FICL_SYSTEM *pSys)
239 {
240     ficlCompileFcn **fnpp;
241     FICL_DICT *dp = pSys->dp;
242     assert (dp);
243 
244     dictAppendWord(dp, "fb-setpixel", ficl_fb_setpixel, FW_DEFAULT);
245     dictAppendWord(dp, "fb-line", ficl_fb_line, FW_DEFAULT);
246     dictAppendWord(dp, "fb-bezier", ficl_fb_bezier, FW_DEFAULT);
247     dictAppendWord(dp, "fb-drawrect", ficl_fb_drawrect, FW_DEFAULT);
248     dictAppendWord(dp, "fb-putimage", ficl_fb_putimage, FW_DEFAULT);
249     dictAppendWord(dp, "term-drawrect", ficl_term_drawrect, FW_DEFAULT);
250     dictAppendWord(dp, "term-putimage", ficl_term_putimage, FW_DEFAULT);
251 
252     return;
253 }
254 FICL_COMPILE_SET(ficlCompileGfx);
255 
256 void
257 gfx_interp_ref(void)
258 {
259 }
260