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 ca5917e05b2ecd6f0f9e74f1c30e078162610f31
Author: [email protected] <[email protected]>
AuthorDate: Wed Apr 29 14:04:34 2026 -0600

    edje: end-to-end transition render test for state dispatch (Task 5.4)
    
    Adds edje_vg_render_box_a_transition test exercising the full Phase 5
    transition pipeline: two descriptions with stroke_width 2→10 connected
    by LINEAR 1.0-second program. Test uses deterministic loop-time rewinding
    (efl_loop_time_set) + canvas animator tick (ecore_evas_animator_tick) to
    drive the transition synchronously without mid-frame sampling. Asserts
    stroke width reaches ~10 after transition completes. Phase 5 now complete.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
 src/tests/edje/data/test_vector_states.edc |  28 ++++++
 src/tests/edje/edje_test_vector_states.c   | 153 +++++++++++++++++++++++++++++
 2 files changed, 181 insertions(+)

diff --git a/src/tests/edje/data/test_vector_states.edc b/src/tests/edje/data/test_vector_states.edc
index 79b873736f..5063d71373 100644
--- a/src/tests/edje/data/test_vector_states.edc
+++ b/src/tests/edje/data/test_vector_states.edc
@@ -63,6 +63,34 @@ collections {
          }
       }
    }
+   /* Task 5.4: transition fixture.
+    * Two descriptions differing only in stroke.width (2 → 10) connected by a
+    * LINEAR 1.0 transition program.  The test advances ecore_loop_time past
+    * the 1.0-second deadline and asserts the post-transition stroke_width
+    * reaches ~10. */
+   group { name: "ui/box_a_transition";
+      parts { part { name: "vg"; type: VECTOR;
+         description { state: "default" 0.0;
+            vector.use: "tile_a";
+            vector.shape { target: "body";
+               stroke.width: 2;
+            }
+         }
+         description { state: "active" 0.0;
+            inherit: "default" 0.0;
+            vector.shape { target: "body";
+               stroke.width: 10;
+            }
+         }
+      } }
+      programs {
+         program { signal: "test,activate"; source: "test";
+            action: STATE_SET "active" 0.0;
+            target: "vg";
+            transition: LINEAR 1.0;
+         }
+      }
+   }
    /* Task 4.4: inherit + per-target merge fixture.
     * The default description sets visible and stroke.width on "body".
     * The active description inherits from default (getting those fields) and
diff --git a/src/tests/edje/edje_test_vector_states.c b/src/tests/edje/edje_test_vector_states.c
index 0dac610f67..2b9593c2de 100644
--- a/src/tests/edje/edje_test_vector_states.c
+++ b/src/tests/edje/edje_test_vector_states.c
@@ -6,6 +6,8 @@
 #include <Eina.h>
 #include <Eet.h>
 #include <Evas.h>
+#include <Ecore.h>
+#include <Ecore_Eo.h>
 #include <Ecore_Evas.h>
 #include "edje_suite.h"
 
@@ -1269,6 +1271,155 @@ EFL_START_TEST(edje_vg_tree_lerp_basic)
 }
 EFL_END_TEST
 
+/* Forward-declare ecore_evas_animator_tick — it is an EAPI symbol defined in
+ * ecore_evas.c but declared only in ecore_evas_private.h which cannot be
+ * included from tests.  The symbol is present in libecore_evas at runtime. */
+EAPI void ecore_evas_animator_tick(Ecore_Evas *ee, Eina_Rectangle *viewport,
+                                   double loop_time);
+
+/* Forward-declare efl_loop_time_set — it is an EAPI symbol generated in
+ * efl_loop.eo.h (build dir) and included via Ecore_Eo.h → efl_loop.eo.h, but
+ * the build-dir generated header may not resolve transitively through the
+ * source-tree include chain.  Forward-declare explicitly to silence the
+ * implicit-declaration warning; the symbol is present in libefl at runtime. */
+EAPI void efl_loop_time_set(Eo *obj, double timepoint);
+
+/*
+ * edje_vg_render_box_a_transition  (Task 5.4)
+ *
+ * End-to-end transition render test for ui/box_a_transition.
+ *
+ * The group has two descriptions: "default" with stroke.width=2 and "active"
+ * with stroke.width=10, connected by a LINEAR 1.0-second program.
+ *
+ * Test strategy (deterministic canvas animator tick with past-biased loop time):
+ *   1. Load the group on a buffer canvas; assert default stroke_width ~2.
+ *   2. Before emitting the signal, rewind the loop clock by 2.0 seconds using
+ *      efl_loop_time_set — this bypasses ecore_loop_time_set's guard against
+ *      future timestamps.  The rewind makes start_time (captured when the
+ *      running program is registered) approximately 2.0s behind wall clock.
+ *   3. Emit "test,activate" — Edje registers a running program with
+ *      start_time = t_past and subscribes _edje_timer_cb to
+ *      EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK (canvas_animator=1 because the
+ *      buffer canvas has an Ecore_Evas backing).
+ *   4. Call ecore_evas_animator_tick(ee, NULL, t_tick) where t_tick is
+ *      ecore_time_get() - 0.01 (just behind wall clock, so ecore_loop_time_set
+ *      accepts it).  Since t_tick - start_time ≈ 1.99s > 1.0s, the transition
+ *      iterator clamps to 1.0, applies the "active" description, clears param2,
+ *      and calls _edje_recalc.
+ *   5. Force-recalc + render; assert post-transition stroke_width ~10.
+ *
+ * This is begin/end-only (no mid-transition sample).  The approach is fully
+ * deterministic: one animator tick at t>start+deadline guarantees the
+ * transition completes in a single synchronous call.
+ *
+ * Note: loop time is restored to wall clock after the final assertion so that
+ * any test added after this one in the case does not inherit the 2-second rewind.
+ */
+EFL_START_TEST(edje_vg_render_box_a_transition)
+{
+   const char *edj = TESTS_BUILD_DIR "/data/test_vector_states.edj";
+   Ecore_Evas *ee;
+   Evas *evas;
+   Evas_Object *obj;
+   Evas_Object *vg_part;
+   Efl_Canvas_Vg_Node *vg_root;
+   Efl_Canvas_Vg_Node *body_node;
+   double sw;
+   double t_past;
+   double t_tick;
+
+   /* --- Setup: buffer canvas, edje object, load group --- */
+   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);
+
+   fail_unless(edje_object_file_set(obj, edj, "ui/box_a_transition"));
+
+   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);
+
+   /* --- Default state: stroke_width should be ~2 --- */
+   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));
+
+   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));
+
+   sw = efl_gfx_shape_stroke_width_get(body_node);
+   ck_assert_msg(sw >= 1.5 && sw <= 2.5,
+                 "Default state stroke_width %.2f != expected ~2.0", sw);
+
+   /* --- Trigger the 1.0-second LINEAR transition --- */
+   /* Step 1: Rewind loop clock to 2 seconds in the past.
+    * efl_loop_time_set bypasses the "not in the future" guard in
+    * ecore_loop_time_set; the running program will capture start_time = t_past
+    * when ecore_loop_time_get() is called inside _edje_program_run. */
+   t_past = ecore_time_get() - 2.0;
+   efl_loop_time_set(efl_main_loop_get(), t_past);
+
+   /* Step 2: Emit signal — _edje_program_run registers the running program
+    * with start_time ≈ t_past and subscribes _edje_timer_cb to the canvas
+    * ANIMATOR_TICK event. */
+   edje_object_signal_emit(obj, "test,activate", "test");
+   edje_object_message_signal_process(obj);
+
+   /* Step 3: Fire the canvas animator tick at t_tick < ecore_time_get().
+    * ecore_evas_animator_tick() calls ecore_loop_time_set(t_tick) internally
+    * (which passes the guard since t_tick < wall clock) and then emits
+    * EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK on the canvas.  The per-object
+    * repeater propagates to ed->obj → _edje_timer_cb → run_iterate(runp, t_tick).
+    * Since t_tick - t_past ≈ 1.99s > 1.0s, the transition completes. */
+   t_tick = ecore_time_get() - 0.01;
+   ecore_evas_animator_tick(ee, NULL, t_tick);
+
+   /* Step 4: Force recalc so _edje_vector_recalc_apply materializes the post-
+    * transition description (param2 = NULL now), then render. */
+   edje_object_calc_force(obj);
+   ecore_evas_manual_render(ee);
+
+   /* --- Post-transition state: stroke_width should be ~10 --- */
+   /* Re-fetch root and body — a fresh Efl_VG hierarchy is built each recalc,
+    * so the previous pointers are stale. */
+   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));
+
+   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));
+
+   sw = efl_gfx_shape_stroke_width_get(body_node);
+   ck_assert_msg(sw >= 9.5 && sw <= 10.5,
+                 "Post-transition stroke_width %.2f != expected ~10.0 "
+                 "(transition lerp or materialize not applied)", sw);
+
+   /* Restore loop time to wall clock so any test added after this one in the
+    * case does not inherit the 2-second rewind. */
+   efl_loop_time_set(efl_main_loop_get(), ecore_time_get());
+
+   /* --- Cleanup --- */
+   evas_object_del(obj);
+   ecore_evas_free(ee);
+}
+EFL_END_TEST
+
 void
 edje_test_vector_states(TCase *tc)
 {
@@ -1294,4 +1445,6 @@ edje_test_vector_states(TCase *tc)
    tcase_add_test(tc, edje_vg_viewbox_lerp_componentwise);
    /* Phase 5.2 tree lerp */
    tcase_add_test(tc, edje_vg_tree_lerp_basic);
+   /* Phase 5.4 end-to-end transition */
+   tcase_add_test(tc, edje_vg_render_box_a_transition);
 }

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to