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 c6598f248795f46f885ed638701bb2808b945ae3
Author: [email protected] <[email protected]>
AuthorDate: Wed Apr 29 09:12:37 2026 -0600
edje: implement description-scope override authoring (Task 4.3)
Enables declarations like vector.shape { target: "body"; fill.color: ... }
at description scope to override individual nodes from inherited base trees.
Context dispatch on four sub-node openers (shape/container/gradient_linear/
gradient_radial) checks parser state to decide between inline-tree nodes
(existing behavior, Mode B) and description-scope override blocks (new).
Both forms parse identically and dispatch via current_vg_tree and
current_vg_node state.
Spec deviation from Phase 2: EDC cannot parse positional quoted args between
a keyword and brace, so override target is identified by a target: statement
inside the block, matching Phase 2.6's stroke.dash precedent.
New _vg_finalize_description_overrides handler at description-close validates:
- Missing target: statement → VEC002 error
- Target not found in base tree → VEC002 error
- Type mismatch with override node type → VEC002 error
Inherit handler upserts parent's _vg_desc_to_tree entry under child
description pointer so finalizer locates the correct base tree even on
inherited descriptions. Task 4.4 inherit-merge work builds on this.
_vg_close_block replaces _vg_close_node in VG_NODE_NESTED_AT macro;
falls back to _vg_close_node when not in override mode so toplevel
vectors {} paths are unchanged.
Test fixture: ui/box_a_hover inherits from tile_a and overrides body shape
fill/stroke in hover state. Parses cleanly; runtime application deferred to
Task 4.5. All 52 edje_suite tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/bin/edje/edje_cc_handlers.c | 207 +++++++++++++++++++++++++++--
src/tests/edje/data/test_vector_states.edc | 19 +++
2 files changed, 217 insertions(+), 9 deletions(-)
diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c
index 99dc50933d..cf36c20b05 100644
--- a/src/bin/edje/edje_cc_handlers.c
+++ b/src/bin/edje/edje_cc_handlers.c
@@ -616,6 +616,12 @@ static void st_collections_group_parts_part_description_vector_frame(void)
static void st_collections_group_parts_part_description_vector_use(void);
static void ob_collections_group_parts_part_description_vector(void);
static void _vg_inline_block_end(void);
+/* Task 4.3: override block helpers */
+static void _vg_open_override(Edje_Vg_Node_Type type);
+static void _vg_close_block(void);
+static void st_vg_override_target(void);
+static const char *_node_type_str(Edje_Vg_Node_Type t);
+static void _vg_finalize_description_overrides(void);
static void ob_collections_group_programs_program(void);
static void st_collections_group_programs_program_name(void);
@@ -1183,6 +1189,11 @@ New_Statement_Handler statement_handlers[] =
VG_GRAD_RADIAL_STATEMENTS("collections.group.parts.part.description.vector.container.container.container.gradient_radial.")
/* Task 2.8: inline tree viewbox: property (reuse toplevel handler). */
{"collections.group.parts.part.description.vector.viewbox", st_vectors_vector_viewbox},
+ /* Task 4.3: target: statement in description-scope override blocks. */
+ {"collections.group.parts.part.description.vector.shape.target", st_vg_override_target},
+ {"collections.group.parts.part.description.vector.container.target", st_vg_override_target},
+ {"collections.group.parts.part.description.vector.gradient_linear.target", st_vg_override_target},
+ {"collections.group.parts.part.description.vector.gradient_radial.target", st_vg_override_target},
IMAGE_STATEMENTS("collections.group.parts.part.description.")
{
"collections.group.parts.part.description.font", st_fonts_font
@@ -1790,10 +1801,49 @@ _vg_open_node(Edje_Vg_Node_Type type)
current_vg_node = n;
}
-static void ob_vg_shape(void) { _vg_open_node(EDJE_VG_NODE_SHAPE); }
-static void ob_vg_container(void) { _vg_open_node(EDJE_VG_NODE_CONTAINER); }
-static void ob_vg_gradient_linear(void) { _vg_open_node(EDJE_VG_NODE_GRADIENT_LINEAR); }
-static void ob_vg_gradient_radial(void) { _vg_open_node(EDJE_VG_NODE_GRADIENT_RADIAL); }
+static void
+ob_vg_shape(void)
+{
+ if (current_vg_tree && current_vg_node)
+ _vg_open_node(EDJE_VG_NODE_SHAPE);
+ else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+ _vg_open_override(EDJE_VG_NODE_SHAPE);
+ else
+ error_and_abort(NULL, "shape outside vector tree or VECTOR description");
+}
+
+static void
+ob_vg_container(void)
+{
+ if (current_vg_tree && current_vg_node)
+ _vg_open_node(EDJE_VG_NODE_CONTAINER);
+ else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+ _vg_open_override(EDJE_VG_NODE_CONTAINER);
+ else
+ error_and_abort(NULL, "container outside vector tree or VECTOR description");
+}
+
+static void
+ob_vg_gradient_linear(void)
+{
+ if (current_vg_tree && current_vg_node)
+ _vg_open_node(EDJE_VG_NODE_GRADIENT_LINEAR);
+ else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+ _vg_open_override(EDJE_VG_NODE_GRADIENT_LINEAR);
+ else
+ error_and_abort(NULL, "gradient_linear outside vector tree or VECTOR description");
+}
+
+static void
+ob_vg_gradient_radial(void)
+{
+ if (current_vg_tree && current_vg_node)
+ _vg_open_node(EDJE_VG_NODE_GRADIENT_RADIAL);
+ else if (current_part && current_part->type == EDJE_PART_TYPE_VECTOR)
+ _vg_open_override(EDJE_VG_NODE_GRADIENT_RADIAL);
+ else
+ error_and_abort(NULL, "gradient_radial outside vector tree or VECTOR description");
+}
static void
_vg_close_node(void)
@@ -1804,6 +1854,125 @@ _vg_close_node(void)
current_vg_node = current_vg_tree ? current_vg_tree->root : NULL;
}
+/* Task 4.3: Open an override block at description scope.
+ * Allocates an Edje_Vg_Override, appends it to the description's list,
+ * and routes subsequent property statements into its payload.
+ * target: must be set by st_vg_override_target before description close.
+ * Note: Task 4.4 will replace the append with a merge-or-append path. */
+static void
+_vg_open_override(Edje_Vg_Node_Type type)
+{
+ Edje_Part_Description_Vector *ed;
+ Edje_Vg_Override *ovr;
+
+ if (!current_part || current_part->type != EDJE_PART_TYPE_VECTOR)
+ error_and_abort(NULL, "vector override outside VECTOR description");
+
+ ed = (Edje_Part_Description_Vector *)current_desc;
+
+ ovr = calloc(1, sizeof(Edje_Vg_Override));
+ if (!ovr) error_and_abort(NULL, "OOM allocating override");
+ ovr->expected_type = type;
+ /* payload zeroed; target_name still NULL.
+ * Append happens immediately here; Task 4.4 will swap this for the
+ * merge-aware path once target: fires. */
+ ed->vg.overrides = eina_list_append(ed->vg.overrides, ovr);
+
+ current_vg_override = ovr;
+ current_vg_node = &ovr->payload;
+}
+
+/* Task 4.3: Close either an override block or an inline-tree node block.
+ * When current_vg_override is set we are in override mode: clear the
+ * pointers without touching the container stack (we never pushed).
+ * Otherwise delegate to the existing _vg_close_node. */
+static void
+_vg_close_block(void)
+{
+ if (current_vg_override)
+ {
+ current_vg_override = NULL;
+ current_vg_node = NULL;
+ }
+ else
+ {
+ _vg_close_node();
+ }
+}
+
+/* Task 4.3: Map a node type to a printable string for VEC002 diagnostics. */
+static const char *
+_node_type_str(Edje_Vg_Node_Type t)
+{
+ switch (t)
+ {
+ case EDJE_VG_NODE_SHAPE: return "shape";
+ case EDJE_VG_NODE_CONTAINER: return "container";
+ case EDJE_VG_NODE_GRADIENT_LINEAR: return "gradient_linear";
+ case EDJE_VG_NODE_GRADIENT_RADIAL: return "gradient_radial";
+ }
+ return "?";
+}
+
+/* Task 4.3: Validate all override blocks on a VECTOR description at
+ * description-close time. Emits VEC002 if target is missing, unknown
+ * in the base tree, or type-mismatched. */
+static void
+_vg_finalize_description_overrides(void)
+{
+ Edje_Part_Description_Vector *ed;
+ Eina_Hash *desc_map;
+ Edje_Vg_Tree *base;
+ Eina_List *l;
+ Edje_Vg_Override *ovr;
+
+ if (!current_part || current_part->type != EDJE_PART_TYPE_VECTOR) return;
+ if (!current_desc) return;
+ ed = (Edje_Part_Description_Vector *)current_desc;
+ if (!ed->vg.overrides) return;
+
+ desc_map = _edje_cc_vg_desc_to_tree_get();
+ base = NULL;
+ if (desc_map) base = eina_hash_find(desc_map, &ed);
+
+ if (!base)
+ error_and_abort(NULL,
+ "vector overrides on a description without an active vector tree (VEC002)");
+
+ EINA_LIST_FOREACH(ed->vg.overrides, l, ovr)
+ {
+ Edje_Vg_Node *node;
+
+ if (!ovr->target_name || !*ovr->target_name)
+ error_and_abort(NULL, "vector override missing target: statement");
+ node = _edje_vg_tree_node_by_name(base, ovr->target_name);
+ if (!node)
+ error_and_abort(NULL,
+ "vector override targets unknown node '%s' (VEC002)",
+ ovr->target_name);
+ if (node->type != ovr->expected_type)
+ error_and_abort(NULL,
+ "vector override target '%s' is type %s but override expects %s (VEC002)",
+ ovr->target_name,
+ _node_type_str(node->type),
+ _node_type_str(ovr->expected_type));
+ }
+}
+
+/* Task 4.3: Set the target name for the current override block. */
+static void
+st_vg_override_target(void)
+{
+ const char *s;
+
+ check_arg_count(1);
+ if (!current_vg_override)
+ error_and_abort(NULL, "target: outside vector override block");
+ s = parse_str(0);
+ eina_stringshare_replace(¤t_vg_override->target_name, s);
+ free((char *)s);
+}
+
/**
* @page edcref
* @property
@@ -2832,15 +3001,19 @@ New_Object_Handler object_handlers_short[] =
};
/* Expands to the four node-kind close-pop entries for a given parent path.
- * Fires _vg_close_node when any node block ends, restoring current_vg_node. */
+ * Uses _vg_close_block which delegates to _vg_close_node for inline-tree
+ * contexts and clears the override pointers for description-scope contexts.
+ * Safe for both toplevel vectors{} and description.vector{} prefixes. */
#define VG_NODE_NESTED_AT(PARENT) \
- {PARENT, "shape", NULL, _vg_close_node}, \
- {PARENT, "container", NULL, _vg_close_node}, \
- {PARENT, "gradient_linear", NULL, _vg_close_node}, \
- {PARENT, "gradient_radial", NULL, _vg_close_node},
+ {PARENT, "shape", NULL, _vg_close_block}, \
+ {PARENT, "container", NULL, _vg_close_block}, \
+ {PARENT, "gradient_linear", NULL, _vg_close_block}, \
+ {PARENT, "gradient_radial", NULL, _vg_close_block},
New_Nested_Handler nested_handlers[] = {
{"collections.group.parts", "part", NULL, edje_cc_handlers_hierarchy_pop },
+ /* Task 4.3: fire VEC002 validation when a description block closes. */
+ {"collections.group.parts.part", "description", NULL, _vg_finalize_description_overrides },
{"collections.vectors", "vector", NULL, _vg_tree_block_end },
{"vectors", "vector", NULL, _vg_tree_block_end },
/* 4-level nesting cap mirrors VG_NODE_OPENERS. */
@@ -9848,6 +10021,22 @@ st_collections_group_parts_part_description_inherit(void)
ied->vg.id = iparent->vg.id;
ied->vg.type = iparent->vg.type;
ied->vg.frame = iparent->vg.frame;
+ /* Task 4.3: propagate parent's base-tree pointer to the child so that
+ * VEC002 validation at description-close can resolve override targets.
+ * The child may later override this with its own vector.use: or
+ * inline vector{} block, which will call _vg_record_use and replace
+ * the entry. */
+ if (_vg_desc_to_tree)
+ {
+ Edje_Vg_Tree *parent_tree = eina_hash_find(_vg_desc_to_tree, &iparent);
+ if (parent_tree)
+ {
+ /* Use set/del to handle the case where a prior inherit
+ * already populated ied's entry (can't happen today but
+ * safe in general). */
+ eina_hash_set(_vg_desc_to_tree, &ied, parent_tree);
+ }
+ }
break;
}
}
diff --git a/src/tests/edje/data/test_vector_states.edc b/src/tests/edje/data/test_vector_states.edc
index 12a4b69bd7..69617c45d0 100644
--- a/src/tests/edje/data/test_vector_states.edc
+++ b/src/tests/edje/data/test_vector_states.edc
@@ -38,4 +38,23 @@ collections {
}
} }
}
+ /* Task 4.3: override authoring fixture.
+ * The hover description references tile_a (inherited from default) and
+ * overrides the "body" shape's fill and stroke. */
+ group { name: "ui/box_a_hover";
+ parts { part { name: "vg"; type: VECTOR;
+ description { state: "default" 0.0;
+ vector.use: "tile_a";
+ }
+ description { state: "hover" 0.0;
+ inherit: "default" 0.0;
+ vector.shape {
+ target: "body";
+ fill.color: 200 200 0 255;
+ stroke.color: 30 30 30 255;
+ stroke.width: 4;
+ }
+ }
+ } }
+ }
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.