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 ) */
60void
61ficl_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 ) */
111void
112ficl_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
150void
151ficl_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
164void
165ficl_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
181void
182ficl_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
200void
201ficl_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
217void
218ficl_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**************************************************************************/
238static 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}
254FICL_COMPILE_SET(ficlCompileGfx);
255
256void
257gfx_interp_ref(void)
258{
259}
260