GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_canvas_rectangle_draw.c Lines: 82 82 100.0 %
Date: 2026-03-06 19:21:09 Branches: 21 21 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present 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
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Canvas Management (Canvas)                                          */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_system.h"
29
#include "gx_utility.h"
30
#include "gx_canvas.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_canvas_rectangle_fill                           PORTABLE C      */
37
/*                                                           6.1          */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Support function for gx_canvas_rectangle_draw, draw a wide border   */
45
/*    by drawing a filled rectangle.                                      */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    rectangle                             Rectangle specification       */
50
/*                                                                        */
51
/*  OUTPUT                                                                */
52
/*                                                                        */
53
/*    status                                Completion status             */
54
/*                                                                        */
55
/*  CALLS                                                                 */
56
/*                                                                        */
57
/*    _gx_utility_rectangle_overlap_detect  Detect rectangle overlap      */
58
/*    _gx_canvas_line_draw                  Draw a line                   */
59
/*    [gx_display_driver_horizontal_line_draw]                            */
60
/*                                          Display driver horizontal     */
61
/*                                            line draw routine           */
62
/*                                                                        */
63
/*  CALLED BY                                                             */
64
/*                                                                        */
65
/*    _gx_canvas_rectangle_draw                                           */
66
/*                                                                        */
67
/**************************************************************************/
68
8
static UINT  _gx_canvas_rectangle_fill(GX_RECTANGLE *rectangle, GX_COLOR fill_color)
69
{
70
GX_DRAW_CONTEXT *context;
71
GX_DISPLAY      *display;
72
GX_RECTANGLE     fill_rect;
73
GX_RECTANGLE     bound;
74
GX_VIEW         *view;
75
GX_VALUE         rectangle_height;
76
77
    /* pick up current drawing context */
78
8
    context = _gx_system_current_draw_context;
79
80
    /* Check to see if the rectangle overlaps the dirty area.  */
81
8
    if (!_gx_utility_rectangle_overlap_detect(rectangle, &context -> gx_draw_context_dirty, &bound))
82
    {
83
        /* nothing to draw, return */
84
1
        return GX_SUCCESS;
85
    }
86
87
    /* pick up current display driver */
88
7
    display = context -> gx_draw_context_display;
89
90
91
    /* test to determine if the bounding rectangle overlaps the region we are allowed to draw
92
       into. For each view that overlaps the bounding rectangle, do some drawing.
93
     */
94
7
    view = context -> gx_draw_context_view_head;
95
96
20
    while (view)
97
    {
98
13
        if (_gx_utility_rectangle_overlap_detect(&bound, &view -> gx_view_rectangle, &fill_rect))
99
        {
100
            /* Pickup the height.  */
101
7
            rectangle_height = (GX_VALUE)(fill_rect.gx_rectangle_bottom - fill_rect.gx_rectangle_top + 1);
102
7
            context -> gx_draw_context_clip = &fill_rect;
103
104
7
            display -> gx_display_driver_horizontal_line_draw(context,
105
7
                                                              fill_rect.gx_rectangle_left,
106
7
                                                              fill_rect.gx_rectangle_right,
107
7
                                                              fill_rect.gx_rectangle_top,
108
                                                              rectangle_height, fill_color);
109
        }
110
13
        view = view -> gx_view_next;
111
    }
112
113
    /* Return successful completion.  */
114
7
    return(GX_SUCCESS);
115
}
116
117
118
119
/**************************************************************************/
120
/*                                                                        */
121
/*  FUNCTION                                               RELEASE        */
122
/*                                                                        */
123
/*    _gx_canvas_rectangle_draw                           PORTABLE C      */
124
/*                                                           6.1          */
125
/*  AUTHOR                                                                */
126
/*                                                                        */
127
/*    Kenneth Maxwell, Microsoft Corporation                              */
128
/*                                                                        */
129
/*  DESCRIPTION                                                           */
130
/*                                                                        */
131
/*    This draws the specified rectangle on the current context.          */
132
/*                                                                        */
133
/*  INPUT                                                                 */
134
/*                                                                        */
135
/*    rectangle                             Rectangle specification       */
136
/*                                                                        */
137
/*  OUTPUT                                                                */
138
/*                                                                        */
139
/*    status                                Completion status             */
140
/*                                                                        */
141
/*  CALLS                                                                 */
142
/*                                                                        */
143
/*    _gx_utility_rectangle_overlap_detect  Detect rectangle overlap      */
144
/*    _gx_canvas_line_draw                  Draw a line                   */
145
/*    _gx_canvas_rectangle_draw             Draw a rectangle              */
146
/*    [gx_display_driver_horizontal_line_draw]                            */
147
/*                                          Display driver horizontal     */
148
/*                                            line draw routine           */
149
/*                                                                        */
150
/*  CALLED BY                                                             */
151
/*                                                                        */
152
/*    _gx_scrollbar_draw                                                  */
153
/*    _gx_slider_needle_draw                                              */
154
/*    _gx_widget_border_draw                                              */
155
/*                                                                        */
156
/**************************************************************************/
157
1150409
UINT  _gx_canvas_rectangle_draw(GX_RECTANGLE *rectangle)
158
{
159
GX_DRAW_CONTEXT *context;
160
GX_DISPLAY      *display;
161
GX_RECTANGLE     fill_rect;
162
GX_RECTANGLE     bound;
163
GX_VIEW         *view;
164
GX_COLOR         fill_color;
165
GX_VALUE         rectangle_height;
166
GX_VALUE         brush_width;
167
168
    /* pick up current drawing context */
169
1150409
    context = _gx_system_current_draw_context;
170
171
    /* Check to see if the rectangle overlaps the dirty area.  */
172
1150409
    if (!_gx_utility_rectangle_overlap_detect(rectangle, &context -> gx_draw_context_dirty, &bound))
173
    {
174
        /* nothing to draw, return */
175
8279
        return GX_SUCCESS;
176
    }
177
178
    /* pick up current display driver */
179
1142130
    display = context -> gx_draw_context_display;
180
181
    /* if the rectangle has a border, call either the line function (for a single-pixel border)
182
       or the rectangle functions (for a wide border), then reduce the size of the rectangle
183
       we are drawing here
184
     */
185
186
1142130
    fill_rect = *rectangle;
187
1142130
    brush_width = context -> gx_draw_context_brush.gx_brush_width;
188
189
1142130
    switch (brush_width)
190
    {
191
1004835
    case 0:
192
        /* no border */
193
1004835
        break;
194
195
137293
    case 1:
196
        /* thin border */
197
137293
        _gx_canvas_line_draw(rectangle -> gx_rectangle_left,
198
137293
                             (GX_VALUE)(rectangle -> gx_rectangle_top + 1),
199
137293
                             rectangle -> gx_rectangle_left,
200
137293
                             (GX_VALUE)(rectangle -> gx_rectangle_bottom - 1));
201
202
137293
        _gx_canvas_line_draw(rectangle -> gx_rectangle_right,
203
137293
                             (GX_VALUE)(rectangle -> gx_rectangle_top + 1),
204
137293
                             rectangle -> gx_rectangle_right,
205
137293
                             (GX_VALUE)(rectangle -> gx_rectangle_bottom - 1));
206
207
137293
        _gx_canvas_line_draw(rectangle -> gx_rectangle_left,
208
137293
                             rectangle -> gx_rectangle_top,
209
137293
                             rectangle -> gx_rectangle_right,
210
137293
                             rectangle -> gx_rectangle_top);
211
212
137293
        _gx_canvas_line_draw(rectangle -> gx_rectangle_left,
213
137293
                             rectangle -> gx_rectangle_bottom,
214
137293
                             rectangle -> gx_rectangle_right,
215
137293
                             rectangle -> gx_rectangle_bottom);
216
217
137293
        fill_rect.gx_rectangle_top = (GX_VALUE)(fill_rect.gx_rectangle_top + 1);
218
137293
        fill_rect.gx_rectangle_bottom = (GX_VALUE)(fill_rect.gx_rectangle_bottom - 1);
219
137293
        fill_rect.gx_rectangle_left = (GX_VALUE)(fill_rect.gx_rectangle_left + 1);
220
137293
        fill_rect.gx_rectangle_right = (GX_VALUE)(fill_rect.gx_rectangle_right - 1);
221
137293
        break;
222
223
2
    default:
224
225
        /* draw the wide top line */
226
2
        fill_rect.gx_rectangle_bottom = (GX_VALUE)(fill_rect.gx_rectangle_top + brush_width - 1);
227
2
        _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
228
229
        /* draw the wide bottom line */
230
2
        fill_rect.gx_rectangle_bottom = rectangle -> gx_rectangle_bottom;
231
2
        fill_rect.gx_rectangle_top = (GX_VALUE)(fill_rect.gx_rectangle_bottom - brush_width + 1);
232
2
        _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
233
234
        /* draw the wide left side */
235
2
        fill_rect.gx_rectangle_top = (GX_VALUE)(rectangle -> gx_rectangle_top + brush_width);
236
2
        fill_rect.gx_rectangle_bottom = (GX_VALUE)(fill_rect.gx_rectangle_bottom - brush_width);
237
2
        fill_rect.gx_rectangle_right = (GX_VALUE)(fill_rect.gx_rectangle_left + brush_width - 1);
238
2
        _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
239
240
        /* draw the wide right side */
241
2
        fill_rect.gx_rectangle_right = rectangle -> gx_rectangle_right;
242
2
        fill_rect.gx_rectangle_left = (GX_VALUE)(fill_rect.gx_rectangle_right - brush_width + 1);
243
2
        _gx_canvas_rectangle_fill(&fill_rect, context -> gx_draw_context_brush.gx_brush_line_color);
244
245
        /* subtract the border from the fill_rect */
246
2
        fill_rect.gx_rectangle_bottom = (GX_VALUE)(rectangle -> gx_rectangle_bottom - brush_width);
247
2
        fill_rect.gx_rectangle_top = (GX_VALUE)(rectangle -> gx_rectangle_top + brush_width);
248
2
        fill_rect.gx_rectangle_left = (GX_VALUE)(rectangle -> gx_rectangle_left + brush_width);
249
2
        fill_rect.gx_rectangle_right = (GX_VALUE)(rectangle -> gx_rectangle_right - brush_width);
250
    }
251
252
1142130
    if (context -> gx_draw_context_brush.gx_brush_width != 0)
253
    {
254
        /* Check again, after reducing size, to see if the rectangle overlaps the dirty area.  */
255
137295
        if (!_gx_utility_rectangle_overlap_detect(&fill_rect, &context -> gx_draw_context_dirty, &bound))
256
        {
257
            /* nothing to draw, return */
258
25
            return GX_SUCCESS;
259
        }
260
    }
261
262
1142105
    if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_SOLID_FILL) == 0)
263
    {
264
8996
        return GX_SUCCESS;
265
    }
266
267
    /* test to determine if the bounding rectangle overlaps the region we are allowed to draw
268
       into. For each view that overlaps the bounding rectangle, do some drawing.
269
     */
270
1133109
    view = context -> gx_draw_context_view_head;
271
272
    /* save the fill color for later */
273
1133109
    fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
274
275
2379033
    while (view)
276
    {
277
1245924
        if (_gx_utility_rectangle_overlap_detect(&bound, &view -> gx_view_rectangle, &fill_rect))
278
        {
279
            /* Pickup the height.  */
280
1210865
            rectangle_height = (GX_VALUE)(fill_rect.gx_rectangle_bottom - fill_rect.gx_rectangle_top + 1);
281
1210865
            context -> gx_draw_context_clip = &fill_rect;
282
283
1210865
            display -> gx_display_driver_horizontal_line_draw(context,
284
1210865
                                                              fill_rect.gx_rectangle_left,
285
1210865
                                                              fill_rect.gx_rectangle_right,
286
1210865
                                                              fill_rect.gx_rectangle_top,
287
                                                              rectangle_height, fill_color);
288
        }
289
1245924
        view = view -> gx_view_next;
290
    }
291
292
    /* Return successful completion.  */
293
1133109
    return(GX_SUCCESS);
294
}
295