GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_widget_border_draw.c Lines: 165 165 100.0 %
Date: 2026-03-06 19:21:09 Branches: 40 40 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
/**   Widget Management (Widget)                                          */
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_canvas.h"
30
#include "gx_context.h"
31
#include "gx_widget.h"
32
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_widget_border_draw                              PORTABLE C      */
39
/*                                                           6.1          */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Kenneth Maxwell, Microsoft Corporation                              */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    This function draws the specified widget.                           */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    widget                                Pointer to widget             */
51
/*    border_color                          Color of border               */
52
/*    upper_color                           Color of upper fill           */
53
/*    lower_color                           Color of lower fill           */
54
/*    fill                                  flag to request fill          */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    None                                                                */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    _gx_widget_border_width_get           Get border width              */
63
/*    _gx_context_raw_line_color_set        Set line color in context     */
64
/*    _gx_context_brush_define              Define the brush of the       */
65
/*                                            context                     */
66
/*    _gx_context_brush_width_set           Set brush width in context    */
67
/*    _gx_canvas_line_draw                  Draw a line                   */
68
/*    _gx_widget_client_get                 Get widget client             */
69
/*    _gx_canvas_rectangle_draw             Draw rectangle                */
70
71
/*    _gx_context_fill_color_set            Set the fill color            */
72
/*    _gx_canvas_pixel_draw                 Draw a pixel                  */
73
/*    _gx_context_line_color_set            Set line color                */
74
/*                                                                        */
75
/*  CALLED BY                                                             */
76
/*                                                                        */
77
/*    Application Code                                                    */
78
/*    GUIX Internal Code                                                  */
79
/*                                                                        */
80
/**************************************************************************/
81
1292611
VOID  _gx_widget_border_draw(GX_WIDGET *widget,
82
                             GX_RESOURCE_ID border_color,
83
                             GX_RESOURCE_ID upper_color,
84
                             GX_RESOURCE_ID lower_color, GX_BOOL fill)
85
{
86
GX_POINT     corner;
87
GX_RECTANGLE fillrect;
88
GX_VALUE     widget_height;
89
INT          left;
90
INT          right;
91
INT          top;
92
GX_VALUE     border_width;
93
1292611
GX_BOOL      rounded = GX_FALSE;
94
95
1292611
    _gx_widget_border_width_get(widget, &border_width);
96
97
1292611
    if (border_width > 0)
98
    {
99
        /* Pick up the current brush.  */
100
101
837807
        _gx_context_line_color_set(border_color);
102
837807
        top = widget -> gx_widget_size.gx_rectangle_top;
103
104
837807
        if (widget -> gx_widget_style & GX_STYLE_BORDER_THICK)
105
        {
106
34692
            _gx_context_brush_width_set((UINT)border_width);
107
34692
            top += border_width / 2;
108
        }
109
        else
110
        {
111
803115
            _gx_context_brush_width_set(1);
112
        }
113
114
        /* Draw line across the top.  */
115
837807
        left = widget -> gx_widget_size.gx_rectangle_left;
116
837807
        right = widget -> gx_widget_size.gx_rectangle_right;
117
118
837807
        if (widget -> gx_widget_parent)
119
        {
120
837806
            if (widget -> gx_widget_parent -> gx_widget_type != GX_TYPE_ROOT_WINDOW ||
121
157966
                (widget -> gx_widget_status & GX_STATUS_TRANSPARENT))
122
            {
123
680069
                rounded = GX_TRUE;
124
680069
                left += 2;
125
680069
                right -= 2;
126
            }
127
        }
128
129
837807
        _gx_canvas_line_draw((GX_VALUE)left, (GX_VALUE)top, (GX_VALUE)right, (GX_VALUE)top);
130
131
        /* Draw line across the bottom.  */
132
837807
        if (widget -> gx_widget_style & GX_STYLE_BORDER_THICK)
133
        {
134
34692
            top = widget -> gx_widget_size.gx_rectangle_bottom - border_width + 1;
135
34692
            top += border_width / 2;
136
34692
            _gx_canvas_line_draw((GX_VALUE)left, (GX_VALUE)top, (GX_VALUE)right, (GX_VALUE)top);
137
        }
138
        else
139
        {
140
803115
            _gx_canvas_line_draw((GX_VALUE)left,
141
803115
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom),
142
803115
                                 (GX_VALUE)right,
143
803115
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom));
144
        }
145
146
        /* Draw line down left side.  */
147
837807
        left = widget -> gx_widget_size.gx_rectangle_left;
148
149
837807
        if (widget -> gx_widget_style & GX_STYLE_BORDER_THICK)
150
        {
151
34692
            left += border_width / 2;
152
        }
153
154
837807
        if (rounded)
155
        {
156
680069
            _gx_canvas_line_draw((GX_VALUE)left, (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2),
157
680069
                                 (GX_VALUE)left, (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2));
158
        }
159
        else
160
        {
161
157738
            _gx_canvas_line_draw((GX_VALUE)left, (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + border_width - 1),
162
157738
                                 (GX_VALUE)left, (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - border_width + 1));
163
        }
164
165
        /* Draw line down right side.  */
166
837807
        right = widget -> gx_widget_size.gx_rectangle_right - border_width + 1;
167
837807
        right += border_width / 2;
168
169
837807
        if (widget -> gx_widget_style & GX_STYLE_BORDER_THICK)
170
        {
171
34692
            _gx_canvas_line_draw((GX_VALUE)right, (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + border_width - 1),
172
34692
                                 (GX_VALUE)right, (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - border_width + 1));
173
174
            /* draw highlight along top border */
175
34692
            _gx_context_line_color_set(GX_COLOR_ID_SHINE);
176
34692
            _gx_context_brush_width_set(1);
177
178
34692
            _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2),
179
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1),
180
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2),
181
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1));
182
183
            /* draw higtlight along left border */
184
34692
            _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
185
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2),
186
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
187
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2));
188
189
190
            /* draw shadow along right border */
191
34692
            _gx_context_line_color_set(GX_COLOR_ID_SHADOW);
192
193
34692
            _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
194
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2),
195
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
196
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2));
197
198
            /* draw shadow along bottom border */
199
34692
            _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2),
200
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1),
201
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2),
202
34692
                                 (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1));
203
        }
204
        else
205
        {
206
803115
            if (rounded)
207
            {
208
650526
                _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right),
209
650526
                                     (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2),
210
650526
                                     (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right),
211
650526
                                     (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2));
212
            }
213
            else
214
            {
215
152589
                _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right),
216
152589
                                     (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + border_width - 1),
217
152589
                                     (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right),
218
152589
                                     (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - border_width + 1));
219
            }
220
        }
221
    }
222
223

1292611
    if (fill && !(widget -> gx_widget_style & GX_STYLE_TRANSPARENT))
224
    {
225
854879
        _gx_widget_client_get(widget, border_width, &fillrect);
226
227
        /* Pickup widget width and height.  */
228
854879
        _gx_widget_height_get(widget, &widget_height);
229
230
        /* fill my client area */
231
        /* first setup the brush color and style */
232
854879
        _gx_context_brush_define(upper_color, upper_color, GX_BRUSH_SOLID_FILL);
233
854879
        _gx_context_brush_width_set(0);
234
235
854879
        if (upper_color != lower_color)
236
        {
237
111896
            fillrect.gx_rectangle_bottom = (GX_VALUE)(fillrect.gx_rectangle_top + (widget_height / 2) - 1);
238
111896
            _gx_canvas_rectangle_draw(&fillrect);
239
240
111896
            _gx_context_fill_color_set(lower_color);
241
111896
            fillrect.gx_rectangle_top = (GX_VALUE)(fillrect.gx_rectangle_bottom + 1);
242
111896
            fillrect.gx_rectangle_bottom = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1);
243
        }
244
854879
        _gx_canvas_rectangle_draw(&fillrect);
245
    }
246
247
1292611
    if ((widget -> gx_widget_style & GX_STYLE_BORDER_MASK) == GX_STYLE_BORDER_NONE)
248
    {
249
1016990
        return;
250
    }
251
252
837808
    if (rounded)
253
    {
254
680069
        _gx_context_line_color_set(border_color);
255
256
        /* the top-left corner */
257
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2);
258
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1);
259
680069
        _gx_canvas_pixel_draw(corner);
260
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1);
261
680069
        _gx_canvas_pixel_draw(corner);
262
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2);
263
680069
        _gx_canvas_pixel_draw(corner);
264
265
        /* the top-right corner */
266
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2);
267
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1);
268
680069
        _gx_canvas_pixel_draw(corner);
269
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1);
270
680069
        _gx_canvas_pixel_draw(corner);
271
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2);
272
680069
        _gx_canvas_pixel_draw(corner);
273
274
        /* the bottom-right corner */
275
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2);
276
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1);
277
680069
        _gx_canvas_pixel_draw(corner);
278
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1);
279
680069
        _gx_canvas_pixel_draw(corner);
280
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2);
281
680069
        _gx_canvas_pixel_draw(corner);
282
283
        /* the bottom-left corner */
284
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2);
285
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1);
286
680069
        _gx_canvas_pixel_draw(corner);
287
680069
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1);
288
680069
        _gx_canvas_pixel_draw(corner);
289
680069
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2);
290
680069
        _gx_canvas_pixel_draw(corner);
291
    }
292
293
837808
    if (border_width != 2)
294
    {
295
562187
        return;
296
    }
297
298
    /* check for raised or recessed border style.  */
299
300
275621
    _gx_context_brush_width_set(1);
301
302
275621
    if (widget -> gx_widget_style & GX_STYLE_BORDER_RECESSED)
303
    {
304
        /* pick up the shadow color */
305
87187
        _gx_context_line_color_set(GX_COLOR_ID_SHADOW);
306
    }
307
    else
308
    {
309
188434
        _gx_context_line_color_set(GX_COLOR_ID_SHINE);
310
    }
311
312
275621
    if (rounded)
313
    {
314
        /* line down left edge */
315
274420
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
316
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 3),
317
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
318
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 3));
319
320
        /* line across the top */
321
274420
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 3),
322
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1),
323
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 3),
324
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1));
325
326
274420
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2);
327
274420
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2);
328
274420
        _gx_canvas_pixel_draw(corner);
329
274420
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2);
330
274420
        _gx_canvas_pixel_draw(corner);
331
    }
332
    else
333
    {
334
        /* line down left edge */
335
1201
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
336
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + border_width),
337
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
338
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1));
339
340
        /* line across the top */
341
1201
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 1),
342
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1),
343
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
344
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 1));
345
    }
346
347
275621
    if (widget -> gx_widget_style & GX_STYLE_BORDER_RECESSED)
348
    {
349
87187
        _gx_context_line_color_set(GX_COLOR_ID_SHINE);
350
    }
351
    else
352
    {
353
        /* pick up the shadow color */
354
188434
        _gx_context_line_color_set(GX_COLOR_ID_SHADOW);
355
    }
356
357
275621
    if (rounded)
358
    {
359
        /* line down right edge */
360
274420
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
361
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 3),
362
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
363
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 3));
364
365
        /* line across the bottom */
366
274420
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 3),
367
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1),
368
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 3),
369
274420
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1));
370
371
274420
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2);
372
274420
        corner.gx_point_y = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 2);
373
274420
        _gx_canvas_pixel_draw(corner);
374
274420
        corner.gx_point_x = (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2);
375
274420
        _gx_canvas_pixel_draw(corner);
376
    }
377
    else
378
    {
379
        /* line down right edge */
380
1201
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
381
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_top + 2),
382
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 1),
383
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1));
384
385
        /* line across the bottom */
386
1201
        _gx_canvas_line_draw((GX_VALUE)(widget -> gx_widget_size.gx_rectangle_left + 2),
387
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1),
388
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_right - 2),
389
1201
                             (GX_VALUE)(widget -> gx_widget_size.gx_rectangle_bottom - 1));
390
    }
391
}
392