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

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