GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_pie_fill.c Lines: 204 204 100.0 %
Date: 2026-03-06 19:21:09 Branches: 160 160 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_rotated_simple_pie_fill  PORTABLE C      */
36
/*                                                           6.1.5        */
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_display_driver_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
504
static VOID _gx_display_driver_generic_rotated_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
504
INT                   sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
94
INT                  *pLineEnds;
95
GX_POINT             *pGet;
96
INT                   xmin;
97
INT                   xmax;
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                   width;
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
504
INT                   xpos = 0;
117
504
GX_PIXELMAP          *pixelmap = GX_NULL;
118
INT                   skip_line;
119
GX_FILL_PIXELMAP_INFO info;
120
121
504
    display = context -> gx_draw_context_display;
122
504
    brush = &context -> gx_draw_context_brush;
123
504
    line_draw = display -> gx_display_driver_vertical_line_draw;
124
125
504
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
126
    {
127
407
        if (brush -> gx_brush_pixelmap == GX_NULL)
128
        {
129
2
            return;
130
        }
131
132
        /* Pick up brush pixelmap. */
133
406
        pixelmap = brush -> gx_brush_pixelmap;
134
135
406
        if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
136
        {
137
            /* Display driver only support its native format pixelmap.*/
138
            /* Nothing should be drawn if pixelmap format isn't support. */
139
1
            return;
140
        }
141
142
405
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
143
144
405
        info.pixelmap = pixelmap;
145
405
        info.current_pixel_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_data;
146
405
        if (pixelmap -> gx_pixelmap_aux_data_size)
147
        {
148
150
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
149
        }
150
    }
151
152
502
    pGet = points;
153
154
502
    points[1].gx_point_x = (GX_VALUE)xcenter;
155
502
    points[1].gx_point_y = (GX_VALUE)ycenter;
156
157
502
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &points[0]);
158
502
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &points[2]);
159
160
502
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle,
161
                                        &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
162
163
    /* Pie is in left side. */
164
502
    xmin = points[0].gx_point_x;
165
502
    xmax = points[2].gx_point_x;
166
167
502
    if (xmin > xmax)
168
    {
169
264
        GX_SWAP_VALS(xmin, xmax);
170
    }
171
172
502
    if (xmax < xcenter)
173
    {
174
154
        xmax = xcenter;
175
    }
176
348
    else if (xmin > xcenter)
177
    {
178
156
        xmin = xcenter;
179
    }
180
181
502
    clip = context -> gx_draw_context_clip;
182
183
502
    if (clip -> gx_rectangle_left > xmin)
184
    {
185
14
        xmin = clip -> gx_rectangle_left;
186
    }
187
188
502
    if (clip -> gx_rectangle_right < xmax)
189
    {
190
10
        xmax = clip -> gx_rectangle_right;
191
    }
192
193
502
    width = xmax - xmin + 1;
194
195
502
    pLineEnds = _gx_system_scratchpad;
196
197
    /* default the point array to being off the screen on both sides: */
198
199
93532
    for (loop = 0; loop < width * 2; loop += 2)
200
    {
201
93030
        pLineEnds[loop] = 2000;
202
93030
        pLineEnds[loop + 1] = 0;
203
    }
204
205
502
    curx = 0;
206
502
    cury = (INT)r;
207
502
    decision = 5 - (INT)(4 * r);
208
209
62262
    while (curx <= cury)
210
    {
211
308800
        for (loop = 0; loop < 4; loop++)
212
        {
213
247040
            point.gx_point_x = (GX_VALUE)(curx * sign[loop][0] + xcenter);
214
247040
            point.gx_point_y = (GX_VALUE)(cury * sign[loop][1] + ycenter);
215
216

247040
            if ((point.gx_point_x >= xmin) && (point.gx_point_x <= xmax))
217
            {
218

264820
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
219
117136
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point))
220
                {
221
47090
                    Index = (point.gx_point_x - xmin) << 1;
222
47090
                    if (point.gx_point_y < pLineEnds[Index])
223
                    {
224
46898
                        pLineEnds[Index] = point.gx_point_y;
225
                    }
226
227
47090
                    if (point.gx_point_y > pLineEnds[Index + 1])
228
                    {
229
37662
                        pLineEnds[Index + 1] = point.gx_point_y;
230
                    }
231
                }
232
            }
233
234
247040
            point.gx_point_x = (GX_VALUE)(cury * sign[loop][0] + xcenter);
235
247040
            point.gx_point_y = (GX_VALUE)(curx * sign[loop][1] + ycenter);
236
237

247040
            if ((point.gx_point_x >= xmin) && (point.gx_point_x <= xmax))
238
            {
239

138676
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
240
52448
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point))
241
                {
242
36550
                    Index = (point.gx_point_x - xmin) << 1;
243
36550
                    if (point.gx_point_y < pLineEnds[Index])
244
                    {
245
25614
                        pLineEnds[Index] = point.gx_point_y;
246
                    }
247
248
36550
                    if (point.gx_point_y > pLineEnds[Index + 1])
249
                    {
250
25404
                        pLineEnds[Index + 1] = point.gx_point_y;
251
                    }
252
                }
253
            }
254
        }
255
256
61760
        if (decision < 0)
257
        {
258
35794
            decision += 8 * curx + 12;
259
        }
260
        else
261
        {
262
25966
            decision += 8 * (curx - cury) + 20;
263
25966
            cury--;
264
        }
265
61760
        curx++;
266
    }
267
268
    /* Fill in the point array by using Breshenhams line for
269
       2 lines of circle sector
270
     */
271
272
1506
    for (loop = 0; loop < 2; loop++)
273
    {
274
1004
        xstart = pGet -> gx_point_x;
275
1004
        ystart = pGet -> gx_point_y;
276
1004
        pGet++;
277
1004
        xend = pGet -> gx_point_x;
278
1004
        yend = pGet -> gx_point_y;
279
1004
        dx = GX_ABS(xend - xstart);
280
1004
        dy = GX_ABS(yend - ystart);
281
282
        /* Vertical Line. */
283
1004
        if (xstart == xend)
284
        {
285
4
            continue;
286
        }
287
288
        /* Horizontal Line. */
289
1000
        if (ystart == yend)
290
        {
291
326
            if (xstart > xend)
292
            {
293
164
                GX_SWAP_VALS(xstart, xend);
294
164
                GX_SWAP_VALS(ystart, yend);
295
            }
296
297
326
            if (skip_end)
298
            {
299
162
                ystart--;
300
            }
301
302
54092
            for (curx = xstart; curx <= xend; curx++)
303
            {
304

53766
                if ((curx >= xmin) && (curx <= xmax))
305
                {
306
52778
                    Index = (curx - xmin) << 1;
307
52778
                    if (ystart < pLineEnds[Index])
308
                    {
309
32684
                        pLineEnds[Index] = ystart;
310
                    }
311
312
52778
                    if (ystart > pLineEnds[Index + 1])
313
                    {
314
37910
                        pLineEnds[Index + 1] = ystart;
315
                    }
316
                }
317
            }
318
326
            continue;
319
        }
320
321
        /* Simple Line. */
322

674
        if (((dx >= dy && (xstart > xend)) ||
323
362
             ((dy > dx) && ystart > yend)))
324
        {
325
338
            GX_SWAP_VALS(xend, xstart);
326
338
            GX_SWAP_VALS(yend, ystart);
327
        }
328
329
674
        xsign = (xend - xstart) / dx;
330
674
        ysign = (yend - ystart) / dy;
331
332
674
        if (dx >= dy)
333
        {
334
312
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
335
23896
                 decision = (dx >> 1); curx <= nextx; curx++, nextx--,
336
23584
                 decision += dy)
337
            {
338
23584
                if (decision >= dx)
339
                {
340
10772
                    decision -= dx;
341
10772
                    cury += ysign;
342
10772
                    nexty -= ysign;
343
                }
344
345

23584
                if ((curx >= xmin) && (curx <= xmax))
346
                {
347
23056
                    Index = (curx - xmin) << 1;
348
349
23056
                    if (cury < pLineEnds[Index])
350
                    {
351
11218
                        pLineEnds[Index] = cury;
352
                    }
353
354
23056
                    if (cury - 1 > pLineEnds[Index + 1])
355
                    {
356
16768
                        pLineEnds[Index + 1] = cury - 1;
357
                    }
358
                }
359
360

23584
                if ((nextx >= xmin) && (nextx <= xmax))
361
                {
362
22816
                    Index = (nextx - xmin) << 1;
363
364
22816
                    if (nexty < pLineEnds[Index])
365
                    {
366
11196
                        pLineEnds[Index] = nexty;
367
                    }
368
369
22816
                    if (nexty - 1 > pLineEnds[Index + 1])
370
                    {
371
16098
                        pLineEnds[Index + 1] = nexty - 1;
372
                    }
373
                }
374
            }
375
        }
376
        else
377
        {
378
362
            if (start_angle < 180)
379
            {
380
202
                if (loop == 0)
381
                {
382
102
                    fillingwards = 0;
383
                }
384
                else
385
                {
386
100
                    fillingwards = 1;
387
                }
388
            }
389
            else
390
            {
391
160
                if (loop == 0)
392
                {
393
80
                    fillingwards = 1;
394
                }
395
                else
396
                {
397
80
                    fillingwards = 0;
398
                }
399
            }
400
401
362
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
402
31428
                 decision = (dy >> 1); cury <= nexty; cury++, nexty--,
403
31066
                 decision += dx)
404
            {
405
31066
                if (decision >= dy)
406
                {
407
13444
                    decision -= dy;
408
13444
                    curx += xsign;
409
13444
                    nextx -= xsign;
410
                }
411
412

31066
                if ((curx - 1 + fillingwards >= xmin) && (curx - 1 + fillingwards <= xmax))
413
                {
414
30544
                    Index = (curx - 1 + fillingwards - xmin) << 1;
415
416
30544
                    if (cury < pLineEnds[Index])
417
                    {
418
5990
                        pLineEnds[Index] = cury;
419
                    }
420
421
30544
                    if (cury > pLineEnds[Index + 1])
422
                    {
423
15788
                        pLineEnds[Index + 1] = cury;
424
                    }
425
                }
426
427

31066
                if ((nextx - 1 + fillingwards >= xmin) && (nextx - 1 + fillingwards <= xmax))
428
                {
429
30470
                    Index = (nextx - 1 + fillingwards - xmin) << 1;
430
431
30470
                    if (nexty < pLineEnds[Index])
432
                    {
433
16986
                        pLineEnds[Index] = nexty;
434
                    }
435
436
30470
                    if (nexty > pLineEnds[Index + 1])
437
                    {
438
8488
                        pLineEnds[Index + 1] = nexty;
439
                    }
440
                }
441
            }
442
        }
443
    }
444
445
    /* Filling circle sector with horizontal line. */
446
502
    if (pixelmap)
447
    {
448
405
        if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
449
        {
450
237
            skip_line = (xmax - (xcenter - (INT)r) + 1) % pixelmap -> gx_pixelmap_width;
451
452
            /*Skip the un-draw line.*/
453
237
            if (skip_line)
454
            {
455
236
                skip_line = pixelmap -> gx_pixelmap_width - skip_line;
456
            }
457
458
237
            Index = (width - 1) << 1;
459
237
            xsign = -1;
460
237
            xstart = xmax;
461
        }
462
        else
463
        {
464
168
            skip_line = (xmin - clip -> gx_rectangle_left);
465
466
168
            Index = 0;
467
168
            xsign = 1;
468
168
            xstart = xmin;
469
        }
470
471
        /*Skip the un-draw line.*/
472
405
        if (skip_line)
473
        {
474
404
            info.draw = GX_FALSE;
475
26707
            while (skip_line--)
476
            {
477
26303
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
478
            }
479
        }
480
481
405
        info.draw = GX_TRUE;
482
405
        xpos = ycenter - (INT)r;
483
484
75152
        for (curx = xmin; curx <= xmax; curx++)
485
        {
486
74747
            if (pLineEnds[Index] < clip -> gx_rectangle_top)
487
            {
488
7818
                pLineEnds[Index] = clip -> gx_rectangle_top;
489
            }
490
491
74747
            if (pLineEnds[Index + 1] > clip -> gx_rectangle_bottom)
492
            {
493
793
                pLineEnds[Index + 1] = clip -> gx_rectangle_bottom;
494
            }
495
496
74747
            info.x_offset = pLineEnds[Index] - xpos;
497
498
            /* Filling pie area with pixelmap. */
499
74747
            display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], xstart, &info);
500
501
74747
            xstart += xsign;
502
74747
            Index += xsign;
503
74747
            Index += xsign;
504
        }
505
    }
506
    else
507
    {
508
97
        Index = 0;
509
18380
        for (curx = xmin; curx <= xmax; curx++)
510
        {
511
18283
            if (pLineEnds[Index] < clip -> gx_rectangle_top)
512
            {
513
1418
                pLineEnds[Index] = clip -> gx_rectangle_top;
514
            }
515
516
18283
            if (pLineEnds[Index + 1] > clip -> gx_rectangle_bottom)
517
            {
518
793
                pLineEnds[Index + 1] = clip -> gx_rectangle_bottom;
519
            }
520
521
18283
            if (pLineEnds[Index] <= pLineEnds[Index + 1])
522
            {
523
17934
                line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], curx, 1,
524
                          brush -> gx_brush_fill_color);
525
            }
526
527
18283
            Index += 2;
528
        }
529
    }
530
}
531
532
/**************************************************************************/
533
/*                                                                        */
534
/*  FUNCTION                                               RELEASE        */
535
/*                                                                        */
536
/*    _gx_display_driver_generic_rotated_pie_fill         PORTABLE C      */
537
/*                                                           6.1.3        */
538
/*  AUTHOR                                                                */
539
/*                                                                        */
540
/*    Kenneth Maxwell, Microsoft Corporation                              */
541
/*                                                                        */
542
/*  DESCRIPTION                                                           */
543
/*                                                                        */
544
/*    Display driver to fill a pie.                                       */
545
/*                                                                        */
546
/*  INPUT                                                                 */
547
/*                                                                        */
548
/*    context                               Drawing context               */
549
/*    xcenter                               x-coord of center of circle   */
550
/*    ycenter                               y-coord of center of circle   */
551
/*    r                                     Radius of circle              */
552
/*    start_angle                           The start angle of circle arc */
553
/*    end_angle                             The end angle of circle arc   */
554
/*                                                                        */
555
/*  OUTPUT                                                                */
556
/*                                                                        */
557
/*    None                                                                */
558
/*                                                                        */
559
/*  CALLS                                                                 */
560
/*                                                                        */
561
/*    _gx_display_driver_generic_simple_pie_fill                          */
562
/*                                          Real display driver draw      */
563
/*                                            filled-pie function         */
564
/*                                                                        */
565
/*  CALLED BY                                                             */
566
/*                                                                        */
567
/*    _gx_canvas_pie_draw                                                 */
568
/*                                                                        */
569
/**************************************************************************/
570
342
VOID _gx_display_driver_generic_rotated_pie_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
571
{
572
    /* The function fills a pie.*/
573
574
575
342
    if (start_angle < 180)
576
    {
577
186
        if (end_angle < 180)
578
        {
579
106
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, start_angle, end_angle, GX_FALSE);
580
        }
581
80
        else if (end_angle < 360)
582
        {
583
            /* Skip-end parameter should only be set when drawing the above area.
584
               It would be set to GX_TRUE to skip the bottom line to avoid case that this line will be drawn twice, which
585
               is not correct, when brush alpha is set. */
586
78
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, start_angle, 180, GX_TRUE);
587
78
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, 180, end_angle, GX_FALSE);
588
        }
589
        else
590
        {
591
2
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, start_angle, 180, GX_TRUE);
592
2
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, 180, 360, GX_FALSE);
593
2
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, 0, end_angle - 360, GX_TRUE);
594
        }
595
    }
596
    else
597
    {
598
156
        if (end_angle < 360)
599
        {
600
78
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, start_angle, end_angle, GX_FALSE);
601
        }
602
78
        else if (end_angle < 540)
603
        {
604
76
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, start_angle, 360, GX_FALSE);
605
76
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, 0, end_angle - 360, GX_TRUE);
606
        }
607
        else
608
        {
609
2
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, start_angle, 360, GX_FALSE);
610
2
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, 0, 180, GX_TRUE);
611
2
            _gx_display_driver_generic_rotated_simple_pie_fill(context, xcenter, ycenter, r, 180, end_angle - 360, GX_FALSE);
612
        }
613
    }
614
342
}
615
616
#endif
617