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.

Reply via email to