Add initial bits for Qt6 support
[carla.git] / source / modules / ysfx / sources / ysfx_api_gfx_lice.hpp
bloba98994badfe20b4dcf0fbb6cb5b8291b85c53868
1 //
2 // This file is based in part on modified source code from `WDL/eel2/eel_lice.h`.
3 // The zlib license from the WDL applies to this source file.
4 //
5 //------------------------------------------------------------------------------
6 //
7 // Copyright (C) 2021 and later Jean Pierre Cimalando
8 // Copyright (C) 2005 and later Cockos Incorporated
9 //
11 // Portions copyright other contributors, see each source file for more information
13 // This software is provided 'as-is', without any express or implied
14 // warranty. In no event will the authors be held liable for any damages
15 // arising from the use of this software.
17 // Permission is granted to anyone to use this software for any purpose,
18 // including commercial applications, and to alter it and redistribute it
19 // freely, subject to the following restrictions:
21 // 1. The origin of this software must not be misrepresented; you must not
22 // claim that you wrote the original software. If you use this software
23 // in a product, an acknowledgment in the product documentation would be
24 // appreciated but is not required.
25 // 2. Altered source versions must be plainly marked as such, and must not be
26 // misrepresented as being the original software.
27 // 3. This notice may not be removed or altered from any source distribution.
29 // SPDX-License-Identifier: Zlib
32 #pragma once
33 #include "ysfx_api_eel.hpp"
34 #include "WDL/wdlstring.h"
35 #include "WDL/wdlcstring.h"
36 #include "WDL/wdlutf8.h"
37 #include <algorithm>
38 #include <cmath>
39 #include <cstdio>
40 #include <cstring>
42 // help clangd to figure things out
43 #if defined(__CLANGD__)
44 # include "ysfx_api_gfx.cpp"
45 #endif
47 #define EEL_LICE_GET_CONTEXT(opaque) ((opaque) ? ((ysfx_t *)(opaque))->gfx.state->lice.get() : nullptr)
49 //------------------------------------------------------------------------------
51 #define LICE_FUNCTION_VALID(x) (sizeof(int) > 0)
53 static HDC LICE__GetDC(LICE_IBitmap *bm)
55 return bm->getDC();
57 static int LICE__GetWidth(LICE_IBitmap *bm)
59 return bm->getWidth();
61 static int LICE__GetHeight(LICE_IBitmap *bm)
63 return bm->getHeight();
65 static void LICE__Destroy(LICE_IBitmap *bm)
67 delete bm;
69 static void LICE__SetFromHFont(LICE_IFont * ifont, HFONT font, int flags)
71 if (ifont) ifont->SetFromHFont(font,flags);
73 static LICE_pixel LICE__SetTextColor(LICE_IFont* ifont, LICE_pixel color)
75 if (ifont) return ifont->SetTextColor(color);
76 return 0;
78 static void LICE__SetTextCombineMode(LICE_IFont* ifont, int mode, float alpha)
80 if (ifont) ifont->SetCombineMode(mode, alpha);
82 static int LICE__DrawText(LICE_IFont* ifont, LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags)
84 if (ifont) return ifont->DrawText(bm, str, strcnt, rect, dtFlags);
85 return 0;
89 static LICE_IFont *LICE_CreateFont()
91 return new LICE_CachedFont();
93 static void LICE__DestroyFont(LICE_IFont *bm)
95 delete bm;
97 static bool LICE__resize(LICE_IBitmap *bm, int w, int h)
99 return bm->resize(w,h);
102 static LICE_IBitmap *__LICE_CreateBitmap(int mode, int w, int h)
104 if (mode==1) return new LICE_SysBitmap(w,h);
105 return new LICE_MemBitmap(w,h);
108 class eel_lice_state
110 public:
112 eel_lice_state(NSEEL_VMCTX vm, void *ctx, int image_slots, int font_slots);
113 ~eel_lice_state();
115 LICE_IBitmap *m_framebuffer, *m_framebuffer_extra;
116 int m_framebuffer_dirty;
117 WDL_TypedBuf<LICE_IBitmap *> m_gfx_images;
118 struct gfxFontStruct {
119 LICE_IFont *font;
120 char last_fontname[128];
121 char actual_fontname[128];
122 int last_fontsize;
123 int last_fontflag;
125 int use_fonth;
127 WDL_TypedBuf<gfxFontStruct> m_gfx_fonts;
128 enum {
129 EELFONT_FLAG_BOLD = (1<<24),
130 EELFONT_FLAG_ITALIC = (2<<24),
131 EELFONT_FLAG_UNDERLINE = (4<<24),
132 EELFONT_FLAG_MASK = EELFONT_FLAG_BOLD|EELFONT_FLAG_ITALIC|EELFONT_FLAG_UNDERLINE
135 int m_gfx_font_active; // -1 for default, otherwise index into gfx_fonts (NOTE: this differs from the exposed API, which defines 0 as default, 1-n)
136 LICE_IFont *GetActiveFont() { return m_gfx_font_active>=0&&m_gfx_font_active<m_gfx_fonts.GetSize() && m_gfx_fonts.Get()[m_gfx_font_active].use_fonth ? m_gfx_fonts.Get()[m_gfx_font_active].font : NULL; }
138 LICE_IBitmap *GetImageForIndex(EEL_F idx, const char *callername)
140 if (idx>-2.0)
142 if (idx < 0.0) return m_framebuffer;
144 const int a = (int)idx;
145 if (a >= 0 && a < m_gfx_images.GetSize()) return m_gfx_images.Get()[a];
147 return NULL;
150 void SetImageDirty(LICE_IBitmap *bm)
152 if (bm == m_framebuffer && !m_framebuffer_dirty)
154 if (m_gfx_clear && *m_gfx_clear > -1.0)
156 const int a=(int)*m_gfx_clear;
157 if (LICE_FUNCTION_VALID(LICE_Clear)) LICE_Clear(m_framebuffer,LICE_RGBA((a&0xff),((a>>8)&0xff),((a>>16)&0xff),0));
159 m_framebuffer_dirty=1;
163 // R, G, B, A, w, h, x, y, mode(1=add,0=copy)
164 EEL_F *m_gfx_r, *m_gfx_g, *m_gfx_b, *m_gfx_w, *m_gfx_h, *m_gfx_a, *m_gfx_x, *m_gfx_y, *m_gfx_mode, *m_gfx_clear, *m_gfx_texth,*m_gfx_dest, *m_gfx_a2;
165 EEL_F *m_mouse_x, *m_mouse_y, *m_mouse_cap, *m_mouse_wheel, *m_mouse_hwheel;
166 EEL_F *m_gfx_ext_retina;
168 NSEEL_VMCTX m_vmref;
169 void *m_user_ctx;
171 void gfx_lineto(EEL_F xpos, EEL_F ypos, EEL_F aaflag);
172 void gfx_rectto(EEL_F xpos, EEL_F ypos);
173 void gfx_line(int np, EEL_F **parms);
174 void gfx_rect(int np, EEL_F **parms);
175 void gfx_roundrect(int np, EEL_F **parms);
176 void gfx_arc(int np, EEL_F **parms);
177 void gfx_set(int np, EEL_F **parms);
178 void gfx_grad_or_muladd_rect(int mode, int np, EEL_F **parms);
179 void gfx_setpixel(EEL_F r, EEL_F g, EEL_F b);
180 void gfx_getpixel(EEL_F *r, EEL_F *g, EEL_F *b);
181 void gfx_drawnumber(EEL_F n, EEL_F ndigits);
182 void gfx_drawchar(EEL_F ch);
183 void gfx_getimgdim(EEL_F img, EEL_F *w, EEL_F *h);
184 EEL_F gfx_setimgdim(int img, EEL_F *w, EEL_F *h);
185 void gfx_blurto(EEL_F x, EEL_F y);
186 void gfx_blitext(EEL_F img, EEL_F *coords, EEL_F angle);
187 void gfx_blitext2(int np, EEL_F **parms, int mode); // 0=blit, 1=deltablit
188 void gfx_transformblit(EEL_F **parms, int div_w, int div_h, EEL_F *tab); // parms[0]=src, 1-4=x,y,w,h
189 void gfx_circle(float x, float y, float r, bool fill, bool aaflag);
190 void gfx_triangle(EEL_F** parms, int nparms);
191 void gfx_drawstr(void *opaque, EEL_F **parms, int nparms, int formatmode); // formatmode=1 for format, 2 for purely measure no format, 3 for measure char
192 EEL_F gfx_loadimg(void *opaque, int img, EEL_F loadFrom);
193 EEL_F gfx_setfont(void *opaque, int np, EEL_F **parms);
194 EEL_F gfx_getfont(void *opaque, int np, EEL_F **parms);
196 LICE_pixel getCurColor();
197 int getCurMode();
198 int getCurModeForBlit(bool isFBsrc);
200 // these have to be **parms because of the hack for getting string from parm index
201 EEL_F gfx_setcursor(void* opaque, EEL_F** parms, int nparms);
204 eel_lice_state::eel_lice_state(NSEEL_VMCTX vm, void *ctx, int image_slots, int font_slots)
206 m_user_ctx=ctx;
207 m_vmref= vm;
208 m_gfx_font_active=-1;
209 m_gfx_fonts.Resize(font_slots);
210 memset(m_gfx_fonts.Get(),0,m_gfx_fonts.GetSize()*sizeof(m_gfx_fonts.Get()[0]));
212 m_gfx_images.Resize(image_slots);
213 memset(m_gfx_images.Get(),0,m_gfx_images.GetSize()*sizeof(m_gfx_images.Get()[0]));
214 m_framebuffer=m_framebuffer_extra=0;
215 m_framebuffer_dirty=0;
217 m_gfx_r = NSEEL_VM_regvar(vm,"gfx_r");
218 m_gfx_g = NSEEL_VM_regvar(vm,"gfx_g");
219 m_gfx_b = NSEEL_VM_regvar(vm,"gfx_b");
220 m_gfx_a = NSEEL_VM_regvar(vm,"gfx_a");
221 m_gfx_a2 = NSEEL_VM_regvar(vm,"gfx_a2");
223 m_gfx_w = NSEEL_VM_regvar(vm,"gfx_w");
224 m_gfx_h = NSEEL_VM_regvar(vm,"gfx_h");
225 m_gfx_x = NSEEL_VM_regvar(vm,"gfx_x");
226 m_gfx_y = NSEEL_VM_regvar(vm,"gfx_y");
227 m_gfx_mode = NSEEL_VM_regvar(vm,"gfx_mode");
228 m_gfx_clear = NSEEL_VM_regvar(vm,"gfx_clear");
229 m_gfx_texth = NSEEL_VM_regvar(vm,"gfx_texth");
230 m_gfx_dest = NSEEL_VM_regvar(vm,"gfx_dest");
231 m_gfx_ext_retina = NSEEL_VM_regvar(vm,"gfx_ext_retina");
233 m_mouse_x = NSEEL_VM_regvar(vm,"mouse_x");
234 m_mouse_y = NSEEL_VM_regvar(vm,"mouse_y");
235 m_mouse_cap = NSEEL_VM_regvar(vm,"mouse_cap");
236 m_mouse_wheel=NSEEL_VM_regvar(vm,"mouse_wheel");
237 m_mouse_hwheel=NSEEL_VM_regvar(vm,"mouse_hwheel");
239 if (m_gfx_texth) *m_gfx_texth=8;
241 eel_lice_state::~eel_lice_state()
243 if (LICE_FUNCTION_VALID(LICE__Destroy))
245 LICE__Destroy(m_framebuffer_extra);
246 LICE__Destroy(m_framebuffer);
247 int x;
248 for (x=0;x<m_gfx_images.GetSize();x++)
250 LICE__Destroy(m_gfx_images.Get()[x]);
253 if (LICE_FUNCTION_VALID(LICE__DestroyFont))
255 int x;
256 for (x=0;x<m_gfx_fonts.GetSize();x++)
258 if (m_gfx_fonts.Get()[x].font) LICE__DestroyFont(m_gfx_fonts.Get()[x].font);
263 int eel_lice_state::getCurMode()
265 const int gmode = (int) (*m_gfx_mode);
266 const int sm=(gmode>>4)&0xf;
267 if (sm > LICE_BLIT_MODE_COPY && sm <= LICE_BLIT_MODE_HSVADJ) return sm;
269 return (gmode&1) ? LICE_BLIT_MODE_ADD : LICE_BLIT_MODE_COPY;
271 int eel_lice_state::getCurModeForBlit(bool isFBsrc)
273 const int gmode = (int) (*m_gfx_mode);
275 const int sm=(gmode>>4)&0xf;
277 int mode;
278 if (sm > LICE_BLIT_MODE_COPY && sm <= LICE_BLIT_MODE_HSVADJ) mode=sm;
279 else mode=((gmode&1) ? LICE_BLIT_MODE_ADD : LICE_BLIT_MODE_COPY);
282 if (!isFBsrc && !(gmode&2)) mode|=LICE_BLIT_USE_ALPHA;
283 if (!(gmode&4)) mode|=LICE_BLIT_FILTER_BILINEAR;
285 return mode;
287 LICE_pixel eel_lice_state::getCurColor()
289 int red=(int) (*m_gfx_r*255.0);
290 int green=(int) (*m_gfx_g*255.0);
291 int blue=(int) (*m_gfx_b*255.0);
292 int a2=(int) (*m_gfx_a2*255.0);
293 if (red<0) red=0;else if (red>255)red=255;
294 if (green<0) green=0;else if (green>255)green=255;
295 if (blue<0) blue=0; else if (blue>255) blue=255;
296 if (a2<0) a2=0; else if (a2>255) a2=255;
297 return LICE_RGBA(red,green,blue,a2);
301 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_lineto(void *opaque, EEL_F *xpos, EEL_F *ypos, EEL_F *useaa)
303 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
304 if (ctx) ctx->gfx_lineto(*xpos, *ypos, *useaa);
305 return xpos;
307 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_lineto2(void *opaque, EEL_F *xpos, EEL_F *ypos)
309 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
310 if (ctx) ctx->gfx_lineto(*xpos, *ypos, 1.0f);
311 return xpos;
314 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_rectto(void *opaque, EEL_F *xpos, EEL_F *ypos)
316 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
317 if (ctx) ctx->gfx_rectto(*xpos, *ypos);
318 return xpos;
321 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_line(void *opaque, INT_PTR np, EEL_F **parms)
323 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
324 if (ctx) ctx->gfx_line((int)np,parms);
325 return 0.0;
328 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_rect(void *opaque, INT_PTR np, EEL_F **parms)
330 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
331 if (ctx) ctx->gfx_rect((int)np,parms);
332 return 0.0;
334 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_roundrect(void *opaque, INT_PTR np, EEL_F **parms)
336 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
337 if (ctx) ctx->gfx_roundrect((int)np,parms);
338 return 0.0;
340 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_arc(void *opaque, INT_PTR np, EEL_F **parms)
342 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
343 if (ctx) ctx->gfx_arc((int)np,parms);
344 return 0.0;
346 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_set(void *opaque, INT_PTR np, EEL_F **parms)
348 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
349 if (ctx) ctx->gfx_set((int)np,parms);
350 return 0.0;
352 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_gradrect(void *opaque, INT_PTR np, EEL_F **parms)
354 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
355 if (ctx) ctx->gfx_grad_or_muladd_rect(0,(int)np,parms);
356 return 0.0;
359 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_muladdrect(void *opaque, INT_PTR np, EEL_F **parms)
361 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
362 if (ctx) ctx->gfx_grad_or_muladd_rect(1,(int)np,parms);
363 return 0.0;
366 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_deltablit(void *opaque, INT_PTR np, EEL_F **parms)
368 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
369 if (ctx) ctx->gfx_blitext2((int)np,parms,1);
370 return 0.0;
373 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_transformblit(void *opaque, INT_PTR np, EEL_F **parms)
375 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
376 if (ctx)
378 #ifndef EEL_LICE_NO_RAM
379 const int divw = (int) (parms[5][0]+0.5);
380 const int divh = (int) (parms[6][0]+0.5);
381 if (divw < 1 || divh < 1) return 0.0;
382 const int sz = divw*divh*2;
384 #ifdef EEL_LICE_RAMFUNC
385 EEL_F *d = EEL_LICE_RAMFUNC(opaque,7,sz);
386 if (!d) return 0.0;
387 #else
388 EEL_F **blocks = ctx->m_vmref ? ((compileContext*)ctx->m_vmref)->ram_state->blocks : 0;
389 if (!blocks || np < 8) return 0.0;
391 const int addr1= (int) (parms[7][0]+0.5);
392 EEL_F *d=__NSEEL_RAMAlloc(blocks,addr1);
393 if (sz>NSEEL_RAM_ITEMSPERBLOCK)
395 int x;
396 for(x=NSEEL_RAM_ITEMSPERBLOCK;x<sz-1;x+=NSEEL_RAM_ITEMSPERBLOCK)
397 if (__NSEEL_RAMAlloc(blocks,addr1+x) != d+x) return 0.0;
399 EEL_F *end=__NSEEL_RAMAlloc(blocks,addr1+sz-1);
400 if (end != d+sz-1) return 0.0; // buffer not contiguous
401 #endif
403 ctx->gfx_transformblit(parms,divw,divh,d);
404 #endif
406 return 0.0;
409 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_circle(void *opaque, INT_PTR np, EEL_F **parms)
411 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
412 bool aa = true, fill = false;
413 if (np>3) fill = parms[3][0] > 0.5;
414 if (np>4) aa = parms[4][0] > 0.5;
415 if (ctx) ctx->gfx_circle((float)parms[0][0], (float)parms[1][0], (float)parms[2][0], fill, aa);
416 return 0.0;
419 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_triangle(void* opaque, INT_PTR np, EEL_F **parms)
421 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
422 if (ctx) ctx->gfx_triangle(parms, (int)np);
423 return 0.0;
426 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_drawnumber(void *opaque, EEL_F *n, EEL_F *nd)
428 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
429 if (ctx) ctx->gfx_drawnumber(*n, *nd);
430 return n;
433 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_drawchar(void *opaque, EEL_F *n)
435 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
436 if (ctx) ctx->gfx_drawchar(*n);
437 return n;
440 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_measurestr(void *opaque, EEL_F *str, EEL_F *xOut, EEL_F *yOut)
442 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
443 if (ctx)
445 EEL_F *p[3]={str,xOut,yOut};
446 ctx->gfx_drawstr(opaque,p,3,2);
448 return str;
450 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_measurechar(void *opaque, EEL_F *str, EEL_F *xOut, EEL_F *yOut)
452 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
453 if (ctx)
455 EEL_F *p[3]={str,xOut,yOut};
456 ctx->gfx_drawstr(opaque,p,3,3);
458 return str;
461 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_drawstr(void *opaque, INT_PTR nparms, EEL_F **parms)
463 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
464 if (ctx) ctx->gfx_drawstr(opaque,parms,(int)nparms,0);
465 return parms[0][0];
468 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_printf(void *opaque, INT_PTR nparms, EEL_F **parms)
470 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
471 if (ctx && nparms>0)
473 EEL_F v= **parms;
474 ctx->gfx_drawstr(opaque,parms,(int)nparms,1);
475 return v;
477 return 0.0;
480 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_setpixel(void *opaque, EEL_F *r, EEL_F *g, EEL_F *b)
482 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
483 if (ctx) ctx->gfx_setpixel(*r, *g, *b);
484 return r;
487 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_getpixel(void *opaque, EEL_F *r, EEL_F *g, EEL_F *b)
489 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
490 if (ctx) ctx->gfx_getpixel(r, g, b);
491 return r;
494 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_setfont(void *opaque, INT_PTR np, EEL_F **parms)
496 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
497 if (ctx) return ctx->gfx_setfont(opaque,(int)np,parms);
498 return 0.0;
501 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_getfont(void *opaque, INT_PTR np, EEL_F **parms)
503 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
504 if (ctx)
506 const int idx=ctx->m_gfx_font_active;
507 if (idx>=0 && idx < ctx->m_gfx_fonts.GetSize())
509 eel_lice_state::gfxFontStruct* f=ctx->m_gfx_fonts.Get()+idx;
511 EEL_STRING_MUTEXLOCK_SCOPE
513 #ifdef NOT_EEL_STRING_UPDATE_STRING
514 NOT_EEL_STRING_UPDATE_STRING(parms[0][0],f->actual_fontname);
515 #else
516 WDL_FastString *fs=NULL;
517 EEL_STRING_GET_FOR_WRITE(parms[0][0],&fs);
518 if (fs) fs->Set(f->actual_fontname);
519 #endif
521 return idx;
523 return 0.0;
526 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_blit2(void *opaque, INT_PTR np, EEL_F **parms)
528 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
529 if (ctx && np>=3)
531 ctx->gfx_blitext2((int)np,parms,0);
532 return *(parms[0]);
534 return 0.0;
537 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_blitext(void *opaque, EEL_F *img, EEL_F *coordidx, EEL_F *rotate)
539 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
540 if (ctx)
542 #ifndef EEL_LICE_NO_RAM
543 #ifdef EEL_LICE_RAMFUNC
544 EEL_F *buf = EEL_LICE_RAMFUNC(opaque,1,10);
545 if (!buf) return img;
546 #else
547 EEL_F fc = *coordidx;
548 if (fc < -0.5 || fc >= NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK) return img;
549 int a=(int)fc;
550 if (a<0) return img;
552 EEL_F buf[10];
553 int x;
554 EEL_F **blocks = ctx->m_vmref ? ((compileContext*)ctx->m_vmref)->ram_state->blocks : 0;
555 if (!blocks) return img;
556 for (x = 0;x < 10; x ++)
558 EEL_F *d=__NSEEL_RAMAlloc(blocks,a++);
559 if (!d || d==&nseel_ramalloc_onfail) return img;
560 buf[x]=*d;
562 #endif
563 // read megabuf
564 ctx->gfx_blitext(*img,buf,*rotate);
565 #endif
567 return img;
571 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_blurto(void *opaque, EEL_F *x, EEL_F *y)
573 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
574 if (ctx) ctx->gfx_blurto(*x,*y);
575 return x;
578 static EEL_F * NSEEL_CGEN_CALL ysfx_api_gfx_getimgdim(void *opaque, EEL_F *img, EEL_F *w, EEL_F *h)
580 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
581 if (ctx) ctx->gfx_getimgdim(*img,w,h);
582 return img;
585 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_loadimg(void *opaque, EEL_F *img, EEL_F *fr)
587 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
588 if (ctx) return ctx->gfx_loadimg(opaque,(int)*img,*fr);
589 return 0.0;
592 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_setimgdim(void *opaque, EEL_F *img, EEL_F *w, EEL_F *h)
594 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
595 if (ctx) return ctx->gfx_setimgdim((int)*img,w,h);
596 return 0.0;
599 static EEL_F NSEEL_CGEN_CALL ysfx_api_gfx_getsyscol(void* ctxe, INT_PTR np, EEL_F **parms)
601 return (EEL_F)LICE_RGBA_FROMNATIVE(GetSysColor(COLOR_3DFACE));
604 void eel_lice_state::gfx_lineto(EEL_F xpos, EEL_F ypos, EEL_F aaflag)
606 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_lineto");
607 if (!dest) return;
609 int x1=(int)floor(xpos),y1=(int)floor(ypos),x2=(int)floor(*m_gfx_x), y2=(int)floor(*m_gfx_y);
610 if (LICE_FUNCTION_VALID(LICE__GetWidth) && LICE_FUNCTION_VALID(LICE__GetHeight) && LICE_FUNCTION_VALID(LICE_Line) &&
611 LICE_FUNCTION_VALID(LICE_ClipLine) &&
612 LICE_ClipLine(&x1,&y1,&x2,&y2,0,0,LICE__GetWidth(dest),LICE__GetHeight(dest)))
614 SetImageDirty(dest);
615 LICE_Line(dest,x1,y1,x2,y2,getCurColor(),(float) *m_gfx_a,getCurMode(),aaflag > 0.5);
617 *m_gfx_x = xpos;
618 *m_gfx_y = ypos;
622 void eel_lice_state::gfx_circle(float x, float y, float r, bool fill, bool aaflag)
624 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_circle");
625 if (!dest) return;
627 if (LICE_FUNCTION_VALID(LICE_Circle) && LICE_FUNCTION_VALID(LICE_FillCircle))
629 SetImageDirty(dest);
630 if(fill)
631 LICE_FillCircle(dest, x, y, r, getCurColor(), (float) *m_gfx_a, getCurMode(), aaflag);
632 else
633 LICE_Circle(dest, x, y, r, getCurColor(), (float) *m_gfx_a, getCurMode(), aaflag);
637 void eel_lice_state::gfx_triangle(EEL_F** parms, int np)
639 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest, "gfx_triangle");
640 if (np >= 6)
642 np &= ~1;
643 SetImageDirty(dest);
644 if (np == 6)
646 if (!LICE_FUNCTION_VALID(LICE_FillTriangle)) return;
648 LICE_FillTriangle(dest, (int)parms[0][0], (int)parms[1][0], (int)parms[2][0], (int)parms[3][0],
649 (int)parms[4][0], (int)parms[5][0], getCurColor(), (float)*m_gfx_a, getCurMode());
651 else
653 if (!LICE_FUNCTION_VALID(LICE_FillConvexPolygon)) return;
655 const int maxpt = 512;
656 const int n = wdl_min(np/2, maxpt);
657 int i, rdi=0;
658 int x[maxpt], y[maxpt];
659 for (i=0; i < n; i++)
661 x[i]=(int)parms[rdi++][0];
662 y[i]=(int)parms[rdi++][0];
665 LICE_FillConvexPolygon(dest, x, y, n, getCurColor(), (float)*m_gfx_a, getCurMode());
670 void eel_lice_state::gfx_rectto(EEL_F xpos, EEL_F ypos)
672 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_rectto");
673 if (!dest) return;
675 EEL_F x1=xpos,y1=ypos,x2=*m_gfx_x, y2=*m_gfx_y;
676 if (x2<x1) { x1=x2; x2=xpos; }
677 if (y2<y1) { y1=y2; y2=ypos; }
679 if (LICE_FUNCTION_VALID(LICE_FillRect) && x2-x1 > 0.5 && y2-y1 > 0.5)
681 SetImageDirty(dest);
682 LICE_FillRect(dest,(int)x1,(int)y1,(int)(x2-x1),(int)(y2-y1),getCurColor(),(float)*m_gfx_a,getCurMode());
684 *m_gfx_x = xpos;
685 *m_gfx_y = ypos;
689 void eel_lice_state::gfx_line(int np, EEL_F **parms)
691 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_line");
692 if (!dest) return;
694 int x1=(int)floor(parms[0][0]),y1=(int)floor(parms[1][0]),x2=(int)floor(parms[2][0]), y2=(int)floor(parms[3][0]);
695 if (LICE_FUNCTION_VALID(LICE__GetWidth) &&
696 LICE_FUNCTION_VALID(LICE__GetHeight) &&
697 LICE_FUNCTION_VALID(LICE_Line) &&
698 LICE_FUNCTION_VALID(LICE_ClipLine) && LICE_ClipLine(&x1,&y1,&x2,&y2,0,0,LICE__GetWidth(dest),LICE__GetHeight(dest)))
700 SetImageDirty(dest);
701 LICE_Line(dest,x1,y1,x2,y2,getCurColor(),(float)*m_gfx_a,getCurMode(),np< 5 || parms[4][0] > 0.5);
705 void eel_lice_state::gfx_rect(int np, EEL_F **parms)
707 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_rect");
708 if (!dest) return;
710 int x1=(int)floor(parms[0][0]),y1=(int)floor(parms[1][0]),w=(int)floor(parms[2][0]),h=(int)floor(parms[3][0]);
711 int filled=(np < 5 || parms[4][0] > 0.5);
713 if (LICE_FUNCTION_VALID(LICE_FillRect) && LICE_FUNCTION_VALID(LICE_DrawRect) && w>0 && h>0)
715 SetImageDirty(dest);
716 if (filled) LICE_FillRect(dest,x1,y1,w,h,getCurColor(),(float)*m_gfx_a,getCurMode());
717 else LICE_DrawRect(dest, x1, y1, w-1, h-1, getCurColor(), (float)*m_gfx_a, getCurMode());
721 void eel_lice_state::gfx_roundrect(int np, EEL_F **parms)
723 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_roundrect");
724 if (!dest) return;
726 const bool aa = np <= 5 || parms[5][0]>0.5;
728 if (LICE_FUNCTION_VALID(LICE_RoundRect) && parms[2][0]>0 && parms[3][0]>0)
730 SetImageDirty(dest);
731 LICE_RoundRect(dest, (float)parms[0][0], (float)parms[1][0], (float)parms[2][0], (float)parms[3][0], (int)parms[4][0], getCurColor(), (float)*m_gfx_a, getCurMode(), aa);
735 void eel_lice_state::gfx_arc(int np, EEL_F **parms)
737 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_arc");
738 if (!dest) return;
740 const bool aa = np <= 5 || parms[5][0]>0.5;
742 if (LICE_FUNCTION_VALID(LICE_Arc))
744 SetImageDirty(dest);
745 LICE_Arc(dest, (float)parms[0][0], (float)parms[1][0], (float)parms[2][0], (float)parms[3][0], (float)parms[4][0], getCurColor(), (float)*m_gfx_a, getCurMode(), aa);
749 void eel_lice_state::gfx_grad_or_muladd_rect(int whichmode, int np, EEL_F **parms)
751 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,whichmode==0?"gfx_gradrect":"gfx_muladdrect");
752 if (!dest) return;
754 const int x1=(int)floor(parms[0][0]),y1=(int)floor(parms[1][0]),w=(int)floor(parms[2][0]), h=(int)floor(parms[3][0]);
756 if (w>0 && h>0)
758 SetImageDirty(dest);
759 if (whichmode==0 && LICE_FUNCTION_VALID(LICE_GradRect) && np > 7)
761 LICE_GradRect(dest,x1,y1,w,h,(float)parms[4][0],(float)parms[5][0],(float)parms[6][0],(float)parms[7][0],
762 np > 8 ? (float)parms[8][0]:0.0f, np > 9 ? (float)parms[9][0]:0.0f, np > 10 ? (float)parms[10][0]:0.0f, np > 11 ? (float)parms[11][0]:0.0f,
763 np > 12 ? (float)parms[12][0]:0.0f, np > 13 ? (float)parms[13][0]:0.0f, np > 14 ? (float)parms[14][0]:0.0f, np > 15 ? (float)parms[15][0]:0.0f,
764 getCurMode());
766 else if (whichmode==1 && LICE_FUNCTION_VALID(LICE_MultiplyAddRect) && np > 6)
768 const double sc = 255.0;
769 LICE_MultiplyAddRect(dest,x1,y1,w,h,(float)parms[4][0],(float)parms[5][0],(float)parms[6][0],np>7 ? (float)parms[7][0]:1.0f,
770 (float)(np > 8 ? sc*parms[8][0]:0.0), (float)(np > 9 ? sc*parms[9][0]:0.0), (float)(np > 10 ? sc*parms[10][0]:0.0), (float)(np > 11 ? sc*parms[11][0]:0.0));
777 void eel_lice_state::gfx_setpixel(EEL_F r, EEL_F g, EEL_F b)
779 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_setpixel");
780 if (!dest) return;
782 int red=(int) (r*255.0);
783 int green=(int) (g*255.0);
784 int blue=(int) (b*255.0);
785 if (red<0) red=0;else if (red>255)red=255;
786 if (green<0) green=0;else if (green>255)green=255;
787 if (blue<0) blue=0; else if (blue>255) blue=255;
789 if (LICE_FUNCTION_VALID(LICE_PutPixel))
791 SetImageDirty(dest);
792 LICE_PutPixel(dest,(int)*m_gfx_x, (int)*m_gfx_y,LICE_RGBA(red,green,blue,255), (float)*m_gfx_a,getCurMode());
796 void eel_lice_state::gfx_getimgdim(EEL_F img, EEL_F *w, EEL_F *h)
798 *w=*h=0;
799 #ifdef DYNAMIC_LICE
800 if (!LICE__GetWidth || !LICE__GetHeight) return;
801 #endif
803 LICE_IBitmap *bm=GetImageForIndex(img,"gfx_getimgdim");
804 if (bm)
806 *w=LICE__GetWidth(bm);
807 *h=LICE__GetHeight(bm);
811 EEL_F eel_lice_state::gfx_loadimg(void *opaque, int img, EEL_F loadFrom)
813 #ifdef DYNAMIC_LICE
814 if (!__LICE_LoadImage || !LICE__Destroy) return 0.0;
815 #endif
817 if (img >= 0 && img < m_gfx_images.GetSize())
819 WDL_FastString fs;
820 bool ok = EEL_LICE_GET_FILENAME_FOR_STRING(loadFrom,&fs,0);
822 if (ok && fs.GetLength())
824 LICE_IBitmap *bm = LICE_LoadImage(fs.Get(),NULL,false);
825 if (bm)
827 LICE__Destroy(m_gfx_images.Get()[img]);
828 m_gfx_images.Get()[img]=bm;
829 return img;
833 return -1.0;
837 EEL_F eel_lice_state::gfx_setimgdim(int img, EEL_F *w, EEL_F *h)
839 int rv=0;
840 #ifdef DYNAMIC_LICE
841 if (!LICE__resize ||!LICE__GetWidth || !LICE__GetHeight||!__LICE_CreateBitmap) return 0.0;
842 #endif
844 int use_w = (int)*w;
845 int use_h = (int)*h;
846 if (use_w<1 || use_h < 1) use_w=use_h=0;
847 if (use_w > 8192) use_w=8192;
848 if (use_h > 8192) use_h=8192;
850 LICE_IBitmap *bm=NULL;
851 if (img >= 0 && img < m_gfx_images.GetSize())
853 bm=m_gfx_images.Get()[img];
854 if (!bm)
856 m_gfx_images.Get()[img] = bm = __LICE_CreateBitmap(1,use_w,use_h);
857 rv=!!bm;
859 else
861 rv=LICE__resize(bm,use_w,use_h);
865 return rv?1.0:0.0;
868 void eel_lice_state::gfx_blurto(EEL_F x, EEL_F y)
870 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_blurto");
871 if (!dest
872 #ifdef DYNAMIC_LICE
873 ||!LICE_Blur
874 #endif
875 ) return;
877 SetImageDirty(dest);
879 int srcx = (int)x;
880 int srcy = (int)y;
881 int srcw=(int) (*m_gfx_x-x);
882 int srch=(int) (*m_gfx_y-y);
883 if (srch < 0) { srch=-srch; srcy = (int)*m_gfx_y; }
884 if (srcw < 0) { srcw=-srcw; srcx = (int)*m_gfx_x; }
885 LICE_Blur(dest,dest,srcx,srcy,srcx,srcy,srcw,srch);
886 *m_gfx_x = x;
887 *m_gfx_y = y;
890 static bool CoordsSrcDestOverlap(EEL_F *coords)
892 if (coords[0]+coords[2] < coords[4]) return false;
893 if (coords[0] > coords[4] + coords[6]) return false;
894 if (coords[1]+coords[3] < coords[5]) return false;
895 if (coords[1] > coords[5] + coords[7]) return false;
896 return true;
899 void eel_lice_state::gfx_transformblit(EEL_F **parms, int div_w, int div_h, EEL_F *tab)
901 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_transformblit");
903 if (!dest
904 #ifdef DYNAMIC_LICE
905 ||!LICE_ScaledBlit || !LICE_TransformBlit2 ||!LICE__GetWidth||!LICE__GetHeight
906 #endif
907 ) return;
909 LICE_IBitmap *bm=GetImageForIndex(parms[0][0],"gfx_transformblit:src");
910 if (!bm) return;
912 const int bmw=LICE__GetWidth(bm);
913 const int bmh=LICE__GetHeight(bm);
915 const bool isFromFB = bm==m_framebuffer;
917 SetImageDirty(dest);
919 if (bm == dest)
921 if (!m_framebuffer_extra && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer_extra=__LICE_CreateBitmap(0,bmw,bmh);
922 if (m_framebuffer_extra)
925 LICE__resize(bm=m_framebuffer_extra,bmw,bmh);
926 LICE_ScaledBlit(bm,dest, // copy the entire image
927 0,0,bmw,bmh,
928 0.0f,0.0f,(float)bmw,(float)bmh,
929 1.0f,LICE_BLIT_MODE_COPY);
932 LICE_TransformBlit2(dest,bm,(int)floor(parms[1][0]),(int)floor(parms[2][0]),(int)floor(parms[3][0]),(int)floor(parms[4][0]),tab,div_w,div_h, (float)*m_gfx_a,getCurModeForBlit(isFromFB));
935 EEL_F eel_lice_state::gfx_setfont(void *opaque, int np, EEL_F **parms)
937 int a = np>0 ? ((int)floor(parms[0][0]))-1 : -1;
939 if (a>=0 && a < m_gfx_fonts.GetSize())
941 gfxFontStruct *s = m_gfx_fonts.Get()+a;
942 if (np>1 && LICE_FUNCTION_VALID(LICE_CreateFont) && LICE_FUNCTION_VALID(LICE__SetFromHFont))
944 const int sz=np>2 ? (int)parms[2][0] : 10;
946 bool doCreate=false;
947 int fontflag=0;
948 if (!s->font) s->actual_fontname[0]=0;
951 EEL_STRING_MUTEXLOCK_SCOPE
953 const char *face=EEL_STRING_GET_FOR_INDEX(parms[1][0],NULL);
954 #ifdef EEL_STRING_DEBUGOUT
955 if (!face) EEL_STRING_DEBUGOUT("gfx_setfont: invalid string identifier %f",parms[1][0]);
956 #endif
957 if (!face || !*face) face="Arial";
960 unsigned int c = np > 3 ? (unsigned int) parms[3][0] : 0;
961 while (c)
963 switch (toupper(c&0xff))
965 case 'B': fontflag|=EELFONT_FLAG_BOLD; break;
966 case 'I': fontflag|=EELFONT_FLAG_ITALIC; break;
967 case 'U': fontflag|=EELFONT_FLAG_UNDERLINE; break;
968 case 'R': fontflag|=16; break; //LICE_FONT_FLAG_FX_BLUR
969 case 'V': fontflag|=32; break; //LICE_FONT_FLAG_FX_INVERT
970 case 'M': fontflag|=64; break; //LICE_FONT_FLAG_FX_MONO
971 case 'S': fontflag|=128; break; //LICE_FONT_FLAG_FX_SHADOW
972 case 'O': fontflag|=256; break; //LICE_FONT_FLAG_FX_OUTLINE
973 case 'Z': fontflag|=1; break; //LICE_FONT_FLAG_VERTICAL
974 case 'Y': fontflag|=1|2; break; //LICE_FONT_FLAG_VERTICAL|LICE_FONT_FLAG_VERTICAL_BOTTOMUP
976 c>>=8;
981 if (fontflag != s->last_fontflag || sz!=s->last_fontsize || strncmp(s->last_fontname,face,sizeof(s->last_fontname)-1))
983 lstrcpyn_safe(s->last_fontname,face,sizeof(s->last_fontname));
984 s->last_fontsize=sz;
985 s->last_fontflag=fontflag;
986 doCreate=1;
990 if (doCreate)
992 s->actual_fontname[0]=0;
993 if (!s->font) s->font=LICE_CreateFont();
994 if (s->font)
996 const int fw = (fontflag&EELFONT_FLAG_BOLD) ? FW_BOLD : FW_NORMAL;
997 const bool italic = !!(fontflag&EELFONT_FLAG_ITALIC);
998 const bool underline = !!(fontflag&EELFONT_FLAG_UNDERLINE);
999 HFONT hf=NULL;
1000 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
1001 WCHAR wf[256];
1002 if (WDL_DetectUTF8(s->last_fontname)>0 &&
1003 GetVersion()<0x80000000 &&
1004 MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,s->last_fontname,-1,wf,256))
1006 hf = CreateFontW(sz,0,0,0,fw,italic,underline,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,wf);
1008 #endif
1009 if (!hf) hf = CreateFont(sz,0,0,0,fw,italic,underline,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,s->last_fontname);
1011 if (!hf)
1013 s->use_fonth=0; // disable this font
1015 else
1017 TEXTMETRIC tm;
1018 tm.tmHeight = sz;
1020 if (!m_framebuffer && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer=__LICE_CreateBitmap(1,64,64);
1022 if (m_framebuffer && LICE_FUNCTION_VALID(LICE__GetDC))
1024 HGDIOBJ oldFont = 0;
1025 HDC hdc=LICE__GetDC(m_framebuffer);
1026 if (hdc)
1028 oldFont = SelectObject(hdc,hf);
1029 GetTextMetrics(hdc,&tm);
1031 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
1032 if (GetVersion()<0x80000000 &&
1033 GetTextFaceW(hdc,sizeof(wf)/sizeof(wf[0]),wf) &&
1034 WideCharToMultiByte(CP_UTF8,0,wf,-1,s->actual_fontname,sizeof(s->actual_fontname),NULL,NULL))
1036 s->actual_fontname[sizeof(s->actual_fontname)-1]=0;
1038 else
1039 #endif
1040 GetTextFace(hdc, sizeof(s->actual_fontname), s->actual_fontname);
1041 SelectObject(hdc,oldFont);
1045 s->use_fonth=wdl_max(tm.tmHeight,1);
1046 LICE__SetFromHFont(s->font,hf, (fontflag & ~EELFONT_FLAG_MASK) | 512 /*LICE_FONT_FLAG_OWNS_HFONT*/);
1053 if (s->font && s->use_fonth)
1055 m_gfx_font_active=a;
1056 if (m_gfx_texth) *m_gfx_texth=s->use_fonth;
1057 return 1.0;
1059 // try to init this font
1061 #ifdef EEL_STRING_DEBUGOUT
1062 if (a >= m_gfx_fonts.GetSize()) EEL_STRING_DEBUGOUT("gfx_setfont: invalid font %d specified",a);
1063 #endif
1065 if (a<0||a>=m_gfx_fonts.GetSize()||!m_gfx_fonts.Get()[a].font)
1067 m_gfx_font_active=-1;
1068 if (m_gfx_texth) *m_gfx_texth=8;
1069 return 1.0;
1071 return 0.0;
1074 void eel_lice_state::gfx_blitext2(int np, EEL_F **parms, int blitmode)
1076 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_blitext2");
1078 if (!dest
1079 #ifdef DYNAMIC_LICE
1080 ||!LICE_ScaledBlit || !LICE_RotatedBlit||!LICE__GetWidth||!LICE__GetHeight
1081 #endif
1082 ) return;
1084 LICE_IBitmap *bm=GetImageForIndex(parms[0][0],"gfx_blitext2:src");
1085 if (!bm) return;
1087 const int bmw=LICE__GetWidth(bm);
1088 const int bmh=LICE__GetHeight(bm);
1090 // 0=img, 1=scale, 2=rotate
1091 double coords[8];
1092 const double sc = blitmode==0 && np > 1 ? parms[1][0] : 1.0,
1093 angle = blitmode==0 && np > 2 ? parms[2][0] : 0.0;
1094 if (blitmode==0)
1096 parms+=2;
1097 np -= 2;
1100 coords[0]=np > 1 ? parms[1][0] : 0.0f;
1101 coords[1]=np > 2 ? parms[2][0] : 0.0f;
1102 coords[2]=np > 3 ? parms[3][0] : bmw;
1103 coords[3]=np > 4 ? parms[4][0] : bmh;
1104 coords[4]=np > 5 ? parms[5][0] : *m_gfx_x;
1105 coords[5]=np > 6 ? parms[6][0] : *m_gfx_y;
1106 coords[6]=np > 7 ? parms[7][0] : coords[2]*sc;
1107 coords[7]=np > 8 ? parms[8][0] : coords[3]*sc;
1109 const bool isFromFB = bm == m_framebuffer;
1110 SetImageDirty(dest);
1112 if (bm == dest &&
1113 (blitmode != 0 || np > 1) && // legacy behavior to matech previous gfx_blit(3parm), do not use temp buffer
1114 CoordsSrcDestOverlap(coords))
1116 if (!m_framebuffer_extra && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer_extra=__LICE_CreateBitmap(0,bmw,bmh);
1117 if (m_framebuffer_extra)
1120 LICE__resize(bm=m_framebuffer_extra,bmw,bmh);
1121 LICE_ScaledBlit(bm,dest, // copy the source portion
1122 (int)coords[0],(int)coords[1],(int)coords[2],(int)coords[3],
1123 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1124 1.0f,LICE_BLIT_MODE_COPY);
1128 if (blitmode==1)
1130 if (LICE_FUNCTION_VALID(LICE_DeltaBlit))
1131 LICE_DeltaBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1132 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1133 np > 9 ? (float)parms[9][0]:1.0f, // dsdx
1134 np > 10 ? (float)parms[10][0]:0.0f, // dtdx
1135 np > 11 ? (float)parms[11][0]:0.0f, // dsdy
1136 np > 12 ? (float)parms[12][0]:1.0f, // dtdy
1137 np > 13 ? (float)parms[13][0]:0.0f, // dsdxdy
1138 np > 14 ? (float)parms[14][0]:0.0f, // dtdxdy
1139 np <= 15 || parms[15][0] > 0.5, (float)*m_gfx_a,getCurModeForBlit(isFromFB));
1141 else if (fabs(angle)>0.000000001)
1143 LICE_RotatedBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1144 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1145 (float)angle,true, (float)*m_gfx_a,getCurModeForBlit(isFromFB),
1146 np > 9 ? (float)parms[9][0] : 0.0f,
1147 np > 10 ? (float)parms[10][0] : 0.0f);
1149 else
1151 LICE_ScaledBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1152 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3], (float)*m_gfx_a,getCurModeForBlit(isFromFB));
1156 void eel_lice_state::gfx_blitext(EEL_F img, EEL_F *coords, EEL_F angle)
1158 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_blitext");
1160 if (!dest
1161 #ifdef DYNAMIC_LICE
1162 ||!LICE_ScaledBlit || !LICE_RotatedBlit||!LICE__GetWidth||!LICE__GetHeight
1163 #endif
1164 ) return;
1166 LICE_IBitmap *bm=GetImageForIndex(img,"gfx_blitext:src");
1167 if (!bm) return;
1169 SetImageDirty(dest);
1170 const bool isFromFB = bm == m_framebuffer;
1172 int bmw=LICE__GetWidth(bm);
1173 int bmh=LICE__GetHeight(bm);
1175 if (bm == dest && CoordsSrcDestOverlap(coords))
1177 if (!m_framebuffer_extra && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer_extra=__LICE_CreateBitmap(0,bmw,bmh);
1178 if ( m_framebuffer_extra)
1181 LICE__resize(bm=m_framebuffer_extra,bmw,bmh);
1182 LICE_ScaledBlit(bm,dest, // copy the source portion
1183 (int)coords[0],(int)coords[1],(int)coords[2],(int)coords[3],
1184 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1185 1.0f,LICE_BLIT_MODE_COPY);
1189 if (fabs(angle)>0.000000001)
1191 LICE_RotatedBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1192 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],(float)angle,
1193 true, (float)*m_gfx_a,getCurModeForBlit(isFromFB),
1194 (float)coords[8],(float)coords[9]);
1196 else
1198 LICE_ScaledBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1199 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3], (float)*m_gfx_a,getCurModeForBlit(isFromFB));
1203 void eel_lice_state::gfx_set(int np, EEL_F **parms)
1205 if (np < 1) return;
1206 if (m_gfx_r) *m_gfx_r = parms[0][0];
1207 if (m_gfx_g) *m_gfx_g = np > 1 ? parms[1][0] : parms[0][0];
1208 if (m_gfx_b) *m_gfx_b = np > 2 ? parms[2][0] : parms[0][0];
1209 if (m_gfx_a) *m_gfx_a = np > 3 ? parms[3][0] : 1.0;
1210 if (m_gfx_mode) *m_gfx_mode = np > 4 ? parms[4][0] : 0;
1211 if (np > 5 && m_gfx_dest) *m_gfx_dest = parms[5][0];
1212 if (m_gfx_a2) *m_gfx_a2 = np > 6 ? parms[6][0] : 1.0;
1215 void eel_lice_state::gfx_getpixel(EEL_F *r, EEL_F *g, EEL_F *b)
1217 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_getpixel");
1218 if (!dest) return;
1220 int ret=LICE_FUNCTION_VALID(LICE_GetPixel)?LICE_GetPixel(dest,(int)*m_gfx_x, (int)*m_gfx_y):0;
1222 *r=LICE_GETR(ret)/255.0;
1223 *g=LICE_GETG(ret)/255.0;
1224 *b=LICE_GETB(ret)/255.0;
1229 static int __drawTextWithFont(LICE_IBitmap *dest, const RECT *rect, LICE_IFont *font, const char *buf, int buflen,
1230 int fg, int mode, float alpha, int flags, EEL_F *wantYoutput, EEL_F **measureOnly)
1232 if (font && LICE_FUNCTION_VALID(LICE__DrawText))
1234 RECT tr=*rect;
1235 LICE__SetTextColor(font,fg);
1236 LICE__SetTextCombineMode(font,mode,alpha);
1238 int maxx=0;
1239 RECT r={0,0,tr.left,0};
1240 while (buflen>0)
1242 int thislen = 0;
1243 while (thislen < buflen && buf[thislen] != '\n') thislen++;
1244 memset(&r,0,sizeof(r));
1245 int lineh = LICE__DrawText(font,dest,buf,thislen?thislen:1,&r,DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT);
1246 if (!measureOnly)
1248 r.right += tr.left;
1249 lineh = LICE__DrawText(font,dest,buf,thislen?thislen:1,&tr,DT_SINGLELINE|DT_NOPREFIX|flags);
1250 if (wantYoutput) *wantYoutput = tr.top;
1252 else
1254 if (r.right > maxx) maxx=r.right;
1256 tr.top += lineh;
1258 buflen -= thislen+1;
1259 buf += thislen+1;
1261 if (measureOnly)
1263 measureOnly[0][0] = maxx;
1264 measureOnly[1][0] = tr.top;
1266 return r.right;
1268 else
1270 int xpos=rect->left, ypos=rect->top;
1271 int x;
1272 int maxx=0,maxy=0;
1274 LICE_SubBitmap sbm(
1275 #ifdef DYNAMIC_LICE
1276 (LICE_IBitmap_disabledAPI*)
1277 #endif
1278 dest,rect->left,rect->top,rect->right-rect->left,rect->bottom-rect->top);
1280 if (!measureOnly)
1282 if (!(flags & DT_NOCLIP))
1284 if (rect->right <= rect->left || rect->bottom <= rect->top) return 0; // invalid clip rect hm
1286 xpos = ypos = 0;
1287 dest = &sbm;
1289 if (flags & (DT_RIGHT|DT_BOTTOM|DT_CENTER|DT_VCENTER))
1291 EEL_F w=0.0,h=0.0;
1292 EEL_F *mo[2] = { &w,&h};
1293 RECT tr={0,};
1294 __drawTextWithFont(dest,&tr,NULL,buf,buflen,0,0,0.0f,0,NULL,mo);
1296 if (flags & DT_RIGHT) xpos += (rect->right-rect->left) - (int)floor(w);
1297 else if (flags & DT_CENTER) xpos += (rect->right-rect->left)/2 - (int)floor(w*.5);
1299 if (flags & DT_BOTTOM) ypos += (rect->bottom-rect->top) - (int)floor(h);
1300 else if (flags & DT_VCENTER) ypos += (rect->bottom-rect->top)/2 - (int)floor(h*.5);
1303 const int sxpos = xpos;
1305 if (LICE_FUNCTION_VALID(LICE_DrawChar)) for(x=0;x<buflen;x++)
1307 switch (buf[x])
1309 case '\n':
1310 ypos += 8;
1311 case '\r':
1312 xpos = sxpos;
1313 break;
1314 case ' ': xpos += 8; break;
1315 case '\t': xpos += 8*5; break;
1316 default:
1317 if (!measureOnly) LICE_DrawChar(dest,xpos,ypos,buf[x], fg,alpha,mode);
1318 xpos += 8;
1319 if (xpos > maxx) maxx=xpos;
1320 maxy = ypos + 8;
1321 break;
1324 if (measureOnly)
1326 measureOnly[0][0]=maxx;
1327 measureOnly[1][0]=maxy;
1329 else
1331 if (wantYoutput) *wantYoutput=ypos;
1333 return xpos;
1337 void eel_lice_state::gfx_drawstr(void *opaque, EEL_F **parms, int nparms, int formatmode)// formatmode=1 for format, 2 for purely measure no format
1339 int nfmtparms = nparms-1;
1340 EEL_F **fmtparms = parms+1;
1341 const char *funcname = formatmode==1?"gfx_printf":
1342 formatmode==2?"gfx_measurestr":
1343 formatmode==3?"gfx_measurechar" : "gfx_drawstr";
1345 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,funcname);
1346 if (!dest) return;
1348 #ifdef DYNAMIC_LICE
1349 if (!LICE__GetWidth || !LICE__GetHeight) return;
1350 #endif
1352 EEL_STRING_MUTEXLOCK_SCOPE
1354 WDL_FastString *fs=NULL;
1355 char buf[4096];
1356 int s_len=0;
1358 const char *s;
1359 if (formatmode==3)
1361 s_len = WDL_MakeUTFChar(buf, (int)parms[0][0], sizeof(buf));
1362 s=buf;
1364 else
1366 s=EEL_STRING_GET_FOR_INDEX(parms[0][0],&fs);
1367 #ifdef EEL_STRING_DEBUGOUT
1368 if (!s) EEL_STRING_DEBUGOUT("gfx_%s: invalid string identifier %f",funcname,parms[0][0]);
1369 #endif
1370 if (!s)
1372 s="<bad string>";
1373 s_len = 12;
1375 else if (formatmode==1)
1377 extern int eel_format_strings(void *, const char *s, const char *ep, char *, int, int, EEL_F **);
1378 s_len = eel_format_strings(opaque,s,fs?(s+fs->GetLength()):NULL,buf,sizeof(buf),nfmtparms,fmtparms);
1379 if (s_len<1) return;
1380 s=buf;
1382 else
1384 s_len = fs?fs->GetLength():(int)strlen(s);
1388 if (s_len)
1390 SetImageDirty(dest);
1391 if (formatmode>=2)
1393 if (nfmtparms==2)
1395 RECT r={0,0,0,0};
1396 __drawTextWithFont(dest,&r,GetActiveFont(),s,s_len,
1397 getCurColor(),getCurMode(),(float)*m_gfx_a,0,NULL,fmtparms);
1400 else
1402 RECT r={(int)floor(*m_gfx_x),(int)floor(*m_gfx_y),0,0};
1403 int flags=DT_NOCLIP;
1404 if (formatmode == 0 && nparms >= 4)
1406 flags=(int)*parms[1];
1407 flags &= (DT_CENTER|DT_RIGHT|DT_VCENTER|DT_BOTTOM|DT_NOCLIP);
1408 r.right=(int)*parms[2];
1409 r.bottom=(int)*parms[3];
1411 *m_gfx_x=__drawTextWithFont(dest,&r,GetActiveFont(),s,s_len,
1412 getCurColor(),getCurMode(),(float)*m_gfx_a,flags,m_gfx_y,NULL);
1417 void eel_lice_state::gfx_drawchar(EEL_F ch)
1419 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_drawchar");
1420 if (!dest) return;
1422 SetImageDirty(dest);
1424 int a=(int)(ch+0.5);
1425 if (a == '\r' || a=='\n') a=' ';
1427 char buf[32];
1428 const int buflen = WDL_MakeUTFChar(buf, a, sizeof(buf));
1430 RECT r={(int)floor(*m_gfx_x),(int)floor(*m_gfx_y),0,0};
1431 *m_gfx_x = __drawTextWithFont(dest,&r,
1432 GetActiveFont(),buf,buflen,
1433 getCurColor(),getCurMode(),(float)*m_gfx_a,DT_NOCLIP,NULL,NULL);
1438 void eel_lice_state::gfx_drawnumber(EEL_F n, EEL_F ndigits)
1440 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_drawnumber");
1441 if (!dest) return;
1443 SetImageDirty(dest);
1445 char buf[512];
1446 int a=(int)(ndigits+0.5);
1447 if (a <0)a=0;
1448 else if (a > 16) a=16;
1449 snprintf(buf,sizeof(buf),"%.*f",a,n);
1451 RECT r={(int)floor(*m_gfx_x),(int)floor(*m_gfx_y),0,0};
1452 *m_gfx_x = __drawTextWithFont(dest,&r,
1453 GetActiveFont(),buf,(int)strlen(buf),
1454 getCurColor(),getCurMode(),(float)*m_gfx_a,DT_NOCLIP,NULL,NULL);