more langpackedit sort tweaks -- from ee8753f8
[wdl.git] / WDL / eel2 / eel_lice.h
blob78f1a0ca98ca178fd0c40e022679486057d0e612
1 #ifndef _EEL_LICE_H_
2 #define _EEL_LICE_H_
4 // #define EEL_LICE_GET_FILENAME_FOR_STRING(idx, fs, p) (((sInst*)opaque)->GetFilenameForParameter(idx,fs,p))
5 // #define EEL_LICE_GET_CONTEXT(opaque) (((opaque) ? (((sInst *)opaque)->m_gfx_state) : NULL)
8 void eel_lice_register();
10 #ifdef DYNAMIC_LICE
11 #define LICE_IBitmap LICE_IBitmap_disabledAPI
12 #include "../lice/lice.h"
14 #undef LICE_IBitmap
15 typedef void LICE_IBitmap; // prevent us from using LICE api directly, in case it ever changes
17 class LICE_IFont;
19 #ifdef EEL_LICE_API_ONLY
20 #define EEL_LICE_FUNCDEF extern
21 #else
22 #define EEL_LICE_FUNCDEF
23 #endif
25 #define LICE_FUNCTION_VALID(x) (x)
27 EEL_LICE_FUNCDEF LICE_IBitmap *(*__LICE_CreateBitmap)(int, int, int);
28 EEL_LICE_FUNCDEF void (*__LICE_Clear)(LICE_IBitmap *dest, LICE_pixel color);
29 EEL_LICE_FUNCDEF void (*__LICE_Line)(LICE_IBitmap *dest, int x1, int y1, int x2, int y2, LICE_pixel color, float alpha, int mode, bool aa);
30 EEL_LICE_FUNCDEF bool (*__LICE_ClipLine)(int* pX1, int* pY1, int* pX2, int* pY2, int xLo, int yLo, int xHi, int yHi);
31 EEL_LICE_FUNCDEF void (*__LICE_DrawText)(LICE_IBitmap *bm, int x, int y, const char *string,
32 LICE_pixel color, float alpha, int mode);
33 EEL_LICE_FUNCDEF void (*__LICE_DrawChar)(LICE_IBitmap *bm, int x, int y, char c,
34 LICE_pixel color, float alpha, int mode);
35 EEL_LICE_FUNCDEF void (*__LICE_MeasureText)(const char *string, int *w, int *h);
36 EEL_LICE_FUNCDEF void (*__LICE_PutPixel)(LICE_IBitmap *bm, int x, int y, LICE_pixel color, float alpha, int mode);
37 EEL_LICE_FUNCDEF LICE_pixel (*__LICE_GetPixel)(LICE_IBitmap *bm, int x, int y);
38 EEL_LICE_FUNCDEF void (*__LICE_FillRect)(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel color, float alpha, int mode);
39 EEL_LICE_FUNCDEF void (*__LICE_DrawRect)(LICE_IBitmap *dest, int x, int y, int w, int h, LICE_pixel color, float alpha, int mode);
40 EEL_LICE_FUNCDEF LICE_IBitmap *(*__LICE_LoadImage)(const char* filename, LICE_IBitmap* bmp, bool tryIgnoreExtension);
41 EEL_LICE_FUNCDEF void (*__LICE_Blur)(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int srcx, int srcy, int srcw, int srch); // src and dest can overlap, however it may look fudgy if they do
42 EEL_LICE_FUNCDEF void (*__LICE_ScaledBlit)(LICE_IBitmap *dest, LICE_IBitmap *src, int dstx, int dsty, int dstw, int dsth,
43 float srcx, float srcy, float srcw, float srch, float alpha, int mode);
44 EEL_LICE_FUNCDEF void (*__LICE_Circle)(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa);
45 EEL_LICE_FUNCDEF void (*__LICE_FillCircle)(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa);
46 EEL_LICE_FUNCDEF void (*__LICE_FillTriangle)(LICE_IBitmap* dest, int x1, int y1, int x2, int y2, int x3, int y3, LICE_pixel color, float alpha, int mode);
47 EEL_LICE_FUNCDEF void (*__LICE_FillConvexPolygon)(LICE_IBitmap* dest, const int* x, const int* y, int npoints, LICE_pixel color, float alpha, int mode);
48 EEL_LICE_FUNCDEF void (*__LICE_RoundRect)(LICE_IBitmap *drawbm, float xpos, float ypos, float w, float h, int cornerradius, LICE_pixel col, float alpha, int mode, bool aa);
49 EEL_LICE_FUNCDEF void (*__LICE_Arc)(LICE_IBitmap* dest, float cx, float cy, float r, float minAngle, float maxAngle, LICE_pixel color, float alpha, int mode, bool aa);
51 // if cliptosourcerect is false, then areas outside the source rect can get in (otherwise they are not drawn)
52 EEL_LICE_FUNCDEF void (*__LICE_RotatedBlit)(LICE_IBitmap *dest, LICE_IBitmap *src,
53 int dstx, int dsty, int dstw, int dsth,
54 float srcx, float srcy, float srcw, float srch,
55 float angle,
56 bool cliptosourcerect, float alpha, int mode,
57 float rotxcent, float rotycent); // these coordinates are offset from the center of the image, in source pixel coordinates
60 EEL_LICE_FUNCDEF void (*__LICE_MultiplyAddRect)(LICE_IBitmap *dest, int x, int y, int w, int h,
61 float rsc, float gsc, float bsc, float asc, // 0-1, or -100 .. +100 if you really are insane
62 float radd, float gadd, float badd, float aadd); // 0-255 is the normal range on these.. of course its clamped
64 EEL_LICE_FUNCDEF void (*__LICE_GradRect)(LICE_IBitmap *dest, int dstx, int dsty, int dstw, int dsth,
65 float ir, float ig, float ib, float ia,
66 float drdx, float dgdx, float dbdx, float dadx,
67 float drdy, float dgdy, float dbdy, float dady,
68 int mode);
70 EEL_LICE_FUNCDEF void (*__LICE_TransformBlit2)(LICE_IBitmap *dest, LICE_IBitmap *src,
71 int dstx, int dsty, int dstw, int dsth,
72 double *srcpoints, int div_w, int div_h, // srcpoints coords should be div_w*div_h*2 long, and be in source image coordinates
73 float alpha, int mode);
75 EEL_LICE_FUNCDEF void (*__LICE_DeltaBlit)(LICE_IBitmap *dest, LICE_IBitmap *src,
76 int dstx, int dsty, int dstw, int dsth,
77 float srcx, float srcy, float srcw, float srch,
78 double dsdx, double dtdx, double dsdy, double dtdy,
79 double dsdxdy, double dtdxdy,
80 bool cliptosourcerect, float alpha, int mode);
83 #define LICE_Blur __LICE_Blur
84 #define LICE_Clear __LICE_Clear
85 #define LICE_Line __LICE_Line
86 #define LICE_ClipLine __LICE_ClipLine
87 #define LICE_FillRect __LICE_FillRect
88 #define LICE_DrawRect __LICE_DrawRect
89 #define LICE_PutPixel __LICE_PutPixel
90 #define LICE_GetPixel __LICE_GetPixel
91 #define LICE_DrawText __LICE_DrawText
92 #define LICE_DrawChar __LICE_DrawChar
93 #define LICE_MeasureText __LICE_MeasureText
94 #define LICE_LoadImage __LICE_LoadImage
95 #define LICE_RotatedBlit __LICE_RotatedBlit
96 #define LICE_ScaledBlit __LICE_ScaledBlit
97 #define LICE_MultiplyAddRect __LICE_MultiplyAddRect
98 #define LICE_GradRect __LICE_GradRect
99 #define LICE_TransformBlit2 __LICE_TransformBlit2
100 #define LICE_DeltaBlit __LICE_DeltaBlit
101 #define LICE_Circle __LICE_Circle
102 #define LICE_FillCircle __LICE_FillCircle
103 #define LICE_FillTriangle __LICE_FillTriangle
104 #define LICE_FillConvexPolygon __LICE_FillConvexPolygon
105 #define LICE_RoundRect __LICE_RoundRect
106 #define LICE_Arc __LICE_Arc
108 EEL_LICE_FUNCDEF HDC (*LICE__GetDC)(LICE_IBitmap *bm);
109 EEL_LICE_FUNCDEF int (*LICE__GetWidth)(LICE_IBitmap *bm);
110 EEL_LICE_FUNCDEF int (*LICE__GetHeight)(LICE_IBitmap *bm);
111 EEL_LICE_FUNCDEF void (*LICE__Destroy)(LICE_IBitmap *bm);
112 EEL_LICE_FUNCDEF bool (*LICE__resize)(LICE_IBitmap *bm, int w, int h);
114 EEL_LICE_FUNCDEF void (*LICE__DestroyFont)(LICE_IFont* font);
115 EEL_LICE_FUNCDEF LICE_IFont *(*LICE_CreateFont)();
116 EEL_LICE_FUNCDEF void (*LICE__SetFromHFont)(LICE_IFont* ifont, HFONT font, int flags);
117 EEL_LICE_FUNCDEF LICE_pixel (*LICE__SetTextColor)(LICE_IFont* ifont, LICE_pixel color);
118 EEL_LICE_FUNCDEF void (*LICE__SetTextCombineMode)(LICE_IFont* ifont, int mode, float alpha);
119 EEL_LICE_FUNCDEF int (*LICE__DrawText)(LICE_IFont* ifont, LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags);
121 #else
123 #include "../lice/lice.h"
124 #include "../lice/lice_text.h"
126 #define LICE_FUNCTION_VALID(x) (sizeof(int) > 0)
128 static HDC LICE__GetDC(LICE_IBitmap *bm)
130 return bm->getDC();
132 static int LICE__GetWidth(LICE_IBitmap *bm)
134 return bm->getWidth();
136 static int LICE__GetHeight(LICE_IBitmap *bm)
138 return bm->getHeight();
140 static void LICE__Destroy(LICE_IBitmap *bm)
142 delete bm;
144 static void LICE__SetFromHFont(LICE_IFont * ifont, HFONT font, int flags)
146 if (ifont) ifont->SetFromHFont(font,flags);
148 static LICE_pixel LICE__SetTextColor(LICE_IFont* ifont, LICE_pixel color)
150 if (ifont) return ifont->SetTextColor(color);
151 return 0;
153 static void LICE__SetTextCombineMode(LICE_IFont* ifont, int mode, float alpha)
155 if (ifont) ifont->SetCombineMode(mode, alpha);
157 static int LICE__DrawText(LICE_IFont* ifont, LICE_IBitmap *bm, const char *str, int strcnt, RECT *rect, UINT dtFlags)
159 if (ifont) return ifont->DrawText(bm, str, strcnt, rect, dtFlags);
160 return 0;
164 static LICE_IFont *LICE_CreateFont()
166 return new LICE_CachedFont();
168 static void LICE__DestroyFont(LICE_IFont *bm)
170 delete bm;
172 static bool LICE__resize(LICE_IBitmap *bm, int w, int h)
174 return bm->resize(w,h);
177 static LICE_IBitmap *__LICE_CreateBitmap(int mode, int w, int h)
179 if (mode==1) return new LICE_SysBitmap(w,h);
180 return new LICE_MemBitmap(w,h);
184 #endif
186 #include "../wdlutf8.h"
189 class eel_lice_state
191 public:
193 eel_lice_state(NSEEL_VMCTX vm, void *ctx, int image_slots, int font_slots);
194 ~eel_lice_state();
196 void resetVarsToStock()
198 if (m_gfx_a&&m_gfx_r&&m_gfx_g&&m_gfx_b) *m_gfx_r=*m_gfx_g=*m_gfx_b=*m_gfx_a=1.0;
199 if (m_gfx_a2) *m_gfx_a2=1.0;
200 if (m_gfx_dest) *m_gfx_dest=-1.0;
201 if (m_mouse_wheel) *m_mouse_wheel=0.0;
202 if (m_mouse_hwheel) *m_mouse_hwheel=0.0;
203 // todo: reset others?
206 LICE_IBitmap *m_framebuffer, *m_framebuffer_extra;
207 int m_framebuffer_dirty;
209 struct img_shared_state
211 LICE_IBitmap *bm;
212 int refcnt;
214 img_shared_state(LICE_IBitmap *b) : bm(b), refcnt(1) { }
216 void release()
218 if (wdl_atomic_decr(&refcnt)==0) delete this;
221 private:
223 ~img_shared_state()
225 s_img_cache_mutex.Enter();
226 for (int x = 0; x < s_img_cache.GetSize(); x ++)
228 if (s_img_cache.Enumerate(x) == this)
230 s_img_cache.DeleteByIndex(x);
231 break;
234 s_img_cache_mutex.Leave();
235 if (LICE_FUNCTION_VALID(LICE__Destroy))
236 LICE__Destroy(bm);
240 static WDL_StringKeyedArray<img_shared_state *> s_img_cache;
241 static WDL_Mutex s_img_cache_mutex;
243 struct img_state
245 LICE_IBitmap *bm;
246 img_shared_state *shared;
248 void clear(LICE_IBitmap *bmnew=NULL, img_shared_state *sharednew=NULL)
250 if (shared) shared->release();
251 if (bm && LICE_FUNCTION_VALID(LICE__Destroy))
252 LICE__Destroy(bm);
253 bm = bmnew;
254 shared = sharednew;
256 void on_write()
258 if (shared && WDL_NORMALLY(shared->bm))
260 const int bmw = LICE__GetWidth(shared->bm), bmh = LICE__GetHeight(shared->bm);
261 bm = __LICE_CreateBitmap(1,bmw,bmh);
262 LICE_ScaledBlit(bm,shared->bm, // copy the entire image
263 0,0,bmw,bmh,
264 0.0f,0.0f,(float)bmw,(float)bmh,
265 1.0f,LICE_BLIT_MODE_COPY);
266 shared->release();
267 shared = NULL;
272 bool do_load_image(int img, const char *str);
274 WDL_TypedBuf<img_state> m_gfx_images;
275 struct gfxFontStruct {
276 LICE_IFont *font;
277 char last_fontname[128];
278 char actual_fontname[128];
279 int last_fontsize;
280 int last_fontflag;
282 int use_fonth;
284 WDL_TypedBuf<gfxFontStruct> m_gfx_fonts;
285 enum {
286 EELFONT_FLAG_BOLD = (1<<24),
287 EELFONT_FLAG_ITALIC = (2<<24),
288 EELFONT_FLAG_UNDERLINE = (4<<24),
289 EELFONT_FLAG_MASK = EELFONT_FLAG_BOLD|EELFONT_FLAG_ITALIC|EELFONT_FLAG_UNDERLINE
292 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)
293 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; }
295 LICE_IBitmap *GetImageForIndex(EEL_F idx, const char *callername, bool is_wr=true)
297 if (idx>-2.0)
299 if (idx < 0.0) return m_framebuffer;
301 const int a = (int)idx;
302 if (a >= 0 && a < m_gfx_images.GetSize())
304 img_state *rec = m_gfx_images.Get() + a;
305 if (is_wr) rec->on_write();
306 return rec->shared ? rec->shared->bm : rec->bm;
309 return NULL;
312 void SetImageDirty(LICE_IBitmap *bm)
314 if (bm == m_framebuffer && !m_framebuffer_dirty)
316 if (m_gfx_clear && *m_gfx_clear > -1.0)
318 const int a=(int)*m_gfx_clear;
319 if (LICE_FUNCTION_VALID(LICE_Clear)) LICE_Clear(m_framebuffer,LICE_RGBA((a&0xff),((a>>8)&0xff),((a>>16)&0xff),0));
321 m_framebuffer_dirty=1;
325 // R, G, B, A, w, h, x, y, mode(1=add,0=copy)
326 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;
327 EEL_F *m_mouse_x, *m_mouse_y, *m_mouse_cap, *m_mouse_wheel, *m_mouse_hwheel;
328 EEL_F *m_gfx_ext_retina;
330 NSEEL_VMCTX m_vmref;
331 void *m_user_ctx;
333 int setup_frame(HWND hwnd, RECT r, int _mouse_x=0, int _mouse_y=0, int has_dpi=0); // mouse_x/y used only if hwnd is NULL
334 void finish_draw();
336 void gfx_lineto(EEL_F xpos, EEL_F ypos, EEL_F aaflag);
337 void gfx_rectto(EEL_F xpos, EEL_F ypos);
338 void gfx_line(int np, EEL_F **parms);
339 void gfx_rect(int np, EEL_F **parms);
340 void gfx_roundrect(int np, EEL_F **parms);
341 void gfx_arc(int np, EEL_F **parms);
342 void gfx_set(int np, EEL_F **parms);
343 void gfx_grad_or_muladd_rect(int mode, int np, EEL_F **parms);
344 void gfx_setpixel(EEL_F r, EEL_F g, EEL_F b);
345 void gfx_getpixel(EEL_F *r, EEL_F *g, EEL_F *b);
346 void gfx_drawnumber(EEL_F n, EEL_F ndigits);
347 void gfx_drawchar(EEL_F ch);
348 void gfx_getimgdim(EEL_F img, EEL_F *w, EEL_F *h);
349 EEL_F gfx_setimgdim(int img, EEL_F *w, EEL_F *h);
350 void gfx_blurto(EEL_F x, EEL_F y);
351 void gfx_blitext(EEL_F img, EEL_F *coords, EEL_F angle);
352 void gfx_blitext2(int np, EEL_F **parms, int mode); // 0=blit, 1=deltablit
353 void gfx_transformblit(EEL_F **parms, int div_w, int div_h, EEL_F *tab); // parms[0]=src, 1-4=x,y,w,h
354 void gfx_circle(float x, float y, float r, bool fill, bool aaflag);
355 void gfx_triangle(EEL_F** parms, int nparms);
356 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
357 EEL_F gfx_loadimg(void *opaque, int img, EEL_F loadFrom);
358 EEL_F gfx_setfont(void *opaque, int np, EEL_F **parms);
359 EEL_F gfx_getfont(void *opaque, int np, EEL_F **parms);
360 EEL_F gfx_getdropfile(void *opaque, int np, EEL_F **parms);
362 LICE_pixel getCurColor();
363 int getCurMode();
364 int getCurModeForBlit(bool isFBsrc);
366 #ifdef EEL_LICE_WANT_STANDALONE
367 HWND create_wnd(HWND par, int isChild);
368 HWND hwnd_standalone;
369 int hwnd_standalone_kb_state[32]; // pressed keys, if any
371 // these have to be **parms because of the hack for getting string from parm index
372 EEL_F gfx_showmenu(void* opaque, EEL_F** parms, int nparms);
373 EEL_F gfx_setcursor(void* opaque, EEL_F** parms, int nparms);
375 int m_kb_queue[64];
376 unsigned char m_kb_queue_valid;
377 unsigned char m_kb_queue_pos;
378 HCURSOR m_cursor;
379 int m_cursor_resid;
380 #ifdef EEL_LICE_LOADTHEMECURSOR
381 char m_cursor_name[128];
382 #endif
384 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
385 RECT m_last_undocked_r;
386 #endif
388 #endif
390 DWORD m_last_menu_time;
391 int m_last_menu_cnt;
393 int m_has_cap; // high 16 bits are current capture state, low 16 bits are temporary flags from mousedown
394 bool m_has_had_getch; // set on first gfx_getchar(), makes mouse_cap updated with modifiers even when no mouse click is down
396 WDL_PtrList<char> m_ddrop_files;
400 #ifndef EEL_LICE_API_ONLY
402 WDL_StringKeyedArray<eel_lice_state::img_shared_state *> eel_lice_state::s_img_cache(true);
403 WDL_Mutex eel_lice_state::s_img_cache_mutex;
405 eel_lice_state::eel_lice_state(NSEEL_VMCTX vm, void *ctx, int image_slots, int font_slots)
407 #ifdef EEL_LICE_WANT_STANDALONE
408 hwnd_standalone=NULL;
409 memset(hwnd_standalone_kb_state,0,sizeof(hwnd_standalone_kb_state));
410 m_kb_queue_valid=0;
411 m_cursor_resid=0;
412 m_cursor = NULL;
413 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
414 memset(&m_last_undocked_r,0,sizeof(m_last_undocked_r));
415 #endif
417 #ifdef EEL_LICE_LOADTHEMECURSOR
418 m_cursor_name[0]=0;
419 #endif
420 #endif
421 m_user_ctx=ctx;
422 m_vmref= vm;
423 m_gfx_font_active=-1;
424 m_gfx_fonts.Resize(font_slots);
425 memset(m_gfx_fonts.Get(),0,m_gfx_fonts.GetSize()*sizeof(m_gfx_fonts.Get()[0]));
427 m_gfx_images.Resize(image_slots);
428 memset(m_gfx_images.Get(),0,m_gfx_images.GetSize()*sizeof(m_gfx_images.Get()[0]));
429 m_framebuffer=m_framebuffer_extra=0;
430 m_framebuffer_dirty=0;
432 m_gfx_r = NSEEL_VM_regvar(vm,"gfx_r");
433 m_gfx_g = NSEEL_VM_regvar(vm,"gfx_g");
434 m_gfx_b = NSEEL_VM_regvar(vm,"gfx_b");
435 m_gfx_a = NSEEL_VM_regvar(vm,"gfx_a");
436 m_gfx_a2 = NSEEL_VM_regvar(vm,"gfx_a2");
438 m_gfx_w = NSEEL_VM_regvar(vm,"gfx_w");
439 m_gfx_h = NSEEL_VM_regvar(vm,"gfx_h");
440 m_gfx_x = NSEEL_VM_regvar(vm,"gfx_x");
441 m_gfx_y = NSEEL_VM_regvar(vm,"gfx_y");
442 m_gfx_mode = NSEEL_VM_regvar(vm,"gfx_mode");
443 m_gfx_clear = NSEEL_VM_regvar(vm,"gfx_clear");
444 m_gfx_texth = NSEEL_VM_regvar(vm,"gfx_texth");
445 m_gfx_dest = NSEEL_VM_regvar(vm,"gfx_dest");
446 m_gfx_ext_retina = NSEEL_VM_regvar(vm,"gfx_ext_retina");
448 m_mouse_x = NSEEL_VM_regvar(vm,"mouse_x");
449 m_mouse_y = NSEEL_VM_regvar(vm,"mouse_y");
450 m_mouse_cap = NSEEL_VM_regvar(vm,"mouse_cap");
451 m_mouse_wheel=NSEEL_VM_regvar(vm,"mouse_wheel");
452 m_mouse_hwheel=NSEEL_VM_regvar(vm,"mouse_hwheel");
454 if (m_gfx_texth) *m_gfx_texth=8;
456 m_has_cap=0;
457 m_has_had_getch=false;
458 m_last_menu_time = GetTickCount() - 100000;
459 m_last_menu_cnt = 0;
461 eel_lice_state::~eel_lice_state()
463 #ifdef EEL_LICE_WANT_STANDALONE
464 if (hwnd_standalone) DestroyWindow(hwnd_standalone);
465 #endif
466 if (LICE_FUNCTION_VALID(LICE__Destroy))
468 LICE__Destroy(m_framebuffer_extra);
469 LICE__Destroy(m_framebuffer);
471 for (int x=0;x<m_gfx_images.GetSize();x++)
472 m_gfx_images.Get()[x].clear();
473 if (LICE_FUNCTION_VALID(LICE__DestroyFont))
475 for (int x=0;x<m_gfx_fonts.GetSize();x++)
477 if (m_gfx_fonts.Get()[x].font) LICE__DestroyFont(m_gfx_fonts.Get()[x].font);
480 m_ddrop_files.Empty(true,free);
483 int eel_lice_state::getCurMode()
485 const int gmode = (int) (*m_gfx_mode);
486 const int sm=(gmode>>4)&0xf;
487 if (sm > LICE_BLIT_MODE_COPY && sm <= LICE_BLIT_MODE_HSVADJ) return sm;
489 return (gmode&1) ? LICE_BLIT_MODE_ADD : LICE_BLIT_MODE_COPY;
491 int eel_lice_state::getCurModeForBlit(bool isFBsrc)
493 const int gmode = (int) (*m_gfx_mode);
495 const int sm=(gmode>>4)&0xf;
497 int mode;
498 if (sm > LICE_BLIT_MODE_COPY && sm <= LICE_BLIT_MODE_HSVADJ) mode=sm;
499 else mode=((gmode&1) ? LICE_BLIT_MODE_ADD : LICE_BLIT_MODE_COPY);
502 if (!isFBsrc && !(gmode&2)) mode|=LICE_BLIT_USE_ALPHA;
503 if (!(gmode&4)) mode|=LICE_BLIT_FILTER_BILINEAR;
505 return mode;
507 LICE_pixel eel_lice_state::getCurColor()
509 int red=(int) (*m_gfx_r*255.0);
510 int green=(int) (*m_gfx_g*255.0);
511 int blue=(int) (*m_gfx_b*255.0);
512 int a2=(int) (*m_gfx_a2*255.0);
513 if (red<0) red=0;else if (red>255)red=255;
514 if (green<0) green=0;else if (green>255)green=255;
515 if (blue<0) blue=0; else if (blue>255) blue=255;
516 if (a2<0) a2=0; else if (a2>255) a2=255;
517 return LICE_RGBA(red,green,blue,a2);
521 static EEL_F * NSEEL_CGEN_CALL _gfx_lineto(void *opaque, EEL_F *xpos, EEL_F *ypos, EEL_F *useaa)
523 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
524 if (ctx) ctx->gfx_lineto(*xpos, *ypos, *useaa);
525 return xpos;
527 static EEL_F * NSEEL_CGEN_CALL _gfx_lineto2(void *opaque, EEL_F *xpos, EEL_F *ypos)
529 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
530 if (ctx) ctx->gfx_lineto(*xpos, *ypos, 1.0f);
531 return xpos;
534 static EEL_F * NSEEL_CGEN_CALL _gfx_rectto(void *opaque, EEL_F *xpos, EEL_F *ypos)
536 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
537 if (ctx) ctx->gfx_rectto(*xpos, *ypos);
538 return xpos;
541 static EEL_F NSEEL_CGEN_CALL _gfx_line(void *opaque, INT_PTR np, EEL_F **parms)
543 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
544 if (ctx) ctx->gfx_line((int)np,parms);
545 return 0.0;
548 static EEL_F NSEEL_CGEN_CALL _gfx_rect(void *opaque, INT_PTR np, EEL_F **parms)
550 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
551 if (ctx) ctx->gfx_rect((int)np,parms);
552 return 0.0;
554 static EEL_F NSEEL_CGEN_CALL _gfx_roundrect(void *opaque, INT_PTR np, EEL_F **parms)
556 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
557 if (ctx) ctx->gfx_roundrect((int)np,parms);
558 return 0.0;
560 static EEL_F NSEEL_CGEN_CALL _gfx_arc(void *opaque, INT_PTR np, EEL_F **parms)
562 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
563 if (ctx) ctx->gfx_arc((int)np,parms);
564 return 0.0;
566 static EEL_F NSEEL_CGEN_CALL _gfx_set(void *opaque, INT_PTR np, EEL_F **parms)
568 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
569 if (ctx) ctx->gfx_set((int)np,parms);
570 return 0.0;
572 static EEL_F NSEEL_CGEN_CALL _gfx_gradrect(void *opaque, INT_PTR np, EEL_F **parms)
574 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
575 if (ctx) ctx->gfx_grad_or_muladd_rect(0,(int)np,parms);
576 return 0.0;
579 static EEL_F NSEEL_CGEN_CALL _gfx_muladdrect(void *opaque, INT_PTR np, EEL_F **parms)
581 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
582 if (ctx) ctx->gfx_grad_or_muladd_rect(1,(int)np,parms);
583 return 0.0;
586 static EEL_F NSEEL_CGEN_CALL _gfx_deltablit(void *opaque, INT_PTR np, EEL_F **parms)
588 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
589 if (ctx) ctx->gfx_blitext2((int)np,parms,1);
590 return 0.0;
593 static EEL_F NSEEL_CGEN_CALL _gfx_transformblit(void *opaque, INT_PTR np, EEL_F **parms)
595 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
596 if (ctx)
598 #ifndef EEL_LICE_NO_RAM
599 const int divw = (int) (parms[5][0]+0.5);
600 const int divh = (int) (parms[6][0]+0.5);
601 if (divw < 1 || divh < 1) return 0.0;
602 const int sz = divw*divh*2;
604 #ifdef EEL_LICE_RAMFUNC
605 EEL_F *d = EEL_LICE_RAMFUNC(opaque,7,sz);
606 if (!d) return 0.0;
607 #else
608 EEL_F **blocks = ctx->m_vmref ? ((compileContext*)ctx->m_vmref)->ram_state->blocks : 0;
609 if (!blocks || np < 8) return 0.0;
611 const int addr1= (int) (parms[7][0]+0.5);
612 EEL_F *d=__NSEEL_RAMAlloc(blocks,addr1);
613 if (sz>NSEEL_RAM_ITEMSPERBLOCK)
615 int x;
616 for(x=NSEEL_RAM_ITEMSPERBLOCK;x<sz-1;x+=NSEEL_RAM_ITEMSPERBLOCK)
617 if (__NSEEL_RAMAlloc(blocks,addr1+x) != d+x) return 0.0;
619 EEL_F *end=__NSEEL_RAMAlloc(blocks,addr1+sz-1);
620 if (end != d+sz-1) return 0.0; // buffer not contiguous
621 #endif
623 ctx->gfx_transformblit(parms,divw,divh,d);
624 #endif
626 return 0.0;
629 static EEL_F NSEEL_CGEN_CALL _gfx_circle(void *opaque, INT_PTR np, EEL_F **parms)
631 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
632 bool aa = true, fill = false;
633 if (np>3) fill = parms[3][0] > 0.5;
634 if (np>4) aa = parms[4][0] > 0.5;
635 if (ctx) ctx->gfx_circle((float)parms[0][0], (float)parms[1][0], (float)parms[2][0], fill, aa);
636 return 0.0;
639 static EEL_F NSEEL_CGEN_CALL _gfx_triangle(void* opaque, INT_PTR np, EEL_F **parms)
641 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
642 if (ctx) ctx->gfx_triangle(parms, (int)np);
643 return 0.0;
646 static EEL_F * NSEEL_CGEN_CALL _gfx_drawnumber(void *opaque, EEL_F *n, EEL_F *nd)
648 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
649 if (ctx) ctx->gfx_drawnumber(*n, *nd);
650 return n;
653 static EEL_F * NSEEL_CGEN_CALL _gfx_drawchar(void *opaque, EEL_F *n)
655 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
656 if (ctx) ctx->gfx_drawchar(*n);
657 return n;
660 static EEL_F * NSEEL_CGEN_CALL _gfx_measurestr(void *opaque, EEL_F *str, EEL_F *xOut, EEL_F *yOut)
662 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
663 if (ctx)
665 EEL_F *p[3]={str,xOut,yOut};
666 ctx->gfx_drawstr(opaque,p,3,2);
668 return str;
670 static EEL_F * NSEEL_CGEN_CALL _gfx_measurechar(void *opaque, EEL_F *str, EEL_F *xOut, EEL_F *yOut)
672 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
673 if (ctx)
675 EEL_F *p[3]={str,xOut,yOut};
676 ctx->gfx_drawstr(opaque,p,3,3);
678 return str;
681 static EEL_F NSEEL_CGEN_CALL _gfx_drawstr(void *opaque, INT_PTR nparms, EEL_F **parms)
683 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
684 if (ctx) ctx->gfx_drawstr(opaque,parms,(int)nparms,0);
685 return parms[0][0];
688 static EEL_F NSEEL_CGEN_CALL _gfx_printf(void *opaque, INT_PTR nparms, EEL_F **parms)
690 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
691 if (ctx && nparms>0)
693 EEL_F v= **parms;
694 ctx->gfx_drawstr(opaque,parms,(int)nparms,1);
695 return v;
697 return 0.0;
700 static EEL_F NSEEL_CGEN_CALL _gfx_showmenu(void* opaque, INT_PTR nparms, EEL_F **parms)
702 eel_lice_state* ctx=EEL_LICE_GET_CONTEXT(opaque);
703 if (ctx) return ctx->gfx_showmenu(opaque, parms, (int)nparms);
704 return 0.0;
707 static EEL_F NSEEL_CGEN_CALL _gfx_setcursor(void* opaque, INT_PTR nparms, EEL_F **parms)
709 eel_lice_state* ctx=EEL_LICE_GET_CONTEXT(opaque);
710 if (ctx) return ctx->gfx_setcursor(opaque, parms, (int)nparms);
711 return 0.0;
714 static EEL_F * NSEEL_CGEN_CALL _gfx_setpixel(void *opaque, EEL_F *r, EEL_F *g, EEL_F *b)
716 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
717 if (ctx) ctx->gfx_setpixel(*r, *g, *b);
718 return r;
721 static EEL_F * NSEEL_CGEN_CALL _gfx_getpixel(void *opaque, EEL_F *r, EEL_F *g, EEL_F *b)
723 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
724 if (ctx) ctx->gfx_getpixel(r, g, b);
725 return r;
728 static EEL_F NSEEL_CGEN_CALL _gfx_setfont(void *opaque, INT_PTR np, EEL_F **parms)
730 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
731 if (ctx) return ctx->gfx_setfont(opaque,(int)np,parms);
732 return 0.0;
735 static EEL_F NSEEL_CGEN_CALL _gfx_getfont(void *opaque, INT_PTR np, EEL_F **parms)
737 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
738 if (ctx)
740 const int idx=ctx->m_gfx_font_active;
741 if (idx>=0 && idx < ctx->m_gfx_fonts.GetSize())
743 eel_lice_state::gfxFontStruct* f=ctx->m_gfx_fonts.Get()+idx;
745 EEL_STRING_MUTEXLOCK_SCOPE
747 #ifdef NOT_EEL_STRING_UPDATE_STRING
748 NOT_EEL_STRING_UPDATE_STRING(parms[0][0],f->actual_fontname);
749 #else
750 WDL_FastString *fs=NULL;
751 EEL_STRING_GET_FOR_WRITE(parms[0][0],&fs);
752 if (fs) fs->Set(f->actual_fontname);
753 #endif
755 return idx;
757 return 0.0;
760 static EEL_F NSEEL_CGEN_CALL _gfx_blit2(void *opaque, INT_PTR np, EEL_F **parms)
762 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
763 if (ctx && np>=3)
765 ctx->gfx_blitext2((int)np,parms,0);
766 return *(parms[0]);
768 return 0.0;
771 static EEL_F * NSEEL_CGEN_CALL _gfx_blitext(void *opaque, EEL_F *img, EEL_F *coordidx, EEL_F *rotate)
773 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
774 if (ctx)
776 #ifndef EEL_LICE_NO_RAM
777 #ifdef EEL_LICE_RAMFUNC
778 EEL_F *buf = EEL_LICE_RAMFUNC(opaque,1,10);
779 if (!buf) return img;
780 #else
781 EEL_F fc = *coordidx;
782 if (fc < -0.5 || fc >= NSEEL_RAM_BLOCKS*NSEEL_RAM_ITEMSPERBLOCK) return img;
783 int a=(int)fc;
784 if (a<0) return img;
786 EEL_F buf[10];
787 int x;
788 EEL_F **blocks = ctx->m_vmref ? ((compileContext*)ctx->m_vmref)->ram_state->blocks : 0;
789 if (!blocks) return img;
790 for (x = 0;x < 10; x ++)
792 EEL_F *d=__NSEEL_RAMAlloc(blocks,a++);
793 if (!d || d==&nseel_ramalloc_onfail) return img;
794 buf[x]=*d;
796 #endif
797 // read megabuf
798 ctx->gfx_blitext(*img,buf,*rotate);
799 #endif
801 return img;
805 static EEL_F * NSEEL_CGEN_CALL _gfx_blurto(void *opaque, EEL_F *x, EEL_F *y)
807 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
808 if (ctx) ctx->gfx_blurto(*x,*y);
809 return x;
812 static EEL_F * NSEEL_CGEN_CALL _gfx_getimgdim(void *opaque, EEL_F *img, EEL_F *w, EEL_F *h)
814 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
815 if (ctx) ctx->gfx_getimgdim(*img,w,h);
816 return img;
819 static EEL_F NSEEL_CGEN_CALL _gfx_loadimg(void *opaque, EEL_F *img, EEL_F *fr)
821 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
822 if (ctx) return ctx->gfx_loadimg(opaque,(int)*img,*fr);
823 return 0.0;
826 static EEL_F NSEEL_CGEN_CALL _gfx_getdropfile(void *opaque, INT_PTR np, EEL_F **parms)
828 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
829 if (ctx) return ctx->gfx_getdropfile(opaque,(int) np, parms);
830 return 0.0;
832 static EEL_F NSEEL_CGEN_CALL _gfx_setimgdim(void *opaque, EEL_F *img, EEL_F *w, EEL_F *h)
834 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
835 if (ctx) return ctx->gfx_setimgdim((int)*img,w,h);
836 return 0.0;
839 static EEL_F NSEEL_CGEN_CALL _gfx_getsyscol(void* ctxe, INT_PTR np, EEL_F **parms)
841 return (EEL_F)LICE_RGBA_FROMNATIVE(GetSysColor(COLOR_3DFACE));
844 void eel_lice_state::gfx_lineto(EEL_F xpos, EEL_F ypos, EEL_F aaflag)
846 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_lineto");
847 if (!dest) return;
849 int x1=(int)floor(xpos),y1=(int)floor(ypos),x2=(int)floor(*m_gfx_x), y2=(int)floor(*m_gfx_y);
850 if (LICE_FUNCTION_VALID(LICE__GetWidth) && LICE_FUNCTION_VALID(LICE__GetHeight) && LICE_FUNCTION_VALID(LICE_Line) &&
851 LICE_FUNCTION_VALID(LICE_ClipLine) &&
852 LICE_ClipLine(&x1,&y1,&x2,&y2,0,0,LICE__GetWidth(dest),LICE__GetHeight(dest)))
854 SetImageDirty(dest);
855 LICE_Line(dest,x1,y1,x2,y2,getCurColor(),(float) *m_gfx_a,getCurMode(),aaflag > 0.5);
857 *m_gfx_x = xpos;
858 *m_gfx_y = ypos;
862 void eel_lice_state::gfx_circle(float x, float y, float r, bool fill, bool aaflag)
864 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_circle");
865 if (!dest) return;
867 if (LICE_FUNCTION_VALID(LICE_Circle) && LICE_FUNCTION_VALID(LICE_FillCircle))
869 SetImageDirty(dest);
870 if(fill)
871 LICE_FillCircle(dest, x, y, r, getCurColor(), (float) *m_gfx_a, getCurMode(), aaflag);
872 else
873 LICE_Circle(dest, x, y, r, getCurColor(), (float) *m_gfx_a, getCurMode(), aaflag);
877 void eel_lice_state::gfx_triangle(EEL_F** parms, int np)
879 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest, "gfx_triangle");
880 if (np >= 6)
882 np &= ~1;
883 SetImageDirty(dest);
884 if (np == 6)
886 if (!LICE_FUNCTION_VALID(LICE_FillTriangle)) return;
888 LICE_FillTriangle(dest, (int)parms[0][0], (int)parms[1][0], (int)parms[2][0], (int)parms[3][0],
889 (int)parms[4][0], (int)parms[5][0], getCurColor(), (float)*m_gfx_a, getCurMode());
891 else
893 if (!LICE_FUNCTION_VALID(LICE_FillConvexPolygon)) return;
895 const int maxpt = 512;
896 const int n = wdl_min(np/2, maxpt);
897 int i, rdi=0;
898 int x[maxpt], y[maxpt];
899 for (i=0; i < n; i++)
901 x[i]=(int)parms[rdi++][0];
902 y[i]=(int)parms[rdi++][0];
905 LICE_FillConvexPolygon(dest, x, y, n, getCurColor(), (float)*m_gfx_a, getCurMode());
910 void eel_lice_state::gfx_rectto(EEL_F xpos, EEL_F ypos)
912 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_rectto");
913 if (!dest) return;
915 EEL_F x1=xpos,y1=ypos,x2=*m_gfx_x, y2=*m_gfx_y;
916 if (x2<x1) { x1=x2; x2=xpos; }
917 if (y2<y1) { y1=y2; y2=ypos; }
919 if (LICE_FUNCTION_VALID(LICE_FillRect) && x2-x1 > 0.5 && y2-y1 > 0.5)
921 SetImageDirty(dest);
922 LICE_FillRect(dest,(int)x1,(int)y1,(int)(x2-x1),(int)(y2-y1),getCurColor(),(float)*m_gfx_a,getCurMode());
924 *m_gfx_x = xpos;
925 *m_gfx_y = ypos;
929 void eel_lice_state::gfx_line(int np, EEL_F **parms)
931 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_line");
932 if (!dest) return;
934 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]);
935 if (LICE_FUNCTION_VALID(LICE__GetWidth) &&
936 LICE_FUNCTION_VALID(LICE__GetHeight) &&
937 LICE_FUNCTION_VALID(LICE_Line) &&
938 LICE_FUNCTION_VALID(LICE_ClipLine) && LICE_ClipLine(&x1,&y1,&x2,&y2,0,0,LICE__GetWidth(dest),LICE__GetHeight(dest)))
940 SetImageDirty(dest);
941 LICE_Line(dest,x1,y1,x2,y2,getCurColor(),(float)*m_gfx_a,getCurMode(),np< 5 || parms[4][0] > 0.5);
945 void eel_lice_state::gfx_rect(int np, EEL_F **parms)
947 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_rect");
948 if (!dest) return;
950 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]);
951 int filled=(np < 5 || parms[4][0] > 0.5);
953 if (LICE_FUNCTION_VALID(LICE_FillRect) && LICE_FUNCTION_VALID(LICE_DrawRect) && w>0 && h>0)
955 SetImageDirty(dest);
956 if (filled) LICE_FillRect(dest,x1,y1,w,h,getCurColor(),(float)*m_gfx_a,getCurMode());
957 else LICE_DrawRect(dest, x1, y1, w-1, h-1, getCurColor(), (float)*m_gfx_a, getCurMode());
961 void eel_lice_state::gfx_roundrect(int np, EEL_F **parms)
963 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_roundrect");
964 if (!dest) return;
966 const bool aa = np <= 5 || parms[5][0]>0.5;
968 if (LICE_FUNCTION_VALID(LICE_RoundRect) && parms[2][0]>0 && parms[3][0]>0)
970 SetImageDirty(dest);
971 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);
975 void eel_lice_state::gfx_arc(int np, EEL_F **parms)
977 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_arc");
978 if (!dest) return;
980 const bool aa = np <= 5 || parms[5][0]>0.5;
982 if (LICE_FUNCTION_VALID(LICE_Arc))
984 SetImageDirty(dest);
985 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);
989 void eel_lice_state::gfx_grad_or_muladd_rect(int whichmode, int np, EEL_F **parms)
991 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,whichmode==0?"gfx_gradrect":"gfx_muladdrect");
992 if (!dest) return;
994 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]);
996 if (w>0 && h>0)
998 SetImageDirty(dest);
999 if (whichmode==0 && LICE_FUNCTION_VALID(LICE_GradRect) && np > 7)
1001 LICE_GradRect(dest,x1,y1,w,h,(float)parms[4][0],(float)parms[5][0],(float)parms[6][0],(float)parms[7][0],
1002 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,
1003 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,
1004 getCurMode());
1006 else if (whichmode==1 && LICE_FUNCTION_VALID(LICE_MultiplyAddRect) && np > 6)
1008 const double sc = 255.0;
1009 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,
1010 (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));
1017 void eel_lice_state::gfx_setpixel(EEL_F r, EEL_F g, EEL_F b)
1019 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_setpixel");
1020 if (!dest) return;
1022 int red=(int) (r*255.0);
1023 int green=(int) (g*255.0);
1024 int blue=(int) (b*255.0);
1025 if (red<0) red=0;else if (red>255)red=255;
1026 if (green<0) green=0;else if (green>255)green=255;
1027 if (blue<0) blue=0; else if (blue>255) blue=255;
1029 if (LICE_FUNCTION_VALID(LICE_PutPixel))
1031 SetImageDirty(dest);
1032 LICE_PutPixel(dest,(int)*m_gfx_x, (int)*m_gfx_y,LICE_RGBA(red,green,blue,255), (float)*m_gfx_a,getCurMode());
1036 void eel_lice_state::gfx_getimgdim(EEL_F img, EEL_F *w, EEL_F *h)
1038 *w=*h=0;
1039 #ifdef DYNAMIC_LICE
1040 if (!LICE__GetWidth || !LICE__GetHeight) return;
1041 #endif
1043 LICE_IBitmap *bm=GetImageForIndex(img,"gfx_getimgdim",false);
1044 if (bm)
1046 *w=LICE__GetWidth(bm);
1047 *h=LICE__GetHeight(bm);
1051 EEL_F eel_lice_state::gfx_getdropfile(void *opaque, int np, EEL_F **parms)
1053 const int idx = (int) parms[0][0];
1054 if (idx<0) m_ddrop_files.Empty(true,free);
1055 if (idx < 0 || idx >= m_ddrop_files.GetSize()) return 0.0;
1057 #ifdef NOT_EEL_STRING_UPDATE_STRING
1058 NOT_EEL_STRING_UPDATE_STRING(parms[1][0],m_ddrop_files.Get(idx));
1059 #else
1060 if (np > 1)
1062 EEL_STRING_MUTEXLOCK_SCOPE
1063 WDL_FastString *fs=NULL;
1064 EEL_STRING_GET_FOR_WRITE(parms[1][0], &fs);
1065 if (fs) fs->Set(m_ddrop_files.Get(idx));
1067 #endif
1068 return 1.0;
1071 bool eel_lice_state::do_load_image(int img, const char *str)
1073 s_img_cache_mutex.Enter();
1074 img_shared_state *s = s_img_cache.Get(str);
1075 if (s)
1077 wdl_atomic_incr(&s->refcnt);
1079 else
1081 s_img_cache_mutex.Leave();
1083 LICE_IBitmap *bm = LICE_LoadImage(str,NULL,false);
1084 if (!bm) return false;
1086 s = new img_shared_state(bm);
1087 s_img_cache_mutex.Enter();
1088 s_img_cache.Insert(str,s);
1090 s_img_cache_mutex.Leave();
1091 m_gfx_images.Get()[img].clear(NULL,s);
1093 return true;
1096 EEL_F eel_lice_state::gfx_loadimg(void *opaque, int img, EEL_F loadFrom)
1098 #ifdef DYNAMIC_LICE
1099 if (!__LICE_LoadImage || !LICE__Destroy) return 0.0;
1100 #endif
1102 if (img >= 0 && img < m_gfx_images.GetSize())
1104 WDL_FastString fs;
1105 bool ok = EEL_LICE_GET_FILENAME_FOR_STRING(loadFrom,&fs,0);
1107 if (ok && fs.GetLength())
1109 if (do_load_image(img,fs.Get()))
1110 return img;
1113 return -1.0;
1117 EEL_F eel_lice_state::gfx_setimgdim(int img, EEL_F *w, EEL_F *h)
1119 int rv=0;
1120 #ifdef DYNAMIC_LICE
1121 if (!LICE__resize ||!LICE__GetWidth || !LICE__GetHeight||!__LICE_CreateBitmap) return 0.0;
1122 #endif
1124 int use_w = (int)*w;
1125 int use_h = (int)*h;
1126 if (use_w<1 || use_h < 1) use_w=use_h=0;
1127 if (use_w > 8192) use_w=8192;
1128 if (use_h > 8192) use_h=8192;
1130 LICE_IBitmap *bm=NULL;
1131 if (img >= 0 && img < m_gfx_images.GetSize())
1133 m_gfx_images.Get()[img].on_write();
1134 bm=m_gfx_images.Get()[img].bm;
1135 if (!bm)
1137 m_gfx_images.Get()[img].bm = bm = __LICE_CreateBitmap(1,use_w,use_h);
1138 rv=!!bm;
1140 else
1142 rv=LICE__resize(bm,use_w,use_h);
1146 return rv?1.0:0.0;
1149 void eel_lice_state::gfx_blurto(EEL_F x, EEL_F y)
1151 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_blurto");
1152 if (!dest
1153 #ifdef DYNAMIC_LICE
1154 ||!LICE_Blur
1155 #endif
1156 ) return;
1158 SetImageDirty(dest);
1160 int srcx = (int)x;
1161 int srcy = (int)y;
1162 int srcw=(int) (*m_gfx_x-x);
1163 int srch=(int) (*m_gfx_y-y);
1164 if (srch < 0) { srch=-srch; srcy = (int)*m_gfx_y; }
1165 if (srcw < 0) { srcw=-srcw; srcx = (int)*m_gfx_x; }
1166 LICE_Blur(dest,dest,srcx,srcy,srcx,srcy,srcw,srch);
1167 *m_gfx_x = x;
1168 *m_gfx_y = y;
1171 static bool CoordsSrcDestOverlap(EEL_F *coords)
1173 if (coords[0]+coords[2] < coords[4]) return false;
1174 if (coords[0] > coords[4] + coords[6]) return false;
1175 if (coords[1]+coords[3] < coords[5]) return false;
1176 if (coords[1] > coords[5] + coords[7]) return false;
1177 return true;
1180 void eel_lice_state::gfx_transformblit(EEL_F **parms, int div_w, int div_h, EEL_F *tab)
1182 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_transformblit");
1184 if (!dest
1185 #ifdef DYNAMIC_LICE
1186 ||!LICE_ScaledBlit || !LICE_TransformBlit2 ||!LICE__GetWidth||!LICE__GetHeight
1187 #endif
1188 ) return;
1190 LICE_IBitmap *bm=GetImageForIndex(parms[0][0],"gfx_transformblit:src",false);
1191 if (!bm) return;
1193 const int bmw=LICE__GetWidth(bm);
1194 const int bmh=LICE__GetHeight(bm);
1196 const bool isFromFB = bm==m_framebuffer;
1198 SetImageDirty(dest);
1200 if (bm == dest)
1202 if (!m_framebuffer_extra && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer_extra=__LICE_CreateBitmap(0,bmw,bmh);
1203 if (m_framebuffer_extra)
1206 LICE__resize(bm=m_framebuffer_extra,bmw,bmh);
1207 LICE_ScaledBlit(bm,dest, // copy the entire image
1208 0,0,bmw,bmh,
1209 0.0f,0.0f,(float)bmw,(float)bmh,
1210 1.0f,LICE_BLIT_MODE_COPY);
1213 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));
1216 EEL_F eel_lice_state::gfx_setfont(void *opaque, int np, EEL_F **parms)
1218 int a = np>0 ? ((int)floor(parms[0][0]))-1 : -1;
1220 if (a>=0 && a < m_gfx_fonts.GetSize())
1222 gfxFontStruct *s = m_gfx_fonts.Get()+a;
1223 if (np>1 && LICE_FUNCTION_VALID(LICE_CreateFont) && LICE_FUNCTION_VALID(LICE__SetFromHFont))
1225 const int sz=np>2 ? (int)parms[2][0] : 10;
1227 bool doCreate=false;
1228 int fontflag=0;
1229 if (!s->font) s->actual_fontname[0]=0;
1232 EEL_STRING_MUTEXLOCK_SCOPE
1234 const char *face=EEL_STRING_GET_FOR_INDEX(parms[1][0],NULL);
1235 #ifdef EEL_STRING_DEBUGOUT
1236 if (!face) EEL_STRING_DEBUGOUT("gfx_setfont: invalid string identifier %f",parms[1][0]);
1237 #endif
1238 if (!face || !*face) face="Arial";
1241 unsigned int c = np > 3 ? (unsigned int) parms[3][0] : 0;
1242 while (c)
1244 switch (toupper_safe(c&0xff))
1246 case 'B': fontflag|=EELFONT_FLAG_BOLD; break;
1247 case 'I': fontflag|=EELFONT_FLAG_ITALIC; break;
1248 case 'U': fontflag|=EELFONT_FLAG_UNDERLINE; break;
1249 case 'R': fontflag|=16; break; //LICE_FONT_FLAG_FX_BLUR
1250 case 'V': fontflag|=32; break; //LICE_FONT_FLAG_FX_INVERT
1251 case 'M': fontflag|=64; break; //LICE_FONT_FLAG_FX_MONO
1252 case 'S': fontflag|=128; break; //LICE_FONT_FLAG_FX_SHADOW
1253 case 'O': fontflag|=256; break; //LICE_FONT_FLAG_FX_OUTLINE
1254 case 'Z': fontflag|=1; break; //LICE_FONT_FLAG_VERTICAL
1255 case 'Y': fontflag|=1|2; break; //LICE_FONT_FLAG_VERTICAL|LICE_FONT_FLAG_VERTICAL_BOTTOMUP
1257 c>>=8;
1262 if (fontflag != s->last_fontflag || sz!=s->last_fontsize || strncmp(s->last_fontname,face,sizeof(s->last_fontname)-1))
1264 lstrcpyn_safe(s->last_fontname,face,sizeof(s->last_fontname));
1265 s->last_fontsize=sz;
1266 s->last_fontflag=fontflag;
1267 doCreate=1;
1271 if (doCreate)
1273 s->actual_fontname[0]=0;
1274 if (!s->font) s->font=LICE_CreateFont();
1275 if (s->font)
1277 const int fw = (fontflag&EELFONT_FLAG_BOLD) ? FW_BOLD : FW_NORMAL;
1278 const bool italic = !!(fontflag&EELFONT_FLAG_ITALIC);
1279 const bool underline = !!(fontflag&EELFONT_FLAG_UNDERLINE);
1280 HFONT hf=NULL;
1281 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
1282 WCHAR wf[256];
1283 if (WDL_DetectUTF8(s->last_fontname)>0 &&
1284 GetVersion()<0x80000000 &&
1285 MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,s->last_fontname,-1,wf,256))
1287 hf = CreateFontW(sz,0,0,0,fw,italic,underline,FALSE,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,wf);
1289 #endif
1290 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);
1292 if (!hf)
1294 s->use_fonth=0; // disable this font
1296 else
1298 TEXTMETRIC tm;
1299 tm.tmHeight = sz;
1301 if (!m_framebuffer && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer=__LICE_CreateBitmap(1,64,64);
1303 if (m_framebuffer && LICE_FUNCTION_VALID(LICE__GetDC))
1305 HGDIOBJ oldFont = 0;
1306 HDC hdc=LICE__GetDC(m_framebuffer);
1307 if (hdc)
1309 oldFont = SelectObject(hdc,hf);
1310 GetTextMetrics(hdc,&tm);
1312 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
1313 if (GetVersion()<0x80000000 &&
1314 GetTextFaceW(hdc,sizeof(wf)/sizeof(wf[0]),wf) &&
1315 WideCharToMultiByte(CP_UTF8,0,wf,-1,s->actual_fontname,sizeof(s->actual_fontname),NULL,NULL))
1317 s->actual_fontname[sizeof(s->actual_fontname)-1]=0;
1319 else
1320 #endif
1321 GetTextFace(hdc, sizeof(s->actual_fontname), s->actual_fontname);
1322 SelectObject(hdc,oldFont);
1326 s->use_fonth=wdl_max(tm.tmHeight,1);
1327 LICE__SetFromHFont(s->font,hf, (fontflag & ~EELFONT_FLAG_MASK) | 512 /*LICE_FONT_FLAG_OWNS_HFONT*/);
1334 if (s->font && s->use_fonth)
1336 m_gfx_font_active=a;
1337 if (m_gfx_texth) *m_gfx_texth=s->use_fonth;
1338 return 1.0;
1340 // try to init this font
1342 #ifdef EEL_STRING_DEBUGOUT
1343 if (a >= m_gfx_fonts.GetSize()) EEL_STRING_DEBUGOUT("gfx_setfont: invalid font %d specified",a);
1344 #endif
1346 if (a<0||a>=m_gfx_fonts.GetSize()||!m_gfx_fonts.Get()[a].font)
1348 m_gfx_font_active=-1;
1349 if (m_gfx_texth) *m_gfx_texth=8;
1350 return 1.0;
1352 return 0.0;
1355 void eel_lice_state::gfx_blitext2(int np, EEL_F **parms, int blitmode)
1357 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_blitext2");
1359 if (!dest
1360 #ifdef DYNAMIC_LICE
1361 ||!LICE_ScaledBlit || !LICE_RotatedBlit||!LICE__GetWidth||!LICE__GetHeight
1362 #endif
1363 ) return;
1365 LICE_IBitmap *bm=GetImageForIndex(parms[0][0],"gfx_blitext2:src",false);
1366 if (!bm) return;
1368 const int bmw=LICE__GetWidth(bm);
1369 const int bmh=LICE__GetHeight(bm);
1371 // 0=img, 1=scale, 2=rotate
1372 double coords[8];
1373 const double sc = blitmode==0 && np > 1 ? parms[1][0] : 1.0,
1374 angle = blitmode==0 && np > 2 ? parms[2][0] : 0.0;
1375 if (blitmode==0)
1377 parms+=2;
1378 np -= 2;
1381 coords[0]=np > 1 ? parms[1][0] : 0.0f;
1382 coords[1]=np > 2 ? parms[2][0] : 0.0f;
1383 coords[2]=np > 3 ? parms[3][0] : bmw;
1384 coords[3]=np > 4 ? parms[4][0] : bmh;
1385 coords[4]=np > 5 ? parms[5][0] : *m_gfx_x;
1386 coords[5]=np > 6 ? parms[6][0] : *m_gfx_y;
1387 coords[6]=np > 7 ? parms[7][0] : coords[2]*sc;
1388 coords[7]=np > 8 ? parms[8][0] : coords[3]*sc;
1390 const bool isFromFB = bm == m_framebuffer;
1391 SetImageDirty(dest);
1393 if (bm == dest &&
1394 (blitmode != 0 || np > 1) && // legacy behavior to matech previous gfx_blit(3parm), do not use temp buffer
1395 CoordsSrcDestOverlap(coords))
1397 if (!m_framebuffer_extra && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer_extra=__LICE_CreateBitmap(0,bmw,bmh);
1398 if (m_framebuffer_extra)
1401 LICE__resize(bm=m_framebuffer_extra,bmw,bmh);
1402 LICE_ScaledBlit(bm,dest, // copy the source portion
1403 (int)coords[0],(int)coords[1],(int)coords[2],(int)coords[3],
1404 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1405 1.0f,LICE_BLIT_MODE_COPY);
1409 if (blitmode==1)
1411 if (LICE_FUNCTION_VALID(LICE_DeltaBlit))
1412 LICE_DeltaBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1413 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1414 np > 9 ? (float)parms[9][0]:1.0f, // dsdx
1415 np > 10 ? (float)parms[10][0]:0.0f, // dtdx
1416 np > 11 ? (float)parms[11][0]:0.0f, // dsdy
1417 np > 12 ? (float)parms[12][0]:1.0f, // dtdy
1418 np > 13 ? (float)parms[13][0]:0.0f, // dsdxdy
1419 np > 14 ? (float)parms[14][0]:0.0f, // dtdxdy
1420 np <= 15 || parms[15][0] > 0.5, (float)*m_gfx_a,getCurModeForBlit(isFromFB));
1422 else if (fabs(angle)>0.000000001)
1424 LICE_RotatedBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1425 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1426 (float)angle,true, (float)*m_gfx_a,getCurModeForBlit(isFromFB),
1427 np > 9 ? (float)parms[9][0] : 0.0f,
1428 np > 10 ? (float)parms[10][0] : 0.0f);
1430 else
1432 LICE_ScaledBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1433 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3], (float)*m_gfx_a,getCurModeForBlit(isFromFB));
1437 void eel_lice_state::gfx_blitext(EEL_F img, EEL_F *coords, EEL_F angle)
1439 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_blitext");
1441 if (!dest
1442 #ifdef DYNAMIC_LICE
1443 ||!LICE_ScaledBlit || !LICE_RotatedBlit||!LICE__GetWidth||!LICE__GetHeight
1444 #endif
1445 ) return;
1447 LICE_IBitmap *bm=GetImageForIndex(img,"gfx_blitext:src",false);
1448 if (!bm) return;
1450 SetImageDirty(dest);
1451 const bool isFromFB = bm == m_framebuffer;
1453 int bmw=LICE__GetWidth(bm);
1454 int bmh=LICE__GetHeight(bm);
1456 if (bm == dest && CoordsSrcDestOverlap(coords))
1458 if (!m_framebuffer_extra && LICE_FUNCTION_VALID(__LICE_CreateBitmap)) m_framebuffer_extra=__LICE_CreateBitmap(0,bmw,bmh);
1459 if ( m_framebuffer_extra)
1462 LICE__resize(bm=m_framebuffer_extra,bmw,bmh);
1463 LICE_ScaledBlit(bm,dest, // copy the source portion
1464 (int)coords[0],(int)coords[1],(int)coords[2],(int)coords[3],
1465 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],
1466 1.0f,LICE_BLIT_MODE_COPY);
1470 if (fabs(angle)>0.000000001)
1472 LICE_RotatedBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1473 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3],(float)angle,
1474 true, (float)*m_gfx_a,getCurModeForBlit(isFromFB),
1475 (float)coords[8],(float)coords[9]);
1477 else
1479 LICE_ScaledBlit(dest,bm,(int)coords[4],(int)coords[5],(int)coords[6],(int)coords[7],
1480 (float)coords[0],(float)coords[1],(float)coords[2],(float)coords[3], (float)*m_gfx_a,getCurModeForBlit(isFromFB));
1484 void eel_lice_state::gfx_set(int np, EEL_F **parms)
1486 if (np < 1) return;
1487 if (m_gfx_r) *m_gfx_r = parms[0][0];
1488 if (m_gfx_g) *m_gfx_g = np > 1 ? parms[1][0] : parms[0][0];
1489 if (m_gfx_b) *m_gfx_b = np > 2 ? parms[2][0] : parms[0][0];
1490 if (m_gfx_a) *m_gfx_a = np > 3 ? parms[3][0] : 1.0;
1491 if (m_gfx_mode) *m_gfx_mode = np > 4 ? parms[4][0] : 0;
1492 if (np > 5 && m_gfx_dest) *m_gfx_dest = parms[5][0];
1493 if (m_gfx_a2) *m_gfx_a2 = np > 6 ? parms[6][0] : 1.0;
1496 void eel_lice_state::gfx_getpixel(EEL_F *r, EEL_F *g, EEL_F *b)
1498 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_getpixel",false);
1499 if (!dest) return;
1501 int ret=LICE_FUNCTION_VALID(LICE_GetPixel)?LICE_GetPixel(dest,(int)*m_gfx_x, (int)*m_gfx_y):0;
1503 *r=LICE_GETR(ret)/255.0;
1504 *g=LICE_GETG(ret)/255.0;
1505 *b=LICE_GETB(ret)/255.0;
1510 static int __drawTextWithFont(LICE_IBitmap *dest, const RECT *rect, LICE_IFont *font, const char *buf, int buflen,
1511 int fg, int mode, float alpha, int flags, EEL_F *wantYoutput, EEL_F **measureOnly)
1513 if (font && LICE_FUNCTION_VALID(LICE__DrawText))
1515 RECT tr=*rect;
1516 LICE__SetTextColor(font,fg);
1517 LICE__SetTextCombineMode(font,mode,alpha);
1519 int maxx=0;
1520 RECT r={0,0,tr.left,0};
1521 while (buflen>0)
1523 int thislen = 0;
1524 while (thislen < buflen && buf[thislen] != '\n') thislen++;
1525 memset(&r,0,sizeof(r));
1526 int lineh = LICE__DrawText(font,dest,buf,thislen?thislen:1,&r,DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT);
1527 if (!measureOnly)
1529 r.right += tr.left;
1530 lineh = LICE__DrawText(font,dest,buf,thislen?thislen:1,&tr,DT_SINGLELINE|DT_NOPREFIX|flags);
1531 if (wantYoutput) *wantYoutput = tr.top;
1533 else
1535 if (r.right > maxx) maxx=r.right;
1537 tr.top += lineh;
1539 buflen -= thislen+1;
1540 buf += thislen+1;
1542 if (measureOnly)
1544 measureOnly[0][0] = maxx;
1545 measureOnly[1][0] = tr.top;
1547 return r.right;
1549 else
1551 int xpos=rect->left, ypos=rect->top;
1552 int x;
1553 int maxx=0,maxy=0;
1555 LICE_SubBitmap sbm(
1556 #ifdef DYNAMIC_LICE
1557 (LICE_IBitmap_disabledAPI*)
1558 #endif
1559 dest,rect->left,rect->top,rect->right-rect->left,rect->bottom-rect->top);
1561 if (!measureOnly)
1563 if (!(flags & DT_NOCLIP))
1565 if (rect->right <= rect->left || rect->bottom <= rect->top) return 0; // invalid clip rect hm
1567 xpos = ypos = 0;
1568 dest = &sbm;
1570 if (flags & (DT_RIGHT|DT_BOTTOM|DT_CENTER|DT_VCENTER))
1572 EEL_F w=0.0,h=0.0;
1573 EEL_F *mo[2] = { &w,&h};
1574 RECT tr={0,};
1575 __drawTextWithFont(dest,&tr,NULL,buf,buflen,0,0,0.0f,0,NULL,mo);
1577 if (flags & DT_RIGHT) xpos += (rect->right-rect->left) - (int)floor(w);
1578 else if (flags & DT_CENTER) xpos += (rect->right-rect->left)/2 - (int)floor(w*.5);
1580 if (flags & DT_BOTTOM) ypos += (rect->bottom-rect->top) - (int)floor(h);
1581 else if (flags & DT_VCENTER) ypos += (rect->bottom-rect->top)/2 - (int)floor(h*.5);
1584 const int sxpos = xpos;
1586 if (LICE_FUNCTION_VALID(LICE_DrawChar)) for(x=0;x<buflen;x++)
1588 switch (buf[x])
1590 case '\n':
1591 ypos += 8;
1592 WDL_FALLTHROUGH;
1593 case '\r':
1594 xpos = sxpos;
1595 break;
1596 case ' ': xpos += 8; break;
1597 case '\t': xpos += 8*5; break;
1598 default:
1599 if (!measureOnly) LICE_DrawChar(dest,xpos,ypos,buf[x], fg,alpha,mode);
1600 xpos += 8;
1601 if (xpos > maxx) maxx=xpos;
1602 maxy = ypos + 8;
1603 break;
1606 if (measureOnly)
1608 measureOnly[0][0]=maxx;
1609 measureOnly[1][0]=maxy;
1611 else
1613 if (wantYoutput) *wantYoutput=ypos;
1615 return xpos;
1619 static HMENU PopulateMenuFromStr(const char** str, int* startid)
1621 HMENU hm=CreatePopupMenu();
1622 int pos=0;
1623 int id=*startid;
1625 char buf[1024];
1626 const char* p=*str;
1627 const char* sep=strchr(p, '|');
1628 while (sep || *p)
1630 int len = (int)(sep ? sep-p : strlen(p));
1631 int destlen=wdl_min(len, (int)sizeof(buf)-1);
1632 lstrcpyn(buf, p, destlen+1);
1633 p += len;
1634 if (sep) sep=strchr(++p, '|');
1636 const char* q=buf;
1637 HMENU subm=NULL;
1638 bool done=false;
1639 int flags=MF_BYPOSITION|MF_STRING;
1640 while (strspn(q, ">#!<"))
1642 if (*q == '>' && !subm)
1644 subm=PopulateMenuFromStr(&p, &id);
1645 sep=strchr(p, '|');
1647 if (*q == '#') flags |= MF_GRAYED;
1648 if (*q == '!') flags |= MF_CHECKED;
1649 if (*q == '<') done=true;
1650 ++q;
1652 if (subm) flags |= MF_POPUP;
1653 if (*q) InsertMenu(hm, pos++, flags, (subm ? (INT_PTR)subm : (INT_PTR)id++), q);
1654 else if (!done) InsertMenu(hm, pos++, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
1655 if (done) break;
1658 *str=p;
1659 *startid=id;
1661 if (!pos)
1663 DestroyMenu(hm);
1664 return NULL;
1666 return hm;
1669 EEL_F eel_lice_state::gfx_showmenu(void* opaque, EEL_F** parms, int nparms)
1671 const char* p=EEL_STRING_GET_FOR_INDEX(parms[0][0], NULL);
1672 if (!p || !p[0]) return 0.0;
1674 if ((GetTickCount()-m_last_menu_time) < (m_last_menu_cnt>=5 ? 3000 : 500))
1676 if (m_last_menu_cnt >= 5) return 0;
1677 m_last_menu_cnt++;
1679 else
1681 m_last_menu_cnt=0;
1684 int id=1;
1685 HMENU hm=PopulateMenuFromStr(&p, &id);
1687 int ret=0;
1688 if (hm)
1690 POINT pt;
1691 HWND par = hwnd_standalone;
1692 if (par)
1694 #ifdef __APPLE__
1695 if (*m_gfx_ext_retina > 1.0)
1697 pt.x = (short)(*m_gfx_x * .5);
1698 pt.y = (short)(*m_gfx_y * .5);
1700 else
1701 #endif
1703 pt.x = (short)*m_gfx_x;
1704 pt.y = (short)*m_gfx_y;
1706 ClientToScreen(par, &pt);
1708 else
1710 #ifdef EEL_LICE_STANDALONE_PARENT
1711 par = EEL_LICE_STANDALONE_PARENT(opaque);
1712 #endif
1713 GetCursorPos(&pt);
1716 ret=TrackPopupMenu(hm, TPM_NONOTIFY|TPM_RETURNCMD, pt.x, pt.y, 0, par, NULL);
1717 m_last_menu_time = GetTickCount();
1718 if (ret) m_last_menu_cnt = 0;
1719 DestroyMenu(hm);
1721 return (EEL_F)ret;
1724 EEL_F eel_lice_state::gfx_setcursor(void* opaque, EEL_F** parms, int nparms)
1726 if (!hwnd_standalone) return 0.0;
1728 bool chg = false;
1729 const int nc = (int)parms[0][0];
1730 if (m_cursor_resid != nc)
1732 m_cursor_resid = nc;
1733 chg = true;
1736 const char *p = NULL;
1737 #ifdef EEL_LICE_LOADTHEMECURSOR
1738 if (nparms > 1) p=EEL_STRING_GET_FOR_INDEX(parms[1][0], NULL);
1740 if (strncmp(p?p:"",m_cursor_name,sizeof(m_cursor_name)-1))
1742 lstrcpyn(m_cursor_name, p?p:"", sizeof(m_cursor_name));
1743 chg = true;
1745 #endif
1747 if (chg)
1749 m_cursor = NULL;
1750 if (!p || !*p) m_cursor = m_cursor_resid > 0 ? LoadCursor(NULL, MAKEINTRESOURCE(m_cursor_resid)) : NULL;
1751 #ifdef EEL_LICE_LOADTHEMECURSOR
1752 else m_cursor = EEL_LICE_LOADTHEMECURSOR(m_cursor_resid, p);
1753 #endif
1755 bool do_set = GetCapture() == hwnd_standalone;
1756 if (!do_set && GetFocus() == hwnd_standalone)
1758 POINT pt;
1759 RECT r;
1760 GetCursorPos(&pt);
1761 ScreenToClient(hwnd_standalone,&pt);
1762 GetClientRect(hwnd_standalone,&r);
1763 do_set = PtInRect(&r,pt)!=0;
1766 if (do_set)
1768 SetCursor(m_cursor ? m_cursor : LoadCursor(NULL,IDC_ARROW));
1772 return 1.0;
1776 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
1778 int nfmtparms = nparms-1;
1779 EEL_F **fmtparms = parms+1;
1780 const char *funcname = formatmode==1?"gfx_printf":
1781 formatmode==2?"gfx_measurestr":
1782 formatmode==3?"gfx_measurechar" : "gfx_drawstr";
1784 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,funcname);
1785 if (!dest) return;
1787 #ifdef DYNAMIC_LICE
1788 if (!LICE__GetWidth || !LICE__GetHeight) return;
1789 #endif
1791 EEL_STRING_MUTEXLOCK_SCOPE
1793 WDL_FastString *fs=NULL;
1794 char buf[4096];
1795 int s_len=0;
1797 const char *s;
1798 if (formatmode==3)
1800 s_len = WDL_MakeUTFChar(buf, (int)parms[0][0], sizeof(buf));
1801 s=buf;
1803 else
1805 s=EEL_STRING_GET_FOR_INDEX(parms[0][0],&fs);
1806 #ifdef EEL_STRING_DEBUGOUT
1807 if (!s) EEL_STRING_DEBUGOUT("gfx_%s: invalid string identifier %f",funcname,parms[0][0]);
1808 #endif
1809 if (!s)
1811 s="<bad string>";
1812 s_len = 12;
1814 else if (formatmode==1)
1816 extern int eel_format_strings(void *, const char *s, const char *ep, char *, int, int, EEL_F **);
1817 s_len = eel_format_strings(opaque,s,fs?(s+fs->GetLength()):NULL,buf,sizeof(buf),nfmtparms,fmtparms);
1818 if (s_len<1) return;
1819 s=buf;
1821 else
1823 s_len = fs?fs->GetLength():(int)strlen(s);
1827 if (s_len)
1829 if (formatmode>=2)
1831 if (nfmtparms==2)
1833 RECT r={0,0,0,0};
1834 __drawTextWithFont(dest,&r,GetActiveFont(),s,s_len,
1835 getCurColor(),getCurMode(),(float)*m_gfx_a,0,NULL,fmtparms);
1838 else
1840 RECT r={(int)floor(*m_gfx_x),(int)floor(*m_gfx_y),0,0};
1841 int flags=DT_NOCLIP;
1842 if (formatmode == 0 && nparms >= 4)
1844 flags=(int)*parms[1];
1845 flags &= (DT_CENTER|DT_RIGHT|DT_VCENTER|DT_BOTTOM|DT_NOCLIP);
1846 r.right=(int)*parms[2];
1847 r.bottom=(int)*parms[3];
1849 SetImageDirty(dest);
1850 *m_gfx_x=__drawTextWithFont(dest,&r,GetActiveFont(),s,s_len,
1851 getCurColor(),getCurMode(),(float)*m_gfx_a,flags,m_gfx_y,NULL);
1856 void eel_lice_state::gfx_drawchar(EEL_F ch)
1858 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_drawchar");
1859 if (!dest) return;
1861 SetImageDirty(dest);
1863 int a=(int)(ch+0.5);
1864 if (a == '\r' || a=='\n') a=' ';
1866 char buf[32];
1867 const int buflen = WDL_MakeUTFChar(buf, a, sizeof(buf));
1869 RECT r={(int)floor(*m_gfx_x),(int)floor(*m_gfx_y),0,0};
1870 *m_gfx_x = __drawTextWithFont(dest,&r,
1871 GetActiveFont(),buf,buflen,
1872 getCurColor(),getCurMode(),(float)*m_gfx_a,DT_NOCLIP,NULL,NULL);
1877 void eel_lice_state::gfx_drawnumber(EEL_F n, EEL_F ndigits)
1879 LICE_IBitmap *dest = GetImageForIndex(*m_gfx_dest,"gfx_drawnumber");
1880 if (!dest) return;
1882 SetImageDirty(dest);
1884 char buf[512];
1885 int a=(int)(ndigits+0.5);
1886 if (a <0)a=0;
1887 else if (a > 16) a=16;
1888 snprintf(buf,sizeof(buf),"%.*f",a,n);
1890 RECT r={(int)floor(*m_gfx_x),(int)floor(*m_gfx_y),0,0};
1891 *m_gfx_x = __drawTextWithFont(dest,&r,
1892 GetActiveFont(),buf,(int)strlen(buf),
1893 getCurColor(),getCurMode(),(float)*m_gfx_a,DT_NOCLIP,NULL,NULL);
1896 int eel_lice_state::setup_frame(HWND hwnd, RECT r, int _mouse_x, int _mouse_y, int has_dpi)
1898 int use_w = r.right - r.left;
1899 int use_h = r.bottom - r.top;
1901 POINT pt = { _mouse_x, _mouse_y };
1902 if (hwnd)
1904 GetCursorPos(&pt);
1905 ScreenToClient(hwnd,&pt);
1908 *m_mouse_x=pt.x-r.left;
1909 *m_mouse_y=pt.y-r.top;
1911 if (has_dpi>0 && *m_gfx_ext_retina > 0.0)
1913 *m_gfx_ext_retina = has_dpi/256.0;
1915 else if (*m_gfx_ext_retina > 0.0)
1917 #ifdef __APPLE__
1918 *m_gfx_ext_retina = (hwnd && SWELL_IsRetinaHWND(hwnd)) ? 2.0 : 1.0;
1919 if (*m_gfx_ext_retina > 1.0)
1921 *m_mouse_x *= 2.0;
1922 *m_mouse_y *= 2.0;
1923 use_w*=2;
1924 use_h*=2;
1926 #else
1927 *m_gfx_ext_retina = 1.0;
1928 #ifdef _WIN32
1929 static UINT (WINAPI *__GetDpiForWindow)(HWND);
1930 if (!__GetDpiForWindow)
1932 HINSTANCE h = LoadLibrary("user32.dll");
1933 if (h) *(void **)&__GetDpiForWindow = GetProcAddress(h,"GetDpiForWindow");
1934 if (!__GetDpiForWindow)
1935 *(void **)&__GetDpiForWindow = (void*)(INT_PTR)1;
1937 if (hwnd && (UINT_PTR)__GetDpiForWindow > (UINT_PTR)1)
1939 int dpi = __GetDpiForWindow(hwnd);
1940 if (dpi != 96)
1941 *m_gfx_ext_retina = dpi / 96.0;
1943 #else
1944 const int rsc = SWELL_GetScaling256();
1945 if (rsc > 256) *m_gfx_ext_retina = rsc/256.0;
1946 #endif
1947 #endif
1949 int dr=0;
1950 if (!m_framebuffer && LICE_FUNCTION_VALID(__LICE_CreateBitmap))
1952 m_framebuffer=__LICE_CreateBitmap(1,use_w,use_h);
1953 dr=1;
1956 if (!m_framebuffer || !LICE_FUNCTION_VALID(LICE__GetHeight) || !LICE_FUNCTION_VALID(LICE__GetWidth)) return -1;
1958 if (use_w != LICE__GetWidth(m_framebuffer) || use_h != LICE__GetHeight(m_framebuffer))
1960 LICE__resize(m_framebuffer,use_w,use_h);
1961 dr=1;
1963 *m_gfx_w = use_w;
1964 *m_gfx_h = use_h;
1966 if (*m_gfx_clear > -1.0 && dr)
1968 const int a=(int)*m_gfx_clear;
1969 if (LICE_FUNCTION_VALID(LICE_Clear)) LICE_Clear(m_framebuffer,LICE_RGBA((a&0xff),((a>>8)&0xff),((a>>16)&0xff),0));
1971 m_framebuffer_dirty = dr;
1973 int vflags=0;
1975 if (m_has_cap)
1977 bool swap = false;
1978 #ifdef _WIN32
1979 swap = !!GetSystemMetrics(SM_SWAPBUTTON);
1980 #endif
1981 vflags|=m_has_cap&0xffff;
1982 if (GetAsyncKeyState(VK_LBUTTON)&0x8000) vflags|=swap?2:1;
1983 if (GetAsyncKeyState(VK_RBUTTON)&0x8000) vflags|=swap?1:2;
1984 if (GetAsyncKeyState(VK_MBUTTON)&0x8000) vflags|=64;
1986 if (m_has_cap || (m_has_had_getch && hwnd && GetFocus()==hwnd))
1988 if (GetAsyncKeyState(VK_CONTROL)&0x8000) vflags|=4;
1989 if (GetAsyncKeyState(VK_SHIFT)&0x8000) vflags|=8;
1990 if (GetAsyncKeyState(VK_MENU)&0x8000) vflags|=16;
1991 if (GetAsyncKeyState(VK_LWIN)&0x8000) vflags|=32;
1993 m_has_cap &= 0xf0000;
1995 *m_mouse_cap=(EEL_F)vflags;
1997 *m_gfx_dest = -1.0; // m_framebuffer
1998 *m_gfx_a2 = *m_gfx_a = 1.0; // default to full alpha every call
1999 int fh;
2000 if (m_gfx_font_active>=0&&m_gfx_font_active<m_gfx_fonts.GetSize() && (fh=m_gfx_fonts.Get()[m_gfx_font_active].use_fonth)>0)
2001 *m_gfx_texth=fh;
2002 else
2003 *m_gfx_texth = 8;
2005 return dr;
2008 void eel_lice_state::finish_draw()
2010 if (hwnd_standalone && m_framebuffer_dirty)
2012 #ifdef __APPLE__
2013 void *p = SWELL_InitAutoRelease();
2014 #endif
2016 InvalidateRect(hwnd_standalone,NULL,FALSE);
2017 UpdateWindow(hwnd_standalone);
2019 #ifdef __APPLE__
2020 SWELL_QuitAutoRelease(p);
2021 #endif
2022 m_framebuffer_dirty = 0;
2026 #ifndef EEL_LICE_NO_REGISTER
2027 void eel_lice_register()
2029 NSEEL_addfunc_retptr("gfx_lineto",3,NSEEL_PProc_THIS,&_gfx_lineto);
2030 NSEEL_addfunc_retptr("gfx_lineto",2,NSEEL_PProc_THIS,&_gfx_lineto2);
2031 NSEEL_addfunc_retptr("gfx_rectto",2,NSEEL_PProc_THIS,&_gfx_rectto);
2032 NSEEL_addfunc_varparm("gfx_rect",4,NSEEL_PProc_THIS,&_gfx_rect);
2033 NSEEL_addfunc_varparm("gfx_line",4,NSEEL_PProc_THIS,&_gfx_line); // 5th param is optionally AA
2034 NSEEL_addfunc_varparm("gfx_gradrect",8,NSEEL_PProc_THIS,&_gfx_gradrect);
2035 NSEEL_addfunc_varparm("gfx_muladdrect",7,NSEEL_PProc_THIS,&_gfx_muladdrect);
2036 NSEEL_addfunc_varparm("gfx_deltablit",9,NSEEL_PProc_THIS,&_gfx_deltablit);
2037 NSEEL_addfunc_exparms("gfx_transformblit",8,NSEEL_PProc_THIS,&_gfx_transformblit);
2038 NSEEL_addfunc_varparm("gfx_circle",3,NSEEL_PProc_THIS,&_gfx_circle);
2039 NSEEL_addfunc_varparm("gfx_triangle", 6, NSEEL_PProc_THIS, &_gfx_triangle);
2040 NSEEL_addfunc_varparm("gfx_roundrect",5,NSEEL_PProc_THIS,&_gfx_roundrect);
2041 NSEEL_addfunc_varparm("gfx_arc",5,NSEEL_PProc_THIS,&_gfx_arc);
2042 NSEEL_addfunc_retptr("gfx_blurto",2,NSEEL_PProc_THIS,&_gfx_blurto);
2043 NSEEL_addfunc_exparms("gfx_showmenu",1,NSEEL_PProc_THIS,&_gfx_showmenu);
2044 NSEEL_addfunc_varparm("gfx_setcursor",1, NSEEL_PProc_THIS, &_gfx_setcursor);
2045 NSEEL_addfunc_retptr("gfx_drawnumber",2,NSEEL_PProc_THIS,&_gfx_drawnumber);
2046 NSEEL_addfunc_retptr("gfx_drawchar",1,NSEEL_PProc_THIS,&_gfx_drawchar);
2047 NSEEL_addfunc_varparm("gfx_drawstr",1,NSEEL_PProc_THIS,&_gfx_drawstr);
2048 NSEEL_addfunc_retptr("gfx_measurestr",3,NSEEL_PProc_THIS,&_gfx_measurestr);
2049 NSEEL_addfunc_retptr("gfx_measurechar",3,NSEEL_PProc_THIS,&_gfx_measurechar);
2050 NSEEL_addfunc_varparm("gfx_printf",1,NSEEL_PProc_THIS,&_gfx_printf);
2051 NSEEL_addfunc_retptr("gfx_setpixel",3,NSEEL_PProc_THIS,&_gfx_setpixel);
2052 NSEEL_addfunc_retptr("gfx_getpixel",3,NSEEL_PProc_THIS,&_gfx_getpixel);
2053 NSEEL_addfunc_retptr("gfx_getimgdim",3,NSEEL_PProc_THIS,&_gfx_getimgdim);
2054 NSEEL_addfunc_retval("gfx_setimgdim",3,NSEEL_PProc_THIS,&_gfx_setimgdim);
2055 NSEEL_addfunc_retval("gfx_loadimg",2,NSEEL_PProc_THIS,&_gfx_loadimg);
2056 NSEEL_addfunc_retptr("gfx_blitext",3,NSEEL_PProc_THIS,&_gfx_blitext);
2057 NSEEL_addfunc_varparm("gfx_blit",1,NSEEL_PProc_THIS,&_gfx_blit2);
2058 NSEEL_addfunc_varparm("gfx_setfont",1,NSEEL_PProc_THIS,&_gfx_setfont);
2059 NSEEL_addfunc_varparm("gfx_getfont",1,NSEEL_PProc_THIS,&_gfx_getfont);
2060 NSEEL_addfunc_varparm("gfx_set",1,NSEEL_PProc_THIS,&_gfx_set);
2061 NSEEL_addfunc_varparm("gfx_getdropfile",1,NSEEL_PProc_THIS,&_gfx_getdropfile);
2062 NSEEL_addfunc_varparm("gfx_getsyscol",0,NSEEL_PProc_THIS,&_gfx_getsyscol);
2064 #endif
2066 #ifdef EEL_LICE_WANT_STANDALONE
2068 #ifdef _WIN32
2069 static HINSTANCE eel_lice_hinstance;
2070 #endif
2071 static const char *eel_lice_standalone_classname;
2073 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
2074 static EEL_F * NSEEL_CGEN_CALL _gfx_update(void *opaque, EEL_F *n)
2076 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2077 if (ctx)
2079 ctx->m_ddrop_files.Empty(true,free);
2080 if (ctx->hwnd_standalone)
2082 #ifndef EEL_LICE_WANT_STANDALONE_UPDATE_NO_SETUPFRAME
2083 ctx->finish_draw();
2084 #endif
2086 // run message pump
2087 #ifndef EEL_LICE_WANT_STANDALONE_UPDATE_NO_MSGPUMP
2089 #ifdef _WIN32
2090 MSG msg;
2091 while (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
2093 TranslateMessage(&msg);
2094 DispatchMessage(&msg);
2096 #else
2097 void SWELL_RunEvents();
2098 SWELL_RunEvents();
2099 #endif
2100 #endif
2101 #ifndef EEL_LICE_WANT_STANDALONE_UPDATE_NO_SETUPFRAME
2102 RECT r;
2103 GetClientRect(ctx->hwnd_standalone,&r);
2104 ctx->setup_frame(ctx->hwnd_standalone,r);
2105 #endif
2108 return n;
2110 #endif
2114 static EEL_F NSEEL_CGEN_CALL _gfx_getchar(void *opaque, INT_PTR np, EEL_F **plist)
2116 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2117 if (np > 1) plist[1][0] = 0.0;
2118 if (ctx)
2120 EEL_F *p = plist[0];
2121 ctx->m_has_had_getch=true;
2122 if (*p >= 2.0)
2124 if (*p == 65536.0 || *p == 65537.0)
2126 int rv = 1;
2127 if (ctx->hwnd_standalone)
2129 if (ctx->hwnd_standalone==GetFocus()) rv|=2;
2130 if (IsWindowVisible(ctx->hwnd_standalone))
2132 rv|=4;
2133 if (*p != 65537.0)
2135 POINT pt;
2136 GetCursorPos(&pt);
2137 RECT r;
2138 GetWindowRect(ctx->hwnd_standalone,&r);
2139 if (r.top > r.bottom)
2141 const int a = r.top;
2142 r.top = r.bottom;
2143 r.bottom = a;
2145 if (PtInRect(&r,pt) && WindowFromPoint(pt) == ctx->hwnd_standalone) rv|=8;
2149 return rv;
2151 int x;
2152 const int n = sizeof(ctx->hwnd_standalone_kb_state) / sizeof(ctx->hwnd_standalone_kb_state[0]);
2153 int *st = ctx->hwnd_standalone_kb_state;
2154 int a = (int)*p;
2155 for (x=0;x<n && st[x] != a;x++);
2156 return x<n ? 1.0 : 0.0;
2159 if (!ctx->hwnd_standalone) return -1.0;
2161 if (ctx->m_kb_queue_valid)
2163 const int qsize = sizeof(ctx->m_kb_queue)/sizeof(ctx->m_kb_queue[0]);
2164 int a = ctx->m_kb_queue[ctx->m_kb_queue_pos & (qsize-1)];
2165 ctx->m_kb_queue_pos++;
2166 ctx->m_kb_queue_valid--;
2168 #ifdef _WIN32
2169 if (np > 1 && (a>>24) != 'u' && ctx->m_kb_queue_valid > 0)
2171 int a2 = ctx->m_kb_queue[ctx->m_kb_queue_pos & (qsize-1)];
2172 if ((a2>>24)=='u')
2174 ctx->m_kb_queue_pos++;
2175 ctx->m_kb_queue_valid--;
2176 plist[1][0] = (a2&0xffffff);
2178 return a;
2180 #else
2181 if (a > 32 && a < 256 && np > 1)
2182 plist[1][0] = a;
2183 #endif
2184 if ((a>>24) == 'u')
2186 if ((a&0xffffff) < 256)
2187 a &= 0xff;
2188 if (np > 1) plist[1][0] = a&0xffffff;
2191 return a;
2194 return 0.0;
2197 static int eel_lice_key_xlate(int msg, int wParam, int lParam, bool *isAltOut)
2199 #define EEL_MB_C(a) (sizeof(a)<=2 ? a[0] : \
2200 sizeof(a)==3 ? (((a[0])<<8)+(a[1])) : \
2201 sizeof(a)==4 ? (((a[0])<<16)+((a[1])<<8)+(a[2])) : \
2202 (((a[0])<<24)+((a[1])<<16)+((a[2])<<8)+(a[3])))
2204 if (msg != WM_CHAR)
2206 #ifndef _WIN32
2207 if (lParam & FVIRTKEY)
2208 #endif
2209 switch (wParam)
2211 case VK_HOME: return EEL_MB_C("home");
2212 case VK_UP: return EEL_MB_C("up");
2213 case VK_PRIOR: return EEL_MB_C("pgup");
2214 case VK_LEFT: return EEL_MB_C("left");
2215 case VK_RIGHT: return EEL_MB_C("rght");
2216 case VK_END: return EEL_MB_C("end");
2217 case VK_DOWN: return EEL_MB_C("down");
2218 case VK_NEXT: return EEL_MB_C("pgdn");
2219 case VK_INSERT: return EEL_MB_C("ins");
2220 case VK_DELETE: return EEL_MB_C("del");
2221 case VK_F1: return EEL_MB_C("f1");
2222 case VK_F2: return EEL_MB_C("f2");
2223 case VK_F3: return EEL_MB_C("f3");
2224 case VK_F4: return EEL_MB_C("f4");
2225 case VK_F5: return EEL_MB_C("f5");
2226 case VK_F6: return EEL_MB_C("f6");
2227 case VK_F7: return EEL_MB_C("f7");
2228 case VK_F8: return EEL_MB_C("f8");
2229 case VK_F9: return EEL_MB_C("f9");
2230 case VK_F10: return EEL_MB_C("f10");
2231 case VK_F11: return EEL_MB_C("f11");
2232 case VK_F12: return EEL_MB_C("f12");
2233 #ifndef _WIN32
2234 case VK_SUBTRACT: return '-'; // numpad -
2235 case VK_ADD: return '+';
2236 case VK_MULTIPLY: return '*';
2237 case VK_DIVIDE: return '/';
2238 case VK_DECIMAL: return '.';
2239 case VK_NUMPAD0: return '0';
2240 case VK_NUMPAD1: return '1';
2241 case VK_NUMPAD2: return '2';
2242 case VK_NUMPAD3: return '3';
2243 case VK_NUMPAD4: return '4';
2244 case VK_NUMPAD5: return '5';
2245 case VK_NUMPAD6: return '6';
2246 case VK_NUMPAD7: return '7';
2247 case VK_NUMPAD8: return '8';
2248 case VK_NUMPAD9: return '9';
2249 case (32768|VK_RETURN): return VK_RETURN;
2250 #endif
2253 switch (wParam)
2255 case VK_RETURN:
2256 case VK_BACK:
2257 case VK_TAB:
2258 case VK_ESCAPE:
2259 return wParam;
2261 case VK_CONTROL: break;
2263 default:
2265 const bool isctrl = !!(GetAsyncKeyState(VK_CONTROL)&0x8000);
2266 const bool isalt = !!(GetAsyncKeyState(VK_MENU)&0x8000);
2268 #ifdef __APPLE__
2269 // SWELL_MacKeyToWindowsKeyEx maps control(FLWIN)+A-Z to 1-26
2270 if (wParam > 0 && wParam <= 26 && !(lParam&FVIRTKEY))
2272 *isAltOut=isalt;
2273 return wParam;
2275 #endif
2277 if(isctrl || isalt)
2280 if (wParam>='a' && wParam<='z')
2282 if (isctrl) wParam += 1-'a';
2283 if (isalt) wParam += 256;
2284 *isAltOut=isalt;
2285 return wParam;
2287 if (wParam>='A' && wParam<='Z')
2289 if (isctrl) wParam += 1-'A';
2290 if (isalt) wParam += 256;
2291 *isAltOut=isalt;
2292 return wParam;
2296 break;
2300 if(wParam>=32)
2302 #ifdef _WIN32
2303 if (msg == WM_CHAR)
2305 return (wParam&0xffffff) | ('u'<<24); // windows encodes all wm_chars as 'u'<<24
2307 #else
2308 if (!(GetAsyncKeyState(VK_SHIFT)&0x8000))
2310 if (wParam>='A' && wParam<='Z')
2312 if ((GetAsyncKeyState(VK_LWIN)&0x8000)) wParam -= 'A'-1;
2313 else
2314 wParam += 'a'-'A';
2317 if (wParam >= 0x100)
2318 return (wParam&0xffffff) | ('u'<<24);
2319 return wParam;
2320 #endif
2322 return 0;
2324 #undef EEL_MB_C
2326 static LRESULT WINAPI eel_lice_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
2327 #ifdef __APPLE__
2328 extern "C"
2330 void *objc_getClass(const char *p);
2331 #ifndef _OBJC_OBJC_H_
2332 void *sel_getUid(const char *p);
2333 #endif
2334 void objc_msgSend(void);
2336 #endif
2339 HWND eel_lice_state::create_wnd(HWND par, int isChild)
2341 if (hwnd_standalone) return hwnd_standalone;
2342 #ifdef _WIN32
2343 return CreateWindowEx(WS_EX_ACCEPTFILES,eel_lice_standalone_classname,"",
2344 isChild ? (WS_CHILD|WS_TABSTOP) : (WS_POPUP|WS_CAPTION|WS_THICKFRAME|WS_SYSMENU),CW_USEDEFAULT,CW_USEDEFAULT,100,100,par,NULL,eel_lice_hinstance,this);
2345 #else
2346 HWND h = SWELL_CreateDialog(NULL,isChild ? NULL : ((const char *)(INT_PTR)0x400001),par,(DLGPROC)eel_lice_wndproc,(LPARAM)this);
2347 if (h)
2349 SWELL_SetClassName(h,eel_lice_standalone_classname);
2350 SWELL_EnableMetal(h,1);
2352 return h;
2353 #endif
2356 #ifdef EEL_LICE_WANTDOCK
2357 #ifndef ID_DOCKWINDOW
2358 #define ID_DOCKWINDOW 40269
2359 #endif
2361 static EEL_F NSEEL_CGEN_CALL _gfx_dock(void *opaque, INT_PTR np, EEL_F **parms)
2363 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2364 if (ctx)
2366 if (np > 0 && parms[0][0] >= 0.0 && ctx->hwnd_standalone) EEL_LICE_WANTDOCK(ctx,(int)parms[0][0]);
2368 if (np > 1 && parms[1]) parms[1][0] = ctx->m_last_undocked_r.left;
2369 if (np > 2 && parms[2]) parms[2][0] = ctx->m_last_undocked_r.top;
2370 if (np > 3 && parms[3]) parms[3][0] = ctx->m_last_undocked_r.right;
2371 if (np > 4 && parms[4]) parms[4][0] = ctx->m_last_undocked_r.bottom;
2373 #ifdef EEL_LICE_ISDOCKED
2374 return EEL_LICE_ISDOCKED(ctx);
2375 #endif
2377 return 0.0;
2380 #endif //EEL_LICE_WANTDOCK
2383 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
2385 static EEL_F * NSEEL_CGEN_CALL _gfx_quit(void *opaque, EEL_F *n)
2387 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2388 if (ctx)
2390 if (ctx->hwnd_standalone)
2392 DestroyWindow(ctx->hwnd_standalone);
2394 ctx->hwnd_standalone=0;
2396 return n;
2399 static EEL_F NSEEL_CGEN_CALL _gfx_init(void *opaque, INT_PTR np, EEL_F **parms)
2401 #ifdef EEL_LICE_GET_CONTEXT_INIT
2402 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT_INIT(opaque);
2403 #else
2404 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2405 #endif
2406 if (ctx)
2408 bool wantShow=false, wantResize=true;
2409 int sug_w = np > 1 ? (int)parms[1][0] : 640;
2410 int sug_h = np > 2 ? (int)parms[2][0] : 480;
2411 if (sug_w <1 && sug_h < 1 && ctx->hwnd_standalone)
2413 RECT r;
2414 GetClientRect(ctx->hwnd_standalone,&r);
2415 sug_w = r.right;
2416 sug_h = r.bottom;
2418 #ifdef EEL_LICE_WANTDOCK
2419 const int pos_offs = 4;
2420 #else
2421 const int pos_offs = 3;
2422 #endif
2424 if (sug_w < 16) sug_w=16;
2425 else if (sug_w > 8192) sug_w=8192;
2426 if (sug_h < 16) sug_h=16;
2427 else if (sug_h > 8192) sug_h=8192;
2429 if (!ctx->hwnd_standalone)
2431 #ifdef __APPLE__
2432 void *(*send_msg)(void *, void *) = (void *(*)(void *, void *))objc_msgSend;
2433 void (*send_msg_longparm)(void *, void *, long) = (void (*)(void *, void *, long))objc_msgSend; // long = NSInteger
2435 void *nsapp=send_msg( objc_getClass("NSApplication"), sel_getUid("sharedApplication"));
2436 send_msg_longparm(nsapp,sel_getUid("setActivationPolicy:"), 0);
2437 send_msg_longparm(nsapp,sel_getUid("activateIgnoringOtherApps:"), 1);
2439 #endif
2441 #ifdef EEL_LICE_STANDALONE_PARENT
2442 HWND par = EEL_LICE_STANDALONE_PARENT(opaque);
2443 #elif defined(_WIN32)
2444 HWND par=GetDesktopWindow();
2445 #else
2446 HWND par=NULL;
2447 #endif
2449 ctx->create_wnd(par,0);
2450 // resize client
2452 if (ctx->hwnd_standalone)
2454 int px=0,py=0;
2455 if (np >= pos_offs+2)
2457 px = (int) floor(parms[pos_offs][0] + 0.5);
2458 py = (int) floor(parms[pos_offs+1][0] + 0.5);
2459 #ifdef EEL_LICE_VALIDATE_RECT_ON_SCREEN
2460 RECT r = {px,py,px+sug_w,py+sug_h};
2461 EEL_LICE_VALIDATE_RECT_ON_SCREEN(r);
2462 px=r.left; py=r.top; sug_w = r.right-r.left; sug_h = r.bottom-r.top;
2463 #endif
2464 ctx->m_last_undocked_r.left = px;
2465 ctx->m_last_undocked_r.top = py;
2466 ctx->m_last_undocked_r.right = sug_w;
2467 ctx->m_last_undocked_r.bottom = sug_h;
2470 RECT r1,r2;
2471 GetWindowRect(ctx->hwnd_standalone,&r1);
2472 GetClientRect(ctx->hwnd_standalone,&r2);
2473 sug_w += (r1.right-r1.left) - r2.right;
2474 sug_h += abs(r1.bottom-r1.top) - r2.bottom;
2476 SetWindowPos(ctx->hwnd_standalone,NULL,px,py,sug_w,sug_h,(np >= pos_offs+2 ? 0:SWP_NOMOVE)|SWP_NOZORDER|SWP_NOACTIVATE);
2478 wantShow=true;
2479 #ifdef EEL_LICE_WANTDOCK
2480 if (np > 3) EEL_LICE_WANTDOCK(ctx,parms[3][0]);
2481 #endif
2482 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
2484 RECT r;
2485 GetClientRect(ctx->hwnd_standalone,&r);
2486 ctx->setup_frame(ctx->hwnd_standalone,r);
2488 #endif
2490 wantResize=false;
2492 if (!ctx->hwnd_standalone) return 0;
2494 if (np>0)
2496 EEL_STRING_MUTEXLOCK_SCOPE
2497 const char *title=EEL_STRING_GET_FOR_INDEX(parms[0][0],NULL);
2498 #ifdef EEL_STRING_DEBUGOUT
2499 if (!title) EEL_STRING_DEBUGOUT("gfx_init: invalid string identifier %f",parms[0][0]);
2500 #endif
2501 if (title&&*title)
2503 SetWindowText(ctx->hwnd_standalone,title);
2504 wantResize=false; // ignore resize if we're setting title
2507 if (wantShow)
2508 ShowWindow(ctx->hwnd_standalone,SW_SHOW);
2509 if (wantResize && np>2 && !(GetWindowLong(ctx->hwnd_standalone,GWL_STYLE)&WS_CHILD))
2511 RECT r1,r2;
2512 GetWindowRect(ctx->hwnd_standalone,&r1);
2513 GetClientRect(ctx->hwnd_standalone,&r2);
2514 const bool do_size = sug_w != r2.right || sug_h != r2.bottom;
2516 sug_w += (r1.right-r1.left) - r2.right;
2517 sug_h += abs(r1.bottom-r1.top) - r2.bottom;
2519 int px=0,py=0;
2520 const bool do_move=(np >= pos_offs+2);
2521 if (do_move)
2523 px = (int) floor(parms[pos_offs][0] + 0.5);
2524 py = (int) floor(parms[pos_offs+1][0] + 0.5);
2525 #ifdef EEL_LICE_VALIDATE_RECT_ON_SCREEN
2526 RECT r = {px,py,px+sug_w,py+sug_h};
2527 EEL_LICE_VALIDATE_RECT_ON_SCREEN(r);
2528 px=r.left; py=r.top; sug_w = r.right-r.left; sug_h = r.bottom-r.top;
2529 #endif
2531 if (do_size || do_move)
2532 SetWindowPos(ctx->hwnd_standalone,NULL,px,py,sug_w,sug_h,
2533 (do_size ? 0 : SWP_NOSIZE)|(do_move? 0:SWP_NOMOVE)|SWP_NOZORDER|SWP_NOACTIVATE);
2535 return 1;
2537 return 0;
2540 static EEL_F NSEEL_CGEN_CALL _gfx_screentoclient(void *opaque, EEL_F *x, EEL_F *y)
2542 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2543 if (ctx && ctx->hwnd_standalone)
2545 POINT pt={(int) *x, (int) *y};
2546 ScreenToClient(ctx->hwnd_standalone,&pt);
2547 *x = pt.x;
2548 *y = pt.y;
2549 return 1.0;
2551 return 0.0;
2554 static EEL_F NSEEL_CGEN_CALL _gfx_clienttoscreen(void *opaque, EEL_F *x, EEL_F *y)
2556 eel_lice_state *ctx=EEL_LICE_GET_CONTEXT(opaque);
2557 if (ctx && ctx->hwnd_standalone)
2559 POINT pt={(int) *x, (int) *y};
2560 ClientToScreen(ctx->hwnd_standalone,&pt);
2561 *x = pt.x;
2562 *y = pt.y;
2563 return 1.0;
2565 return 0.0;
2568 #endif // !EEL_LICE_STANDALONE_NOINITQUIT
2571 #ifndef WM_MOUSEWHEEL
2572 #define WM_MOUSEWHEEL 0x20A
2573 #endif
2574 #ifndef WM_MOUSEHWHEEL
2575 #define WM_MOUSEHWHEEL 0x20E
2576 #endif
2578 LRESULT WINAPI eel_lice_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2580 #ifdef WIN32
2581 static UINT Scroll_Message;
2582 static bool sm_init;
2583 if (!sm_init)
2585 sm_init=true;
2586 Scroll_Message = RegisterWindowMessage("MSWHEEL_ROLLMSG");
2588 if (Scroll_Message && uMsg == Scroll_Message)
2590 uMsg=WM_MOUSEWHEEL;
2591 wParam<<=16;
2593 #endif
2595 switch (uMsg)
2597 case WM_CREATE:
2599 #ifdef _WIN32
2600 LPCREATESTRUCT lpcs= (LPCREATESTRUCT )lParam;
2601 eel_lice_state *ctx=(eel_lice_state*)lpcs->lpCreateParams;
2602 SetWindowLongPtr(hwnd,GWLP_USERDATA,(LPARAM)lpcs->lpCreateParams);
2603 #else
2604 eel_lice_state *ctx=(eel_lice_state*)lParam;
2605 SetWindowLongPtr(hwnd,GWLP_USERDATA,lParam);
2606 SetWindowLong(hwnd,GWL_EXSTYLE, GetWindowLong(hwnd,GWL_EXSTYLE) | WS_EX_ACCEPTFILES);
2607 #endif
2608 ctx->m_kb_queue_valid=0;
2609 ctx->hwnd_standalone=hwnd;
2611 return 0;
2612 #ifndef _WIN32
2613 case WM_CLOSE:
2614 DestroyWindow(hwnd);
2615 return 0;
2616 #endif
2617 case WM_DESTROY:
2619 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
2620 if (ctx)
2622 #ifdef EEL_LICE_WANTDOCK
2623 EEL_LICE_WANTDOCK(ctx,0);
2624 #endif
2625 ctx->hwnd_standalone=NULL;
2628 return 0;
2629 case WM_ACTIVATE:
2631 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
2632 if (ctx) memset(&ctx->hwnd_standalone_kb_state,0,sizeof(ctx->hwnd_standalone_kb_state));
2634 break;
2635 case WM_SETCURSOR:
2637 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2638 if (ctx && ctx->m_cursor)
2640 POINT p;
2641 GetCursorPos(&p);
2642 ScreenToClient(hwnd, &p);
2643 RECT r;
2644 GetClientRect(hwnd, &r);
2645 if (PtInRect(&r,p))
2647 SetCursor(ctx->m_cursor);
2648 return TRUE;
2652 break;
2653 #ifdef EEL_LICE_WANTDOCK
2654 case WM_CONTEXTMENU:
2656 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2657 if (ctx)
2659 char title[512], buf[1024];
2660 GetWindowText(hwnd, title, sizeof(title)-1);
2661 if (!title[0]) strcpy(title, "ReaScript");
2663 HMENU hm=CreatePopupMenu();
2664 int pos=0;
2666 int flag=((EEL_LICE_ISDOCKED(ctx)&1) ? MF_CHECKED : 0);
2667 snprintf(buf, sizeof(buf), "Dock %s window in Docker", title);
2668 InsertMenu(hm, pos++, MF_BYPOSITION|MF_STRING|flag, ID_DOCKWINDOW, buf);
2669 snprintf(buf, sizeof(buf), "Close %s window", title);
2670 InsertMenu(hm, pos++, MF_BYPOSITION|MF_STRING, IDCANCEL, buf);
2672 POINT pt;
2673 GetCursorPos(&pt);
2674 TrackPopupMenu(hm, 0, pt.x, pt.y, 0, hwnd, NULL);
2675 DestroyMenu(hm);
2678 return 0;
2679 #endif
2680 case WM_COMMAND:
2681 switch (LOWORD(wParam))
2683 #ifdef EEL_LICE_WANTDOCK
2684 case ID_DOCKWINDOW:
2686 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2687 if (ctx) EEL_LICE_WANTDOCK(ctx, EEL_LICE_ISDOCKED(ctx)^1);
2689 return 0;
2690 #endif
2691 case IDCANCEL:
2692 DestroyWindow(hwnd);
2693 return 0;
2695 break;
2696 case WM_USER+1001:
2697 if (wParam == 0xdddd && lParam)
2699 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2700 if (ctx)
2702 ctx->m_ddrop_files.Empty(true,free);
2703 const char *r = (const char *)lParam;
2704 while (*r)
2706 ctx->m_ddrop_files.Add(strdup(r));
2707 r += strlen(r)+1;
2711 return 0;
2712 case WM_DROPFILES:
2714 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2715 if (ctx && wParam)
2717 ctx->m_ddrop_files.Empty(true,free);
2719 HDROP hDrop = (HDROP) wParam;
2720 const int n=DragQueryFile(hDrop,-1,NULL,0);
2721 for (int x=0;x<n;x++)
2723 char buf[4096];
2724 buf[0]=0;
2725 DragQueryFile(hDrop,x,buf,sizeof(buf));
2726 if (buf[0]) ctx->m_ddrop_files.Add(strdup(buf));
2728 DragFinish(hDrop);
2731 return 0;
2732 case WM_MOUSEHWHEEL:
2733 case WM_MOUSEWHEEL:
2735 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
2736 if (ctx)
2738 EEL_F *p= uMsg==WM_MOUSEHWHEEL ? ctx->m_mouse_hwheel : ctx->m_mouse_wheel;
2739 if (p) *p += (EEL_F) (short)HIWORD(wParam);
2742 return -1;
2743 #ifdef _WIN32
2744 case WM_SYSKEYDOWN:
2745 case WM_SYSKEYUP:
2746 #endif
2747 case WM_KEYDOWN:
2748 case WM_KEYUP:
2749 case WM_CHAR:
2751 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
2752 #ifdef __APPLE__
2754 int f=0;
2755 wParam = SWELL_MacKeyToWindowsKeyEx(NULL,&f,1);
2756 lParam=f;
2758 #endif
2760 bool hadAltAdj=false;
2761 int a=eel_lice_key_xlate(uMsg,(int)wParam,(int)lParam, &hadAltAdj);
2762 if (a == -1) return 0;
2763 #ifdef _WIN32
2764 if (!a && (uMsg == WM_KEYUP || uMsg == WM_SYSKEYUP))
2766 // will not end up in queue, just for state tracking
2767 if (wParam >= 'A' && wParam <= 'Z') a=(int)wParam + 'a' - 'A';
2768 else a = (int)MapVirtualKey((UINT)wParam,2/*MAPVK_VK_TO_CHAR*/);
2770 #endif
2771 const int mask = hadAltAdj ? ~256 : ~0;
2773 if (a & mask)
2775 int a_no_alt = (a&mask);
2776 if (a_no_alt >= ('u'<<24) && a_no_alt < ('v'<<24))
2777 a_no_alt &= 0xffffff;
2778 const int lowera = a_no_alt >= 1 && a_no_alt < 27 ? (a_no_alt+'a'-1) : a_no_alt >= 'A' && a_no_alt <= 'Z' ? a_no_alt+'a'-'A' : a_no_alt;
2780 int *st = ctx->hwnd_standalone_kb_state;
2782 const int n = sizeof(ctx->hwnd_standalone_kb_state) / sizeof(ctx->hwnd_standalone_kb_state[0]);
2783 int zp=n-1,x;
2785 for (x=0;x<n && st[x] != lowera;x++) if (x < zp && !st[x]) zp=x;
2787 if (uMsg==WM_KEYUP
2788 #ifdef _WIN32
2789 ||uMsg == WM_SYSKEYUP
2790 #endif
2793 if (x<n) st[x]=0;
2795 else if (x==n) // key not already down
2797 st[zp]=lowera;
2801 if (a && uMsg != WM_KEYUP
2802 #ifdef _WIN32
2803 && uMsg != WM_SYSKEYUP
2804 #endif
2807 // add to queue
2808 const int qsize = sizeof(ctx->m_kb_queue)/sizeof(ctx->m_kb_queue[0]);
2809 if (ctx->m_kb_queue_valid>=qsize) // queue full, dump an old event!
2811 ctx->m_kb_queue_valid--;
2812 ctx->m_kb_queue_pos++;
2814 ctx->m_kb_queue[(ctx->m_kb_queue_pos + ctx->m_kb_queue_valid++) & (qsize-1)] = a;
2815 if (ctx->m_last_menu_cnt && (GetTickCount()-ctx->m_last_menu_time)>250) ctx->m_last_menu_cnt = 0;
2819 return 0;
2820 case WM_LBUTTONDBLCLK:
2821 case WM_RBUTTONDBLCLK:
2822 case WM_MBUTTONDBLCLK:
2823 case WM_RBUTTONDOWN:
2824 case WM_MBUTTONDOWN:
2825 case WM_LBUTTONDOWN:
2827 POINT p = { (short)LOWORD(lParam), (short)HIWORD(lParam) };
2828 RECT r;
2829 GetClientRect(hwnd, &r);
2830 if (p.x >= r.left && p.x < r.right && p.y >= r.top && p.y < r.bottom)
2832 if (GetCapture()!=hwnd) SetFocus(hwnd);
2833 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2834 if (ctx)
2836 if (GetCapture()!=hwnd) SetCapture(hwnd);
2837 int f = 0;
2838 if (uMsg == WM_LBUTTONDBLCLK || uMsg == WM_LBUTTONDOWN) f=0x10001;
2839 else if (uMsg == WM_RBUTTONDBLCLK || uMsg == WM_RBUTTONDOWN) f=0x20002;
2840 else if (uMsg == WM_MBUTTONDBLCLK || uMsg == WM_MBUTTONDOWN) f=0x40040;
2842 if (GetAsyncKeyState(VK_CONTROL)&0x8000) f|=4;
2843 if (GetAsyncKeyState(VK_SHIFT)&0x8000) f|=8;
2844 if (GetAsyncKeyState(VK_MENU)&0x8000) f|=16;
2845 if (GetAsyncKeyState(VK_LWIN)&0x8000) f|=32;
2847 ctx->m_has_cap|=f;
2848 if (ctx->m_last_menu_cnt && (GetTickCount()-ctx->m_last_menu_time)>250) ctx->m_last_menu_cnt = 0;
2852 return 1;
2853 case WM_LBUTTONUP:
2854 case WM_RBUTTONUP:
2855 case WM_MBUTTONUP:
2856 case WM_CAPTURECHANGED:
2858 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
2859 if (ctx)
2861 if (uMsg == WM_CAPTURECHANGED)
2863 ctx->m_has_cap &= 0xffff;
2865 else
2867 if (ctx->m_last_menu_cnt && (GetTickCount()-ctx->m_last_menu_time)>250) ctx->m_last_menu_cnt = 0;
2868 if (uMsg == WM_LBUTTONUP) ctx->m_has_cap &= ~0x10000;
2869 else if (uMsg == WM_RBUTTONUP) ctx->m_has_cap &= ~0x20000;
2870 else if (uMsg == WM_MBUTTONUP) ctx->m_has_cap &= ~0x40000;
2872 if (!(ctx->m_has_cap & 0xf0000))
2874 ReleaseCapture();
2879 return 1;
2880 #ifdef _WIN32
2881 case WM_GETDLGCODE:
2882 if (GetWindowLong(hwnd,GWL_STYLE)&WS_CHILD) return DLGC_WANTALLKEYS;
2883 break;
2884 case 0x02E0: //WM_DPICHANGED
2885 if (!(GetWindowLong(hwnd,GWL_STYLE)&WS_CHILD))
2887 RECT *prcNewWindow = (RECT*)lParam;
2888 SetWindowPos(hwnd,
2889 NULL,
2890 prcNewWindow ->left,
2891 prcNewWindow ->top,
2892 prcNewWindow->right - prcNewWindow->left,
2893 prcNewWindow->bottom - prcNewWindow->top,
2894 SWP_NOZORDER | SWP_NOACTIVATE);
2896 break;
2897 #endif
2898 case WM_SIZE:
2899 // fall through
2900 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
2901 case WM_MOVE:
2902 if (uMsg != WM_SIZE || wParam != SIZE_MINIMIZED)
2904 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
2905 if (ctx
2906 #ifdef EEL_LICE_ISDOCKED
2907 && !(GetWindowLong(hwnd,GWL_STYLE)&WS_CHILD)
2908 #endif
2911 RECT r;
2912 GetWindowRect(hwnd,&ctx->m_last_undocked_r);
2913 GetClientRect(hwnd,&r);
2914 if (ctx->m_last_undocked_r.bottom < ctx->m_last_undocked_r.top) ctx->m_last_undocked_r.top = ctx->m_last_undocked_r.bottom;
2915 ctx->m_last_undocked_r.right = r.right;
2916 ctx->m_last_undocked_r.bottom = r.bottom;
2920 #endif
2922 break;
2924 case WM_PAINT:
2926 PAINTSTRUCT ps;
2927 if (BeginPaint(hwnd,&ps))
2929 eel_lice_state *ctx=(eel_lice_state*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
2930 if (ctx && ctx->m_framebuffer &&
2931 LICE_FUNCTION_VALID(LICE__GetDC) && LICE_FUNCTION_VALID(LICE__GetWidth) && LICE_FUNCTION_VALID(LICE__GetHeight))
2933 int w = LICE__GetWidth(ctx->m_framebuffer);
2934 int h = LICE__GetHeight(ctx->m_framebuffer);
2935 #ifdef __APPLE__
2936 if (*ctx->m_gfx_ext_retina > 1.0)
2938 StretchBlt(ps.hdc,0,0,w/2,h/2,LICE__GetDC(ctx->m_framebuffer),0,0,w,h,SRCCOPY);
2940 else
2941 #endif
2942 BitBlt(ps.hdc,0,0,w,h,LICE__GetDC(ctx->m_framebuffer),0,0,SRCCOPY);
2944 EndPaint(hwnd,&ps);
2947 return 0;
2948 case WM_GETMINMAXINFO:
2950 LPMINMAXINFO p=(LPMINMAXINFO)lParam;
2951 if (p->ptMinTrackSize.x > 10) p->ptMinTrackSize.x = 10;
2952 if (p->ptMinTrackSize.y > 10) p->ptMinTrackSize.y = 10;
2954 return 0;
2957 #ifdef _WIN32
2958 return DefWindowProcW(hwnd,uMsg,wParam,lParam);
2959 #else
2960 return DefWindowProc(hwnd,uMsg,wParam,lParam);
2961 #endif
2966 void eel_lice_register_standalone(HINSTANCE hInstance, const char *classname, HWND hwndPar, HICON icon)
2968 eel_lice_standalone_classname=classname && *classname ? classname : "EEL_LICE_gfx_standalone";
2969 #ifdef _WIN32
2970 static bool reg;
2971 if (!reg)
2973 eel_lice_hinstance=hInstance;
2974 WCHAR tmp[256];
2975 int x = 0;
2976 while (eel_lice_standalone_classname[x])
2978 if (WDL_NOT_NORMALLY(x == 255)) break;
2979 tmp[x] = eel_lice_standalone_classname[x];
2980 x++;
2982 tmp[x]=0;
2984 WNDCLASSW wc={CS_DBLCLKS,eel_lice_wndproc,0,0,hInstance,icon,LoadCursor(NULL,IDC_ARROW), NULL, NULL,tmp};
2985 RegisterClassW(&wc);
2986 reg = true;
2988 #endif
2990 #ifndef EEL_LICE_NO_REGISTER
2991 // gfx_init(title[, w,h, flags])
2992 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
2993 NSEEL_addfunc_varparm("gfx_init",1,NSEEL_PProc_THIS,&_gfx_init);
2994 NSEEL_addfunc_retptr("gfx_quit",1,NSEEL_PProc_THIS,&_gfx_quit);
2996 NSEEL_addfunc_retval("gfx_screentoclient",2,NSEEL_PProc_THIS,&_gfx_screentoclient);
2997 NSEEL_addfunc_retval("gfx_clienttoscreen",2,NSEEL_PProc_THIS,&_gfx_clienttoscreen);
2999 #endif
3000 #ifdef EEL_LICE_WANTDOCK
3001 NSEEL_addfunc_varparm("gfx_dock",1,NSEEL_PProc_THIS,&_gfx_dock);
3002 #endif
3004 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
3005 NSEEL_addfunc_retptr("gfx_update",1,NSEEL_PProc_THIS,&_gfx_update);
3006 #endif
3008 NSEEL_addfunc_varparm("gfx_getchar",1,NSEEL_PProc_THIS,&_gfx_getchar);
3009 #endif
3013 #endif
3015 #endif//!EEL_LICE_API_ONLY
3020 #ifdef DYNAMIC_LICE
3021 static WDL_STATICFUNC_UNUSED void eel_lice_initfuncs(void *(*getFunc)(const char *name))
3023 if (!getFunc) return;
3025 *(void **)&__LICE_CreateBitmap = getFunc("LICE_CreateBitmap");
3026 *(void **)&LICE_Clear = getFunc("LICE_Clear");
3027 *(void **)&LICE_Line = getFunc("LICE_LineInt");
3028 *(void **)&LICE_ClipLine = getFunc("LICE_ClipLine");
3029 *(void **)&LICE_FillRect = getFunc("LICE_FillRect");
3030 *(void **)&LICE_DrawRect = getFunc("LICE_DrawRect");
3031 *(void **)&LICE_PutPixel = getFunc("LICE_PutPixel");
3032 *(void **)&LICE_GetPixel = getFunc("LICE_GetPixel");
3033 *(void **)&LICE_DrawText = getFunc("LICE_DrawText");
3034 *(void **)&LICE_DrawChar = getFunc("LICE_DrawChar");
3035 *(void **)&LICE_MeasureText = getFunc("LICE_MeasureText");
3036 *(void **)&LICE_LoadImage = getFunc("LICE_LoadImage");
3037 *(void **)&LICE__GetDC = getFunc("LICE__GetDC");
3038 *(void **)&LICE__Destroy = getFunc("LICE__Destroy");
3039 *(void **)&LICE__GetWidth = getFunc("LICE__GetWidth");
3040 *(void **)&LICE__GetHeight = getFunc("LICE__GetHeight");
3041 *(void **)&LICE__resize = getFunc("LICE__resize");
3042 *(void **)&LICE_Blur = getFunc("LICE_Blur");
3043 *(void **)&LICE_RotatedBlit = getFunc("LICE_RotatedBlit");
3044 *(void **)&LICE_ScaledBlit = getFunc("LICE_ScaledBlit");
3045 *(void **)&LICE_Circle = getFunc("LICE_Circle");
3046 *(void **)&LICE_FillCircle = getFunc("LICE_FillCircle");
3047 *(void **)&LICE_FillTriangle=getFunc("LICE_FillTriangle");
3048 *(void **)&LICE_FillConvexPolygon=getFunc("LICE_FillConvexPolygon");
3049 *(void **)&LICE_RoundRect = getFunc("LICE_RoundRect");
3050 *(void **)&LICE_Arc = getFunc("LICE_Arc");
3052 *(void **)&LICE_MultiplyAddRect = getFunc("LICE_MultiplyAddRect");
3053 *(void **)&LICE_GradRect = getFunc("LICE_GradRect");
3054 *(void **)&LICE_TransformBlit2 = getFunc("LICE_TransformBlit2");
3055 *(void **)&LICE_DeltaBlit = getFunc("LICE_DeltaBlit");
3057 *(void **)&LICE__DestroyFont = getFunc("LICE__DestroyFont");
3058 *(void **)&LICE_CreateFont = getFunc("LICE_CreateFont");
3059 *(void **)&LICE__SetFromHFont = getFunc("LICE__SetFromHFont2");
3061 *(void **)&LICE__SetTextColor = getFunc("LICE__SetTextColor");
3062 *(void **)&LICE__SetTextCombineMode = getFunc("LICE__SetTextCombineMode");
3063 *(void **)&LICE__DrawText = getFunc("LICE__DrawText");
3065 #endif
3067 #ifdef EEL_WANT_DOCUMENTATION
3069 #ifdef EELSCRIPT_LICE_MAX_IMAGES
3070 #define MKSTR2(x) #x
3071 #define MKSTR(x) MKSTR2(x)
3072 #define EEL_LICE_DOC_MAXHANDLE MKSTR(EELSCRIPT_LICE_MAX_IMAGES-1)
3073 #else
3074 #define EEL_LICE_DOC_MAXHANDLE "127"
3075 #endif
3078 static const char *eel_lice_function_reference =
3079 #ifdef EEL_LICE_WANT_STANDALONE
3080 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
3081 #ifdef EEL_LICE_WANTDOCK
3082 "gfx_init\t\"name\"[,width,height,dockstate,xpos,ypos]\tInitializes the graphics window with title name. Suggested width and height can be specified. If window is already open, a non-empty name will re-title window, or an empty title will resize window. \n\n"
3083 #else
3084 "gfx_init\t\"name\"[,width,height,xpos,ypos]\tInitializes the graphics window with title name. Suggested width and height can be specified. If window is already open, a non-empty name will re-title window, or an empty title will resize window.\n\n"
3085 #endif
3086 "Once the graphics window is open, gfx_update() should be called periodically. \0"
3087 "gfx_quit\t\tCloses the graphics window.\0"
3088 #endif
3089 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
3090 "gfx_update\t\tUpdates the graphics display, if opened\0"
3091 #endif
3092 #endif
3093 #ifdef EEL_LICE_WANTDOCK
3094 "gfx_dock\tv[,wx,wy,ww,wh]\tCall with v=-1 to query docked state, otherwise v>=0 to set docked state. State is &1 if docked, second byte is docker index (or last docker index if undocked). If wx-wh are specified, they will be filled with the undocked window position/size\0"
3095 #endif
3096 "gfx_aaaaa\t\t"
3097 "The following global variables are special and will be used by the graphics system:\n\n\3"
3098 // we depend on the formatting here -- following gfx_aaaaa, search for \4[gfx_*|mouse_*]- for syntax highlight etc
3099 "\4gfx_r - current red component (0..1) used by drawing operations.\n"
3100 "\4gfx_g - current green component (0..1) used by drawing operations.\n"
3101 "\4gfx_b - current blue component (0..1) used by drawing operations.\n"
3102 "\4gfx_a2 - current alpha component (0..1) used by drawing operations when writing solid colors (normally ignored but useful when creating transparent images).\n"
3103 "\4gfx_a - alpha for drawing (1=normal).\n"
3104 "\4gfx_mode - blend mode for drawing. Set mode to 0 for default options. Add 1.0 for additive blend mode (if you wish to do subtractive, set gfx_a to negative and use gfx_mode as additive). Add 2.0 to disable source alpha for gfx_blit(). Add 4.0 to disable filtering for gfx_blit(). \n"
3105 "\4gfx_w - width of the UI framebuffer. \n"
3106 "\4gfx_h - height of the UI framebuffer. \n"
3107 "\4gfx_x - current graphics position X. Some drawing functions use as start position and update. \n"
3108 "\4gfx_y - current graphics position Y. Some drawing functions use as start position and update. \n"
3109 "\4gfx_clear - if greater than -1.0, framebuffer will be cleared to that color. the color for this one is packed RGB (0..255), i.e. red+green*256+blue*65536. The default is 0 (black). \n"
3110 "\4gfx_dest - destination for drawing operations, -1 is main framebuffer, set to 0.." EEL_LICE_DOC_MAXHANDLE " to have drawing operations go to an offscreen buffer (or loaded image).\n"
3111 "\4gfx_texth - the (READ-ONLY) height of a line of text in the current font. Do not modify this variable.\n"
3112 "\4gfx_ext_retina - to support hidpi/retina, callers should set to 1.0 on initialization, this value will be updated to value greater than 1.0 (such as 2.0) if retina/hidpi. On macOS gfx_w/gfx_h/etc will be doubled, but on other systems gfx_w/gfx_h will remain the same and gfx_ext_retina is a scaling hint for drawing.\n"
3113 "\4mouse_x - current X coordinate of the mouse relative to the graphics window.\n"
3114 "\4mouse_y - current Y coordinate of the mouse relative to the graphics window.\n"
3115 "\4mouse_wheel - wheel position, will change typically by 120 or a multiple thereof, the caller should clear the state to 0 after reading it.\n"
3116 "\4mouse_hwheel - horizontal wheel positions, will change typically by 120 or a multiple thereof, the caller should clear the state to 0 after reading it.\n"
3117 "\4mouse_cap - a bitfield of mouse and keyboard modifier state. Note that a script must call gfx_getchar() at least once in order to get modifier state when the mouse is not captured by the window. Bitfield bits:\3"
3118 "\4" "1: left mouse button\n"
3119 "\4" "2: right mouse button\n"
3120 "\4" "4: Control (Windows) or Command (macOS) key\n"
3121 "\4" "8: Shift key\n"
3122 "\4" "16: Alt (Windows) or Option (macOS) key\n"
3123 "\4" "32: Windows (Windows) or Control (macOS) key\n"
3124 "\4" "64: middle mouse button\n"
3125 "\2"
3126 "\2\0"
3128 "gfx_getchar\t[char, unichar]\tIf char is 0 or omitted, returns a character from the keyboard queue, or 0 if no character is available, or -1 if the graphics window is not open. "
3129 "If char is specified and nonzero, that character's status will be checked, and the function will return greater than 0 if it is pressed. Note that calling gfx_getchar() at least once causes mouse_cap to reflect keyboard modifiers even when the mouse is not captured.\n\n"
3130 "Common values are standard ASCII, such as 'a', 'A', '=' and '1', but for many keys multi-byte values are used, including 'home', 'up', 'down', 'left', 'rght', 'f1'.. 'f12', 'pgup', 'pgdn', 'ins', and 'del'. \n\n"
3131 "Modified and special keys can also be returned, including:\3\n"
3132 "\4Ctrl/Cmd+A..Ctrl+Z as 1..26\n"
3133 "\4Ctrl/Cmd+Alt+A..Z as 257..282\n"
3134 "\4Alt+A..Z as 'A'+256..'Z'+256\n"
3135 "\4" "27 for ESC\n"
3136 "\4" "13 for Enter\n"
3137 "\4' ' for space\n"
3138 "\4" "65536 for query of special flags, returns: &1 (supported), &2=window has focus, &4=window is visible, &8=mouse click would hit window. 65537 queries special flags but does not do the mouse click hit testing (faster).\n"
3139 "\4If unichar is specified, it will be set to the unicode value of the key if available (and the return value may be the unicode value or a raw key value as described above, depending). If unichar is not specified, unicode codepoints greater than 255 will be returned as 'u'<<24 + value\n"
3140 "\2\0"
3142 "gfx_showmenu\t\"str\"\tShows a popup menu at gfx_x,gfx_y. str is a list of fields separated by | characters. "
3143 "Each field represents a menu item.\nFields can start with special characters:\n\n"
3144 "# : grayed out\n"
3145 "! : checked\n"
3146 "> : this menu item shows a submenu\n"
3147 "< : last item in the current submenu\n\n"
3148 "An empty field will appear as a separator in the menu. "
3149 "gfx_showmenu returns 0 if the user selected nothing from the menu, 1 if the first field is selected, etc.\nExample:\n\n"
3150 "gfx_showmenu(\"first item, followed by separator||!second item, checked|>third item which spawns a submenu|#first item in submenu, grayed out|<second and last item in submenu|fourth item in top menu\")\0"
3152 #ifdef EEL_LICE_LOADTHEMECURSOR
3153 "gfx_setcursor\tresource_id,custom_cursor_name\tSets the mouse cursor to resource_id and/or custom_cursor_name. \0" // REAPER has extended help elsewhere
3154 #else
3155 "gfx_setcursor\tresource_id\tSets the mouse cursor. resource_id is a value like 32512 (for an arrow cursor).\0"
3156 #endif
3157 "gfx_lineto\tx,y[,aa]\tDraws a line from gfx_x,gfx_y to x,y. If aa is 0.5 or greater, then antialiasing is used. Updates gfx_x and gfx_y to x,y.\0"
3158 "gfx_line\tx,y,x2,y2[,aa]\tDraws a line from x,y to x2,y2, and if aa is not specified or 0.5 or greater, it will be antialiased. \0"
3159 "gfx_rectto\tx,y\tFills a rectangle from gfx_x,gfx_y to x,y. Updates gfx_x,gfx_y to x,y. \0"
3160 "gfx_rect\tx,y,w,h[,filled]\tFills a rectangle at x,y, w,h pixels in dimension, filled by default. \0"
3161 "gfx_setpixel\tr,g,b\tWrites a pixel of r,g,b to gfx_x,gfx_y.\0"
3162 "gfx_getpixel\tr,g,b\tGets the value of the pixel at gfx_x,gfx_y into r,g,b. \0"
3163 "gfx_drawnumber\tn,ndigits\tDraws the number n with ndigits of precision to gfx_x, gfx_y, and updates gfx_x to the right side of the drawing. The text height is gfx_texth.\0"
3164 "gfx_drawchar\tchar\tDraws the character (can be a numeric ASCII code as well), to gfx_x, gfx_y, and moves gfx_x over by the size of the character.\0"
3165 "gfx_drawstr\t\"str\"[,flags,right,bottom]\tDraws a string at gfx_x, gfx_y, and updates gfx_x/gfx_y so that subsequent draws will occur in a similar place.\n\n"
3166 "If flags, right ,bottom passed in:\n"
3167 "\4flags&1: center horizontally\n"
3168 "\4flags&2: right justify\n"
3169 "\4flags&4: center vertically\n"
3170 "\4flags&8: bottom justify\n"
3171 "\4flags&256: ignore right/bottom, otherwise text is clipped to (gfx_x, gfx_y, right, bottom)\0"
3172 "gfx_measurestr\t\"str\",&w,&h\tMeasures the drawing dimensions of a string with the current font (as set by gfx_setfont). \0"
3173 "gfx_measurechar\tcharacter,&w,&h\tMeasures the drawing dimensions of a character with the current font (as set by gfx_setfont). \0"
3174 "gfx_setfont\tidx[,\"fontface\", sz, flags]\tCan select a font and optionally configure it. idx=0 for default bitmapped font, no configuration is possible for this font. idx=1..16 for a configurable font, specify fontface such as \"Arial\", sz of 8-100, and optionally specify flags, which is a multibyte character, which can include 'i' for italics, 'u' for underline, or 'b' for bold. These flags may or may not be supported depending on the font and OS. After calling gfx_setfont(), gfx_texth may be updated to reflect the new average line height.\0"
3175 "gfx_getfont\t[#str]\tReturns current font index. If a string is passed, it will receive the actual font face used by this font, if available.\0"
3176 "gfx_printf\t\"format\"[, ...]\tFormats and draws a string at gfx_x, gfx_y, and updates gfx_x/gfx_y accordingly (the latter only if the formatted string contains newline). For more information on format strings, see sprintf()\0"
3177 "gfx_blurto\tx,y\tBlurs the region of the screen between gfx_x,gfx_y and x,y, and updates gfx_x,gfx_y to x,y.\0"
3178 "gfx_blit\tsource[, scale, rotation, srcx, srcy, srcw, srch, destx, desty, destw, desth, rotxoffs, rotyoffs]\t"
3179 "Copies from source (-1 = main framebuffer, or an image from gfx_loadimg() etc), using current opacity and copy mode (set with gfx_a, gfx_mode).\n"
3180 "If destx/desty are not specified, gfx_x/gfx_y will be used as the destination position.\n"
3181 "scale (1.0 is unscaled) will be used only if destw/desth are not specified.\n"
3182 "rotation is an angle in radians\n"
3183 "srcx/srcy/srcw/srch specify the source rectangle (if omitted srcw/srch default to image size)\n"
3184 "destx/desty/destw/desth specify destination rectangle (if not specified destw/desth default to srcw/srch * scale). \0"
3185 "gfx_blitext\tsource,coordinatelist,rotation\tDeprecated, use gfx_blit instead.\0"
3186 "gfx_getimgdim\timage,w,h\tRetreives the dimensions of image (representing a filename: index number) into w and h. Sets these values to 0 if an image failed loading (or if the filename index is invalid).\0"
3187 "gfx_setimgdim\timage,w,h\tResize image referenced by index 0.." EEL_LICE_DOC_MAXHANDLE ", width and height must be 0-8192. The contents of the image will be undefined after the resize.\0"
3188 "gfx_loadimg\timage,\"filename\"\tLoad image from filename into slot 0.." EEL_LICE_DOC_MAXHANDLE " specified by image. Returns the image index if success, otherwise -1 if failure. The image will be resized to the dimensions of the image file. \0"
3189 "gfx_gradrect\tx,y,w,h, r,g,b,a[, drdx, dgdx, dbdx, dadx, drdy, dgdy, dbdy, dady]\tFills a gradient rectangle with the color and alpha specified. drdx-dadx reflect the adjustment (per-pixel) applied for each pixel moved to the right, drdy-dady are the adjustment applied for each pixel moved toward the bottom. Normally drdx=adjustamount/w, drdy=adjustamount/h, etc.\0"
3190 "gfx_muladdrect\tx,y,w,h,mul_r,mul_g,mul_b[,mul_a,add_r,add_g,add_b,add_a]\tMultiplies each pixel by mul_* and adds add_*, and updates in-place. Useful for changing brightness/contrast, or other effects.\0"
3191 "gfx_deltablit\tsrcimg,srcs,srct,srcw,srch,destx,desty,destw,desth,dsdx,dtdx,dsdy,dtdy,dsdxdy,dtdxdy[,usecliprect=1]\tBlits from srcimg(srcx,srcy,srcw,srch) "
3192 "to destination (destx,desty,destw,desth). Source texture coordinates are s/t, dsdx represents the change in s coordinate for each x pixel"
3193 ", dtdy represents the change in t coordinate for each y pixel, etc. dsdxdy represents the change in dsdx for each line. If usecliprect is specified and 0, then srcw/srch are ignored.\0"
3194 "gfx_transformblit\tsrcimg,destx,desty,destw,desth,div_w,div_h,table\tBlits to destination at (destx,desty), size (destw,desth). "
3195 "div_w and div_h should be 2..64, and table should point to a table of 2*div_w*div_h values (this table must not cross a "
3196 "65536 item boundary). Each pair in the table represents a S,T coordinate in the source image, and the table is treated as "
3197 "a left-right, top-bottom list of texture coordinates, which will then be rendered to the destination.\0"
3198 "gfx_circle\tx,y,r[,fill,antialias]\tDraws a circle, optionally filling/antialiasing. \0"
3199 "gfx_triangle\tx1,y1,x2,y2,x3,y3[x4,y4...]\tDraws a filled triangle, or any convex polygon. \0"
3200 "gfx_roundrect\tx,y,w,h,radius[,antialias]\tDraws a rectangle with rounded corners. \0"
3201 "gfx_arc\tx,y,r,ang1,ang2[,antialias]\tDraws an arc of the circle centered at x,y, with ang1/ang2 being specified in radians.\0"
3202 "gfx_set\tr[,g,b,a,mode,dest,a2]\tSets gfx_r/gfx_g/gfx_b/gfx_a/gfx_mode/gfx_a2, sets gfx_dest if final parameter specified\0"
3203 "gfx_getdropfile\tidx[,#str]\tEnumerates any drag/dropped files. call gfx_dropfile(-1) to clear the list when finished. Returns 1 if idx is valid, 0 if idx is out of range.\0"
3205 #ifdef EEL_LICE_WANT_STANDALONE
3206 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
3207 "gfx_clienttoscreen\tx,y\tConverts client coordinates x,y to screen coordinates.\0"
3208 "gfx_screentoclient\tx,y\tConverts screen coordinates x,y to client coordinates.\0"
3209 #endif
3210 #endif
3212 #ifdef EELSCRIPT_LICE_MAX_IMAGES
3213 #undef MKSTR2
3214 #undef MKSTR
3215 #endif
3216 #endif
3218 #endif//_EEL_LICE_H_