This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch edje-vector-intergration
in repository efl.
View the commit online.
commit f873e873a6c12cd830ec3893e2d3b0a4f5ad0251
Author: [email protected] <[email protected]>
AuthorDate: Tue Apr 28 12:33:41 2026 -0600
edje: add shape-specific property handlers (Task 2.6)
This implements 11 EDC statement handlers for properties that are only valid
within shape {} blocks: path, fill.color, fill.color_class, fill.gradient,
stroke.color, stroke.color_class, stroke.width, stroke.cap, stroke.join,
stroke.dash, and fill_rule. Each writes to the corresponding field in
the shape node's data structure.
The dispatcher distinguishes these from node-level properties (Task 2.5)
via the path prefix: "shape.fill.color" (shape-level) vs "shape.color"
(node-level). A VG_SHAPE_STATEMENTS(PFX) macro registers 88 entries
(11 handlers × 4 nesting depths × 2 EDC contexts) to avoid duplication.
Each handler guards its execution with EXPECT_SHAPE() to catch erroneous
use on containers or gradients.
Notable design choice: stroke.dash syntax accepts space-separated floats
(e.g. "stroke.dash: 5 3 2 2;") rather than comma-separated pairs as shown
in spec rev 2. This is because EDC's tokenizer treats commas as parameter
boundaries and cannot tokenize them inside parameters. The pair-count
constraint (must be even, at least 2) is enforced at parse time. The spec
example should be updated in a follow-up commit.
Path validation (VEC003) and gradient reference resolution (VEC002) are
deferred to Phase 7 validation; both are stored verbatim at parse time.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/bin/edje/edje_cc_handlers.c | 312 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 312 insertions(+)
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index 2b6319b968..06fa22529d 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -297,6 +297,18 @@ static void st_vg_node_transform_translate(void);
static void st_vg_node_transform_rotate(void);
static void st_vg_node_transform_scale(void);
static void st_vg_node_transform_matrix(void);
+/* Task 2.6: shape-specific property handlers */
+static void st_vg_shape_path(void);
+static void st_vg_shape_fill_color(void);
+static void st_vg_shape_fill_color_class(void);
+static void st_vg_shape_fill_gradient(void);
+static void st_vg_shape_stroke_color(void);
+static void st_vg_shape_stroke_color_class(void);
+static void st_vg_shape_stroke_width(void);
+static void st_vg_shape_stroke_cap(void);
+static void st_vg_shape_stroke_join(void);
+static void st_vg_shape_stroke_dash(void);
+static void st_vg_shape_fill_rule(void);
static void ob_filters_filter(void);
static void ob_filters_filter_script(void);
@@ -688,6 +700,23 @@ static void _handle_vector_image(void);
VG_NODE_COMMON_STATEMENTS(PARENT_PFX "gradient_linear.") \
VG_NODE_COMMON_STATEMENTS(PARENT_PFX "gradient_radial.")
+/* Task 2.6: shape-specific property statements.
+ * PFX must be the fully-qualified shape prefix including trailing dot,
+ * e.g. "vectors.vector.shape." — note fill/stroke sub-properties are
+ * spelled as flat dotted names, not as opener sub-blocks. */
+#define VG_SHAPE_STATEMENTS(PFX) \
+ {PFX "path", st_vg_shape_path}, /* dup */ \
+ {PFX "fill.color", st_vg_shape_fill_color}, /* dup */ \
+ {PFX "fill.color_class", st_vg_shape_fill_color_class}, /* dup */ \
+ {PFX "fill.gradient", st_vg_shape_fill_gradient}, /* dup */ \
+ {PFX "stroke.color", st_vg_shape_stroke_color}, /* dup */ \
+ {PFX "stroke.color_class", st_vg_shape_stroke_color_class}, /* dup */ \
+ {PFX "stroke.width", st_vg_shape_stroke_width}, /* dup */ \
+ {PFX "stroke.cap", st_vg_shape_stroke_cap}, /* dup */ \
+ {PFX "stroke.join", st_vg_shape_stroke_join}, /* dup */ \
+ {PFX "stroke.dash", st_vg_shape_stroke_dash}, /* dup */ \
+ {PFX "fill_rule", st_vg_shape_fill_rule}, /* dup */
+
New_Statement_Handler statement_handlers[] =
{
{"id", st_id},
@@ -705,6 +734,11 @@ New_Statement_Handler statement_handlers[] =
VG_NODE_ALL_KINDS_STATEMENTS("vectors.vector.container.")
VG_NODE_ALL_KINDS_STATEMENTS("vectors.vector.container.container.")
VG_NODE_ALL_KINDS_STATEMENTS("vectors.vector.container.container.container.")
+ /* Task 2.6: shape-specific statements — toplevel vectors.vector prefix. */
+ VG_SHAPE_STATEMENTS("vectors.vector.shape.")
+ VG_SHAPE_STATEMENTS("vectors.vector.container.shape.")
+ VG_SHAPE_STATEMENTS("vectors.vector.container.container.shape.")
+ VG_SHAPE_STATEMENTS("vectors.vector.container.container.container.shape.")
{
"data.item", st_data_item
},
@@ -728,6 +762,11 @@ New_Statement_Handler statement_handlers[] =
VG_NODE_ALL_KINDS_STATEMENTS("collections.vectors.vector.container.")
VG_NODE_ALL_KINDS_STATEMENTS("collections.vectors.vector.container.container.")
VG_NODE_ALL_KINDS_STATEMENTS("collections.vectors.vector.container.container.container.")
+ /* Task 2.6: shape-specific statements — collections.vectors.vector prefix. */
+ VG_SHAPE_STATEMENTS("collections.vectors.vector.shape.")
+ VG_SHAPE_STATEMENTS("collections.vectors.vector.container.shape.")
+ VG_SHAPE_STATEMENTS("collections.vectors.vector.container.container.shape.")
+ VG_SHAPE_STATEMENTS("collections.vectors.vector.container.container.container.shape.")
{
"collections.base_scale", st_collections_base_scale
},
@@ -1808,6 +1847,279 @@ st_vg_node_transform_matrix(void)
current_vg_node->xform.has_matrix = 1;
}
+/* -----------------------------------------------------------------------
+ * Task 2.6: Shape-specific property handlers
+ *
+ * All handlers below are only valid inside a shape {} block. The
+ * EXPECT_SHAPE() guard aborts compilation with a clear error if they are
+ * mistakenly used on a container or gradient node.
+ * ----------------------------------------------------------------------- */
+
+#define EXPECT_SHAPE() \
+ do { \
+ if (!current_vg_node || current_vg_node->type != EDJE_VG_NODE_SHAPE) \
+ error_and_abort(NULL, "shape-only property on non-shape node"); \
+ } while (0)
+
+/**
+ * @page edcref
+ * @property
+ * path
+ * @parameters
+ * [string]
+ * @effect
+ * SVG 'd' attribute command string describing the shape's geometry.
+ * The string is stored verbatim; no validation is performed at parse
+ * time (VEC003 validation is Phase 7).
+ * @endproperty
+ */
+static void
+st_vg_shape_path(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *p = parse_str(0);
+ eina_stringshare_replace(¤t_vg_node->shape.path, p);
+ free(p);
+}
+
+/**
+ * @page edcref
+ * @property
+ * fill.color
+ * @parameters
+ * [red] [green] [blue] [alpha]
+ * @effect
+ * Base fill color for the shape, as non-premultiplied RGBA integers
+ * each in [0, 255]. Default is 255 255 255 255 (opaque white).
+ * @endproperty
+ */
+static void
+st_vg_shape_fill_color(void)
+{
+ check_arg_count(4);
+ EXPECT_SHAPE();
+ current_vg_node->shape.fill.r = parse_int_range(0, 0, 255);
+ current_vg_node->shape.fill.g = parse_int_range(1, 0, 255);
+ current_vg_node->shape.fill.b = parse_int_range(2, 0, 255);
+ current_vg_node->shape.fill.a = parse_int_range(3, 0, 255);
+}
+
+/**
+ * @page edcref
+ * @property
+ * fill.color_class
+ * @parameters
+ * [string]
+ * @effect
+ * Associates a color class with the shape's fill color slot. At
+ * runtime the resolved class value replaces the base fill color.
+ * @endproperty
+ */
+static void
+st_vg_shape_fill_color_class(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *s = parse_str(0);
+ eina_stringshare_replace(¤t_vg_node->shape.fill.color_class, s);
+ free(s);
+}
+
+/**
+ * @page edcref
+ * @property
+ * fill.gradient
+ * @parameters
+ * [string]
+ * @effect
+ * Names a sibling gradient_linear or gradient_radial node whose paint
+ * is used as this shape's fill. The reference is stored verbatim;
+ * VEC002 name validation is Phase 7.
+ * @endproperty
+ */
+static void
+st_vg_shape_fill_gradient(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *s = parse_str(0);
+ eina_stringshare_replace(¤t_vg_node->shape.gradient_ref, s);
+ free(s);
+}
+
+/**
+ * @page edcref
+ * @property
+ * stroke.color
+ * @parameters
+ * [red] [green] [blue] [alpha]
+ * @effect
+ * Base stroke color as non-premultiplied RGBA integers in [0, 255].
+ * Default is 0 0 0 255 (opaque black).
+ * @endproperty
+ */
+static void
+st_vg_shape_stroke_color(void)
+{
+ check_arg_count(4);
+ EXPECT_SHAPE();
+ current_vg_node->shape.stroke_color.r = parse_int_range(0, 0, 255);
+ current_vg_node->shape.stroke_color.g = parse_int_range(1, 0, 255);
+ current_vg_node->shape.stroke_color.b = parse_int_range(2, 0, 255);
+ current_vg_node->shape.stroke_color.a = parse_int_range(3, 0, 255);
+}
+
+/**
+ * @page edcref
+ * @property
+ * stroke.color_class
+ * @parameters
+ * [string]
+ * @effect
+ * Associates a color class with the shape's stroke color slot.
+ * @endproperty
+ */
+static void
+st_vg_shape_stroke_color_class(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *s = parse_str(0);
+ eina_stringshare_replace(¤t_vg_node->shape.stroke_color.color_class, s);
+ free(s);
+}
+
+/**
+ * @page edcref
+ * @property
+ * stroke.width
+ * @parameters
+ * [float]
+ * @effect
+ * Width of the stroke in viewbox units. Default is 1.0.
+ * @endproperty
+ */
+static void
+st_vg_shape_stroke_width(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ current_vg_node->shape.stroke_width = parse_float(0);
+}
+
+/**
+ * @page edcref
+ * @property
+ * stroke.cap
+ * @parameters
+ * [BUTT|ROUND|SQUARE]
+ * @effect
+ * Line-cap style used at open path endpoints. Default is BUTT.
+ * @endproperty
+ */
+static void
+st_vg_shape_stroke_cap(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *s = parse_str(0);
+ if (!strcmp(s, "BUTT")) current_vg_node->shape.stroke_cap = EFL_GFX_CAP_BUTT;
+ else if (!strcmp(s, "ROUND")) current_vg_node->shape.stroke_cap = EFL_GFX_CAP_ROUND;
+ else if (!strcmp(s, "SQUARE")) current_vg_node->shape.stroke_cap = EFL_GFX_CAP_SQUARE;
+ else
+ {
+ free(s);
+ error_and_abort(NULL, "stroke.cap: unknown value (BUTT|ROUND|SQUARE)");
+ }
+ free(s);
+}
+
+/**
+ * @page edcref
+ * @property
+ * stroke.join
+ * @parameters
+ * [MITER|ROUND|BEVEL]
+ * @effect
+ * Line-join style used at path corners. Default is MITER.
+ * @endproperty
+ */
+static void
+st_vg_shape_stroke_join(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *s = parse_str(0);
+ if (!strcmp(s, "MITER")) current_vg_node->shape.stroke_join = EFL_GFX_JOIN_MITER;
+ else if (!strcmp(s, "ROUND")) current_vg_node->shape.stroke_join = EFL_GFX_JOIN_ROUND;
+ else if (!strcmp(s, "BEVEL")) current_vg_node->shape.stroke_join = EFL_GFX_JOIN_BEVEL;
+ else
+ {
+ free(s);
+ error_and_abort(NULL, "stroke.join: unknown value (MITER|ROUND|BEVEL)");
+ }
+ free(s);
+}
+
+/**
+ * @page edcref
+ * @property
+ * stroke.dash
+ * @parameters
+ * [len] [gap] [len gap] ...
+ * @effect
+ * Dash pattern as one or more length/gap pairs of floats, all
+ * space-separated. The total argument count must be even and at
+ * least 2. Any previous dash pattern on the node is discarded
+ * before the new one is installed.
+ * @endproperty
+ */
+static void
+st_vg_shape_stroke_dash(void)
+{
+ EXPECT_SHAPE();
+ int n = get_arg_count();
+ if (n < 2 || (n % 2) != 0)
+ error_and_abort(NULL, "stroke.dash: expected even number (>=2) of len/gap floats");
+ free(current_vg_node->shape.stroke_dash);
+ current_vg_node->shape.stroke_dash = malloc((size_t)n * sizeof(double));
+ if (!current_vg_node->shape.stroke_dash)
+ error_and_abort(NULL, "stroke.dash: allocation failed");
+ int i;
+ for (i = 0; i < n; i++)
+ current_vg_node->shape.stroke_dash[i] = parse_float(i);
+ current_vg_node->shape.stroke_dash_count = (unsigned int)n;
+}
+
+/**
+ * @page edcref
+ * @property
+ * fill_rule
+ * @parameters
+ * [WINDING|EVEN_ODD]
+ * @effect
+ * Fill rule governing which regions of a self-intersecting path are
+ * painted. WINDING uses the non-zero winding number rule; EVEN_ODD
+ * uses the even-odd rule. Default is WINDING.
+ * @endproperty
+ */
+static void
+st_vg_shape_fill_rule(void)
+{
+ check_arg_count(1);
+ EXPECT_SHAPE();
+ char *s = parse_str(0);
+ if (!strcmp(s, "WINDING")) current_vg_node->shape.fill_rule = EFL_GFX_FILL_RULE_WINDING;
+ else if (!strcmp(s, "EVEN_ODD")) current_vg_node->shape.fill_rule = EFL_GFX_FILL_RULE_ODD_EVEN;
+ else
+ {
+ free(s);
+ error_and_abort(NULL, "fill_rule: unknown value (WINDING|EVEN_ODD)");
+ }
+ free(s);
+}
+
#define PROGRAM_OBJECTS(PREFIX) \
{PREFIX ".program", ob_collections_group_programs_program}, /* dup */ \
{PREFIX ".program.script", ob_collections_group_programs_program_script}, /* dup */ \
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.