From 9fbb706db60f37f535093603394951f89b2157fd Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Tue, 5 Mar 2024 00:51:20 +0100 Subject: [PATCH 01/10] Simplification, less memory allocation, better performance for large paths in pd-vanilla --- pdlua.h | 6 + pdlua_gfx.h | 436 ++++++++++++++++++++++------------------------------ 2 files changed, 186 insertions(+), 256 deletions(-) diff --git a/pdlua.h b/pdlua.h index 4d9862d..920c0d8 100644 --- a/pdlua.h +++ b/pdlua.h @@ -31,14 +31,20 @@ typedef struct _pdlua_gfx { // Size variables int width, height; + void *object; #if !PLUGDATA char object_tag[128]; // Tcl/tk tag that is attached to all drawings char order_tag[64]; // Tag for invisible line, used to preserve correct object ordering + char current_item_tag[64]; // Tcl/tk tag that is only attached to the current drawing in progress + gfx_transform* transforms; + int num_transforms; + char current_color[8]; // Keep track of current color // Variables to keep track of mouse button state and drag position int mouse_drag_x, mouse_drag_y, mouse_down; int first_draw; + #else void(*plugdata_draw_callback)(void*, t_symbol*, int, t_atom*); // Callback to perform drawing in plugdata #endif diff --git a/pdlua_gfx.h b/pdlua_gfx.h index 799b75b..7457efb 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -97,7 +97,6 @@ static int scale(lua_State* L); static int reset_transform(lua_State* L); static int free_path(lua_State* L); -static int free_graphics_context(lua_State* L); // pdlua_gfx_clear, pdlua_gfx_repaint and pdlua_gfx_mouse_* correspond to the various callbacks the user can assign @@ -177,24 +176,10 @@ typedef struct _path_state } t_path_state; -// Represents the graphics context object "g" that is passed to the user by the paint function -// This holds the object it is associated with, and for pd-vanilla also some of the current graphics state -typedef struct _graphics_context -{ - t_pdlua *object; -#if !PLUGDATA - char* object_tag; - char current_item_tag[64]; // Tcl/tk tag that is only attached to the current drawing in progress - gfx_transform* transforms; - int num_transforms; - char current_color[8]; // Keep track of current color -#endif -} t_graphics_context; - // Pops the graphics context off the argument list and returns it -static t_graphics_context *pop_graphics_context(lua_State* L) +static t_pdlua_gfx *pop_graphics_context(lua_State* L) { - t_graphics_context* ctx = (t_graphics_context*)luaL_checkudata(L, 1, "GraphicsContext"); + t_pdlua_gfx* ctx = (t_pdlua_gfx*)luaL_checkudata(L, 1, "GraphicsContext"); lua_remove(L, 1); return ctx; } @@ -234,7 +219,6 @@ static const luaL_Reg gfx_methods[] = { {"translate", translate}, {"scale", scale}, {"reset_transform", reset_transform}, - {"__gc", free_graphics_context}, {NULL, NULL} // Sentinel to end the list }; @@ -298,6 +282,7 @@ static void pdlua_gfx_clear(t_pdlua *obj, int removed) { static int gfx_initialize(t_pdlua *obj) { + obj->gfx.object = obj; pdlua_gfx_repaint(obj, 0); // Initial repaint return 0; } @@ -325,10 +310,7 @@ static int start_paint(lua_State* L) { } t_pdlua *obj = (t_pdlua*)lua_touserdata(L, 1); - // Set graphics context as return value - t_graphics_context *ctx = (t_graphics_context *)lua_newuserdata(L, sizeof(t_graphics_context)); - ctx->object = obj; - + lua_pushlightuserdata(L, &obj->gfx); luaL_setmetatable(L, "GraphicsContext"); plugdata_draw_callback = obj->gfx.plugdata_draw_callback; @@ -337,21 +319,15 @@ static int start_paint(lua_State* L) { } static int end_paint(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; plugdata_draw(obj, gensym("lua_end_paint"), 0, NULL); return 0; } -static int free_graphics_context(lua_State* L) -{ - // Nothing to do here - return 0; -} - static int set_color(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; if (lua_gettop(L) == 1) { // Single argument: parse as color ID instead of RGB t_atom arg; SETFLOAT(&arg, luaL_checknumber(L, 1)); // color ID @@ -376,72 +352,72 @@ static int set_color(lua_State* L) { } static int fill_ellipse(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[4]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y SETFLOAT(args + 2, luaL_checknumber(L, 3)); // w SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h - plugdata_draw(ctx->object, gensym("lua_fill_ellipse"), 4, args); + plugdata_draw(gfx->object, gensym("lua_fill_ellipse"), 4, args); return 0; } static int stroke_ellipse(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[5]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y SETFLOAT(args + 2, luaL_checknumber(L, 3)); // w SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h SETFLOAT(args + 4, luaL_checknumber(L, 5)); // width - plugdata_draw(ctx->object, gensym("lua_stroke_ellipse"), 5, args); + plugdata_draw(gfx->object, gensym("lua_stroke_ellipse"), 5, args); return 0; } static int fill_all(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; plugdata_draw(obj, gensym("lua_fill_all"), 0, NULL); return 0; } static int fill_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[4]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y SETFLOAT(args + 2, luaL_checknumber(L, 3)); // w SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h - plugdata_draw(ctx->object, gensym("lua_fill_rect"), 4, args); + plugdata_draw(gfx->object, gensym("lua_fill_rect"), 4, args); return 0; } static int stroke_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[5]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y SETFLOAT(args + 2, luaL_checknumber(L, 3)); // w SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h SETFLOAT(args + 4, luaL_checknumber(L, 5)); // corner_radius - plugdata_draw(ctx->object, gensym("lua_stroke_rect"), 5, args); + plugdata_draw(gfx->object, gensym("lua_stroke_rect"), 5, args); return 0; } static int fill_rounded_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[5]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y SETFLOAT(args + 2, luaL_checknumber(L, 3)); // w SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h SETFLOAT(args + 4, luaL_checknumber(L, 5)); // corner radius - plugdata_draw(ctx->object, gensym("lua_fill_rounded_rect"), 5, args); + plugdata_draw(gfx->object, gensym("lua_fill_rounded_rect"), 5, args); return 0; } static int stroke_rounded_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[6]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y @@ -449,25 +425,25 @@ static int stroke_rounded_rect(lua_State* L) { SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h SETFLOAT(args + 4, luaL_checknumber(L, 5)); // corner_radius SETFLOAT(args + 5, luaL_checknumber(L, 6)); // width - plugdata_draw(ctx->object, gensym("lua_stroke_rounded_rect"), 6, args); + plugdata_draw(gfx->object, gensym("lua_stroke_rounded_rect"), 6, args); return 0; } static int draw_line(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_atom args[5]; SETFLOAT(args, luaL_checknumber(L, 1)); // x SETFLOAT(args + 1, luaL_checknumber(L, 2)); // y SETFLOAT(args + 2, luaL_checknumber(L, 3)); // w SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h SETFLOAT(args + 4, luaL_checknumber(L, 5)); // line width - plugdata_draw(ctx->object, gensym("lua_draw_line"), 5, args); + plugdata_draw(gfx->object, gensym("lua_draw_line"), 5, args); return 0; } static int draw_text(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); const char* text = luaL_checkstring(L, 1); t_atom args[5]; SETSYMBOL(args, gensym(text)); @@ -475,7 +451,7 @@ static int draw_text(lua_State* L) { SETFLOAT(args + 2, luaL_checknumber(L, 3)); // y SETFLOAT(args + 3, luaL_checknumber(L, 4)); // w SETFLOAT(args + 4, luaL_checknumber(L, 5)); // h - plugdata_draw(ctx->object, gensym("lua_draw_text"), 5, args); + plugdata_draw(gfx->object, gensym("lua_draw_text"), 5, args); return 0; } @@ -557,30 +533,30 @@ static int free_path(lua_State* L) { } static int stroke_path(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); t_atom args[2]; SETPOINTER(args, path->path_id); // path id SETFLOAT(args + 1, luaL_checknumber(L, 2)); // line thickness - plugdata_draw(ctx->object, gensym("lua_stroke_path"), 2, args); + plugdata_draw(gfx->object, gensym("lua_stroke_path"), 2, args); return 0; } static int fill_path(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); t_atom args; SETPOINTER(&args, path->path_id); // path id - plugdata_draw(ctx->object, gensym("lua_fill_path"), 1, &args); + plugdata_draw(gfx->object, gensym("lua_fill_path"), 1, &args); return 0; } static int translate(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_atom args[2]; SETFLOAT(args, luaL_checknumber(L, 1)); // tx SETFLOAT(args + 1, luaL_checknumber(L, 2)); // ty @@ -589,8 +565,8 @@ static int translate(lua_State* L) { } static int scale(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_atom args[2]; SETFLOAT(args, luaL_checknumber(L, 1)); // sx SETFLOAT(args + 1, luaL_checknumber(L, 2)); // sy @@ -599,8 +575,8 @@ static int scale(lua_State* L) { } static int reset_transform(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; plugdata_draw(obj, gensym("lua_reset_transform"), 0, NULL); return 0; } @@ -641,29 +617,29 @@ static int free_path(lua_State* L) return 0; } -static void transform_size(t_graphics_context *ctx, int* w, int* h) { - for(int i = ctx->num_transforms - 1; i >= 0; i--) +static void transform_size(t_pdlua_gfx *gfx, int* w, int* h) { + for(int i = gfx->num_transforms - 1; i >= 0; i--) { - if(ctx->transforms[i].type == SCALE) + if(gfx->transforms[i].type == SCALE) { - *w *= ctx->transforms[i].x; - *h *= ctx->transforms[i].y; + *w *= gfx->transforms[i].x; + *h *= gfx->transforms[i].y; } } } -static void transform_point(t_graphics_context *ctx, int* x, int* y) { - for(int i = ctx->num_transforms - 1; i >= 0; i--) +static void transform_point(t_pdlua_gfx *gfx, int* x, int* y) { + for(int i = gfx->num_transforms - 1; i >= 0; i--) { - if(ctx->transforms[i].type == SCALE) + if(gfx->transforms[i].type == SCALE) { - *x *= ctx->transforms[i].x; - *y *= ctx->transforms[i].y; + *x *= gfx->transforms[i].x; + *y *= gfx->transforms[i].y; } else // translate { - *x += ctx->transforms[i].x; - *y += ctx->transforms[i].y; + *x += gfx->transforms[i].x; + *y += gfx->transforms[i].y; } } } @@ -683,7 +659,7 @@ static void pdlua_gfx_clear(t_pdlua *obj, int removed) { glist_eraseiofor(glist_getcanvas(cnv), &obj->pd, gfx->object_tag); } -static void get_bounds_args(lua_State* L, t_pdlua *obj, t_graphics_context *ctx, int* x1, int* y1, int* x2, int* y2) { +static void get_bounds_args(lua_State* L, t_pdlua *obj, int* x1, int* y1, int* x2, int* y2) { t_canvas *cnv = glist_getcanvas(obj->canvas); int x = luaL_checknumber(L, 1); @@ -691,8 +667,8 @@ static void get_bounds_args(lua_State* L, t_pdlua *obj, t_graphics_context *ctx, int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); - transform_point(ctx, &x, &y); - transform_size(ctx, &w, &h); + transform_point(&obj->gfx, &x, &y); + transform_size(&obj->gfx, &w, &h); x += text_xpix((t_object*)obj, obj->canvas) / glist_getzoom(cnv); y += text_ypix((t_object*)obj, obj->canvas) / glist_getzoom(cnv); @@ -715,10 +691,10 @@ static void gfx_displace(t_pdlua *x, t_glist *glist, int dx, int dy) glist_drawiofor(x->canvas, (t_object*)x, 0, x->gfx.object_tag, xpos, ypos, xpos + (x->gfx.width * scale), ypos + (x->gfx.height * scale)); } -static const char* register_drawing(t_graphics_context *ctx) +static const char* register_drawing(t_pdlua_gfx *gfx) { - generate_random_id(ctx->current_item_tag, 64); - return ctx->current_item_tag; + generate_random_id(gfx->current_item_tag, 64); + return gfx->current_item_tag; } static int gfx_initialize(t_pdlua *obj) @@ -728,6 +704,9 @@ static int gfx_initialize(t_pdlua *obj) snprintf(gfx->object_tag, 128, ".x%lx", (long)obj); gfx->object_tag[127] = '\0'; gfx->order_tag[0] = '\0'; + gfx->object = obj; + gfx->transforms = NULL; + gfx->num_transforms = 0; pdlua_gfx_repaint(obj, 0); return 0; @@ -768,13 +747,13 @@ static int start_paint(lua_State* L) { int can_draw = (glist_isvisible(obj->canvas) && gobj_shouldvis(&obj->pd.te_g, obj->canvas)) || obj->gfx.first_draw; if(can_draw) { - t_graphics_context *ctx = (t_graphics_context *)lua_newuserdata(L, sizeof(t_graphics_context)); - luaL_setmetatable(L, "GraphicsContext"); - ctx->object = obj; - ctx->object_tag = &gfx->object_tag[0]; - ctx->num_transforms = 0; - ctx->transforms = NULL; + if(gfx->transforms) freebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform)); + gfx->num_transforms = 0; + gfx->transforms = NULL; + + lua_pushlightuserdata(L, gfx); + luaL_setmetatable(L, "GraphicsContext"); // clear anything that was painted before if(strlen(gfx->object_tag)) pdlua_gfx_clear(obj, 0); @@ -800,8 +779,8 @@ static int start_paint(lua_State* L) { } static int end_paint(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = (t_pdlua*)gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int scale = glist_getzoom(glist_getcanvas(obj->canvas)); @@ -810,26 +789,18 @@ static int end_paint(lua_State* L) { int xpos = text_xpix((t_object*)obj, obj->canvas); int ypos = text_ypix((t_object*)obj, obj->canvas); - t_pdlua_gfx *gfx = &obj->gfx; - glist_drawiofor(glist_getcanvas(obj->canvas), (t_object*)obj, 1, ctx->object_tag, xpos, ypos, xpos + (obj->gfx.width * scale), ypos + (obj->gfx.height * scale)); + glist_drawiofor(glist_getcanvas(obj->canvas), (t_object*)obj, 1, gfx->object_tag, xpos, ypos, xpos + (gfx->width * scale), ypos + (gfx->height * scale)); if(!gfx->first_draw && gfx->order_tag[0] != '\0') { // Move everything to below the order marker, to make sure redrawn stuff isn't always on top - pdgui_vmess(0, "crss", cnv, "lower", ctx->object_tag, gfx->order_tag); + pdgui_vmess(0, "crss", cnv, "lower", gfx->object_tag, gfx->order_tag); } return 0; } -static int free_graphics_context(lua_State* L) -{ - t_graphics_context* ctx = (t_graphics_context*)luaL_checkudata(L, 1, "GraphicsContext"); - if(ctx && ctx->transforms) freebytes(ctx->transforms, ctx->num_transforms * sizeof(gfx_transform)); - return 0; -} - static int set_color(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); int r, g, b; if (lua_gettop(L) == 1) { // Single argument: parse as color ID instead of RGB @@ -853,51 +824,49 @@ static int set_color(lua_State* L) { } // AFAIK, alpha is not supported in tcl/tk - - snprintf(ctx->current_color, 8, "#%02X%02X%02X", r, g, b); - ctx->current_color[7] = '\0'; + snprintf(gfx->current_color, 8, "#%02X%02X%02X", r, g, b); + gfx->current_color[7] = '\0'; return 0; } static int fill_ellipse(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; - get_bounds_args(L, obj, ctx, &x1, &y1, &x2, &y2); + get_bounds_args(L, obj, &x1, &y1, &x2, &y2); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; + + pdgui_vmess(0, "crr iiii rs ri rS", cnv, "create", "oval", x1, y1, x2, y2, "-fill", gfx->current_color, "-width", 0, "-tags", 2, tags); - pdgui_vmess(0, "crr iiii rs ri rS", cnv, "create", "oval", x1, y1, x2, y2, "-fill", ctx->current_color, "-width", 0, "-tags", 2, tags); - return 0; } static int stroke_ellipse(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; - get_bounds_args(L, obj, ctx, &x1, &y1, &x2, &y2); + get_bounds_args(L, obj, &x1, &y1, &x2, &y2); int line_width = luaL_checknumber(L, 5) * glist_getzoom(cnv); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y1, x2, y2, "-width", line_width, "-outline", ctx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y1, x2, y2, "-width", line_width, "-outline", gfx->current_color, "-tags", 2, tags); return 0; } static int fill_all(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; - t_pdlua_gfx *gfx = &obj->gfx; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); @@ -906,120 +875,119 @@ static int fill_all(lua_State* L) { int x2 = x1 + gfx->width * glist_getzoom(cnv); int y2 = y1 + gfx->height * glist_getzoom(cnv); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - pdgui_vmess(0, "crr iiii rs rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-fill", ctx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii rs rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-fill", gfx->current_color, "-tags", 2, tags); return 0; } static int fill_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; - get_bounds_args(L, obj, ctx, &x1, &y1, &x2, &y2); + get_bounds_args(L, obj, &x1, &y1, &x2, &y2); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - pdgui_vmess(0, "crr iiii rs ri rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-fill", ctx->current_color, "-width", 0, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii rs ri rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-fill", gfx->current_color, "-width", 0, "-tags", 2, tags); return 0; } static int stroke_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; - get_bounds_args(L, obj, ctx, &x1, &y1, &x2, &y2); + get_bounds_args(L, obj, &x1, &y1, &x2, &y2); int line_width = luaL_checknumber(L, 5) * glist_getzoom(cnv); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-width", line_width, "-outline", ctx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-width", line_width, "-outline", gfx->current_color, "-tags", 2, tags); return 0; } static int fill_rounded_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; - get_bounds_args(L, obj, ctx, &x1, &y1, &x2, &y2); + get_bounds_args(L, obj, &x1, &y1, &x2, &y2); int radius = luaL_checknumber(L, 5); // Radius for rounded corners int radius_x = radius * glist_getzoom(cnv); int radius_y = radius * glist_getzoom(cnv); - transform_size(ctx, &radius_x, &radius_y); + transform_size(gfx, &radius_x, &radius_y); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; // Tcl/tk can't fill rounded rectangles, so we draw 2 smaller rectangles with 4 ovals over the corners - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y1, x1 + radius_x * 2, y1 + radius_y * 2, "-width", 0, "-fill", ctx->current_color, "-tags", 2, tags); - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x2 - radius_x * 2 , y1, x2, y1 + radius_y * 2, "-width", 0, "-fill", ctx->current_color, "-tags", 2, tags); - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y2 - radius_y * 2, x1 + radius_x * 2, y2, "-width", 0, "-fill", ctx->current_color, "-tags", 2, tags); - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x2 - radius_x * 2, y2 - radius_y * 2, x2, y2, "-width", 0, "-fill", ctx->current_color, "-tags", 2, tags); - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1 + radius_x, y1, x2 - radius_x, y2, "-width", 0, "-fill", ctx->current_color, "-tag", 2, tags); - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1, y1 + radius_y, x2, y2 - radius_y, "-width", 0, "-fill", ctx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y1, x1 + radius_x * 2, y1 + radius_y * 2, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x2 - radius_x * 2 , y1, x2, y1 + radius_y * 2, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y2 - radius_y * 2, x1 + radius_x * 2, y2, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x2 - radius_x * 2, y2 - radius_y * 2, x2, y2, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1 + radius_x, y1, x2 - radius_x, y2, "-width", 0, "-fill", gfx->current_color, "-tag", 2, tags); + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1, y1 + radius_y, x2, y2 - radius_y, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); return 0; } static int stroke_rounded_rect(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; - get_bounds_args(L, obj, ctx, &x1, &y1, &x2, &y2); + get_bounds_args(L, obj, &x1, &y1, &x2, &y2); int radius = luaL_checknumber(L, 5); // Radius for rounded corners int radius_x = radius * glist_getzoom(cnv); int radius_y = radius * glist_getzoom(cnv); - transform_size(ctx, &radius_x, &radius_y); + transform_size(gfx, &radius_x, &radius_y); int line_width = luaL_checknumber(L, 6) * glist_getzoom(cnv); - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; // Tcl/tk can't stroke rounded rectangles either, so we draw 2 lines connecting with 4 arcs at the corners pdgui_vmess(0, "crr iiii ri ri ri ri rs rs rS", cnv, "create", "arc", x1, y1 + radius_y*2, x1 + radius_x*2, y1, - "-start", 0, "-extent", 90, "-width", line_width, "-start", 90, "-outline", ctx->current_color, "-style", "arc", "-tags", 2, tags); + "-start", 0, "-extent", 90, "-width", line_width, "-start", 90, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri ri ri ri rs rs rS", cnv, "create", "arc", x2 - radius_x*2, y1, x2, y1 + radius_y*2, - "-start", 270, "-extent", 90, "-width", line_width, "-start", 0, "-outline", ctx->current_color, "-style", "arc", "-tags", 2, tags); + "-start", 270, "-extent", 90, "-width", line_width, "-start", 0, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri ri ri ri rs rs rS", cnv, "create", "arc", x1, y2 - radius_y*2, x1 + radius_x*2, y2, - "-start", 180, "-extent", 90, "-width", line_width, "-start", 180, "-outline", ctx->current_color, "-style", "arc", "-tags", 2, tags); + "-start", 180, "-extent", 90, "-width", line_width, "-start", 180, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri ri ri ri rs rs rS", cnv, "create", "arc", x2 - radius_x*2, y2, x2, y2 - radius_y*2, - "-start", 90, "-extent", 90, "-width", line_width, "-start", 270, "-outline", ctx->current_color, "-style", "arc", "-tags", 2, tags); + "-start", 90, "-extent", 90, "-width", line_width, "-start", 270, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); // Connect with lines pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x1 + radius_x, y1, x2 - radius_x, y1, - "-width", line_width, "-fill", ctx->current_color, "-tags", 2, tags); + "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x1 + radius_y, y2, x2 - radius_y, y2, - "-width", line_width, "-fill", ctx->current_color, "-tags", 2, tags); + "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x1 , y1 + radius_y, x1, y2 - radius_y, - "-width", line_width, "-fill", ctx->current_color, "-tags", 2, tags); + "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x2 , y1 + radius_y, x2, y2 - radius_y, - "-width", line_width, "-fill", ctx->current_color, "-tags", 2, tags); + "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); return 0; } static int draw_line(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; - t_canvas *cnv = glist_getcanvas(obj->canvas); int x1 = luaL_checknumber(L, 1); @@ -1028,8 +996,8 @@ static int draw_line(lua_State* L) { int y2 = luaL_checknumber(L, 4); int line_width = luaL_checknumber(L, 5); - transform_point(ctx, &x1, &y1); - transform_point(ctx, &x2, &y2); + transform_point(gfx, &x1, &y1); + transform_point(gfx, &x2, &y2); int canvas_zoom = glist_getzoom(cnv); @@ -1044,17 +1012,17 @@ static int draw_line(lua_State* L) { y2 *= canvas_zoom; line_width *= canvas_zoom; - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x1, y1, x2, y2, - "-width", line_width, "-fill", ctx->current_color, "-tags", 2, tags); + "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); return 0; } static int draw_text(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); @@ -1065,8 +1033,8 @@ static int draw_text(lua_State* L) { int font_height = luaL_checknumber(L, 5); font_height = sys_hostfontsize(font_height, glist_getzoom(cnv)); - transform_point(ctx, &x, &y); - transform_size(ctx, &w, &font_height); + transform_point(gfx, &x, &y); + transform_size(gfx, &w, &font_height); int canvas_zoom = glist_getzoom(cnv); x += text_xpix((t_object*)obj, obj->canvas) / canvas_zoom; @@ -1076,7 +1044,7 @@ static int draw_text(lua_State* L) { y *= canvas_zoom; w *= canvas_zoom; - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; pdgui_vmess(0, "crr ii rs ri rs rS", cnv, "create", "text", 0, 0, "-anchor", "nw", "-width", w, "-text", text, "-tags", 2, tags); @@ -1088,7 +1056,7 @@ static int draw_text(lua_State* L) { pdgui_vmess(0, "crs rA rs rs", cnv, "itemconfigure", tags[1], "-font", 3, fontatoms, - "-fill", ctx->current_color, + "-fill", gfx->current_color, "-justify", "left"); pdgui_vmess(0, "crs ii", cnv, "coords", tags[1], x, y); @@ -1208,66 +1176,42 @@ static int close_path(lua_State* L) { } static int stroke_path(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - // Apply transformations to all coordinates - // Apply transformations to all coordinates int obj_x = text_xpix((t_object*)obj, obj->canvas); int obj_y = text_ypix((t_object*)obj, obj->canvas); - for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - - transform_point(ctx, &x, &y); - - int canvas_zoom = glist_getzoom(cnv); - path->path_segments[i * 2] = (x * canvas_zoom) + obj_x; - path->path_segments[i * 2 + 1] = (y * canvas_zoom) + obj_y; - } + int canvas_zoom = glist_getzoom(cnv); - int totalSize = 0; - // Determine the total size needed - for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - // Calculate size for x and y - totalSize += snprintf(NULL, 0, "%i %i ", x, y); - } - char *coordinates = (char*)getbytes(totalSize + 1); // +1 for null terminator + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - int offset = 0; + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", 0, 0, 0, 0, "-width", stroke_width, "-fill", gfx->current_color, "-tags", 2, tags); + + int last_x, last_y; + + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); for (int i = 0; i < path->num_path_segments; i++) { int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - int charsWritten = snprintf(coordinates + offset, totalSize - offset, "%i %i ", x, y); - if (charsWritten >= 0) { - offset += charsWritten; - } else { - break; - } - } - // Replace the trailing space with string terminator - if (offset > 0) { - coordinates[offset - 1] = '\0'; + if(i > 1 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + last_x = x; + last_y = y; + + transform_point(gfx, &x, &y); + sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); } - - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; - - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", 0, 0, 0, 0, "-width", stroke_width, "-fill", ctx->current_color, "-tags", 2, tags); - - pdgui_vmess(0, "crs r", cnv, "coords", tags[1], coordinates); - - freebytes(coordinates, totalSize+1); + sys_vgui("\n"); return 0; } static int fill_path(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - t_pdlua *obj = ctx->object; + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); @@ -1276,90 +1220,70 @@ static int fill_path(lua_State* L) { // Apply transformations to all coordinates int obj_x = text_xpix((t_object*)obj, obj->canvas); int obj_y = text_ypix((t_object*)obj, obj->canvas); - for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - - transform_point(ctx, &x, &y); + int canvas_zoom = glist_getzoom(cnv); - path->path_segments[i * 2] = x * glist_getzoom(cnv) + obj_x; - path->path_segments[i * 2 + 1] = y * glist_getzoom(cnv) + obj_y; - } + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; + + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "polygon", 0, 0, 0, 0, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); - int totalSize = 0; - // Determine the total size needed - for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - // Calculate size for x and y - totalSize += snprintf(NULL, 0, "%i %i ", x, y); - } - char *coordinates = (char*)getbytes(totalSize + 1); // +1 for null terminator + int last_x, last_y; - int offset = 0; + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); for (int i = 0; i < path->num_path_segments; i++) { int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - int charsWritten = snprintf(coordinates + offset, totalSize - offset, "%i %i ", x, y); - if (charsWritten >= 0) { - offset += charsWritten; - } else { - break; - } - } - - // Remove the trailing space - if (offset > 0) { - coordinates[offset - 1] = '\0'; + if(i > 1 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + last_x = x; + last_y = y; + + transform_point(gfx, &x, &y); + sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); } - - const char* tags[] = { ctx->object_tag, register_drawing(ctx) }; - - pdgui_vmess(0, "crr r ri rs rS", cnv, "create", "polygon", coordinates, "-width", 0, "-fill", ctx->current_color, "-tags", 2, tags); - - freebytes(coordinates, totalSize+1); + sys_vgui("\n"); return 0; } static int translate(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); - if(ctx->num_transforms == 0) + if(gfx->num_transforms == 0) { - ctx->transforms = getbytes(sizeof(gfx_transform)); + gfx->transforms = getbytes(sizeof(gfx_transform)); } else { - ctx->transforms = resizebytes(ctx->transforms, ctx->num_transforms * sizeof(gfx_transform), (ctx->num_transforms + 1) * sizeof(gfx_transform)); + gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); } - ctx->transforms[ctx->num_transforms].type = TRANSLATE; - ctx->transforms[ctx->num_transforms].x = luaL_checknumber(L, 1); - ctx->transforms[ctx->num_transforms].y = luaL_checknumber(L, 2); + gfx->transforms[gfx->num_transforms].type = TRANSLATE; + gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); + gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); - ctx->num_transforms++; + gfx->num_transforms++; return 0; } static int scale(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); + t_pdlua_gfx *gfx = pop_graphics_context(L); - ctx->transforms = resizebytes(ctx->transforms, ctx->num_transforms * sizeof(gfx_transform), (ctx->num_transforms + 1) * sizeof(gfx_transform)); + gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); - ctx->transforms[ctx->num_transforms].type = SCALE; - ctx->transforms[ctx->num_transforms].x = luaL_checknumber(L, 1); - ctx->transforms[ctx->num_transforms].y = luaL_checknumber(L, 2); + gfx->transforms[gfx->num_transforms].type = SCALE; + gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); + gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); - ctx->num_transforms++; + gfx->num_transforms++; return 0; } static int reset_transform(lua_State* L) { - t_graphics_context *ctx = pop_graphics_context(L); - freebytes(ctx->transforms, ctx->num_transforms * sizeof(gfx_transform)); - ctx->transforms = NULL; - ctx->num_transforms = 0; + t_pdlua_gfx *gfx = pop_graphics_context(L); + freebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform)); + gfx->transforms = NULL; + gfx->num_transforms = 0; return 0; } #endif From c4d26fa8fdbb9b993fdf6bcb40ede43b0f8107e9 Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Tue, 5 Mar 2024 01:10:39 +0100 Subject: [PATCH 02/10] Make invisible line actually invisible --- pdlua_gfx.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index 7457efb..8a4de97 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -747,7 +747,6 @@ static int start_paint(lua_State* L) { int can_draw = (glist_isvisible(obj->canvas) && gobj_shouldvis(&obj->pd.te_g, obj->canvas)) || obj->gfx.first_draw; if(can_draw) { - if(gfx->transforms) freebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform)); gfx->num_transforms = 0; gfx->transforms = NULL; @@ -767,7 +766,7 @@ static int start_paint(lua_State* L) { generate_random_id(gfx->order_tag, 64); const char* tags[] = { gfx->order_tag }; - pdgui_vmess(0, "crr iiii ri rS", cnv, "create", "line", 0, 0, 1, 1, + pdgui_vmess(0, "crr iiii ri rS", cnv, "create", "line", 0, 0, 0, 0, "-width", 1, "-tags", 1, tags); } From 7638b2b82bc72fb823b4056cf2060c72fa873ba0 Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Sat, 20 Apr 2024 22:51:49 +0200 Subject: [PATCH 03/10] Changes to plugdata communication for pdlua graphics --- pdlua.h | 2 - pdlua_gfx.h | 356 +++++++++++++++++++++++----------------------------- 2 files changed, 160 insertions(+), 198 deletions(-) diff --git a/pdlua.h b/pdlua.h index 920c0d8..2f24a43 100644 --- a/pdlua.h +++ b/pdlua.h @@ -17,7 +17,6 @@ #include "m_pd.h" -#if !PLUGDATA typedef enum {SCALE, TRANSLATE} transform_type; typedef struct _gfx_transform @@ -25,7 +24,6 @@ typedef struct _gfx_transform transform_type type; float x, y; } gfx_transform; -#endif typedef struct _pdlua_gfx { diff --git a/pdlua_gfx.h b/pdlua_gfx.h index 8a4de97..69cdf6a 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -164,15 +164,11 @@ void pdlua_gfx_mouse_drag(t_pdlua *o, int x, int y) { // for plugdata, it only contains a unique ID to the juce::Path that this is mapped to typedef struct _path_state { -#if PLUGDATA - t_gpointer* path_id; -#else // Variables for managing vector paths int* path_segments; int num_path_segments; int num_path_segments_allocated; int path_start_x, path_start_y; -#endif } t_path_state; @@ -455,105 +451,74 @@ static int draw_text(lua_State* L) { return 0; } -static int start_path(lua_State* L) { - t_path_state *path = (t_path_state *)lua_newuserdata(L, sizeof(t_path_state)); - luaL_setmetatable(L, "Path"); +static int stroke_path(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; - path->path_id = (t_gpointer*)path; + t_canvas *cnv = glist_getcanvas(obj->canvas); - t_atom args[3]; - SETPOINTER(args, path->path_id); // path id - SETFLOAT(args + 1, luaL_checknumber(L, 1)); // x - SETFLOAT(args + 2, luaL_checknumber(L, 2)); // y - plugdata_draw_path(gensym("lua_start_path"), 3, args); - return 1; -} - -static int line_to(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - t_atom args[3]; - SETPOINTER(args, path->path_id); // path id - SETFLOAT(args + 1, luaL_checknumber(L, 2)); // x - SETFLOAT(args + 2, luaL_checknumber(L, 3)); // y - plugdata_draw_path(gensym("lua_line_to"), 3, args); - return 0; -} - -static int quad_to(lua_State* L) { - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + int last_x = 0; + int last_y = 0; - t_atom args[5]; // Assuming quad_to takes 3 arguments - SETPOINTER(args, path->path_id); // path id - SETFLOAT(args + 1, luaL_checknumber(L, 1)); // x1 - SETFLOAT(args + 2, luaL_checknumber(L, 2)); // y1 - SETFLOAT(args + 3, luaL_checknumber(L, 3)); // x2 - SETFLOAT(args + 4, luaL_checknumber(L, 4)); // y2 + t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom) + 1); + SETFLOAT(coordinates, stroke_width); - // Forward the message to the appropriate function - plugdata_draw_path(gensym("lua_quad_to"), 5, args); - return 0; -} + int num_real_segments = 0; -static int cubic_to(lua_State* L) { - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - - t_atom args[7]; // Assuming cubic_to takes 4 arguments + for (int i = 0; i < path->num_path_segments; i++) { + int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + + SETFLOAT(coordinates + (num_real_segments * 2) + 1, x); + SETFLOAT(coordinates + (num_real_segments * 2) + 2, y); + num_real_segments++; + + last_x = x; + last_y = y; + } - SETPOINTER(args, path->path_id); // path id - SETFLOAT(args + 1, luaL_checknumber(L, 2)); // x1 - SETFLOAT(args + 2, luaL_checknumber(L, 3)); // y1 - SETFLOAT(args + 3, luaL_checknumber(L, 4)); // x2 - SETFLOAT(args + 4, luaL_checknumber(L, 5)); // y2 - SETFLOAT(args + 5, luaL_checknumber(L, 6)); // x3 - SETFLOAT(args + 6, luaL_checknumber(L, 7)); // y3 + plugdata_draw(gfx->object, gensym("lua_stroke_path"), num_real_segments * 2 + 1, coordinates); + free(coordinates); - // Forward the message to the appropriate function - plugdata_draw_path(gensym("lua_cubic_to"), 7, args); return 0; } -static int close_path(lua_State* L) { - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); +static int fill_path(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; - t_atom args; - SETPOINTER(&args, path->path_id); // path id + t_canvas *cnv = glist_getcanvas(obj->canvas); - plugdata_draw_path(gensym("lua_close_path"), 1, &args); - return 0; -} - -static int free_path(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - - t_atom args; - SETPOINTER(&args, path->path_id); // path id - plugdata_draw_path(gensym("lua_free_path"), 1, &args); - return 0; -} -static int stroke_path(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + int last_x = 0; + int last_y = 0; - t_atom args[2]; - SETPOINTER(args, path->path_id); // path id - SETFLOAT(args + 1, luaL_checknumber(L, 2)); // line thickness - plugdata_draw(gfx->object, gensym("lua_stroke_path"), 2, args); - return 0; -} + t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom)); + int num_real_segments = 0; -static int fill_path(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + for (int i = 0; i < path->num_path_segments; i++) { + int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + + SETFLOAT(coordinates + (num_real_segments * 2), x); + SETFLOAT(coordinates + (num_real_segments * 2) + 1, y); + num_real_segments++; + + last_x = x; + last_y = y; + } - t_atom args; - SETPOINTER(&args, path->path_id); // path id + plugdata_draw(gfx->object, gensym("lua_fill_path"), num_real_segments * 2, coordinates); + free(coordinates); - plugdata_draw(gfx->object, gensym("lua_fill_path"), 1, &args); return 0; } + static int translate(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; @@ -610,13 +575,6 @@ static void generate_random_id(char *str, size_t len) { str[len - 1] = '\0'; } -static int free_path(lua_State* L) -{ - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - freebytes(path->path_segments, path->num_path_segments_allocated * sizeof(int)); - return 0; -} - static void transform_size(t_pdlua_gfx *gfx, int* w, int* h) { for(int i = gfx->num_transforms - 1; i >= 0; i--) { @@ -1063,6 +1021,118 @@ static int draw_text(lua_State* L) { return 0; } +static int stroke_path(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; + + t_canvas *cnv = glist_getcanvas(obj->canvas); + + t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); + + int obj_x = text_xpix((t_object*)obj, obj->canvas); + int obj_y = text_ypix((t_object*)obj, obj->canvas); + int canvas_zoom = glist_getzoom(cnv); + + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; + + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", 0, 0, 0, 0, "-width", stroke_width, "-fill", gfx->current_color, "-tags", 2, tags); + + int last_x, last_y; + + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); + for (int i = 0; i < path->num_path_segments; i++) { + int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + last_x = x; + last_y = y; + + transform_point(gfx, &x, &y); + sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); + } + sys_vgui("\n"); + + return 0; +} + +static int fill_path(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + t_pdlua *obj = gfx->object; + + t_canvas *cnv = glist_getcanvas(obj->canvas); + + t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + + // Apply transformations to all coordinates + int obj_x = text_xpix((t_object*)obj, obj->canvas); + int obj_y = text_ypix((t_object*)obj, obj->canvas); + int canvas_zoom = glist_getzoom(cnv); + + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; + + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "polygon", 0, 0, 0, 0, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); + + int last_x, last_y; + + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); + for (int i = 0; i < path->num_path_segments; i++) { + int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + last_x = x; + last_y = y; + + transform_point(gfx, &x, &y); + sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); + } + sys_vgui("\n"); + + return 0; +} + + +static int translate(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + + if(gfx->num_transforms == 0) + { + gfx->transforms = getbytes(sizeof(gfx_transform)); + + } + else + { + gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); + + } + + gfx->transforms[gfx->num_transforms].type = TRANSLATE; + gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); + gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); + + gfx->num_transforms++; + return 0; +} + +static int scale(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + + gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); + + gfx->transforms[gfx->num_transforms].type = SCALE; + gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); + gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); + + gfx->num_transforms++; + return 0; +} + +static int reset_transform(lua_State* L) { + t_pdlua_gfx *gfx = pop_graphics_context(L); + freebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform)); + gfx->transforms = NULL; + gfx->num_transforms = 0; + return 0; +} +#endif static void add_path_segment(t_path_state* path, int x, int y) { int path_segment_space = (path->num_path_segments + 1) * 2; @@ -1174,115 +1244,9 @@ static int close_path(lua_State* L) { return 0; } -static int stroke_path(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - t_pdlua *obj = gfx->object; - - t_canvas *cnv = glist_getcanvas(obj->canvas); - - t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - - int obj_x = text_xpix((t_object*)obj, obj->canvas); - int obj_y = text_ypix((t_object*)obj, obj->canvas); - int canvas_zoom = glist_getzoom(cnv); - - const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", 0, 0, 0, 0, "-width", stroke_width, "-fill", gfx->current_color, "-tags", 2, tags); - - int last_x, last_y; - - sys_vgui(".x%lx.c coords %s", cnv, tags[1]); - for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - if(i > 1 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice - last_x = x; - last_y = y; - - transform_point(gfx, &x, &y); - sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); - } - sys_vgui("\n"); - - return 0; -} - -static int fill_path(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - t_pdlua *obj = gfx->object; - - t_canvas *cnv = glist_getcanvas(obj->canvas); - +static int free_path(lua_State* L) +{ t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - - // Apply transformations to all coordinates - int obj_x = text_xpix((t_object*)obj, obj->canvas); - int obj_y = text_ypix((t_object*)obj, obj->canvas); - int canvas_zoom = glist_getzoom(cnv); - - const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - - pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "polygon", 0, 0, 0, 0, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); - - int last_x, last_y; - - sys_vgui(".x%lx.c coords %s", cnv, tags[1]); - for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - if(i > 1 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice - last_x = x; - last_y = y; - - transform_point(gfx, &x, &y); - sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); - } - sys_vgui("\n"); - - return 0; -} - - -static int translate(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - - if(gfx->num_transforms == 0) - { - gfx->transforms = getbytes(sizeof(gfx_transform)); - - } - else - { - gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); - - } - - gfx->transforms[gfx->num_transforms].type = TRANSLATE; - gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); - gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); - - gfx->num_transforms++; - return 0; -} - -static int scale(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - - gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); - - gfx->transforms[gfx->num_transforms].type = SCALE; - gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); - gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); - - gfx->num_transforms++; - return 0; -} - -static int reset_transform(lua_State* L) { - t_pdlua_gfx *gfx = pop_graphics_context(L); - freebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform)); - gfx->transforms = NULL; - gfx->num_transforms = 0; + freebytes(path->path_segments, path->num_path_segments_allocated * sizeof(int)); return 0; } -#endif From 34cd81550e796ee58a25dd82c11ea8841938352a Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Sat, 20 Apr 2024 23:26:03 +0200 Subject: [PATCH 04/10] Fixed rounding problems for path drawing --- pdlua_gfx.h | 383 +++++++++++++++++++++++++++------------------------- 1 file changed, 202 insertions(+), 181 deletions(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index 69cdf6a..ba8034c 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -110,14 +110,14 @@ void pdlua_gfx_repaint(t_pdlua *o, int firsttime) { lua_getglobal(__L(), "pd"); lua_getfield (__L(), -1, "_repaint"); lua_pushlightuserdata(__L(), o); - - + + if (lua_pcall(__L(), 1, 0, 0)) { pd_error(o, "lua: error in repaint:\n%s", lua_tostring(__L(), -1)); lua_pop(__L(), 1); /* pop the error string */ } - + lua_pop(__L(), 1); /* pop the global "pd" */ #if !PLUGDATA o->gfx.first_draw = 0; @@ -126,20 +126,20 @@ void pdlua_gfx_repaint(t_pdlua *o, int firsttime) { // Pass mouse events to lua script void pdlua_gfx_mouse_event(t_pdlua *o, int x, int y, int type) { - + lua_getglobal(__L(), "pd"); lua_getfield (__L(), -1, "_mouseevent"); lua_pushlightuserdata(__L(), o); lua_pushinteger(__L(), x); lua_pushinteger(__L(), y); lua_pushinteger(__L(), type); - + if (lua_pcall(__L(), 4, 0, 0)) { pd_error(o, "lua: error in mouseevent:\n%s", lua_tostring(__L(), -1)); lua_pop(__L(), 1); /* pop the error string */ } - + lua_pop(__L(), 1); /* pop the global "pd" */ } @@ -165,10 +165,10 @@ void pdlua_gfx_mouse_drag(t_pdlua *o, int x, int y) { typedef struct _path_state { // Variables for managing vector paths - int* path_segments; + float* path_segments; int num_path_segments; int num_path_segments_allocated; - int path_start_x, path_start_y; + float path_start_x, path_start_y; } t_path_state; @@ -222,7 +222,7 @@ int pdlua_gfx_setup(lua_State* L) { // for Path(x, y) constructor lua_pushcfunction(L, start_path); lua_setglobal(L, "Path"); - + luaL_newmetatable(L, "Path"); lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); @@ -232,11 +232,11 @@ int pdlua_gfx_setup(lua_State* L) { lua_pushvalue(L, -1); lua_setfield(L, -2, "__index"); luaL_setfuncs(L, gfx_methods, 0); - + // Register functions with Lua luaL_newlib(L, gfx_lib); lua_setglobal(L, "_gfx_internal"); - + return 1; // Number of values pushed onto the stack } @@ -245,7 +245,7 @@ static int get_size(lua_State* L) if (!lua_islightuserdata(L, 1)) { return 0; } - + t_pdlua *obj = (t_pdlua*)lua_touserdata(L, 1); lua_pushnumber(L, (lua_Number)obj->gfx.width); lua_pushnumber(L, (lua_Number)obj->gfx.height); @@ -288,7 +288,7 @@ static int set_size(lua_State* L) if (!lua_islightuserdata(L, 1)) { return 0; } - + t_pdlua *obj = (t_pdlua*)lua_touserdata(L, 1); obj->gfx.width = luaL_checknumber(L, 2); obj->gfx.height = luaL_checknumber(L, 3); @@ -305,10 +305,10 @@ static int start_paint(lua_State* L) { return 1; } t_pdlua *obj = (t_pdlua*)lua_touserdata(L, 1); - + lua_pushlightuserdata(L, &obj->gfx); luaL_setmetatable(L, "GraphicsContext"); - + plugdata_draw_callback = obj->gfx.plugdata_draw_callback; plugdata_draw(obj, gensym("lua_start_paint"), 0, NULL); return 1; @@ -330,12 +330,12 @@ static int set_color(lua_State* L) { plugdata_draw(obj, gensym("lua_set_color"), 1, &arg); return 0; } - + t_atom args[4]; SETFLOAT(args, luaL_checknumber(L, 1)); // r SETFLOAT(args + 1, luaL_checknumber(L, 2)); // g SETFLOAT(args + 2, luaL_checknumber(L, 3)); // b - + if (lua_gettop(L) > 4) { // object and table are already on stack, hence 5 // alpha (optional, default to 1.0) SETFLOAT(args + 3, luaL_checknumber(L, 4)); @@ -434,7 +434,7 @@ static int draw_line(lua_State* L) { SETFLOAT(args + 3, luaL_checknumber(L, 4)); // h SETFLOAT(args + 4, luaL_checknumber(L, 5)); // line width plugdata_draw(gfx->object, gensym("lua_draw_line"), 5, args); - + return 0; } @@ -454,67 +454,67 @@ static int draw_text(lua_State* L) { static int stroke_path(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - - int last_x = 0; - int last_y = 0; - + + float last_x = 0; + float last_y = 0; + t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom) + 1); SETFLOAT(coordinates, stroke_width); - + int num_real_segments = 0; for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice SETFLOAT(coordinates + (num_real_segments * 2) + 1, x); SETFLOAT(coordinates + (num_real_segments * 2) + 2, y); num_real_segments++; - + last_x = x; last_y = y; } - + plugdata_draw(gfx->object, gensym("lua_stroke_path"), num_real_segments * 2 + 1, coordinates); free(coordinates); - + return 0; } static int fill_path(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - int last_x = 0; - int last_y = 0; - + float last_x = 0; + float last_y = 0; + t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom)); int num_real_segments = 0; for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice SETFLOAT(coordinates + (num_real_segments * 2), x); SETFLOAT(coordinates + (num_real_segments * 2) + 1, y); num_real_segments++; - + last_x = x; last_y = y; } - + plugdata_draw(gfx->object, gensym("lua_fill_path"), num_real_segments * 2, coordinates); free(coordinates); - + return 0; } @@ -555,7 +555,7 @@ static unsigned long long custom_rand() { const unsigned long long m = 4294967296; // 2^32 seed = (a * seed + c) % m; if(seed == 0) seed = 1; // We cannot return 0 since we use modulo on this. Having the rhs operator of % be zero leads to div-by-zero error on Windows - + return seed; } @@ -563,15 +563,15 @@ static unsigned long long custom_rand() { static void generate_random_id(char *str, size_t len) { const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; size_t charset_len = strlen(charset); - + str[0] = '.'; str[1] = 'x'; - + for (size_t i = 2; i < len - 1; ++i) { int key = custom_rand() % charset_len; str[i] = charset[key]; } - + str[len - 1] = '\0'; } @@ -602,12 +602,27 @@ static void transform_point(t_pdlua_gfx *gfx, int* x, int* y) { } } +static void transform_point_float(t_pdlua_gfx *gfx, float* x, float* y) { + for(int i = gfx->num_transforms - 1; i >= 0; i--) + { + if(gfx->transforms[i].type == SCALE) + { + *x *= gfx->transforms[i].x; + *y *= gfx->transforms[i].y; + } + else // translate + { + *x += gfx->transforms[i].x; + *y += gfx->transforms[i].y; + } + } +} static void pdlua_gfx_clear(t_pdlua *obj, int removed) { t_pdlua_gfx *gfx = &obj->gfx; t_canvas *cnv = glist_getcanvas(obj->canvas); pdgui_vmess(0, "crs", cnv, "delete", gfx->object_tag); - + if(removed && gfx->order_tag[0] != '\0') { pdgui_vmess(0, "crs", cnv, "delete", gfx->order_tag); @@ -619,18 +634,18 @@ static void pdlua_gfx_clear(t_pdlua *obj, int removed) { static void get_bounds_args(lua_State* L, t_pdlua *obj, int* x1, int* y1, int* x2, int* y2) { t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x = luaL_checknumber(L, 1); int y = luaL_checknumber(L, 2); int w = luaL_checknumber(L, 3); int h = luaL_checknumber(L, 4); - + transform_point(&obj->gfx, &x, &y); transform_size(&obj->gfx, &w, &h); - + x += text_xpix((t_object*)obj, obj->canvas) / glist_getzoom(cnv); y += text_ypix((t_object*)obj, obj->canvas) / glist_getzoom(cnv); - + *x1 = x * glist_getzoom(cnv); *y1 = y * glist_getzoom(cnv); *x2 = (x + w) * glist_getzoom(cnv); @@ -641,9 +656,9 @@ static void gfx_displace(t_pdlua *x, t_glist *glist, int dx, int dy) { sys_vgui(".x%lx.c move .x%lx %d %d\n", glist_getcanvas(x->canvas), (long)x, dx, dy); canvas_fixlinesfor(glist, (t_text*)x); - + int scale = glist_getzoom(glist_getcanvas(x->canvas)); - + int xpos = text_xpix((t_object*)x, x->canvas); int ypos = text_ypix((t_object*)x, x->canvas); glist_drawiofor(x->canvas, (t_object*)x, 0, x->gfx.object_tag, xpos, ypos, xpos + (x->gfx.width * scale), ypos + (x->gfx.height * scale)); @@ -658,14 +673,14 @@ static const char* register_drawing(t_pdlua_gfx *gfx) static int gfx_initialize(t_pdlua *obj) { t_pdlua_gfx *gfx = &obj->gfx; - + snprintf(gfx->object_tag, 128, ".x%lx", (long)obj); gfx->object_tag[127] = '\0'; gfx->order_tag[0] = '\0'; gfx->object = obj; gfx->transforms = NULL; gfx->num_transforms = 0; - + pdlua_gfx_repaint(obj, 0); return 0; } @@ -675,7 +690,7 @@ static int set_size(lua_State* L) if (!lua_islightuserdata(L, 1)) { return 0; } - + t_pdlua *obj = (t_pdlua*)lua_touserdata(L, 1); obj->gfx.width = luaL_checknumber(L, 2); obj->gfx.height = luaL_checknumber(L, 3); @@ -689,7 +704,7 @@ static int start_paint(lua_State* L) { lua_pushnil(L); return 1; } - + t_pdlua* obj = (t_pdlua*)lua_touserdata(L, 1); t_pdlua_gfx *gfx = &obj->gfx; if(gfx->object_tag[0] == '\0') @@ -708,13 +723,13 @@ static int start_paint(lua_State* L) { if(gfx->transforms) freebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform)); gfx->num_transforms = 0; gfx->transforms = NULL; - + lua_pushlightuserdata(L, gfx); luaL_setmetatable(L, "GraphicsContext"); - + // clear anything that was painted before if(strlen(gfx->object_tag)) pdlua_gfx_clear(obj, 0); - + if(gfx->first_draw) { // Whenever the objects gets painted for the first time with a "vis" message, @@ -722,12 +737,12 @@ static int start_paint(lua_State* L) { // We can then use this line to set the correct z-index for the drawings, using the tcl/tk "lower" command t_canvas *cnv = glist_getcanvas(obj->canvas); generate_random_id(gfx->order_tag, 64); - + const char* tags[] = { gfx->order_tag }; pdgui_vmess(0, "crr iiii ri rS", cnv, "create", "line", 0, 0, 0, 0, "-width", 1, "-tags", 1, tags); } - + return 1; } @@ -739,26 +754,26 @@ static int end_paint(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = (t_pdlua*)gfx->object; t_canvas *cnv = glist_getcanvas(obj->canvas); - + int scale = glist_getzoom(glist_getcanvas(obj->canvas)); - + // Draw iolets on top int xpos = text_xpix((t_object*)obj, obj->canvas); int ypos = text_ypix((t_object*)obj, obj->canvas); - + glist_drawiofor(glist_getcanvas(obj->canvas), (t_object*)obj, 1, gfx->object_tag, xpos, ypos, xpos + (gfx->width * scale), ypos + (gfx->height * scale)); - + if(!gfx->first_draw && gfx->order_tag[0] != '\0') { // Move everything to below the order marker, to make sure redrawn stuff isn't always on top pdgui_vmess(0, "crss", cnv, "lower", gfx->object_tag, gfx->order_tag); } - + return 0; } static int set_color(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); - + int r, g, b; if (lua_gettop(L) == 1) { // Single argument: parse as color ID instead of RGB int color_id = luaL_checknumber(L, 1); @@ -783,102 +798,102 @@ static int set_color(lua_State* L) { // AFAIK, alpha is not supported in tcl/tk snprintf(gfx->current_color, 8, "#%02X%02X%02X", r, g, b); gfx->current_color[7] = '\0'; - + return 0; } static int fill_ellipse(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1, y1, x2, y2; get_bounds_args(L, obj, &x1, &y1, &x2, &y2); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + pdgui_vmess(0, "crr iiii rs ri rS", cnv, "create", "oval", x1, y1, x2, y2, "-fill", gfx->current_color, "-width", 0, "-tags", 2, tags); - + return 0; } static int stroke_ellipse(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); int x1, y1, x2, y2; get_bounds_args(L, obj, &x1, &y1, &x2, &y2); - + int line_width = luaL_checknumber(L, 5) * glist_getzoom(cnv); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "oval", x1, y1, x2, y2, "-width", line_width, "-outline", gfx->current_color, "-tags", 2, tags); - + return 0; } static int fill_all(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1 = text_xpix((t_object*)obj, obj->canvas); int y1 = text_ypix((t_object*)obj, obj->canvas); int x2 = x1 + gfx->width * glist_getzoom(cnv); int y2 = y1 + gfx->height * glist_getzoom(cnv); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + pdgui_vmess(0, "crr iiii rs rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-fill", gfx->current_color, "-tags", 2, tags); - + return 0; } static int fill_rect(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1, y1, x2, y2; get_bounds_args(L, obj, &x1, &y1, &x2, &y2); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + pdgui_vmess(0, "crr iiii rs ri rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-fill", gfx->current_color, "-width", 0, "-tags", 2, tags); - + return 0; } static int stroke_rect(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1, y1, x2, y2; get_bounds_args(L, obj, &x1, &y1, &x2, &y2); int line_width = luaL_checknumber(L, 5) * glist_getzoom(cnv); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "rectangle", x1, y1, x2, y2, "-width", line_width, "-outline", gfx->current_color, "-tags", 2, tags); - + return 0; } static int fill_rounded_rect(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1, y1, x2, y2; get_bounds_args(L, obj, &x1, &y1, &x2, &y2); @@ -887,7 +902,7 @@ static int fill_rounded_rect(lua_State* L) { int radius_y = radius * glist_getzoom(cnv); transform_size(gfx, &radius_x, &radius_y); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; // Tcl/tk can't fill rounded rectangles, so we draw 2 smaller rectangles with 4 ovals over the corners @@ -904,20 +919,20 @@ static int fill_rounded_rect(lua_State* L) { static int stroke_rounded_rect(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1, y1, x2, y2; get_bounds_args(L, obj, &x1, &y1, &x2, &y2); - + int radius = luaL_checknumber(L, 5); // Radius for rounded corners int radius_x = radius * glist_getzoom(cnv); int radius_y = radius * glist_getzoom(cnv); transform_size(gfx, &radius_x, &radius_y); int line_width = luaL_checknumber(L, 6) * glist_getzoom(cnv); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + // Tcl/tk can't stroke rounded rectangles either, so we draw 2 lines connecting with 4 arcs at the corners pdgui_vmess(0, "crr iiii ri ri ri ri rs rs rS", cnv, "create", "arc", x1, y1 + radius_y*2, x1 + radius_x*2, y1, "-start", 0, "-extent", 90, "-width", line_width, "-start", 90, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); @@ -927,7 +942,7 @@ static int stroke_rounded_rect(lua_State* L) { "-start", 180, "-extent", 90, "-width", line_width, "-start", 180, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri ri ri ri rs rs rS", cnv, "create", "arc", x2 - radius_x*2, y2, x2, y2 - radius_y*2, "-start", 90, "-extent", 90, "-width", line_width, "-start", 270, "-outline", gfx->current_color, "-style", "arc", "-tags", 2, tags); - + // Connect with lines pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x1 + radius_x, y1, x2 - radius_x, y1, "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); @@ -937,25 +952,25 @@ static int stroke_rounded_rect(lua_State* L) { "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x2 , y1 + radius_y, x2, y2 - radius_y, "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); - + return 0; } static int draw_line(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + int x1 = luaL_checknumber(L, 1); int y1 = luaL_checknumber(L, 2); int x2 = luaL_checknumber(L, 3); int y2 = luaL_checknumber(L, 4); int line_width = luaL_checknumber(L, 5); - + transform_point(gfx, &x1, &y1); transform_point(gfx, &x2, &y2); - + int canvas_zoom = glist_getzoom(cnv); x1 += text_xpix((t_object*)obj, obj->canvas) / canvas_zoom; @@ -968,9 +983,9 @@ static int draw_line(lua_State* L) { x2 *= canvas_zoom; y2 *= canvas_zoom; line_width *= canvas_zoom; - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", x1, y1, x2, y2, "-width", line_width, "-fill", gfx->current_color, "-tags", 2, tags); @@ -980,29 +995,29 @@ static int draw_line(lua_State* L) { static int draw_text(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + const char* text = luaL_checkstring(L, 1); // Assuming text is a string int x = luaL_checknumber(L, 2); int y = luaL_checknumber(L, 3); int w = luaL_checknumber(L, 4); int font_height = luaL_checknumber(L, 5); font_height = sys_hostfontsize(font_height, glist_getzoom(cnv)); - + transform_point(gfx, &x, &y); transform_size(gfx, &w, &font_height); - + int canvas_zoom = glist_getzoom(cnv); x += text_xpix((t_object*)obj, obj->canvas) / canvas_zoom; y += text_ypix((t_object*)obj, obj->canvas) / canvas_zoom; - + x *= canvas_zoom; y *= canvas_zoom; w *= canvas_zoom; - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; - + pdgui_vmess(0, "crr ii rs ri rs rS", cnv, "create", "text", 0, 0, "-anchor", "nw", "-width", w, "-text", text, "-tags", 2, tags); @@ -1015,77 +1030,83 @@ static int draw_text(lua_State* L) { "-font", 3, fontatoms, "-fill", gfx->current_color, "-justify", "left"); - + pdgui_vmess(0, "crs ii", cnv, "coords", tags[1], x, y); - + return 0; } static int stroke_path(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + if(path->num_path_segments < 3) + { + return 0; + } + int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - int obj_x = text_xpix((t_object*)obj, obj->canvas); int obj_y = text_ypix((t_object*)obj, obj->canvas); int canvas_zoom = glist_getzoom(cnv); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", 0, 0, 0, 0, "-width", stroke_width, "-fill", gfx->current_color, "-tags", 2, tags); - - int last_x, last_y; - + + float last_x, last_y; + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; last_x = x; last_y = y; - - transform_point(gfx, &x, &y); - sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); + + transform_point_float(gfx, &x, &y); + sys_vgui(" %f %f", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); } sys_vgui("\n"); - + return 0; } static int fill_path(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); t_pdlua *obj = gfx->object; - + t_canvas *cnv = glist_getcanvas(obj->canvas); - + t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); + if(path->num_path_segments < 3) + { + return 0; + } // Apply transformations to all coordinates int obj_x = text_xpix((t_object*)obj, obj->canvas); int obj_y = text_ypix((t_object*)obj, obj->canvas); int canvas_zoom = glist_getzoom(cnv); - + const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "polygon", 0, 0, 0, 0, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); - - int last_x, last_y; - + + float last_x, last_y; + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); for (int i = 0; i < path->num_path_segments; i++) { - int x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice + float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; last_x = x; last_y = y; - - transform_point(gfx, &x, &y); - sys_vgui(" %d %d", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); + + transform_point_float(gfx, &x, &y); + sys_vgui(" %f %f", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); } sys_vgui("\n"); - + return 0; } @@ -1096,31 +1117,31 @@ static int translate(lua_State* L) { if(gfx->num_transforms == 0) { gfx->transforms = getbytes(sizeof(gfx_transform)); - + } else { gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); - + } - + gfx->transforms[gfx->num_transforms].type = TRANSLATE; gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); - + gfx->num_transforms++; return 0; } static int scale(lua_State* L) { t_pdlua_gfx *gfx = pop_graphics_context(L); - + gfx->transforms = resizebytes(gfx->transforms, gfx->num_transforms * sizeof(gfx_transform), (gfx->num_transforms + 1) * sizeof(gfx_transform)); - + gfx->transforms[gfx->num_transforms].type = SCALE; gfx->transforms[gfx->num_transforms].x = luaL_checknumber(L, 1); gfx->transforms[gfx->num_transforms].y = luaL_checknumber(L, 2); - + gfx->num_transforms++; return 0; } @@ -1133,20 +1154,20 @@ static int reset_transform(lua_State* L) { return 0; } #endif -static void add_path_segment(t_path_state* path, int x, int y) +static void add_path_segment(t_path_state* path, float x, float y) { int path_segment_space = (path->num_path_segments + 1) * 2; int old_size = path->num_path_segments_allocated; int new_size = MAX(path_segment_space, path->num_path_segments_allocated); if(!path->num_path_segments_allocated) { - path->path_segments = (int*)getbytes(new_size * sizeof(int)); + path->path_segments = (float*)getbytes(new_size * sizeof(float)); } else { - path->path_segments = (int*)resizebytes(path->path_segments, old_size * sizeof(int), new_size * sizeof(int)); + path->path_segments = (float*)resizebytes(path->path_segments, old_size * sizeof(float), new_size * sizeof(float)); } path->num_path_segments_allocated = new_size; - + path->path_segments[path->num_path_segments * 2] = x; path->path_segments[path->num_path_segments * 2 + 1] = y; path->num_path_segments++; @@ -1160,7 +1181,7 @@ static int start_path(lua_State* L) { path->num_path_segments_allocated = 0; path->path_start_x = luaL_checknumber(L, 1); path->path_start_y = luaL_checknumber(L, 2); - + add_path_segment(path, path->path_start_x, path->path_start_y); return 1; } @@ -1168,72 +1189,72 @@ static int start_path(lua_State* L) { // Function to add a line to the current path static int line_to(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - int x = luaL_checknumber(L, 2); - int y = luaL_checknumber(L, 3); + float x = luaL_checknumber(L, 2); + float y = luaL_checknumber(L, 3); add_path_segment(path, x, y); return 0; } static int quad_to(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - int x2 = luaL_checknumber(L, 2); - int y2 = luaL_checknumber(L, 3); - int x3 = luaL_checknumber(L, 4); - int y3 = luaL_checknumber(L, 5); - - int x1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2] : x2; - int y1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2 + 1] : y2; - + float x2 = luaL_checknumber(L, 2); + float y2 = luaL_checknumber(L, 3); + float x3 = luaL_checknumber(L, 4); + float y3 = luaL_checknumber(L, 5); + + float x1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2] : x2; + float y1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2 + 1] : y2; + // heuristic for deciding the number of lines in our bezier curve float dx = x3 - x1; float dy = y3 - y1; float distance = sqrtf(dx * dx + dy * dy); float resolution = MAX(10.0f, distance); - + // Get the last point float t = 0.0; while (t <= 1.0) { t += 1.0 / resolution; - + // Calculate quadratic bezier curve as points (source: https://en.wikipedia.org/wiki/B%C3%A9zier_curve) - int x = (1.0f - t) * (1.0f - t) * x1 + 2.0f * (1.0f - t) * t * x2 + t * t * x3; - int y = (1.0f - t) * (1.0f - t) * y1 + 2.0f * (1.0f - t) * t * y2 + t * t * y3; + float x = (1.0f - t) * (1.0f - t) * x1 + 2.0f * (1.0f - t) * t * x2 + t * t * x3; + float y = (1.0f - t) * (1.0f - t) * y1 + 2.0f * (1.0f - t) * t * y2 + t * t * y3; add_path_segment(path, x, y); } - + return 0; } static int cubic_to(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - int x2 = luaL_checknumber(L, 2); - int y2 = luaL_checknumber(L, 3); - int x3 = luaL_checknumber(L, 4); - int y3 = luaL_checknumber(L, 5); - int x4 = luaL_checknumber(L, 6); - int y4 = luaL_checknumber(L, 7); - - int x1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2] : x2; - int y1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2 + 1] : y2; - + float x2 = luaL_checknumber(L, 2); + float y2 = luaL_checknumber(L, 3); + float x3 = luaL_checknumber(L, 4); + float y3 = luaL_checknumber(L, 5); + float x4 = luaL_checknumber(L, 6); + float y4 = luaL_checknumber(L, 7); + + float x1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2] : x2; + float y1 = path->num_path_segments > 0 ? path->path_segments[(path->num_path_segments - 1) * 2 + 1] : y2; + // heuristic for deciding the number of lines in our bezier curve float dx = x3 - x1; float dy = y3 - y1; float distance = sqrtf(dx * dx + dy * dy); float resolution = MAX(10.0f, distance); - + // Get the last point float t = 0.0; while (t <= 1.0) { t += 1.0 / resolution; // Calculate cubic bezier curve as points (source: https://en.wikipedia.org/wiki/B%C3%A9zier_curve) - int x = (1 - t)*(1 - t)*(1 - t) * x1 + 3 * (1 - t)*(1 - t) * t * x2 + 3 * (1 - t) * t*t * x3 + t*t*t * x4; - int y = (1 - t)*(1 - t)*(1 - t) * y1 + 3 * (1 - t)*(1 - t) * t * y2 + 3 * (1 - t) * t*t * y3 + t*t*t * y4; - + float x = (1 - t)*(1 - t)*(1 - t) * x1 + 3 * (1 - t)*(1 - t) * t * x2 + 3 * (1 - t) * t*t * x3 + t*t*t * x4; + float y = (1 - t)*(1 - t)*(1 - t) * y1 + 3 * (1 - t)*(1 - t) * t * y2 + 3 * (1 - t) * t*t * y3 + t*t*t * y4; + add_path_segment(path, x, y); } - + return 0; } From 2962ea5c92f9e61dbd5da6247d27609b9f2251ca Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Thu, 25 Apr 2024 00:57:57 +0200 Subject: [PATCH 05/10] Don't call to canvas_fixlinesfor if the patch isn't currently visible to prevent error message --- pdlua_gfx.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index ba8034c..b382182 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -695,7 +695,9 @@ static int set_size(lua_State* L) obj->gfx.width = luaL_checknumber(L, 2); obj->gfx.height = luaL_checknumber(L, 3); pdlua_gfx_repaint(obj, 0); - canvas_fixlinesfor(obj->canvas, (t_text*)obj); + if(glist_isvisible(obj->canvas) && gobj_shouldvis(&obj->pd.te_g, obj->canvas)) { + canvas_fixlinesfor(obj->canvas, (t_text*)obj); + } return 0; } From 33f6a7e941d37d2241acfabeafb6ec8dd52e0bdc Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Thu, 25 Apr 2024 17:06:02 +0200 Subject: [PATCH 06/10] Cleaned up --- pdlua_gfx.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index b382182..213baeb 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -1058,15 +1058,10 @@ static int stroke_path(lua_State* L) { const char* tags[] = { gfx->object_tag, register_drawing(gfx) }; pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "line", 0, 0, 0, 0, "-width", stroke_width, "-fill", gfx->current_color, "-tags", 2, tags); - - float last_x, last_y; - + sys_vgui(".x%lx.c coords %s", cnv, tags[1]); for (int i = 0; i < path->num_path_segments; i++) { float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - last_x = x; - last_y = y; - transform_point_float(gfx, &x, &y); sys_vgui(" %f %f", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); } @@ -1096,14 +1091,9 @@ static int fill_path(lua_State* L) { pdgui_vmess(0, "crr iiii ri rs rS", cnv, "create", "polygon", 0, 0, 0, 0, "-width", 0, "-fill", gfx->current_color, "-tags", 2, tags); - float last_x, last_y; - sys_vgui(".x%lx.c coords %s", cnv, tags[1]); for (int i = 0; i < path->num_path_segments; i++) { float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - last_x = x; - last_y = y; - transform_point_float(gfx, &x, &y); sys_vgui(" %f %f", (x * canvas_zoom) + obj_x, (y * canvas_zoom) + obj_y); } From 59ec850530b0fab06e846163af8950ba8fc89a36 Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Thu, 25 Apr 2024 17:07:21 +0200 Subject: [PATCH 07/10] Cleaned up --- pdlua_gfx.h | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index 213baeb..54fceb0 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -460,27 +460,16 @@ static int stroke_path(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - float last_x = 0; - float last_y = 0; - t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom) + 1); SETFLOAT(coordinates, stroke_width); - int num_real_segments = 0; - for (int i = 0; i < path->num_path_segments; i++) { float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice - - SETFLOAT(coordinates + (num_real_segments * 2) + 1, x); - SETFLOAT(coordinates + (num_real_segments * 2) + 2, y); - num_real_segments++; - - last_x = x; - last_y = y; + SETFLOAT(coordinates + (path->num_path_segments * 2) + 1, x); + SETFLOAT(coordinates + (path->num_path_segments * 2) + 2, y); } - plugdata_draw(gfx->object, gensym("lua_stroke_path"), num_real_segments * 2 + 1, coordinates); + plugdata_draw(gfx->object, gensym("lua_stroke_path"), path->num_path_segments * 2 + 1, coordinates); free(coordinates); return 0; @@ -494,25 +483,15 @@ static int fill_path(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); - float last_x = 0; - float last_y = 0; - t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom)); - int num_real_segments = 0; - + for (int i = 0; i < path->num_path_segments; i++) { - float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - if(i != 0 && x == last_x && y == last_y) continue; // In case integer rounding causes the same point twice - - SETFLOAT(coordinates + (num_real_segments * 2), x); - SETFLOAT(coordinates + (num_real_segments * 2) + 1, y); - num_real_segments++; - - last_x = x; - last_y = y; + float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; + SETFLOAT(coordinates + (path->num_path_segments * 2), x); + SETFLOAT(coordinates + (path->num_path_segments * 2) + 1, y); } - plugdata_draw(gfx->object, gensym("lua_fill_path"), num_real_segments * 2, coordinates); + plugdata_draw(gfx->object, gensym("lua_fill_path"), path->num_path_segments * 2, coordinates); free(coordinates); return 0; From 747d4b9e2c6fac308cf7fa90538e2fa9add2095a Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Tue, 30 Apr 2024 16:46:42 +0200 Subject: [PATCH 08/10] Bugfix for plugdata --- pdlua_gfx.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index 54fceb0..dcedfa2 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -465,8 +465,8 @@ static int stroke_path(lua_State* L) { for (int i = 0; i < path->num_path_segments; i++) { float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - SETFLOAT(coordinates + (path->num_path_segments * 2) + 1, x); - SETFLOAT(coordinates + (path->num_path_segments * 2) + 2, y); + SETFLOAT(coordinates + (i * 2) + 1, x); + SETFLOAT(coordinates + (i * 2) + 2, y); } plugdata_draw(gfx->object, gensym("lua_stroke_path"), path->num_path_segments * 2 + 1, coordinates); @@ -487,8 +487,8 @@ static int fill_path(lua_State* L) { for (int i = 0; i < path->num_path_segments; i++) { float x = path->path_segments[i * 2], y = path->path_segments[i * 2 + 1]; - SETFLOAT(coordinates + (path->num_path_segments * 2), x); - SETFLOAT(coordinates + (path->num_path_segments * 2) + 1, y); + SETFLOAT(coordinates + (i * 2), x); + SETFLOAT(coordinates + (i * 2) + 1, y); } plugdata_draw(gfx->object, gensym("lua_fill_path"), path->num_path_segments * 2, coordinates); From ed038ea36da8f0fb3730ed0260ce97a2916e3fc0 Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Thu, 13 Jun 2024 13:50:57 +0200 Subject: [PATCH 09/10] Fixed memory bug in plugdata --- pdlua_gfx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdlua_gfx.h b/pdlua_gfx.h index dcedfa2..4868a29 100644 --- a/pdlua_gfx.h +++ b/pdlua_gfx.h @@ -460,7 +460,7 @@ static int stroke_path(lua_State* L) { t_path_state* path = (t_path_state*)luaL_checkudata(L, 1, "Path"); int stroke_width = luaL_checknumber(L, 2) * glist_getzoom(cnv); - t_atom* coordinates = malloc(2 * path->num_path_segments * sizeof(t_atom) + 1); + t_atom* coordinates = malloc((2 * path->num_path_segments + 2) * sizeof(t_atom)); SETFLOAT(coordinates, stroke_width); for (int i = 0; i < path->num_path_segments; i++) { From 22a28233d11ef8dc36eb0b13f41a9d83fbd63895 Mon Sep 17 00:00:00 2001 From: Timothy Schoen Date: Fri, 14 Jun 2024 16:54:02 +0200 Subject: [PATCH 10/10] Fixed clock crash --- pd.lua | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pd.lua b/pd.lua index 94195ac..d644b97 100644 --- a/pd.lua +++ b/pd.lua @@ -184,14 +184,16 @@ function pd.Clock:destruct() end function pd.Clock:dispatch() - local m = self._target[self._method] - if type(m) == "function" then - return m(self._target) - else - self._target:error( - "no method for `" .. self._method .. - "' at clock of Lua object `" .. self._name .. "'" - ) + if pd._objects[self._target] then + local m = self._target[self._method] + if type(m) == "function" then + return m(self._target) + else + self._target:error( + "no method for `" .. self._method .. + "' at clock of Lua object `" .. self._name .. "'" + ) + end end end