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