GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_canvas_drawing_initiate.c Lines: 54 54 100.0 %
Date: 2024-12-05 08:52:37 Branches: 36 36 100.0 %

Line Branch Exec Source
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
/**   Canvas Management (Canvas)                                          */
18
/**                                                                       */
19
/**************************************************************************/
20
21
#define GX_SOURCE_CODE
22
23
24
/* Include necessary system files.  */
25
26
#include "gx_api.h"
27
#include "gx_system.h"
28
#include "gx_utility.h"
29
#include "gx_canvas.h"
30
#include "gx_context.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_canvas_drawing_initiate                         PORTABLE C      */
37
/*                                                           6.3.0        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function initiates drawing on the specified canvas.            */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    canvas                                Canvas control block          */
49
/*    who                                   Widget control block pointer  */
50
/*    dirty_area                            Area to draw on               */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    status                                Completion status             */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _gx_utility_rectangle_define          Define rectangle area.        */
59
/*    _gx_utility_rectangle_combine         Combine adjacent dirty areas. */
60
/*    _gx_context_brush_default             Define a brush                */
61
/*    _gx_system_error_process              Process an error              */
62
/*    _gx_utility_rectangle_overlap_detect  Detects two rectangles being  */
63
/*                                            overlap                     */
64
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    Application Code                                                    */
68
/*    _gx_multi_line_text_view_draw                                       */
69
/*    _gx_single_line_text_view_draw                                      */
70
/*    _gx_system_canvas_refresh                                           */
71
/*    _gx_widget_block_move                                               */
72
/*    _gx_widget_children_draw                                            */
73
/*    _gx_window_client_scroll                                            */
74
/*                                                                        */
75
/*  RELEASE HISTORY                                                       */
76
/*                                                                        */
77
/*    DATE              NAME                      DESCRIPTION             */
78
/*                                                                        */
79
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
80
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
81
/*                                            resulting in version 6.1    */
82
/*  12-31-2020     Kenneth Maxwell          Modified comment(s), added    */
83
/*                                            display rotation support,   */
84
/*                                            resulting in version 6.1.3  */
85
/*  03-02-2021     Kenneth Maxwell          Modified comment(s), added    */
86
/*                                            flip rotation support,      */
87
/*                                            resulting in version 6.1.5  */
88
/*  10-31-2023     Ting Zhu                 Modified comment(s),          */
89
/*                                            added partial canvas buffer */
90
/*                                            support,                    */
91
/*                                            resulting in version 6.3.0  */
92
/*                                                                        */
93
/**************************************************************************/
94
1882178
UINT _gx_canvas_drawing_initiate(GX_CANVAS *canvas, GX_WIDGET *who, GX_RECTANGLE *dirty_area)
95
{
96
GX_WINDOW       *win;
97
GX_DRAW_CONTEXT *new_context;
98
1882178
GX_DRAW_CONTEXT *current_context = _gx_system_current_draw_context;
99
1882178
GX_DISPLAY      *display = canvas -> gx_canvas_display;
100
101
1882178
    if (current_context)
102
    {
103
1757231
        new_context = current_context - 1;
104
105
        /* check for exceeding our maximum stack depth */
106
1757231
        if (new_context < _gx_system_draw_context_stack)
107
        {
108
70
            _gx_system_error_process(GX_DRAW_NESTING_EXCEEDED);
109
70
            return GX_DRAW_NESTING_EXCEEDED;
110
        }
111
    }
112
    else
113
    {
114
124947
        new_context = _gx_system_draw_context_stack_end - 1;
115
    }
116
117
118
    /* test to see if we have draw to this canvas since last refresh */
119
120
1882108
    if (canvas -> gx_canvas_draw_count > 0)
121
    {
122
1759622
        _gx_utility_rectangle_combine(&canvas -> gx_canvas_dirty_area, dirty_area);
123
    }
124
    else
125
    {
126
        /* initialize the dirty rectangle */
127
122486
        canvas -> gx_canvas_dirty_area = *dirty_area;
128
129
#ifdef GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER
130
        if (canvas -> gx_canvas_status & GX_CANVAS_PARTIAL_FRAME_BUFFER)
131
        {
132
            canvas -> gx_canvas_memory_width = (GX_VALUE)(dirty_area -> gx_rectangle_right - dirty_area -> gx_rectangle_left + 1);
133
            canvas -> gx_canvas_memory_width = (GX_VALUE)((canvas -> gx_canvas_memory_width + 3) & 0xFFFC);
134
            canvas -> gx_canvas_memory_height = (GX_VALUE)(canvas -> gx_canvas_memory_size / display -> gx_display_driver_row_pitch_get((USHORT)canvas -> gx_canvas_memory_width));
135
            if (canvas -> gx_canvas_memory_height < (dirty_area -> gx_rectangle_bottom - dirty_area -> gx_rectangle_top + 1))
136
            {
137
                return GX_INVALID_MEMORY_SIZE;
138
            }
139
            canvas -> gx_canvas_memory_offset_x = dirty_area -> gx_rectangle_left;
140
            canvas -> gx_canvas_memory_offset_y = dirty_area -> gx_rectangle_top;
141
        }
142
#endif
143
    }
144
145
    /* Are we nested?  */
146

1882108
    if (canvas -> gx_canvas_draw_nesting > 0 && current_context)
147
    {
148
        /* Yes, clone the previous context.  */
149
1756609
        *new_context =  *current_context;
150
    }
151
    else
152
    {
153
        /* initialize the new context's brush */
154
125499
        _gx_context_brush_default(new_context);
155
156
        /* save the canvas pointer for any function that needs it */
157
125499
        new_context -> gx_draw_context_canvas = canvas;
158
159
        /* copy some canvas params to the context to speed access by drawing APIs */
160
161
125499
        new_context -> gx_draw_context_display = canvas -> gx_canvas_display;
162
125499
        new_context -> gx_draw_context_memory  = canvas -> gx_canvas_memory;
163
164
125499
        if (new_context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_NONE ||
165
20000
            new_context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_FLIP)
166
        {
167
#ifdef GX_ENABLE_CANVAS_PARTIAL_FRAME_BUFFER
168
            if (canvas -> gx_canvas_status & GX_CANVAS_PARTIAL_FRAME_BUFFER)
169
            {
170
                new_context -> gx_draw_context_pitch = canvas -> gx_canvas_memory_width;
171
                new_context -> gx_draw_context_offset_x = canvas -> gx_canvas_memory_offset_x;
172
                new_context -> gx_draw_context_offset_y = canvas -> gx_canvas_memory_offset_y;
173
            }
174
            else
175
            {
176
                new_context -> gx_draw_context_pitch = canvas -> gx_canvas_x_resolution;
177
                new_context -> gx_draw_context_offset_x = 0;
178
                new_context -> gx_draw_context_offset_y = 0;
179
            }
180
181
#else
182
105512
            new_context -> gx_draw_context_pitch = canvas -> gx_canvas_x_resolution;
183
#endif
184
        }
185
        else
186
        {
187
19987
            new_context -> gx_draw_context_pitch = canvas -> gx_canvas_y_resolution;
188
        }
189
    }
190
191
    /* Update canvas draw count and draw nesting.  */
192
193
1882108
    canvas -> gx_canvas_draw_nesting++;
194
1882108
    canvas -> gx_canvas_draw_count++;
195
196
    /* let display driver know if it has notification function */
197
1882108
    if (display -> gx_display_driver_drawing_initiate)
198
    {
199
1
        display -> gx_display_driver_drawing_initiate(display, canvas);
200
    }
201
202
    /* Update the draw context clipping rectangle.  */
203
1882108
    if (who)
204
    {
205
1881555
        _gx_utility_rectangle_overlap_detect(dirty_area,
206
                                             &who -> gx_widget_clip, &new_context -> gx_draw_context_dirty);
207
#if defined(GX_BRUSH_ALPHA_SUPPORT)
208
1881555
        if (who -> gx_widget_style & GX_STYLE_USE_LOCAL_ALPHA)
209
        {
210
26559
            new_context -> gx_draw_context_brush.gx_brush_alpha = who -> gx_widget_alpha;
211
        }
212
#endif
213
    }
214
    else
215
    {
216
553
        new_context -> gx_draw_context_dirty = *dirty_area;
217
    }
218
219
    /* initialize viewports to NULL */
220
1882108
    new_context -> gx_draw_context_view_head = GX_NULL;
221
222
223
    /* pick up the viewport list */
224
225
1882108
    if (canvas -> gx_canvas_status & GX_CANVAS_SIMPLE)
226
    {
227
555
        new_context -> gx_draw_context_simple_view.gx_view_next = NULL;
228
555
        new_context -> gx_draw_context_simple_view.gx_view_rectangle = new_context -> gx_draw_context_dirty;
229
555
        new_context -> gx_draw_context_view_head = &new_context -> gx_draw_context_simple_view;
230
    }
231
    else
232
    {
233
1881553
        if (who)
234
        {
235
            /* is the root window trying to draw */
236
1881552
            if (who -> gx_widget_type == GX_TYPE_ROOT_WINDOW)
237
            {
238
206118
                win = (GX_WINDOW *)who;
239
206118
                new_context -> gx_draw_context_view_head = win -> gx_window_views;
240
            }
241
            else
242
            {
243
3433523
                while (who -> gx_widget_parent)
244
                {
245
3433522
                    if (who -> gx_widget_parent -> gx_widget_type == GX_TYPE_ROOT_WINDOW)
246
                    {
247
1675433
                        if (who -> gx_widget_type >= GX_TYPE_WINDOW &&
248
1671845
                            !(who -> gx_widget_status & GX_STATUS_TRANSPARENT))
249
                        {
250
                            /* child windows of the root window get their own view list */
251
1622588
                            win = (GX_WINDOW *)who;
252
                        }
253
                        else
254
                        {
255
                            /* other widget types just inherit the view list of the root */
256
52845
                            win = (GX_WINDOW *)who -> gx_widget_parent;
257
                        }
258
1675433
                        new_context -> gx_draw_context_view_head = win -> gx_window_views;
259
1675433
                        break;
260
                    }
261
1758089
                    who = who -> gx_widget_parent;
262
                }
263
            }
264
265
            /* the widget being drawn is no longer marked dirty */
266
1881552
            who -> gx_widget_status &= ~GX_STATUS_DIRTY;
267
        }
268
    }
269
270
    /* the new context becomes the current context */
271
1882108
    _gx_system_current_draw_context = new_context;
272
273
1882108
    if (new_context -> gx_draw_context_view_head == GX_NULL)
274
    {
275
        /* no viewports for the caller */
276
94248
        return(GX_NO_VIEWS);
277
    }
278
1787860
    return(GX_SUCCESS);
279
}
280