GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_animation_start.c Lines: 47 47 100.0 %
Date: 2026-08-28 02:37:13 Branches: 26 28 92.9 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026 Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
// Some portions generated by Copilot (Claude Sonnet 4.6).
12
// Some portions generated by Claude Code (Opus 5).
13
14
15
/**************************************************************************/
16
/**************************************************************************/
17
/**                                                                       */
18
/** GUIX Component                                                        */
19
/**                                                                       */
20
/**   Animation Management (Animation)                                    */
21
/**                                                                       */
22
/**************************************************************************/
23
24
#define GX_SOURCE_CODE
25
26
27
/* Include necessary system files.  */
28
29
#include "gx_api.h"
30
#include "gx_widget.h"
31
#include "gx_system.h"
32
#include "gx_canvas.h"
33
#include "gx_animation.h"
34
35
36
/**************************************************************************/
37
/*                                                                        */
38
/*  FUNCTION                                               RELEASE        */
39
/*                                                                        */
40
/*    _gx_animation_start                                 PORTABLE C      */
41
/*                                                           6.1.3        */
42
/*  AUTHOR                                                                */
43
/*                                                                        */
44
/*    Kenneth Maxwell, Microsoft Corporation                              */
45
/*                                                                        */
46
/*  DESCRIPTION                                                           */
47
/*                                                                        */
48
/*    This function starts an animation sequence.                         */
49
/*                                                                        */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    animation                             Pointer to animation control  */
54
/*                                            block                       */
55
/*    info                                  Animation information         */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    status                                Completion status             */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _gx_widget_detach                     Detach a widget from its      */
64
/*                                            parent                      */
65
/*    _gx_widget_shift                      Shift a widget                */
66
/*    _gx_canvas_offset_set                 Set the offset of canvas      */
67
/*    _gx_canvas_alpha_set                  Set the alpha of canvas       */
68
/*    _gx_widget_attach                     Attach a widget to its parent */
69
/*    _gx_widget_show                       Show a widget                 */
70
/*    tx_timer_info_get                     Get the information of        */
71
/*                                            ThreadX timer               */
72
/*    tx_timer_activate                     Start the ThreadX timer       */
73
/*                                                                        */
74
/*  CALLED BY                                                             */
75
/*                                                                        */
76
/*    Application Code                                                    */
77
/*                                                                        */
78
/**************************************************************************/
79
#if (GX_ANIMATION_POOL_SIZE > 0)
80
62
UINT _gx_animation_start(GX_ANIMATION *animation, GX_ANIMATION_INFO *info)
81
{
82
62
UINT            status = GX_SUCCESS;
83
UINT            draw_status;
84
GX_WINDOW_ROOT *root;
85
86
#ifdef GX_THREADX_BINDING
87
#ifndef GX_DISABLE_THREADX_TIMER_SOURCE
88
UINT     tx_timer_active;
89
#endif
90
#endif
91
GX_VALUE left;
92
GX_VALUE top;
93
94
62
    animation -> gx_animation_total_steps = info -> gx_animation_steps;
95
96
62
    if (animation -> gx_animation_canvas)
97
    {
98
        /* Make sure the widget is not attached to any parent */
99
7
        _gx_widget_detach(info -> gx_animation_target);
100
101
        /* position the target widget at 0,0 within the animation canvas */
102
7
        left = info -> gx_animation_target -> gx_widget_size.gx_rectangle_left;
103
7
        top = info -> gx_animation_target -> gx_widget_size.gx_rectangle_top;
104
105

7
        if (left || top)
106
        {
107
2
            _gx_widget_shift(info -> gx_animation_target, (GX_VALUE)-left, (GX_VALUE)-top, GX_FALSE);
108
        }
109
110
        /* position the canvas at the animation starting position */
111
7
        _gx_canvas_offset_set(animation -> gx_animation_canvas,
112
7
                              info -> gx_animation_start_position.gx_point_x,
113
7
                              info -> gx_animation_start_position.gx_point_y);
114
115
        /* link the target to the animation root window */
116
7
        root = _gx_system_root_window_created_list;
117

9
        while (root && root -> gx_window_root_canvas != animation -> gx_animation_canvas)
118
        {
119
2
            root = (GX_WINDOW_ROOT *)root -> gx_widget_next;
120
        }
121
7
        if (root)
122
        {
123
6
            _gx_widget_attach((GX_WIDGET *)root, info -> gx_animation_target);
124
125
            /* and show the animation root window to make everything visible */
126
6
            _gx_widget_show((GX_WIDGET *)root);
127
            /* Keep the drawing status separate from the completion status returned
128
               by this function. _gx_widget_show() above releases the view list of
129
               the animation root window, so _gx_canvas_drawing_initiate() reports
130
               GX_NO_VIEWS here. That is expected for an animation canvas and must
131
               neither be returned to the caller nor prevent the animation from
132
               being linked into the active list below.  */
133
6
            draw_status = _gx_canvas_drawing_initiate(animation -> gx_animation_canvas, (GX_WIDGET *) root, &root -> gx_widget_size);
134
135
            /* Draw and complete only when a draw context was actually pushed.
136
               GX_DRAW_NESTING_EXCEEDED means no context was pushed, so calling
137
               _gx_canvas_drawing_complete() would corrupt the outer context. The
138
               children of a root window with no views are still drawn, matching
139
               the behaviour of _gx_system_canvas_refresh().  */
140

6
            if ((draw_status == GX_SUCCESS) || (draw_status == GX_NO_VIEWS))
141
            {
142
6
                _gx_widget_children_draw((GX_WIDGET *)root);
143
6
                _gx_canvas_drawing_complete(animation -> gx_animation_canvas, GX_FALSE);
144
            }
145
146
            /* set the initial alpha and make our canvas visible */
147
6
            _gx_canvas_alpha_set(animation -> gx_animation_canvas, info -> gx_animation_start_alpha);
148
6
            _gx_canvas_show(animation -> gx_animation_canvas);
149
        }
150
        else
151
        {
152
1
            status = GX_FAILURE;
153
        }
154
    }
155
    else
156
    {
157
55
        if (info -> gx_animation_start_alpha != info -> gx_animation_end_alpha)
158
        {
159
#ifdef GX_BRUSH_ALPHA_SUPPORT
160
16
            info -> gx_animation_target -> gx_widget_style |= GX_STYLE_USE_LOCAL_ALPHA;
161
16
            info -> gx_animation_target -> gx_widget_alpha = info -> gx_animation_start_alpha;
162
#else
163
            status = GX_INVALID_VALUE;
164
#endif
165
        }
166
167
        /* position the target at the starting position */
168
55
        left = (GX_VALUE)(info -> gx_animation_start_position.gx_point_x -
169
55
                          info -> gx_animation_target -> gx_widget_size.gx_rectangle_left);
170
55
        top =  (GX_VALUE)(info -> gx_animation_start_position.gx_point_y -
171
55
                          info -> gx_animation_target -> gx_widget_size.gx_rectangle_top);
172
173

55
        if (left || top)
174
        {
175
44
            _gx_widget_shift(info -> gx_animation_target,
176
                             left, top, GX_TRUE);
177
        }
178
179
        /* link the target to the animation root window */
180
55
        _gx_widget_attach(info -> gx_animation_parent, info -> gx_animation_target);
181
    }
182
183
    /* If we were able to start this animation, link it into the active list */
184
62
    if (status == GX_SUCCESS)
185
    {
186
        /* save the animation parameters */
187
61
        animation -> gx_animation_info = *info;
188
61
        if (info -> gx_animation_start_delay)
189
        {
190
2
            animation -> gx_animation_timer = info -> gx_animation_start_delay;
191
        }
192
        else
193
        {
194
59
            animation -> gx_animation_timer = animation -> gx_animation_info.gx_animation_frame_interval;
195
        }
196
61
        animation -> gx_animation_status = GX_ANIMATION_ACTIVE;
197
61
        animation -> gx_animation_next = _gx_system_animation_list;
198
61
        _gx_system_animation_list = animation;
199
200
#ifdef GX_THREADX_BINDING
201
#ifndef GX_DISABLE_THREADX_TIMER_SOURCE
202
        /* if the low-level timer is not active, start it */
203
61
        tx_timer_info_get(&_gx_system_timer, (CHAR **)TX_NULL, &tx_timer_active,
204
                          (ULONG *)TX_NULL, (ULONG *)TX_NULL, (TX_TIMER **)TX_NULL);
205
206
61
        if (!tx_timer_active)
207
        {
208
47
            tx_timer_activate(&_gx_system_timer);
209
        }
210
#endif
211
#else
212
        GX_TIMER_START;
213
#endif
214
    }
215
216
62
    return(status);
217
}
218
#endif