1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Animation Management (Animation) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_widget.h"
28 #include "gx_system.h"
29 #include "gx_canvas.h"
30 #include "gx_utility.h"
31 #include "gx_animation.h"
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _gx_animation_update PORTABLE C */
38 /* 6.1.11 */
39 /* AUTHOR */
40 /* */
41 /* Kenneth Maxwell, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function executes one step on an animation sequence. */
46 /* */
47 /* */
48 /* INPUT */
49 /* */
50 /* None */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* _gx_canvas_alpha_set Set the alpha of canvas */
59 /* _gx_animation_complete Called when an animation */
60 /* sequence is finished */
61 /* _gx_canvas_offset_set Set the offset of canvas */
62 /* _gx_widget_shift Shift a widget */
63 /* _gx_animation_stop Stop an animation */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _gx_system_timer_update Update active system timers */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
74 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* 12-31-2020 Kenneth Maxwell Modified comment(s), improve */
77 /* linear animation accuracy, */
78 /* resulting in version 6.1.3 */
79 /* 04-25-2022 Ting Zhu Modified comment(s), */
80 /* added block move support, */
81 /* resulting in version 6.1.11 */
82 /* */
83 /**************************************************************************/
_gx_animation_update(VOID)84 VOID _gx_animation_update(VOID)
85 {
86 GX_ANIMATION *animation;
87 GX_ANIMATION *next;
88 GX_WIDGET *target;
89 INT test_alpha;
90 INT x_current;
91 INT y_current;
92 INT x_trans = 0;
93 INT y_trans = 0;
94 GX_ANIMATION_INFO *info;
95 GX_WIDGET *parent;
96 GX_RECTANGLE block;
97
98 animation = _gx_system_animation_list;
99
100 while (animation)
101 {
102 info = &animation -> gx_animation_info;
103 next = animation -> gx_animation_next;
104
105 /* has this animation timer expired ? */
106 if (animation -> gx_animation_timer > 1)
107 {
108 /* no, just decrement timer count and continue */
109 animation -> gx_animation_timer--;
110 animation = next;
111 continue;
112 }
113
114 if (info -> gx_animation_style & GX_ANIMATION_SCREEN_DRAG)
115 {
116 animation = next;
117 continue;
118 }
119
120 /* the animation timer has expired. First reload the
121 timer counter in case we are not on last step
122 */
123
124 info -> gx_animation_steps = (GX_UBYTE)(info -> gx_animation_steps - 1);
125
126 if (info -> gx_animation_steps <= 0)
127 {
128 _gx_animation_complete(animation);
129 animation = next;
130 continue;
131 }
132 else
133 {
134 animation -> gx_animation_timer = info -> gx_animation_frame_interval;
135 }
136
137 target = info -> gx_animation_target;
138
139 /* check for a fade style animation */
140 if (info -> gx_animation_end_alpha !=
141 info -> gx_animation_start_alpha)
142 {
143 _gx_utility_easing_function_calculate(info -> gx_animation_style,
144 info -> gx_animation_start_alpha,
145 info -> gx_animation_end_alpha,
146 animation -> gx_animation_total_steps - info -> gx_animation_steps,
147 animation -> gx_animation_total_steps, &test_alpha);
148
149 if (animation -> gx_animation_canvas)
150 {
151 _gx_canvas_alpha_set(animation -> gx_animation_canvas, (GX_UBYTE)test_alpha);
152 }
153 #if defined(GX_BRUSH_ALPHA_SUPPORT)
154 else
155 {
156 target -> gx_widget_alpha = (GX_UBYTE)test_alpha;
157 if (test_alpha == 0xff)
158 {
159 _gx_system_dirty_mark(target);
160 }
161 else
162 {
163 _gx_system_dirty_partial_add(target -> gx_widget_parent, &target -> gx_widget_size);
164 }
165 }
166 #endif
167 }
168
169 /* check for a slide style animation */
170 if ((info -> gx_animation_end_position.gx_point_x !=
171 info -> gx_animation_start_position.gx_point_x) ||
172 (info -> gx_animation_end_position.gx_point_y !=
173 info -> gx_animation_start_position.gx_point_y))
174 {
175 if (animation -> gx_animation_canvas)
176 {
177 x_current = animation -> gx_animation_canvas -> gx_canvas_display_offset_x;
178 y_current = animation -> gx_animation_canvas -> gx_canvas_display_offset_y;
179 }
180 else
181 {
182 x_current = target -> gx_widget_size.gx_rectangle_left;
183 y_current = target -> gx_widget_size.gx_rectangle_top;
184 }
185
186 if (info -> gx_animation_start_position.gx_point_x != info -> gx_animation_end_position.gx_point_x)
187 {
188 _gx_utility_easing_function_calculate(info -> gx_animation_style,
189 info -> gx_animation_start_position.gx_point_x,
190 info -> gx_animation_end_position.gx_point_x,
191 animation -> gx_animation_total_steps - info -> gx_animation_steps,
192 animation -> gx_animation_total_steps, &x_trans);
193
194 x_trans -= x_current;
195 }
196 else
197 {
198 x_trans = 0;
199 }
200
201 if (info -> gx_animation_start_position.gx_point_y != info -> gx_animation_end_position.gx_point_y)
202 {
203 _gx_utility_easing_function_calculate(info -> gx_animation_style,
204 info -> gx_animation_start_position.gx_point_y,
205 info -> gx_animation_end_position.gx_point_y,
206 animation -> gx_animation_total_steps - info -> gx_animation_steps,
207 animation -> gx_animation_total_steps, &y_trans);
208
209 y_trans -= y_current;
210 }
211 else
212 {
213 y_trans = 0;
214 }
215
216 /* still moving */
217 if (animation -> gx_animation_canvas)
218 {
219 /* adjust canvas offset */
220 _gx_canvas_offset_set(animation -> gx_animation_canvas,
221 (GX_VALUE)(x_current + x_trans), (GX_VALUE)(y_current + y_trans));
222 }
223 else
224 {
225 /* adjust target position */
226 if (animation -> gx_animation_info.gx_animation_style & GX_ANIMATION_BLOCK_MOVE)
227 {
228 parent = animation -> gx_animation_info.gx_animation_parent;
229 if (_gx_utility_rectangle_overlap_detect(&target -> gx_widget_size, &parent -> gx_widget_size, &block))
230 {
231 _gx_widget_scroll_shift(target, (GX_VALUE)x_trans, (GX_VALUE)y_trans, GX_TRUE);
232 _gx_widget_block_move(parent, &block, (GX_VALUE)x_trans, (GX_VALUE)y_trans);
233 }
234 else
235 {
236 _gx_widget_shift(target, (GX_VALUE)x_trans, (GX_VALUE)y_trans, GX_TRUE);
237 }
238 }
239 else
240 {
241 _gx_widget_shift(target, (GX_VALUE)x_trans, (GX_VALUE)y_trans, GX_TRUE);
242 }
243 }
244 }
245 animation = next;
246 }
247 }
248
249