GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_simple_pie_fill.c Lines: 178 178 100.0 %
Date: 2026-03-06 19:21:09 Branches: 152 152 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
/**   Display Management (Display)                                        */
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_display.h"
31
/**************************************************************************/
32
/*                                                                        */
33
/*  FUNCTION                                               RELEASE        */
34
/*                                                                        */
35
/*    _gx_display_driver_generic_simple_pie_fill          PORTABLE C      */
36
/*                                                           6.1          */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Kenneth Maxwell, Microsoft Corporation                              */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    Display driver to fill a pie chart.                                 */
44
/*                                                                        */
45
/*  INPUT                                                                 */
46
/*                                                                        */
47
/*    context                               Drawing context               */
48
/*    xcenter                               x-coord of center of circle   */
49
/*    ycenter                               y-coord of center of circle   */
50
/*    r                                     Radius of circle              */
51
/*    start_angle                           Starting angle                */
52
/*    end_angle                             Ending angle                  */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    None                                                                */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _gx_display_driver_arc_clipping_get   Get an arc clipping.          */
61
/*    _gx_utility_rectangle_overlap_detect  Detects two rectangles being  */
62
/*                                            overlap                     */
63
/*    _gx_utility_rectangle_point_detect    Detect whether a pixel is     */
64
/*                                            inside rectangle            */
65
/*    _gx_utility_circle_point_get          Get point coord on a circle   */
66
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
67
/*                                          Basic display driver          */
68
/*                                            horizontal pixelmap line    */
69
/*                                            draw function               */
70
/*    [gx_display_driver_horizontal_line_draw]                            */
71
/*                                          Basic display driver          */
72
/*                                            horizontal line draw routine*/
73
/*                                                                        */
74
/*  CALLED BY                                                             */
75
/*                                                                        */
76
/*    GUIX Internal Code                                                  */
77
/*                                                                        */
78
/**************************************************************************/
79
#if defined(GX_ARC_DRAWING_SUPPORT)
80
81
2663
VOID _gx_display_driver_generic_simple_pie_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter,
82
                                                UINT r, INT start_angle, INT end_angle, GX_BOOL skip_end)
83
{
84
/* The function will only fill a pie with both start angle and end angle are
85
   between 0 and 180 or beween 180 and 360.*/
86
87
GX_DISPLAY           *display;
88
GX_BRUSH             *brush;
89
GX_RECTANGLE         *clip;
90
GX_RECTANGLE          arc_clip[4];
91
GX_POINT              point;
92
GX_POINT              points[3];
93
2663
INT                   sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
94
INT                  *pLineEnds;
95
GX_POINT             *pGet;
96
INT                   ymin;
97
INT                   ymax;
98
INT                   xstart;
99
INT                   xend;
100
INT                   ystart;
101
INT                   yend;
102
INT                   curx;
103
INT                   cury;
104
INT                   nextx;
105
INT                   nexty;
106
INT                   dx;
107
INT                   dy;
108
INT                   Index;
109
INT                   loop;
110
INT                   height;
111
INT                   xsign;
112
INT                   ysign;
113
INT                   decision;
114
int                   fillingwards;
115
VOID                  (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
116
2663
INT                   xpos = 0;
117
2663
GX_PIXELMAP          *pixelmap = GX_NULL;
118
GX_VALUE              format;
119
INT                   skip_line;
120
GX_FILL_PIXELMAP_INFO info;
121
122
2663
    display = context -> gx_draw_context_display;
123
2663
    brush = &context -> gx_draw_context_brush;
124
2663
    line_draw = display -> gx_display_driver_horizontal_line_draw;
125
126
2663
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
127
    {
128
        /* Pick up pixelmap. */
129
1260
        pixelmap = brush -> gx_brush_pixelmap;
130
1260
        if (pixelmap == GX_NULL)
131
        {
132
12
            return;
133
        }
134
1257
        if (pixelmap -> gx_pixelmap_height <= 0 ||
135
1256
            pixelmap -> gx_pixelmap_width <= 0)
136
        {
137
2
            return;
138
        }
139
140
1255
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
141
1255
        format = display -> gx_display_color_format;
142
143
        /*Check the pixelmap format is supported in this driver or not.*/
144
1255
        if (format >= GX_COLOR_FORMAT_24XRGB)
145
        {
146
            /*32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
147
135
            if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
148
            {
149
                /* Display driver only support its native format pixelmap. */
150
                /* Nothing should be drawn if pixelmap format isn't support. */
151
1
                return;
152
            }
153
        }
154
        else
155
        {
156
1120
            if (pixelmap -> gx_pixelmap_format != format)
157
            {
158
                /* Display driver only support its native format pixelmap. */
159
                /* Nothing should be drawn if pixelmap format isn't support. */
160
6
                return;
161
            }
162
1114
            else if (pixelmap -> gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
163
            {
164
192
                info.mask = 0xf0;
165
            }
166
        }
167
168
1248
        info.pixelmap = pixelmap;
169
1248
        info.current_pixel_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_data;
170
1248
        if (pixelmap -> gx_pixelmap_aux_data_size)
171
        {
172
334
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
173
        }
174
    }
175
176
2651
    pGet = points;
177
178
2651
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle,
179
                                        &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
180
181

2651
    if ((start_angle <= 180) && (end_angle <= 180))
182
    {
183
        /* Pie is in upper side. */
184
1437
        ymin = ycenter - (INT)r;
185
1437
        ymax = ycenter;
186
187
1437
        if (skip_end)
188
        {
189
832
            ymax--;
190
        }
191
    }
192
    else
193
    {
194
        /* Pie is in lower side. */
195
1214
        ymin = ycenter;
196
1214
        ymax = ycenter + (INT)r;
197
    }
198
199
2651
    clip = context -> gx_draw_context_clip;
200
201
2651
    if (clip -> gx_rectangle_top > ymin)
202
    {
203
91
        ymin = clip -> gx_rectangle_top;
204
    }
205
2651
    skip_line = ymin - (ycenter - (INT)r);
206
207
2651
    if (clip -> gx_rectangle_bottom < ymax)
208
    {
209
98
        ymax = clip -> gx_rectangle_bottom;
210
    }
211
212
2651
    height = ymax - ymin + 1;
213
214
2651
    pLineEnds = _gx_system_scratchpad;
215
216
    /* default the point array to being off the screen on both sides: */
217
218
256356
    for (loop = 0; loop < height * 2; loop += 2)
219
    {
220
253705
        pLineEnds[loop] = 2000;
221
253705
        pLineEnds[loop + 1] = 0;
222
    }
223
224
2651
    curx = 0;
225
2651
    cury = (INT)r;
226
2651
    decision = 5 - (INT)(4 * r);
227
228
201034
    while (curx <= cury)
229
    {
230
991915
        for (loop = 0; loop < 4; loop++)
231
        {
232
793532
            point.gx_point_x = (GX_VALUE)(curx * sign[loop][0] + xcenter);
233
793532
            point.gx_point_y = (GX_VALUE)(cury * sign[loop][1] + ycenter);
234
235

793532
            if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
236
            {
237

549742
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
238
241472
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point))
239
                {
240
96345
                    Index = (point.gx_point_y - ymin) << 1;
241
96345
                    if (point.gx_point_x < pLineEnds[Index])
242
                    {
243
65921
                        pLineEnds[Index] = point.gx_point_x;
244
                    }
245
246
96345
                    if (point.gx_point_x > pLineEnds[Index + 1])
247
                    {
248
61617
                        pLineEnds[Index + 1] = point.gx_point_x;
249
                    }
250
                }
251
            }
252
253
793532
            point.gx_point_x = (GX_VALUE)(cury * sign[loop][0] + xcenter);
254
793532
            point.gx_point_y = (GX_VALUE)(curx * sign[loop][1] + ycenter);
255
256

793532
            if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
257
            {
258

651926
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
259
268966
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point))
260
                {
261
129992
                    Index = (point.gx_point_y - ymin) << 1;
262
129992
                    if (point.gx_point_x < pLineEnds[Index])
263
                    {
264
128147
                        pLineEnds[Index] = point.gx_point_x;
265
                    }
266
267
129992
                    if (point.gx_point_x > pLineEnds[Index + 1])
268
                    {
269
93497
                        pLineEnds[Index + 1] = point.gx_point_x;
270
                    }
271
                }
272
            }
273
        }
274
275
198383
        if (decision < 0)
276
        {
277
114732
            decision += 8 * curx + 12;
278
        }
279
        else
280
        {
281
83651
            decision += 8 * (curx - cury) + 20;
282
83651
            cury--;
283
        }
284
198383
        curx++;
285
    }
286
287
    /* Fill in the point array by using Breshenhams line for
288
       2 lines of circle sector
289
     */
290
291
2651
    points[1].gx_point_x = (GX_VALUE)xcenter;
292
2651
    points[1].gx_point_y = (GX_VALUE)ycenter;
293
294
2651
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &points[0]);
295
2651
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &points[2]);
296
297
7953
    for (loop = 0; loop < 2; loop++)
298
    {
299
5302
        xstart = pGet -> gx_point_x;
300
5302
        ystart = pGet -> gx_point_y;
301
5302
        pGet++;
302
5302
        xend = pGet -> gx_point_x;
303
5302
        yend = pGet -> gx_point_y;
304
5302
        dx = GX_ABS(xend - xstart);
305
5302
        dy = GX_ABS(yend - ystart);
306
307
        /* Horizontal Line. */
308
5302
        if (ystart == yend)
309
        {
310
2133
            continue;
311
        }
312
313
        /* Vertical Line. */
314
3169
        if (xstart == xend)
315
        {
316
529
            if (ystart > yend)
317
            {
318
271
                GX_SWAP_VALS(xstart, xend);
319
271
                GX_SWAP_VALS(ystart, yend);
320
            }
321
322
4783
            for (cury = ystart; cury <= yend; cury++)
323
            {
324

4254
                if ((cury >= ymin) && (cury <= ymax))
325
                {
326
1516
                    Index = (cury - ymin) << 1;
327
1516
                    if (xstart <= pLineEnds[Index])
328
                    {
329
1420
                        pLineEnds[Index] = xstart;
330
                    }
331
332
1516
                    if (xstart > pLineEnds[Index + 1])
333
                    {
334
641
                        pLineEnds[Index + 1] = xstart;
335
                    }
336
                }
337
            }
338
529
            continue;
339
        }
340
341
        /* Simple Line. */
342

2640
        if (((dx >= dy && (xstart > xend)) ||
343
1145
             ((dy > dx) && ystart > yend)))
344
        {
345
1348
            GX_SWAP_VALS(xend, xstart);
346
1348
            GX_SWAP_VALS(yend, ystart);
347
        }
348
349
2640
        xsign = (xend - xstart) / dx;
350
2640
        ysign = (yend - ystart) / dy;
351
352
2640
        if (start_angle < 180)
353
        {
354
1470
            if (loop == 0)
355
            {
356
754
                fillingwards = (1 + ysign) >> 1;
357
            }
358
            else
359
            {
360
716
                fillingwards = (1 - ysign) >> 1;
361
            }
362
        }
363
        else
364
        {
365
1170
            if (loop == 0)
366
            {
367
560
                fillingwards = (1 - ysign) >> 1;
368
            }
369
            else
370
            {
371
610
                fillingwards = (1 + ysign) >> 1;
372
            }
373
        }
374
375
2640
        if (dx >= dy)
376
        {
377
1495
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
378
100015
                 decision = (dx >> 1); curx <= nextx; curx++, nextx--,
379
98520
                 decision += dy)
380
            {
381
98520
                if (decision >= dx)
382
                {
383
43244
                    decision -= dx;
384
43244
                    cury += ysign;
385
43244
                    nexty -= ysign;
386
                }
387
388

98520
                if ((cury - 1 + fillingwards >= ymin) && (cury - 1 + fillingwards <= ymax))
389
                {
390
95880
                    Index = (cury - 1 + fillingwards - ymin) << 1;
391
392
95880
                    if (curx < pLineEnds[Index])
393
                    {
394
21007
                        pLineEnds[Index] = curx;
395
                    }
396
397
95880
                    if (curx > pLineEnds[Index + 1])
398
                    {
399
58329
                        pLineEnds[Index + 1] = curx;
400
                    }
401
                }
402
403

98520
                if ((nexty - 1 + fillingwards >= ymin) && (nexty - 1 + fillingwards <= ymax))
404
                {
405
97132
                    Index = (nexty - 1 + fillingwards - ymin) << 1;
406
407
97132
                    if (nextx < pLineEnds[Index])
408
                    {
409
56335
                        pLineEnds[Index] = nextx;
410
                    }
411
412
97132
                    if (nextx > pLineEnds[Index + 1])
413
                    {
414
28682
                        pLineEnds[Index + 1] = nextx;
415
                    }
416
                }
417
            }
418
        }
419
        else
420
        {
421
1145
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
422
72300
                 decision = (dy >> 1); cury <= nexty; cury++, nexty--,
423
71155
                 decision += dx)
424
            {
425
71155
                if (decision >= dy)
426
                {
427
21732
                    decision -= dy;
428
21732
                    curx += xsign;
429
21732
                    nextx -= xsign;
430
                }
431
432

71155
                if ((cury >= ymin) && (cury <= ymax))
433
                {
434
69569
                    Index = (cury - ymin) << 1;
435
436
69569
                    if (curx < pLineEnds[Index])
437
                    {
438
41219
                        pLineEnds[Index] = curx;
439
                    }
440
441
69569
                    if (curx - 1 > pLineEnds[Index + 1])
442
                    {
443
39527
                        pLineEnds[Index + 1] = curx - 1;
444
                    }
445
                }
446
447

71155
                if ((nexty >= ymin) && (nexty <= ymax))
448
                {
449
66854
                    Index = (nexty - ymin) << 1;
450
451
66854
                    if (nextx < pLineEnds[Index])
452
                    {
453
46545
                        pLineEnds[Index] = nextx;
454
                    }
455
456
66854
                    if (nextx - 1 > pLineEnds[Index + 1])
457
                    {
458
35442
                        pLineEnds[Index + 1] = nextx - 1;
459
                    }
460
                }
461
            }
462
        }
463
    }
464
465
2651
    if (pixelmap != NULL)
466
    {
467
        /* Calculate the draw_start position and skip line to fill the pie area. */
468
1248
        xpos = xcenter - (INT)r;
469
470
        /*Skip the un-draw line.*/
471
1248
        if (skip_line > 0)
472
        {
473
622
            skip_line %= info.pixelmap -> gx_pixelmap_height;
474
622
            info.draw = GX_FALSE;
475
22398
            while (skip_line--)
476
            {
477
21776
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, cury, &info);
478
            }
479
        }
480
    }
481
482
    /* Filling circle sector with horizontal line. */
483
2651
    Index = 0;
484
256356
    for (cury = ymin; cury <= ymax; cury++)
485
    {
486
253705
        if (pLineEnds[Index] <= pLineEnds[Index + 1])
487
        {
488
194500
            if (pLineEnds[Index] < clip -> gx_rectangle_left)
489
            {
490
30292
                pLineEnds[Index] = clip -> gx_rectangle_left;
491
            }
492
493
194500
            if (pLineEnds[Index + 1] > clip -> gx_rectangle_right)
494
            {
495
12441
                pLineEnds[Index + 1] = clip -> gx_rectangle_right;
496
            }
497
498
194500
            if (pixelmap)
499
            {
500
107459
                info.draw = GX_TRUE;
501
107459
                info.x_offset = pLineEnds[Index] - xpos;
502
                /* Filling pie area with pixelmap. */
503
107459
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, &info);
504
            }
505
            else
506
            {
507
87041
                line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, 1,
508
                          brush -> gx_brush_fill_color);
509
            }
510
        }
511
        else
512
        {
513
59205
            if (pixelmap != GX_NULL)
514
            {
515
29318
                info.draw = GX_FALSE;
516
29318
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, cury, &info);
517
            }
518
        }
519
520
253705
        Index += 2;
521
    }
522
}
523
524
#endif
525