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
ficl_term_putimage(FICL_VM * pVM)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
ficl_fb_putimage(FICL_VM * pVM)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
ficl_fb_setpixel(FICL_VM * pVM)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
ficl_fb_line(FICL_VM * pVM)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
ficl_fb_bezier(FICL_VM * pVM)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
ficl_fb_drawrect(FICL_VM * pVM)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
ficl_term_drawrect(FICL_VM * pVM)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 **************************************************************************/
ficlCompileGfx(FICL_SYSTEM * pSys)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
gfx_interp_ref(void)257 gfx_interp_ref(void)
258 {
259 }
260