[gegl] bin: improve graph layout
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] bin: improve graph layout
- Date: Sat, 19 Jan 2019 18:48:56 +0000 (UTC)
commit 7a3712df2bd5b7b04ebf0b5e1f518a88595b917f
Author: Øyvind Kolås <pippin gimp org>
Date: Thu Jan 17 19:49:01 2019 +0100
bin: improve graph layout
Adding edges representing connections between nodes, permitting visualization
of graphs that have clones/multiple consumers of the same node.
The graph rendering is preliminary.
bin/ui.c | 456 +++++++++++++++++++++++-------------
operations/external/vector-stroke.c | 11 +-
2 files changed, 296 insertions(+), 171 deletions(-)
---
diff --git a/bin/ui.c b/bin/ui.c
index 5b407e67c..b734be8d0 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -28,14 +28,21 @@
#if HAVE_MRG
const char *css =
-"div.properties { color: blue; position: absolute; top: 1em; left: 22em; }\n"
-"div.property { color: white; margin-top: -.5em; }\n"
-"div.propname { color: white; background: rgba(0,0,0,0.25); }\n"
-"div.propvalue { color: yellow; background: rgba(0,0,0,0.75); }\n"
+"div.properties { color: blue; padding-left:1em; padding-bottom: 1em; position: absolute; top: 50%; left: 0;
width:60%; background-color:rgba(1,0,0,0.5);}\n"
+"div.property { color: white; margin-top: -.5em; background:transparent;}\n"
+"div.propname { color: white;}\n"
+"div.propvalue { color: yellow;}\n"
"dl.bindings { font-size: 1.8vh; color:white; position:absolute;left:1em;top:0%;background-color:
rgba(0,0,0,0.7); width: 100%; height: 40%; padding-left: 1em; padding-top:1em;}\n"
"dt.binding { color:white; }\n"
+"div.graph {position:absolute; top: 0; left: 0; width:30%; height:50%; color:white; }\n"
+
+
+"div.activenode, div.node {border: 1px solid white; background-color: rgba(0,0,0,0.4); color:white;
display:inline; padding-left:1em;padding-right:1em;padding-top:1em;padding-bottom:1em;}\n"
+
+
+"div.props {}\n"
"a { color: yellow; text-decoration: none; }\n"
@@ -69,8 +76,13 @@ void mrg_gegl_dirty (void);
#include "mrg-gegl.h"
#include "argvs.h"
-/* set this to 1 to print the active gegl chain
+/* gets the node which is the direct consumer, and not a clone.
+ *
+ * valid after update_ui_consumers_list (State *o, GeglNode *iter)
*/
+static GeglNode *gegl_node_get_ui_consumer (GeglNode *node,
+ const char *output_pad,
+ const char **consumer_pad);
static GeglNode *gegl_node_get_consumer_no (GeglNode *node,
const char *output_pad,
@@ -414,8 +426,8 @@ static void populate_path_list (State *o)
}
}
-
- // XXX should free namelist[0..n]
+ for (int i = 0; i < n;i++)
+ free(namelist[i]);
free (namelist);
}
@@ -984,6 +996,8 @@ static void on_paint_drag (MrgEvent *e, void *data1, void *data2)
case MRG_DRAG_PRESS:
o->active = add_output (o, o->active, "gegl:over");
o->active = add_aux (o, o->active, "gegl:vector-stroke");
+ /* XXX: gegl:vector-stroke is written to be able to have a chain of it be succesive strokes,
+ it seems like tiles of the buffer are not properly synced for that */
path = gegl_path_new ();
gegl_path_append (path, 'M', x, y);
@@ -995,7 +1009,7 @@ static void on_paint_drag (MrgEvent *e, void *data1, void *data2)
gegl_path_append (path, 'L', x, y);
break;
case MRG_DRAG_RELEASE:
- o->active = gegl_node_get_consumer_no (o->active, "output", NULL, 0);
+ o->active = gegl_node_get_ui_consumer (o->active, "output", NULL);
break;
}
renderer_dirty++;
@@ -1046,7 +1060,7 @@ static void on_move_drag (MrgEvent *e, void *data1, void *data2)
while (iter)
{
const gchar *input_pad = NULL;
- GeglNode *consumer = gegl_node_get_consumer_no (iter, "output", &input_pad, 0);
+ GeglNode *consumer = gegl_node_get_ui_consumer (iter, "output", &input_pad);
last = iter;
if (consumer && g_str_equal (input_pad, "input"))
iter = consumer;
@@ -1593,7 +1607,7 @@ static GeglNode *add_output (State *o, GeglNode *active, const char *optype)
GeglNode *ref = active;
GeglNode *ret = NULL;
const char *consumer_name = NULL;
- GeglNode *consumer = gegl_node_get_consumer_no (ref, "output", &consumer_name, 0);
+ GeglNode *consumer = gegl_node_get_ui_consumer (ref, "output", &consumer_name);
if (!gegl_node_has_pad (ref, "output"))
return NULL;
@@ -1657,7 +1671,7 @@ cmd_node_add (COMMAND_ARGS)
{
GeglNode *ref = o->active;
const char *consumer_name = NULL;
- GeglNode *consumer = gegl_node_get_consumer_no (o->active, "output", &consumer_name, 0);
+ GeglNode *consumer = gegl_node_get_ui_consumer (o->active, "output", &consumer_name);
if (!gegl_node_has_pad (ref, "output"))
return -1;
@@ -1926,7 +1940,7 @@ int cmd_activate (COMMAND_ARGS) /* "activate", 1, "<input|output|aux>", ""*/
}
else if (!strcmp (argv[1], "output"))
{
- ref = gegl_node_get_consumer_no (o->active, "output", NULL, 0);
+ ref = gegl_node_get_ui_consumer (o->active, "output", NULL);
if (ref == o->sink)
ref = NULL;
}
@@ -1971,123 +1985,274 @@ static void set_op (MrgEvent *event, void *data1, void *data2)
mrg_queue_draw (o->mrg, NULL);
}
+
+static void update_ui_consumers_list (State *o, GeglNode *iter)
+{
+ GList *queue = NULL;
+ GeglNode *prev = NULL;
+
+ while (iter)
+ {
+ queue = g_list_prepend (queue, iter);
+ g_hash_table_insert (o->ui_consumer, iter, prev);
+
+ prev = iter;
+ iter = gegl_node_get_producer (iter, "input", NULL);
+
+ if (g_hash_table_lookup (o->ui_consumer, iter))
+ iter = NULL;
+ }
+
+ while (queue)
+ {
+ GeglNode *aux_producer;
+ iter = queue->data;
+ aux_producer = gegl_node_get_producer (iter, "aux", NULL);
+ if (aux_producer &&
+ !g_hash_table_lookup (o->ui_consumer, aux_producer))
+ update_ui_consumers_list (o, aux_producer);
+
+ queue = g_list_remove (queue, iter);
+ }
+}
+
+
static void update_ui_consumers (State *o)
{
g_hash_table_remove_all (o->ui_consumer);
+
+ update_ui_consumers_list (o, o->sink);
+
+}
+
+static GeglNode *gegl_node_get_ui_consumer (GeglNode *node, const char *output_pad, const char
**consumer_pad)
+{
+ GeglNode *ret = g_hash_table_lookup (global_state->ui_consumer, node);
+ if (!ret)
+ {
+ ret = gegl_node_get_consumer_no (node, output_pad, NULL, 0);
+ }
+ if (consumer_pad)
+ {
+ GeglNode **nodes = NULL;
+ const gchar **consumer_names = NULL;
+ int count;
+ int i;
+ if (node == NULL)
+ return NULL;
+ count = gegl_node_get_consumers (node, output_pad, &nodes, &consumer_names);
+ for (i = 0; i < count; i++)
+ if (ret == nodes[i])
+ *consumer_pad = consumer_names[i];
+ g_free (nodes);
+ g_free (consumer_names);
+ }
+
+ return ret;
}
+typedef struct DrawEdge {
+ GeglNode *target;
+ int in_slot_no; /* 0=input 1=aux */
+ int indent;
+ int line_no;
+ GeglNode *source;
+} DrawEdge;
-static void list_ops (State *o, GeglNode *iter, int indent)
+GList *edge_queue = NULL; /* queue of edges to be filled in */
+
+
+static void
+queue_edge (GeglNode *target, int in_slot_no, int indent, int line_no, GeglNode *source)
{
- Mrg *mrg = o->mrg;
-
- while (iter) // && iter != o->source)
- {
- char *opname = NULL;
+ DrawEdge *edge = g_malloc0 (sizeof (DrawEdge));
+ edge->target = target;
+ edge->in_slot_no = in_slot_no;
+ edge->indent = indent;
+ edge->line_no = line_no;
+ edge->source = source;
- g_object_get (iter, "operation", &opname, NULL);
+ edge_queue = g_list_prepend (edge_queue, edge);
+}
- if (iter == o->active)
- {
-#if 0
- mrg_start_with_style (mrg, ".item", NULL, "color:rgb(197,197,197);background-color:
rgba(0,0,0,0.5);padding-right:.5em;");
- for (int i = 0; i < indent; i ++)
- mrg_printf (mrg, INDENT_STR);
- mrg_text_listen (mrg, MRG_CLICK, run_command, "node-add output", NULL);
- mrg_printf (mrg, "+ ");
- mrg_text_listen_done (mrg);
- //mrg_text_listen (mrg, MRG_CLICK, run_command, o, "remove");
- mrg_text_listen (mrg, MRG_CLICK, run_command, "remove", NULL);
- mrg_printf (mrg, " X ");
- mrg_text_listen_done (mrg);
-
- mrg_end (mrg);
- mrg_printf (mrg, "\n");
-#endif
- mrg_start_with_style (mrg, ".item", NULL, "color:white;background-color:
rgba(0,0,0,0.5);padding-right:.5em;");
- }
- else
- {
- mrg_start_with_style (mrg, ".item", NULL, "color:rgb(197,197,197);background-color:
rgba(0,0,0,0.5);padding-right:.5em;");
- }
- for (int i = 0; i < indent; i ++)
- mrg_printf (mrg, INDENT_STR);
- if (iter != o->active)
- {
- mrg_text_listen (mrg, MRG_CLICK, node_press, iter, o);
- }
+static float compute_node_x (Mrg *mrg, int indent, int line_no)
+{
+ float em = mrg_em (mrg);
+ return (1 + 3 * indent) * em;
+}
+static float compute_node_y (Mrg *mrg, int indent, int line_no)
+{
+ float em = mrg_em (mrg);
+ return (4 + line_no * 3.5) * em;
+}
- if (o->active == iter && o->editing_op_name)
- {
- mrg_edit_start (mrg, update_string, &o->new_opname[0]);
- mrg_printf (mrg, "%s", o->new_opname);
- mrg_edit_end (mrg);
- mrg_add_binding (mrg, "return", NULL, NULL, set_op, o);
- }
- else
- {
- if (g_str_has_prefix (opname, "gegl:"))
- mrg_printf (mrg, "%s", opname+5);
- else
- mrg_printf (mrg, "%s", opname);
- }
+static float compute_pad_x (Mrg *mrg, int indent, int line_no, int pad_no)
+{
+ float em = mrg_em (mrg);
+ switch (pad_no)
+ {
+ case 0: // in
+ return compute_node_x (mrg, indent, line_no) + em * 2;
+ case 1: // aux
+ return compute_node_x (mrg, indent, line_no) + em * 5;
+ case 2: // out
+ return compute_node_x (mrg, indent, line_no) + em * 2;
+ }
+ return 0;
+}
+static float compute_pad_y (Mrg *mrg, int indent, int line_no, int pad_no)
+{
+ float em = mrg_em (mrg);
+ switch (pad_no)
+ {
+ case 0: // in
+ case 1: // aux
+ return compute_node_y (mrg, indent, line_no) + 0.5 * em;
+ case 2: // out
+ return compute_node_y (mrg, indent, line_no) - 1.5 * em;
+ }
+ return 0;
+}
- if (iter != o->active)
- {
- mrg_text_listen_done (mrg);
- }
- mrg_end (mrg);
+static void
+draw_node (State *o, int indent, int line_no, GeglNode *node, gboolean active)
+{
+ char *opname = NULL;
+ GList *to_remove = NULL;
+ Mrg *mrg = o->mrg;
+ //float em = mrg_em (mrg);
+ float x = compute_node_x (mrg, indent, line_no);
+ float y = compute_node_y (mrg, indent, line_no);
- if(0){
- const Babl *format = gegl_operation_get_format (gegl_node_get_gegl_operation (iter), "output");
- if (format)
- {
-#if 0
- BablModelFlag flags = babl_get_model_flags (format);
- const Babl *type = babl_format_get_type (format, 0);
-
- mrg_set_xy (mrg, mrg_em (mrg) * 15, mrg_y (mrg));
-
- if (flags & BABL_MODEL_FLAG_GRAY)
- mrg_printf (mrg, "Y");
- else if (flags & BABL_MODEL_FLAG_RGB)
- mrg_printf (mrg, "RGB");
- else if (flags & BABL_MODEL_FLAG_CMYK)
- mrg_printf (mrg, "CMYK");
-
- if ((flags & BABL_MODEL_FLAG_ALPHA) &&
- (flags & BABL_MODEL_FLAG_PREMULTIPLIED))
- mrg_printf (mrg, " AA");
- else if ((flags & BABL_MODEL_FLAG_ALPHA))
- mrg_printf (mrg, " A");
- mrg_printf (mrg, "%s\n", babl_get_name (type));
-#endif
- mrg_printf (mrg, " %s", babl_format_get_encoding (format));
- }
+ /* queue up */
- }
+ if (gegl_node_has_pad (node, "input") &&
+ gegl_node_get_producer (node, "input", NULL))
+ {
+ queue_edge (node, 0, indent, line_no,
+ gegl_node_get_producer (node, "input", NULL));
+ }
- g_free (opname);
+ if (gegl_node_has_pad (node, "aux") &&
+ gegl_node_get_producer (node, "aux", NULL))
+ {
+ queue_edge (node, 1, indent, line_no,
+ gegl_node_get_producer (node, "aux", NULL));
+ }
- mrg_printf (mrg, "\n");
+ mrg_set_xy (mrg, x, y);
-#if 0
- if (iter == o->active && gegl_node_has_pad (iter, "aux"))
- {
- mrg_start_with_style (mrg, ".item", NULL, "color:rgb(197,197,197);background-color:
rgba(0,0,0,0.5);");
- for (int i = 0; i < indent + 1; i ++)
- mrg_printf (mrg, INDENT_STR);
- mrg_text_listen (mrg, MRG_CLICK, NULL, "run-command", "node-add aux");
- mrg_printf (mrg, "+\n");
- mrg_text_listen_done (mrg);
- mrg_end (mrg);
- }
+ g_object_get (node, "operation", &opname, NULL);
+ if (active)
+ {
+ mrg_start_with_style (mrg, "div.activenode", NULL, "color:yellow;");
+ }
+ else
+ {
+ mrg_start_with_style (mrg, "div.node", NULL, "color:white;");
+ }
+
+ if (!active)
+ {
+ mrg_text_listen (mrg, MRG_CLICK, node_press, node, o);
+ }
+
+ if (active && o->editing_op_name)
+ {
+ mrg_edit_start (mrg, update_string, &o->new_opname[0]);
+ mrg_printf (mrg, "%s", o->new_opname);
+ mrg_edit_end (mrg);
+ mrg_add_binding (mrg, "return", NULL, NULL, set_op, o);
+ }
+ else
+ {
+ if (g_str_has_prefix (opname, "gegl:"))
+ mrg_printf (mrg, "%s", opname+5);
+ else
+ mrg_printf (mrg, "%s", opname);
+ }
+ if (!active)
+ {
+ mrg_text_listen_done (mrg);
+ }
+ mrg_end (mrg);
+ g_free (opname);
+
+ if (gegl_node_has_pad (node, "aux"))
+ {
+ cairo_t *cr = mrg_cr (mrg);
+ cairo_new_path (cr);
+ cairo_arc (cr, compute_pad_x (mrg, indent, line_no, 1),
+ compute_pad_y (mrg, indent, line_no, 1), 0.3*mrg_em (mrg), 0, G_PI * 2);
+ cairo_set_source_rgb (cr, 1.0,1.0,1.0);
+ cairo_set_line_width (cr, 1.0f);
+ cairo_stroke (cr);
+ }
+ if (gegl_node_has_pad (node, "input"))
+ {
+ cairo_t *cr = mrg_cr (mrg);
+ cairo_new_path (cr);
+ cairo_arc (cr, compute_pad_x (mrg, indent, line_no, 0),
+ compute_pad_y (mrg, indent, line_no, 0), 0.3*mrg_em (mrg), 0, G_PI * 2);
+ cairo_set_source_rgb (cr, 1.0,1.0,1.0);
+ cairo_set_line_width (cr, 1.0f);
+ cairo_stroke (cr);
+ }
+ if (gegl_node_has_pad (node, "output"))
+ {
+ cairo_t *cr = mrg_cr (mrg);
+ cairo_new_path (cr);
+ cairo_arc (cr, compute_pad_x (mrg, indent, line_no, 2),
+ compute_pad_y (mrg, indent, line_no, 2), 0.3*mrg_em (mrg), 0, G_PI * 2);
+ cairo_set_source_rgb (cr, 1.0,1.0,1.0);
+ cairo_set_line_width (cr, 1.0f);
+ cairo_stroke (cr);
+ }
+
+
+#if 1
+ for (GList *i = edge_queue; i; i = i->next)
+ {
+ DrawEdge *edge = i->data;
+ if (edge->source == node)
+ {
+ cairo_t *cr = mrg_cr (mrg);
+ cairo_new_path (cr);
+ cairo_move_to (cr, compute_pad_x (mrg, indent, line_no, 2),
+ compute_pad_y (mrg, indent, line_no, 2));
+ cairo_line_to (cr, compute_pad_x (mrg, edge->indent, edge->line_no, edge->in_slot_no),
+ compute_pad_y (mrg, edge->indent, edge->line_no, edge->in_slot_no));
+ cairo_set_line_width (cr, 1.5f);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_source_rgb (cr, 1.0,1.0,1.0);
+ cairo_stroke (cr);
+
+ to_remove = g_list_prepend (to_remove, edge);
+ }
+ }
+ while (to_remove)
+ {
+ DrawEdge *edge = to_remove->data;
+ edge_queue = g_list_remove (edge_queue, edge);
+ to_remove = g_list_remove (to_remove, edge);
+ }
#endif
+}
+
+static void list_ops (State *o, GeglNode *iter, int indent, int *no)
+{
+ while (iter)
+ {
+ draw_node (o, indent, *no, iter, iter == o->active);
+
+
+ (*no)++;
+
if (gegl_node_get_producer (iter, "aux", NULL))
{
@@ -2095,61 +2260,28 @@ static void list_ops (State *o, GeglNode *iter, int indent)
{
GeglNode *producer = gegl_node_get_producer (iter, "aux", NULL);
GeglNode *producers_consumer;
+ const char *consumer_name = NULL;
- producers_consumer = gegl_node_get_consumer_no (producer, "output", NULL, 0);
+ producers_consumer = gegl_node_get_ui_consumer (producer, "output", &consumer_name);
- if (producers_consumer == iter)
+ if (producers_consumer == iter && !strcmp (consumer_name, "aux"))
{
- list_ops (o, gegl_node_get_producer (iter, "aux", NULL), indent + 1);
+ list_ops (o, gegl_node_get_producer (iter, "aux", NULL), indent + 1, no);
}
- else
- {
- if (producer)
- {
- for (int i = 0; i < indent + 1; i ++)
- mrg_printf (mrg, INDENT_STR);
- mrg_printf (mrg, "[clone]\n");
- }
- }
}
-
-
-
-
}
-#if 0
- if (iter == o->active && gegl_node_has_pad (iter, "input"))
- {
- mrg_start_with_style (mrg, ".item", NULL, "color:rgb(197,197,197);background-color:
rgba(0,0,0,0.5);");
- for (int i = 0; i < indent; i ++)
- mrg_printf (mrg, INDENT_STR);
- mrg_text_listen (mrg, MRG_CLICK, run_command, "node-add input", NULL);
- mrg_printf (mrg, "+ \n");
- mrg_text_listen_done (mrg);
- mrg_end (mrg);
- }
-#endif
- if (0)
- iter = gegl_node_get_producer (iter, "input", NULL);
- else
{
GeglNode *producer = gegl_node_get_producer (iter, "input", NULL);
GeglNode *producers_consumer;
- producers_consumer = gegl_node_get_consumer_no (producer, "output", NULL, 0);
+ producers_consumer = gegl_node_get_ui_consumer (producer, "output", NULL);
if (producers_consumer == iter)
iter = producer;
else
{
- if (producer)
- {
- for (int i = 0; i < indent; i ++)
- mrg_printf (mrg, INDENT_STR);
- mrg_printf (mrg, "[clone]\n");
- }
iter = NULL;
}
}
@@ -2160,9 +2292,9 @@ static void ui_debug_op_chain (State *o)
{
Mrg *mrg = o->mrg;
GeglNode *iter;
- mrg_start (mrg, "div.editor", NULL);
- mrg_set_font_size (mrg, mrg_height (mrg) * 0.03);
- mrg_set_style (mrg, "color:white; background-color: rgba(0,0,0,0.4)");
+ int no = 0;
+
+ mrg_start (mrg, "div.graph", NULL);
update_ui_consumers (o);
@@ -2171,12 +2303,14 @@ static void ui_debug_op_chain (State *o)
/* skip nop-node */
iter = gegl_node_get_producer (iter, "input", NULL);
- list_ops (o, iter, 1);
+ list_ops (o, iter, 0, &no);
+
+
mrg_end (mrg);
if (o->active)
{
- mrg_set_xy (mrg, mrg_width (mrg), 0);
+ //mrg_set_xy (mrg, mrg_width (mrg), 0);
mrg_start (mrg, "div.props", NULL);
//mrg_set_style (mrg, "color:white; background-color: rgba(0,0,0,0.4)");
list_node_props (o, o->active, 1);
@@ -2459,25 +2593,20 @@ int cmd_remove (COMMAND_ARGS) /* "remove", 0, "", "removes active node"*/
{
State *o = global_state;
GeglNode *node = o->active;
- GeglNode *new_active;
GeglNode *next, *prev;
const gchar *consumer_name = NULL;
-
prev = gegl_node_get_producer (node, "input", NULL);
- next = gegl_node_get_consumer_no (node, "output", &consumer_name, 0);
+ next = gegl_node_get_ui_consumer (node, "output", &consumer_name);
if (next && prev)
{
- gegl_node_disconnect (node, "output");
gegl_node_disconnect (node, "input");
gegl_node_connect_to (prev, "output", next, consumer_name);
+ gegl_node_remove_child (o->gegl, node);
+ o->active = prev;
}
- gegl_node_remove_child (o->gegl, node);
- new_active = prev?prev:next;
-
- o->active = new_active;
mrg_queue_draw (o->mrg, NULL);
renderer_dirty++;
o->rev++;
@@ -2493,17 +2622,15 @@ cmd_swap (COMMAND_ARGS)
GeglNode *node = o->active;
GeglNode *next, *prev;
- const gchar *consumer_name = NULL;
- const gchar *next_consumer_name = NULL;
+ next = gegl_node_get_ui_consumer (node, "output", NULL);
prev = gegl_node_get_producer (node, "input", NULL);
- next = gegl_node_get_consumer_no (node, "output", &consumer_name, 0);
if (next && prev)
{
if (!strcmp (argv[1], "output") && next != o->sink)
{
- GeglNode *next_next = gegl_node_get_consumer_no (next, "output", &next_consumer_name, 0);
+ GeglNode *next_next = gegl_node_get_ui_consumer (next, "output", NULL);
gegl_node_link_many (prev, next, node, next_next, NULL);
}
@@ -2828,7 +2955,7 @@ static void gegl_ui (Mrg *mrg, void *data)
iterate_frame (o);
}
- if (o->show_controls)
+ if (o->show_controls && 0)
{
mrg_printf (mrg, "%s\n", o->path);
}
@@ -3137,6 +3264,7 @@ static void load_path_inner (State *o,
GeglNode *iter;
GeglNode *prev = NULL;
char *containing_path = get_path_parent (path);
+
o->gegl = gegl_node_new_from_serialized (meta, containing_path);
g_free (containing_path);
o->sink = o->gegl;
@@ -3233,8 +3361,6 @@ static void load_path_inner (State *o,
}
-
-
static void load_path (State *o)
{
while (thumb_queue)
diff --git a/operations/external/vector-stroke.c b/operations/external/vector-stroke.c
index 94ebdae3c..90e65b53b 100644
--- a/operations/external/vector-stroke.c
+++ b/operations/external/vector-stroke.c
@@ -68,8 +68,8 @@ static void path_changed (GeglPath *path,
rect.x -= o->width/2;
rect.y -= o->width/2;
- rect.width += o->width;
- rect.height += o->width;
+ rect.width += o->width * 1.5;
+ rect.height += o->width * 1.5;
gegl_operation_invalidate (userdata, &rect, FALSE);
};
@@ -101,7 +101,7 @@ const Babl *color_format = gegl_color_get_format (o->color);
static GeglRectangle
get_bounding_box (GeglOperation *operation)
{
- GeglProperties *o = GEGL_PROPERTIES (operation);
+ GeglProperties *o = GEGL_PROPERTIES (operation);
GeglRectangle defined = { 0, 0, 512, 512 };
GeglRectangle *in_rect;
gdouble x0, x1, y0, y1;
@@ -111,8 +111,8 @@ get_bounding_box (GeglOperation *operation)
gegl_path_get_bounds (o->d, &x0, &x1, &y0, &y1);
defined.x = x0 - o->width/2;
defined.y = y0 - o->width/2;
- defined.width = x1 - x0 + o->width;
- defined.height = y1 - y0 + o->width;
+ defined.width = x1 - x0 + o->width * 1.5;
+ defined.height = y1 - y0 + o->width * 1.5;
if (in_rect)
{
@@ -307,7 +307,6 @@ static GeglNode *detect (GeglOperation *operation,
gegl_path_cairo_play (o->d, cr);
cairo_set_line_width (cr, o->width);
-
if (o->width > 0.1 && o->opacity > 0.0001)
result = cairo_in_stroke (cr, x, y);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]