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 b7a430e87105b64875613f0bbdcadfe3b974b65b
Author: [email protected] <[email protected]>
AuthorDate: Tue Apr 28 22:22:43 2026 -0600
edje: document vector cache invariant and extend render tests (Task 3.3)
This patch closes Phase 3 with three changes:
1. Document borrowed-pointer invariant (edje_private.h): Add a comment
clarifying that cached_base_tree is a borrowed (non-owning) pointer
into ed->file->vector_dir->trees[], kept safe by the part teardown
order in _edje_file_del: parts are freed before vector_dir memory
is released. Future maintainers changing that teardown get a flag.
2. Add Phase 4/5 cache TODO (edje_calc.c): A comment near the
_edje_vg_tree_to_efl_vg() call documents the cache-key requirements
(tree_id, classes_dirty, override-list-hash) and notes that Phase 4
introduces the per-node override list while Phase 5 needs the cache
for 60fps transition performance.
3. Extend render-test coverage: Add edje_vg_render_box_b and
edje_vg_render_box_c tests. Together with the existing box_a test,
the three groups—each with distinct tree_ids (0, 1, 2) and distinct
tree content (shapes named body/body/tiny, viewbox sizes 100x100 /
50x50 / 25x25)—confirm that each description materializes the
correct tree and closes the "Level 2 tree_id verification" gate.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/lib/edje/edje_calc.c | 6 ++
src/lib/edje/edje_private.h | 9 +-
src/tests/edje/edje_test_vector_states.c | 152 +++++++++++++++++++++++++++++++
3 files changed, 165 insertions(+), 2 deletions(-)
diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c
index 4c90e18767..16242e39bd 100644
--- a/src/lib/edje/edje_calc.c
+++ b/src/lib/edje/edje_calc.c
@@ -3304,6 +3304,12 @@ _edje_vector_recalc_apply(Edje *ed, Edje_Real_Part *ep, Edje_Calc_Params *p3 EIN
viewbox = EINA_RECT(t->vbx, t->vby, t->vbw, t->vbh);
+ /* TODO Phase 4/5: cache the materialised Efl_VG tree to avoid
+ re-walking the entire Edje_Vg_Tree on every recalc when the
+ description is unchanged. Cache key: (tree_id, classes_dirty,
+ override-list-hash). Phase 4 introduces the per-node override
+ list; Phase 5 needs the cache for 60fps transition performance
+ where this function fires on every animator tick. */
root = _edje_vg_tree_to_efl_vg(t);
if (!root)
{
diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h
index d853f24955..261eff8bb6 100644
--- a/src/lib/edje/edje_private.h
+++ b/src/lib/edje/edje_private.h
@@ -2034,8 +2034,13 @@ struct _Edje_Real_Part_Vector
Eina_Bool backward : 1;
Eina_Bool loop : 1;
Eina_Bool is_playing : 1;
- /* Phase 4 cache — cached_base_tree is a const pointer into
- ed->file->vector_dir->trees (not an owned ref).
+ /* Phase 4 cache — cached_base_tree is a BORROWED (non-owning) const
+ pointer into ed->file->vector_dir->trees[]. It is safe because
+ _edje_file_del tears down all parts (freeing typedata.vector, which
+ contains this field) BEFORE it calls _edje_cache_file_unref — so the
+ backing Edje_File memory outlives every cached_base_tree pointer held
+ by any part. If this teardown order ever changes, add a
+ cached_base_tree = NULL clear to the part teardown loop above.
cached_tree_id == -1 means the cache is invalid.
classes_dirty is set by color-class observer callbacks and
cleared on recalc. */
diff --git a/src/tests/edje/edje_test_vector_states.c b/src/tests/edje/edje_test_vector_states.c
index ca02840766..b7e8ef654f 100644
--- a/src/tests/edje/edje_test_vector_states.c
+++ b/src/tests/edje/edje_test_vector_states.c
@@ -448,6 +448,156 @@ EFL_START_TEST(edje_vg_render_box_a)
}
EFL_END_TEST
+/*
+ * edje_vg_render_box_b (Task 3.3)
+ *
+ * End-to-end structural test for ui/box_b (Mode A, vector.use: "tile_b",
+ * tree_id 1). tile_b has a 50x50 viewbox and a single shape child named
+ * "body" with a green fill. This test confirms:
+ *
+ * (a) The VG part has a non-NULL root after recalc.
+ * (b) The root is an Efl_Canvas_Vg_Container.
+ * (c) The root has a child named "body" — tile_b's shape name.
+ * (d) The viewbox is {0,0,50,50} — tile_b's viewbox, distinct from tile_a.
+ *
+ * Together with edje_vg_render_box_a this confirms that distinct tree_ids
+ * produce distinct materialised trees, i.e. the correct entry is fetched
+ * from vector_dir->trees[] for each group.
+ */
+EFL_START_TEST(edje_vg_render_box_b)
+{
+ const char *edj = TESTS_BUILD_DIR "/data/test_vector_states.edj";
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *obj;
+ Efl_Canvas_Vg_Node *vg_root;
+ Efl_Canvas_Vg_Node *body_node;
+ Evas_Object *vg_part;
+ Eina_Rect viewbox;
+
+ ee = ecore_evas_buffer_new(VG_RENDER_W, VG_RENDER_H);
+ fail_if(!ee);
+ ecore_evas_show(ee);
+ ecore_evas_manual_render_set(ee, EINA_TRUE);
+
+ evas = ecore_evas_get(ee);
+ fail_if(!evas);
+
+ obj = edje_object_add(evas);
+ fail_if(!obj);
+
+ /* ui/box_b references tile_b (tree_id 1). */
+ fail_unless(edje_object_file_set(obj, edj, "ui/box_b"));
+
+ evas_object_resize(obj, VG_RENDER_W, VG_RENDER_H);
+ evas_object_move(obj, 0, 0);
+ evas_object_show(obj);
+
+ edje_object_calc_force(obj);
+ ecore_evas_manual_render(ee);
+
+ /* (a) + (b) Root must be non-NULL and a container. */
+ vg_part = (Evas_Object *)edje_object_part_object_get(obj, "vg");
+ fail_if(!vg_part);
+
+ vg_root = efl_canvas_vg_object_root_node_get(vg_part);
+ fail_if(vg_root == NULL);
+ fail_if(!efl_isa(vg_root, EFL_CANVAS_VG_CONTAINER_CLASS));
+
+ /* (c) tile_b's shape is named "body". */
+ body_node = efl_canvas_vg_container_child_get(vg_root, "body");
+ fail_if(body_node == NULL);
+ fail_if(!efl_isa(body_node, EFL_CANVAS_VG_SHAPE_CLASS));
+
+ /* (d) tile_b viewbox: {0,0,50,50} — distinct from tile_a's 100x100. */
+ viewbox = efl_canvas_vg_object_viewbox_get(vg_part);
+ ck_assert_msg(viewbox.w >= 49 && viewbox.w <= 51,
+ "Viewbox width %d != expected 50 (tile_b)", viewbox.w);
+ ck_assert_msg(viewbox.h >= 49 && viewbox.h <= 51,
+ "Viewbox height %d != expected 50 (tile_b)", viewbox.h);
+
+ evas_object_del(obj);
+ ecore_evas_free(ee);
+}
+EFL_END_TEST
+
+/*
+ * edje_vg_render_box_c (Task 3.3)
+ *
+ * End-to-end structural test for ui/box_c (Mode B, inline vector{} block,
+ * tree_id 2). The inline tree has a 25x25 viewbox and a single shape child
+ * named "tiny" with a blue fill. This test confirms:
+ *
+ * (a) The VG part has a non-NULL root after recalc.
+ * (b) The root is an Efl_Canvas_Vg_Container.
+ * (c) The root has a child named "tiny" — the inline shape's name.
+ * The absence of "body" (tile_a/b) proves the correct, distinct tree
+ * was fetched (tree_id 2, not 0 or 1).
+ * (d) The viewbox is {0,0,25,25} — the inline tree's viewbox.
+ *
+ * This is the definitive Mode-B (inline anonymous tree) end-to-end test.
+ */
+EFL_START_TEST(edje_vg_render_box_c)
+{
+ const char *edj = TESTS_BUILD_DIR "/data/test_vector_states.edj";
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *obj;
+ Efl_Canvas_Vg_Node *vg_root;
+ Efl_Canvas_Vg_Node *tiny_node;
+ Evas_Object *vg_part;
+ Eina_Rect viewbox;
+
+ ee = ecore_evas_buffer_new(VG_RENDER_W, VG_RENDER_H);
+ fail_if(!ee);
+ ecore_evas_show(ee);
+ ecore_evas_manual_render_set(ee, EINA_TRUE);
+
+ evas = ecore_evas_get(ee);
+ fail_if(!evas);
+
+ obj = edje_object_add(evas);
+ fail_if(!obj);
+
+ /* ui/box_c uses an inline vector{} block (tree_id 2). */
+ fail_unless(edje_object_file_set(obj, edj, "ui/box_c"));
+
+ evas_object_resize(obj, VG_RENDER_W, VG_RENDER_H);
+ evas_object_move(obj, 0, 0);
+ evas_object_show(obj);
+
+ edje_object_calc_force(obj);
+ ecore_evas_manual_render(ee);
+
+ /* (a) + (b) Root must be non-NULL and a container. */
+ vg_part = (Evas_Object *)edje_object_part_object_get(obj, "vg");
+ fail_if(!vg_part);
+
+ vg_root = efl_canvas_vg_object_root_node_get(vg_part);
+ fail_if(vg_root == NULL);
+ fail_if(!efl_isa(vg_root, EFL_CANVAS_VG_CONTAINER_CLASS));
+
+ /* (c) The inline tree's only shape is named "tiny", not "body".
+ Confirming "tiny" is present and "body" is absent proves that tree_id 2
+ (the inline tree) was fetched, not tile_a or tile_b. */
+ tiny_node = efl_canvas_vg_container_child_get(vg_root, "tiny");
+ fail_if(tiny_node == NULL);
+ fail_if(!efl_isa(tiny_node, EFL_CANVAS_VG_SHAPE_CLASS));
+
+ fail_if(efl_canvas_vg_container_child_get(vg_root, "body") != NULL);
+
+ /* (d) Inline tree viewbox: {0,0,25,25}. */
+ viewbox = efl_canvas_vg_object_viewbox_get(vg_part);
+ ck_assert_msg(viewbox.w >= 24 && viewbox.w <= 26,
+ "Viewbox width %d != expected 25 (box_c inline)", viewbox.w);
+ ck_assert_msg(viewbox.h >= 24 && viewbox.h <= 26,
+ "Viewbox height %d != expected 25 (box_c inline)", viewbox.h);
+
+ evas_object_del(obj);
+ ecore_evas_free(ee);
+}
+EFL_END_TEST
+
void
edje_test_vector_states(TCase *tc)
{
@@ -456,4 +606,6 @@ edje_test_vector_states(TCase *tc)
tcase_add_test(tc, edje_vg_round_trip_tree_ids);
tcase_add_test(tc, edje_vg_tree_materializer_basic);
tcase_add_test(tc, edje_vg_render_box_a);
+ tcase_add_test(tc, edje_vg_render_box_b);
+ tcase_add_test(tc, edje_vg_render_box_c);
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.