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();
11 #define LICE_IBitmap LICE_IBitmap_disabledAPI
12 #include "../lice/lice.h"
15 typedef void LICE_IBitmap
; // prevent us from using LICE api directly, in case it ever changes
19 #ifdef EEL_LICE_API_ONLY
20 #define EEL_LICE_FUNCDEF extern
22 #define EEL_LICE_FUNCDEF
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
,
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
,
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
);
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
)
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
)
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
);
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
);
164 static LICE_IFont
*LICE_CreateFont()
166 return new LICE_CachedFont();
168 static void LICE__DestroyFont(LICE_IFont
*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
);
186 #include "../wdlutf8.h"
193 eel_lice_state(NSEEL_VMCTX vm
, void *ctx
, int image_slots
, int font_slots
);
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
214 img_shared_state(LICE_IBitmap
*b
) : bm(b
), refcnt(1) { }
218 if (wdl_atomic_decr(&refcnt
)==0) delete this;
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
);
234 s_img_cache_mutex
.Leave();
235 if (LICE_FUNCTION_VALID(LICE__Destroy
))
240 static WDL_StringKeyedArray
<img_shared_state
*> s_img_cache
;
241 static WDL_Mutex s_img_cache_mutex
;
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
))
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
264 0.0f
,0.0f
,(float)bmw
,(float)bmh
,
265 1.0f
,LICE_BLIT_MODE_COPY
);
272 bool do_load_image(int img
, const char *str
);
274 WDL_TypedBuf
<img_state
> m_gfx_images
;
275 struct gfxFontStruct
{
277 char last_fontname
[128];
278 char actual_fontname
[128];
284 WDL_TypedBuf
<gfxFontStruct
> m_gfx_fonts
;
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)
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
;
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
;
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
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();
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
);
376 unsigned char m_kb_queue_valid
;
377 unsigned char m_kb_queue_pos
;
380 #ifdef EEL_LICE_LOADTHEMECURSOR
381 char m_cursor_name
[128];
384 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
385 RECT m_last_undocked_r
;
390 DWORD m_last_menu_time
;
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
));
413 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
414 memset(&m_last_undocked_r
,0,sizeof(m_last_undocked_r
));
417 #ifdef EEL_LICE_LOADTHEMECURSOR
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;
457 m_has_had_getch
=false;
458 m_last_menu_time
= GetTickCount() - 100000;
461 eel_lice_state::~eel_lice_state()
463 #ifdef EEL_LICE_WANT_STANDALONE
464 if (hwnd_standalone
) DestroyWindow(hwnd_standalone
);
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;
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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);
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
);
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
);
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
)
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
623 ctx
->gfx_transformblit(parms
,divw
,divh
,d
);
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
);
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
);
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
);
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
);
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
);
665 EEL_F
*p
[3]={str
,xOut
,yOut
};
666 ctx
->gfx_drawstr(opaque
,p
,3,2);
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
);
675 EEL_F
*p
[3]={str
,xOut
,yOut
};
676 ctx
->gfx_drawstr(opaque
,p
,3,3);
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);
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
);
694 ctx
->gfx_drawstr(opaque
,parms
,(int)nparms
,1);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
750 WDL_FastString
*fs
=NULL
;
751 EEL_STRING_GET_FOR_WRITE(parms
[0][0],&fs
);
752 if (fs
) fs
->Set(f
->actual_fontname
);
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
);
765 ctx
->gfx_blitext2((int)np
,parms
,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
);
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
;
781 EEL_F fc
= *coordidx
;
782 if (fc
< -0.5 || fc
>= NSEEL_RAM_BLOCKS
*NSEEL_RAM_ITEMSPERBLOCK
) return img
;
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
;
798 ctx
->gfx_blitext(*img
,buf
,*rotate
);
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
);
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
);
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
);
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
);
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
);
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");
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
)))
855 LICE_Line(dest
,x1
,y1
,x2
,y2
,getCurColor(),(float) *m_gfx_a
,getCurMode(),aaflag
> 0.5);
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");
867 if (LICE_FUNCTION_VALID(LICE_Circle
) && LICE_FUNCTION_VALID(LICE_FillCircle
))
871 LICE_FillCircle(dest
, x
, y
, r
, getCurColor(), (float) *m_gfx_a
, getCurMode(), aaflag
);
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");
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());
893 if (!LICE_FUNCTION_VALID(LICE_FillConvexPolygon
)) return;
895 const int maxpt
= 512;
896 const int n
= wdl_min(np
/2, maxpt
);
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");
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)
922 LICE_FillRect(dest
,(int)x1
,(int)y1
,(int)(x2
-x1
),(int)(y2
-y1
),getCurColor(),(float)*m_gfx_a
,getCurMode());
929 void eel_lice_state::gfx_line(int np
, EEL_F
**parms
)
931 LICE_IBitmap
*dest
= GetImageForIndex(*m_gfx_dest
,"gfx_line");
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
)))
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");
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)
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");
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)
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");
980 const bool aa
= np
<= 5 || parms
[5][0]>0.5;
982 if (LICE_FUNCTION_VALID(LICE_Arc
))
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");
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]);
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
,
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");
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
)
1040 if (!LICE__GetWidth
|| !LICE__GetHeight
) return;
1043 LICE_IBitmap
*bm
=GetImageForIndex(img
,"gfx_getimgdim",false);
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
));
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
));
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
);
1077 wdl_atomic_incr(&s
->refcnt
);
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
);
1096 EEL_F
eel_lice_state::gfx_loadimg(void *opaque
, int img
, EEL_F loadFrom
)
1099 if (!__LICE_LoadImage
|| !LICE__Destroy
) return 0.0;
1102 if (img
>= 0 && img
< m_gfx_images
.GetSize())
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()))
1117 EEL_F
eel_lice_state::gfx_setimgdim(int img
, EEL_F
*w
, EEL_F
*h
)
1121 if (!LICE__resize
||!LICE__GetWidth
|| !LICE__GetHeight
||!__LICE_CreateBitmap
) return 0.0;
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
;
1137 m_gfx_images
.Get()[img
].bm
= bm
= __LICE_CreateBitmap(1,use_w
,use_h
);
1142 rv
=LICE__resize(bm
,use_w
,use_h
);
1149 void eel_lice_state::gfx_blurto(EEL_F x
, EEL_F y
)
1151 LICE_IBitmap
*dest
= GetImageForIndex(*m_gfx_dest
,"gfx_blurto");
1158 SetImageDirty(dest
);
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
);
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;
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");
1186 ||!LICE_ScaledBlit
|| !LICE_TransformBlit2
||!LICE__GetWidth
||!LICE__GetHeight
1190 LICE_IBitmap
*bm
=GetImageForIndex(parms
[0][0],"gfx_transformblit:src",false);
1193 const int bmw
=LICE__GetWidth(bm
);
1194 const int bmh
=LICE__GetHeight(bm
);
1196 const bool isFromFB
= bm
==m_framebuffer
;
1198 SetImageDirty(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
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;
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]);
1238 if (!face
|| !*face
) face
="Arial";
1241 unsigned int c
= np
> 3 ? (unsigned int) parms
[3][0] : 0;
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
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
;
1273 s
->actual_fontname
[0]=0;
1274 if (!s
->font
) s
->font
=LICE_CreateFont();
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
);
1281 #if defined(_WIN32) && !defined(WDL_NO_SUPPORT_UTF8)
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
);
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
);
1294 s
->use_fonth
=0; // disable this font
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
);
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;
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
;
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
);
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;
1355 void eel_lice_state::gfx_blitext2(int np
, EEL_F
**parms
, int blitmode
)
1357 LICE_IBitmap
*dest
= GetImageForIndex(*m_gfx_dest
,"gfx_blitext2");
1361 ||!LICE_ScaledBlit
|| !LICE_RotatedBlit
||!LICE__GetWidth
||!LICE__GetHeight
1365 LICE_IBitmap
*bm
=GetImageForIndex(parms
[0][0],"gfx_blitext2:src",false);
1368 const int bmw
=LICE__GetWidth(bm
);
1369 const int bmh
=LICE__GetHeight(bm
);
1371 // 0=img, 1=scale, 2=rotate
1373 const double sc
= blitmode
==0 && np
> 1 ? parms
[1][0] : 1.0,
1374 angle
= blitmode
==0 && np
> 2 ? parms
[2][0] : 0.0;
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
);
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
);
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
);
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");
1443 ||!LICE_ScaledBlit
|| !LICE_RotatedBlit
||!LICE__GetWidth
||!LICE__GetHeight
1447 LICE_IBitmap
*bm
=GetImageForIndex(img
,"gfx_blitext:src",false);
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]);
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
)
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);
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
))
1516 LICE__SetTextColor(font
,fg
);
1517 LICE__SetTextCombineMode(font
,mode
,alpha
);
1520 RECT r
={0,0,tr
.left
,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
);
1530 lineh
= LICE__DrawText(font
,dest
,buf
,thislen
?thislen
:1,&tr
,DT_SINGLELINE
|DT_NOPREFIX
|flags
);
1531 if (wantYoutput
) *wantYoutput
= tr
.top
;
1535 if (r
.right
> maxx
) maxx
=r
.right
;
1539 buflen
-= thislen
+1;
1544 measureOnly
[0][0] = maxx
;
1545 measureOnly
[1][0] = tr
.top
;
1551 int xpos
=rect
->left
, ypos
=rect
->top
;
1557 (LICE_IBitmap_disabledAPI
*)
1559 dest
,rect
->left
,rect
->top
,rect
->right
-rect
->left
,rect
->bottom
-rect
->top
);
1563 if (!(flags
& DT_NOCLIP
))
1565 if (rect
->right
<= rect
->left
|| rect
->bottom
<= rect
->top
) return 0; // invalid clip rect hm
1570 if (flags
& (DT_RIGHT
|DT_BOTTOM
|DT_CENTER
|DT_VCENTER
))
1573 EEL_F
*mo
[2] = { &w
,&h
};
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
++)
1596 case ' ': xpos
+= 8; break;
1597 case '\t': xpos
+= 8*5; break;
1599 if (!measureOnly
) LICE_DrawChar(dest
,xpos
,ypos
,buf
[x
], fg
,alpha
,mode
);
1601 if (xpos
> maxx
) maxx
=xpos
;
1608 measureOnly
[0][0]=maxx
;
1609 measureOnly
[1][0]=maxy
;
1613 if (wantYoutput
) *wantYoutput
=ypos
;
1619 static HMENU
PopulateMenuFromStr(const char** str
, int* startid
)
1621 HMENU hm
=CreatePopupMenu();
1627 const char* sep
=strchr(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);
1634 if (sep
) sep
=strchr(++p
, '|');
1639 int flags
=MF_BYPOSITION
|MF_STRING
;
1640 while (strspn(q
, ">#!<"))
1642 if (*q
== '>' && !subm
)
1644 subm
=PopulateMenuFromStr(&p
, &id
);
1647 if (*q
== '#') flags
|= MF_GRAYED
;
1648 if (*q
== '!') flags
|= MF_CHECKED
;
1649 if (*q
== '<') done
=true;
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
);
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;
1685 HMENU hm
=PopulateMenuFromStr(&p
, &id
);
1691 HWND par
= hwnd_standalone
;
1695 if (*m_gfx_ext_retina
> 1.0)
1697 pt
.x
= (short)(*m_gfx_x
* .5);
1698 pt
.y
= (short)(*m_gfx_y
* .5);
1703 pt
.x
= (short)*m_gfx_x
;
1704 pt
.y
= (short)*m_gfx_y
;
1706 ClientToScreen(par
, &pt
);
1710 #ifdef EEL_LICE_STANDALONE_PARENT
1711 par
= EEL_LICE_STANDALONE_PARENT(opaque
);
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;
1724 EEL_F
eel_lice_state::gfx_setcursor(void* opaque
, EEL_F
** parms
, int nparms
)
1726 if (!hwnd_standalone
) return 0.0;
1729 const int nc
= (int)parms
[0][0];
1730 if (m_cursor_resid
!= nc
)
1732 m_cursor_resid
= nc
;
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
));
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
);
1755 bool do_set
= GetCapture() == hwnd_standalone
;
1756 if (!do_set
&& GetFocus() == hwnd_standalone
)
1761 ScreenToClient(hwnd_standalone
,&pt
);
1762 GetClientRect(hwnd_standalone
,&r
);
1763 do_set
= PtInRect(&r
,pt
)!=0;
1768 SetCursor(m_cursor
? m_cursor
: LoadCursor(NULL
,IDC_ARROW
));
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
);
1788 if (!LICE__GetWidth
|| !LICE__GetHeight
) return;
1791 EEL_STRING_MUTEXLOCK_SCOPE
1793 WDL_FastString
*fs
=NULL
;
1800 s_len
= WDL_MakeUTFChar(buf
, (int)parms
[0][0], sizeof(buf
));
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]);
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;
1823 s_len
= fs
?fs
->GetLength():(int)strlen(s
);
1834 __drawTextWithFont(dest
,&r
,GetActiveFont(),s
,s_len
,
1835 getCurColor(),getCurMode(),(float)*m_gfx_a
,0,NULL
,fmtparms
);
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");
1861 SetImageDirty(dest
);
1863 int a
=(int)(ch
+0.5);
1864 if (a
== '\r' || a
=='\n') a
=' ';
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");
1882 SetImageDirty(dest
);
1885 int a
=(int)(ndigits
+0.5);
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
};
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)
1918 *m_gfx_ext_retina
= (hwnd
&& SWELL_IsRetinaHWND(hwnd
)) ? 2.0 : 1.0;
1919 if (*m_gfx_ext_retina
> 1.0)
1927 *m_gfx_ext_retina
= 1.0;
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
);
1941 *m_gfx_ext_retina
= dpi
/ 96.0;
1944 const int rsc
= SWELL_GetScaling256();
1945 if (rsc
> 256) *m_gfx_ext_retina
= rsc
/256.0;
1950 if (!m_framebuffer
&& LICE_FUNCTION_VALID(__LICE_CreateBitmap
))
1952 m_framebuffer
=__LICE_CreateBitmap(1,use_w
,use_h
);
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
);
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
;
1979 swap
= !!GetSystemMetrics(SM_SWAPBUTTON
);
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
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)
2008 void eel_lice_state::finish_draw()
2010 if (hwnd_standalone
&& m_framebuffer_dirty
)
2013 void *p
= SWELL_InitAutoRelease();
2016 InvalidateRect(hwnd_standalone
,NULL
,FALSE
);
2017 UpdateWindow(hwnd_standalone
);
2020 SWELL_QuitAutoRelease(p
);
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
);
2066 #ifdef EEL_LICE_WANT_STANDALONE
2069 static HINSTANCE eel_lice_hinstance
;
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
);
2079 ctx
->m_ddrop_files
.Empty(true,free
);
2080 if (ctx
->hwnd_standalone
)
2082 #ifndef EEL_LICE_WANT_STANDALONE_UPDATE_NO_SETUPFRAME
2087 #ifndef EEL_LICE_WANT_STANDALONE_UPDATE_NO_MSGPUMP
2091 while (PeekMessage(&msg
,NULL
,0,0,PM_REMOVE
))
2093 TranslateMessage(&msg
);
2094 DispatchMessage(&msg
);
2097 void SWELL_RunEvents();
2101 #ifndef EEL_LICE_WANT_STANDALONE_UPDATE_NO_SETUPFRAME
2103 GetClientRect(ctx
->hwnd_standalone
,&r
);
2104 ctx
->setup_frame(ctx
->hwnd_standalone
,r
);
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;
2120 EEL_F
*p
= plist
[0];
2121 ctx
->m_has_had_getch
=true;
2124 if (*p
== 65536.0 || *p
== 65537.0)
2127 if (ctx
->hwnd_standalone
)
2129 if (ctx
->hwnd_standalone
==GetFocus()) rv
|=2;
2130 if (IsWindowVisible(ctx
->hwnd_standalone
))
2138 GetWindowRect(ctx
->hwnd_standalone
,&r
);
2139 if (r
.top
> r
.bottom
)
2141 const int a
= r
.top
;
2145 if (PtInRect(&r
,pt
) && WindowFromPoint(pt
) == ctx
->hwnd_standalone
) rv
|=8;
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
;
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
--;
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)];
2174 ctx
->m_kb_queue_pos
++;
2175 ctx
->m_kb_queue_valid
--;
2176 plist
[1][0] = (a2
&0xffffff);
2181 if (a
> 32 && a
< 256 && np
> 1)
2186 if ((a
&0xffffff) < 256)
2188 if (np
> 1) plist
[1][0] = a
&0xffffff;
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])))
2207 if (lParam
& FVIRTKEY
)
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");
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
;
2261 case VK_CONTROL
: break;
2265 const bool isctrl
= !!(GetAsyncKeyState(VK_CONTROL
)&0x8000);
2266 const bool isalt
= !!(GetAsyncKeyState(VK_MENU
)&0x8000);
2269 // SWELL_MacKeyToWindowsKeyEx maps control(FLWIN)+A-Z to 1-26
2270 if (wParam
> 0 && wParam
<= 26 && !(lParam
&FVIRTKEY
))
2280 if (wParam
>='a' && wParam
<='z')
2282 if (isctrl
) wParam
+= 1-'a';
2283 if (isalt
) wParam
+= 256;
2287 if (wParam
>='A' && wParam
<='Z')
2289 if (isctrl
) wParam
+= 1-'A';
2290 if (isalt
) wParam
+= 256;
2305 return (wParam
&0xffffff) | ('u'<<24); // windows encodes all wm_chars as 'u'<<24
2308 if (!(GetAsyncKeyState(VK_SHIFT
)&0x8000))
2310 if (wParam
>='A' && wParam
<='Z')
2312 if ((GetAsyncKeyState(VK_LWIN
)&0x8000)) wParam
-= 'A'-1;
2317 if (wParam
>= 0x100)
2318 return (wParam
&0xffffff) | ('u'<<24);
2326 static LRESULT WINAPI
eel_lice_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
2330 void *objc_getClass(const char *p
);
2331 #ifndef _OBJC_OBJC_H_
2332 void *sel_getUid(const char *p
);
2334 void objc_msgSend(void);
2339 HWND
eel_lice_state::create_wnd(HWND par
, int isChild
)
2341 if (hwnd_standalone
) return hwnd_standalone
;
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);
2346 HWND h
= SWELL_CreateDialog(NULL
,isChild
? NULL
: ((const char *)(INT_PTR
)0x400001),par
,(DLGPROC
)eel_lice_wndproc
,(LPARAM
)this);
2349 SWELL_SetClassName(h
,eel_lice_standalone_classname
);
2350 SWELL_EnableMetal(h
,1);
2356 #ifdef EEL_LICE_WANTDOCK
2357 #ifndef ID_DOCKWINDOW
2358 #define ID_DOCKWINDOW 40269
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
);
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
);
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
);
2390 if (ctx
->hwnd_standalone
)
2392 DestroyWindow(ctx
->hwnd_standalone
);
2394 ctx
->hwnd_standalone
=0;
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
);
2404 eel_lice_state
*ctx
=EEL_LICE_GET_CONTEXT(opaque
);
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
)
2414 GetClientRect(ctx
->hwnd_standalone
,&r
);
2418 #ifdef EEL_LICE_WANTDOCK
2419 const int pos_offs
= 4;
2421 const int pos_offs
= 3;
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
)
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);
2441 #ifdef EEL_LICE_STANDALONE_PARENT
2442 HWND par
= EEL_LICE_STANDALONE_PARENT(opaque
);
2443 #elif defined(_WIN32)
2444 HWND par
=GetDesktopWindow();
2449 ctx
->create_wnd(par
,0);
2452 if (ctx
->hwnd_standalone
)
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
;
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
;
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
);
2479 #ifdef EEL_LICE_WANTDOCK
2480 if (np
> 3) EEL_LICE_WANTDOCK(ctx
,parms
[3][0]);
2482 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
2485 GetClientRect(ctx
->hwnd_standalone
,&r
);
2486 ctx
->setup_frame(ctx
->hwnd_standalone
,r
);
2492 if (!ctx
->hwnd_standalone
) return 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]);
2503 SetWindowText(ctx
->hwnd_standalone
,title
);
2504 wantResize
=false; // ignore resize if we're setting title
2508 ShowWindow(ctx
->hwnd_standalone
,SW_SHOW
);
2509 if (wantResize
&& np
>2 && !(GetWindowLong(ctx
->hwnd_standalone
,GWL_STYLE
)&WS_CHILD
))
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
;
2520 const bool do_move
=(np
>= pos_offs
+2);
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
;
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
);
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
);
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
);
2568 #endif // !EEL_LICE_STANDALONE_NOINITQUIT
2571 #ifndef WM_MOUSEWHEEL
2572 #define WM_MOUSEWHEEL 0x20A
2574 #ifndef WM_MOUSEHWHEEL
2575 #define WM_MOUSEHWHEEL 0x20E
2578 LRESULT WINAPI
eel_lice_wndproc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
2581 static UINT Scroll_Message
;
2582 static bool sm_init
;
2586 Scroll_Message
= RegisterWindowMessage("MSWHEEL_ROLLMSG");
2588 if (Scroll_Message
&& uMsg
== Scroll_Message
)
2600 LPCREATESTRUCT lpcs
= (LPCREATESTRUCT
)lParam
;
2601 eel_lice_state
*ctx
=(eel_lice_state
*)lpcs
->lpCreateParams
;
2602 SetWindowLongPtr(hwnd
,GWLP_USERDATA
,(LPARAM
)lpcs
->lpCreateParams
);
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
);
2608 ctx
->m_kb_queue_valid
=0;
2609 ctx
->hwnd_standalone
=hwnd
;
2614 DestroyWindow(hwnd
);
2619 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
,GWLP_USERDATA
);
2622 #ifdef EEL_LICE_WANTDOCK
2623 EEL_LICE_WANTDOCK(ctx
,0);
2625 ctx
->hwnd_standalone
=NULL
;
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
));
2637 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
2638 if (ctx
&& ctx
->m_cursor
)
2642 ScreenToClient(hwnd
, &p
);
2644 GetClientRect(hwnd
, &r
);
2647 SetCursor(ctx
->m_cursor
);
2653 #ifdef EEL_LICE_WANTDOCK
2654 case WM_CONTEXTMENU
:
2656 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
2659 char title
[512], buf
[1024];
2660 GetWindowText(hwnd
, title
, sizeof(title
)-1);
2661 if (!title
[0]) strcpy(title
, "ReaScript");
2663 HMENU hm
=CreatePopupMenu();
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
);
2674 TrackPopupMenu(hm
, 0, pt
.x
, pt
.y
, 0, hwnd
, NULL
);
2681 switch (LOWORD(wParam
))
2683 #ifdef EEL_LICE_WANTDOCK
2686 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
2687 if (ctx
) EEL_LICE_WANTDOCK(ctx
, EEL_LICE_ISDOCKED(ctx
)^1);
2692 DestroyWindow(hwnd
);
2697 if (wParam
== 0xdddd && lParam
)
2699 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
2702 ctx
->m_ddrop_files
.Empty(true,free
);
2703 const char *r
= (const char *)lParam
;
2706 ctx
->m_ddrop_files
.Add(strdup(r
));
2714 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
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
++)
2725 DragQueryFile(hDrop
,x
,buf
,sizeof(buf
));
2726 if (buf
[0]) ctx
->m_ddrop_files
.Add(strdup(buf
));
2732 case WM_MOUSEHWHEEL
:
2735 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
,GWLP_USERDATA
);
2738 EEL_F
*p
= uMsg
==WM_MOUSEHWHEEL
? ctx
->m_mouse_hwheel
: ctx
->m_mouse_wheel
;
2739 if (p
) *p
+= (EEL_F
) (short)HIWORD(wParam
);
2751 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
,GWLP_USERDATA
);
2755 wParam
= SWELL_MacKeyToWindowsKeyEx(NULL
,&f
,1);
2760 bool hadAltAdj
=false;
2761 int a
=eel_lice_key_xlate(uMsg
,(int)wParam
,(int)lParam
, &hadAltAdj
);
2762 if (a
== -1) return 0;
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*/);
2771 const int mask
= hadAltAdj
? ~256 : ~0;
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]);
2785 for (x
=0;x
<n
&& st
[x
] != lowera
;x
++) if (x
< zp
&& !st
[x
]) zp
=x
;
2789 ||uMsg
== WM_SYSKEYUP
2795 else if (x
==n
) // key not already down
2801 if (a
&& uMsg
!= WM_KEYUP
2803 && uMsg
!= WM_SYSKEYUP
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;
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
) };
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
);
2836 if (GetCapture()!=hwnd
) SetCapture(hwnd
);
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;
2848 if (ctx
->m_last_menu_cnt
&& (GetTickCount()-ctx
->m_last_menu_time
)>250) ctx
->m_last_menu_cnt
= 0;
2856 case WM_CAPTURECHANGED
:
2858 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
2861 if (uMsg
== WM_CAPTURECHANGED
)
2863 ctx
->m_has_cap
&= 0xffff;
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))
2882 if (GetWindowLong(hwnd
,GWL_STYLE
)&WS_CHILD
) return DLGC_WANTALLKEYS
;
2884 case 0x02E0: //WM_DPICHANGED
2885 if (!(GetWindowLong(hwnd
,GWL_STYLE
)&WS_CHILD
))
2887 RECT
*prcNewWindow
= (RECT
*)lParam
;
2890 prcNewWindow
->left
,
2892 prcNewWindow
->right
- prcNewWindow
->left
,
2893 prcNewWindow
->bottom
- prcNewWindow
->top
,
2894 SWP_NOZORDER
| SWP_NOACTIVATE
);
2900 #ifndef EEL_LICE_STANDALONE_NOINITQUIT
2902 if (uMsg
!= WM_SIZE
|| wParam
!= SIZE_MINIMIZED
)
2904 eel_lice_state
*ctx
=(eel_lice_state
*)GetWindowLongPtr(hwnd
,GWLP_USERDATA
);
2906 #ifdef EEL_LICE_ISDOCKED
2907 && !(GetWindowLong(hwnd
,GWL_STYLE
)&WS_CHILD
)
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
;
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
);
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
);
2942 BitBlt(ps
.hdc
,0,0,w
,h
,LICE__GetDC(ctx
->m_framebuffer
),0,0,SRCCOPY
);
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;
2958 return DefWindowProcW(hwnd
,uMsg
,wParam
,lParam
);
2960 return DefWindowProc(hwnd
,uMsg
,wParam
,lParam
);
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";
2973 eel_lice_hinstance
=hInstance
;
2976 while (eel_lice_standalone_classname
[x
])
2978 if (WDL_NOT_NORMALLY(x
== 255)) break;
2979 tmp
[x
] = eel_lice_standalone_classname
[x
];
2984 WNDCLASSW wc
={CS_DBLCLKS
,eel_lice_wndproc
,0,0,hInstance
,icon
,LoadCursor(NULL
,IDC_ARROW
), NULL
, NULL
,tmp
};
2985 RegisterClassW(&wc
);
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
);
3000 #ifdef EEL_LICE_WANTDOCK
3001 NSEEL_addfunc_varparm("gfx_dock",1,NSEEL_PProc_THIS
,&_gfx_dock
);
3004 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
3005 NSEEL_addfunc_retptr("gfx_update",1,NSEEL_PProc_THIS
,&_gfx_update
);
3008 NSEEL_addfunc_varparm("gfx_getchar",1,NSEEL_PProc_THIS
,&_gfx_getchar
);
3015 #endif//!EEL_LICE_API_ONLY
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");
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)
3074 #define EEL_LICE_DOC_MAXHANDLE "127"
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"
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"
3086 "Once the graphics window is open, gfx_update() should be called periodically. \0"
3087 "gfx_quit\t\tCloses the graphics window.\0"
3089 #ifdef EEL_LICE_WANT_STANDALONE_UPDATE
3090 "gfx_update\t\tUpdates the graphics display, if opened\0"
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"
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"
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"
3136 "\4" "13 for Enter\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"
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"
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
3155 "gfx_setcursor\tresource_id\tSets the mouse cursor. resource_id is a value like 32512 (for an arrow cursor).\0"
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"
3212 #ifdef EELSCRIPT_LICE_MAX_IMAGES
3218 #endif//_EEL_LICE_H_