GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_arc_fill.c Lines: 179 179 100.0 %
Date: 2026-03-06 19:21:09 Branches: 166 166 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
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_display_driver_generic_arc_fill                 PORTABLE C      */
38
/*                                                           6.1          */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    Display driver to fill circle sector.                               */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    context                               Drawing context               */
50
/*    xcenter                               x-coord of center of circle   */
51
/*    ycenter                               y-coord of center of circle   */
52
/*    r                                     Radius of circle              */
53
/*    start_angle                           The start angle of circle arc */
54
/*    end_angle                             The end angle of circle arc   */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    None                                                                */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    [gx_display_driver_horizontal_line_draw]                            */
63
/*                                          Basic display driver          */
64
/*                                            horizontal line draw routine*/
65
/*    _gx_display_driver_arc_clipping_get   Get an arc clipping.          */
66
/*    _gx_utility_rectangle_point_detect    Detect whether a pixel is     */
67
/*                                            inside rectangle            */
68
/*    _gx_utility_circle_point_get          Get point coord on a circle   */
69
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
70
/*                                          Basic display driver          */
71
/*                                            horizontal pixelmap line    */
72
/*                                            draw function               */
73
/*                                                                        */
74
/*  CALLED BY                                                             */
75
/*                                                                        */
76
/*    _gx_display_driver_generic_arc_draw                                 */
77
/*                                                                        */
78
/**************************************************************************/
79
#if defined(GX_ARC_DRAWING_SUPPORT)
80
81
775
VOID _gx_display_driver_generic_arc_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
82
{
83
84
GX_DISPLAY           *display;
85
GX_RECTANGLE         *clip;
86
GX_RECTANGLE          arc_clip[4];
87
GX_BRUSH             *brush;
88
GX_POINT              point;
89
775
INT                   sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
90
INT                  *pLineEnds;
91
INT                   ymin;
92
INT                   ymax;
93
INT                   xstart;
94
INT                   xend;
95
INT                   ystart;
96
INT                   yend;
97
INT                   curx;
98
INT                   cury;
99
INT                   nextx;
100
INT                   nexty;
101
INT                   dx;
102
INT                   dy;
103
INT                   Index;
104
INT                   Index1;
105
INT                   height;
106
INT                   xsign;
107
INT                   ysign;
108
INT                   decision;
109
VOID                  (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
110
775
GX_PIXELMAP          *pixelmap = GX_NULL;
111
INT                   xpos;
112
INT                   ypos;
113
INT                   inner_offset;
114
GX_VALUE              format;
115
INT                   skip_line;
116
GX_FILL_PIXELMAP_INFO info;
117
118
775
    display = context -> gx_draw_context_display;
119
775
    brush = &context -> gx_draw_context_brush;
120
775
    inner_offset = brush -> gx_brush_width;
121
775
    line_draw = display -> gx_display_driver_horizontal_line_draw;
122
775
    clip = context -> gx_draw_context_clip;
123
124
775
    if (inner_offset)
125
    {
126
679
        inner_offset -= 1;
127
679
        inner_offset >>= 1;
128
    }
129
130
775
    if (r <= (UINT)inner_offset)
131
    {
132
101
        return;
133
    }
134
135
679
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
136
    {
137
        /* Pick up pixelmap. */
138
300
        pixelmap = brush -> gx_brush_pixelmap;
139
140
300
        if (pixelmap == GX_NULL)
141
        {
142
1
            return;
143
        }
144
299
        if (pixelmap -> gx_pixelmap_width <= 0 ||
145
298
            pixelmap -> gx_pixelmap_height <= 0)
146
        {
147
2
            return;
148
        }
149
297
        format = display -> gx_display_color_format;
150
297
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
151
152
297
        if (format >= GX_COLOR_FORMAT_24XRGB)
153
        {
154
            /*32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
155
55
            if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
156
            {
157
                /* Display driver only support its native format pixelmap.*/
158
                /* Nothing should be drawn if pixelmap format isn't support. */
159
1
                return;
160
            }
161
        }
162
        else
163
        {
164
242
            if (pixelmap -> gx_pixelmap_format != format)
165
            {
166
                /* Display driver only support its native format pixelmap.*/
167
                /* Nothing should be drawn if pixelmap format isn't support. */
168
1
                return;
169
            }
170
241
            else if (pixelmap -> gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
171
            {
172
1
                info.mask = 0xf0;
173
            }
174
        }
175
176
295
        info.pixelmap = brush -> gx_brush_pixelmap;
177
295
        info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
178
179
295
        if (pixelmap -> gx_pixelmap_aux_data_size)
180
        {
181
24
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
182
        }
183
    }
184
185
674
    r = (UINT)(r - (UINT)inner_offset);
186
187
674
    ymax = ycenter + (INT)r;
188
674
    ymin = ycenter - (INT)r;
189
190
    /* Get two endpoint of the arc. */
191
674
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &point);
192
193
674
    xstart = point.gx_point_x;
194
674
    ystart = point.gx_point_y;
195
196
674
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &point);
197
198
674
    xend = point.gx_point_x;
199
674
    yend = point.gx_point_y;
200
201
674
    xpos = xcenter - (INT)r;
202
674
    ypos = ycenter - (INT)r;
203
674
    skip_line = 0;
204
205
    /* Calculate minimum y line. */
206

674
    if (((start_angle < 90) && (end_angle < 90)) ||
207
393
        ((start_angle > 90) && (end_angle < 450)))
208
    {
209
474
        if (ystart > yend)
210
        {
211
276
            ymin = yend;
212
        }
213
        else
214
        {
215
198
            ymin = ystart;
216
        }
217
    }
218
219
674
    if (clip -> gx_rectangle_top > ymin)
220
    {
221
18
        ymin = clip -> gx_rectangle_top;
222
    }
223
674
    skip_line = ymin - ypos;
224
225
    /* Calculate maximum y line. */
226

674
    if (((start_angle < 270) && (end_angle < 270)) ||
227
184
        ((start_angle > 270) && (end_angle < 630)))
228
    {
229
467
        if (ystart > yend)
230
        {
231
254
            ymax = ystart;
232
        }
233
        else
234
        {
235
213
            ymax = yend;
236
        }
237
    }
238
239
674
    if (clip -> gx_rectangle_bottom < ymax)
240
    {
241
17
        ymax = clip -> gx_rectangle_bottom;
242
    }
243
244
674
    height = ymax - ymin + 1;
245
246
    /* default the point array to being off the screen on both sides: */
247
674
    pLineEnds = _gx_system_scratchpad;
248
249
75388
    for (Index = 0; Index < height * 2; Index += 2)
250
    {
251
74714
        pLineEnds[Index] = 2000;
252
74714
        pLineEnds[Index + 1] = 0;
253
    }
254
255
    /* Get the clipping rectangles of the circle arc. */
256
674
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle, &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
257
258
674
    curx = 0;
259
674
    cury = (INT)r;
260
674
    decision = (INT)(5 - 4 * r);
261
262
52173
    while (curx <= cury)
263
    {
264
257495
        for (Index = 0; Index < 4; Index++)
265
        {
266
205996
            point.gx_point_x = (GX_VALUE)(curx * sign[Index][0] + xcenter);
267
205996
            point.gx_point_y = (GX_VALUE)(cury * sign[Index][1] + ycenter);
268
269
205996
            if ((point.gx_point_y >= ymin) &&
270
146726
                (point.gx_point_y <= ymax))
271
            {
272

143402
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
273
89873
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
274
58391
                    _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
275
26330
                    _gx_utility_rectangle_point_detect(&arc_clip[3], point))
276
                {
277
60853
                    Index1 = (point.gx_point_y - ymin) << 1;
278
60853
                    if (point.gx_point_x < pLineEnds[Index1])
279
                    {
280
42767
                        pLineEnds[Index1] = point.gx_point_x;
281
                    }
282
283
60853
                    if (point.gx_point_x > pLineEnds[Index1 + 1])
284
                    {
285
36938
                        pLineEnds[Index1 + 1] = point.gx_point_x;
286
                    }
287
                }
288
            }
289
290
205996
            point.gx_point_x = (GX_VALUE)(cury * sign[Index][0] + xcenter);
291
205996
            point.gx_point_y = (GX_VALUE)(curx * sign[Index][1] + ycenter);
292
293
205996
            if ((point.gx_point_y >= ymin) &&
294
167092
                (point.gx_point_y <= ymax))
295
            {
296

194249
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
297
131417
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
298
94070
                    _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
299
44540
                    _gx_utility_rectangle_point_detect(&arc_clip[3], point))
300
                {
301
68010
                    Index1 = (point.gx_point_y - ymin) << 1;
302
68010
                    if (point.gx_point_x < pLineEnds[Index1])
303
                    {
304
66775
                        pLineEnds[Index1] = point.gx_point_x;
305
                    }
306
307
68010
                    if (point.gx_point_x > pLineEnds[Index1 + 1])
308
                    {
309
54094
                        pLineEnds[Index1 + 1] = point.gx_point_x;
310
                    }
311
                }
312
            }
313
        }
314
315
51499
        if (decision < 0)
316
        {
317
29795
            decision += 8 * curx + 12;
318
        }
319
        else
320
        {
321
21704
            decision += 8 * (curx - cury) + 20;
322
21704
            cury--;
323
        }
324
51499
        curx++;
325
    }
326
327
    /* Fill in the point array by using Breshenhams line for
328
       the line that connect two endpoints of the arc. */
329
330
674
    dx = GX_ABS(xend - xstart);
331
674
    dy = GX_ABS(yend - ystart);
332
333
    /* Horizontal Line. */
334
674
    if (ystart != yend)
335
    {
336
        /* Vertical Line. */
337
647
        if (xstart == xend)
338
        {
339
46
            if (ystart > yend)
340
            {
341
26
                GX_SWAP_VALS(xstart, xend);
342
26
                GX_SWAP_VALS(ystart, yend);
343
            }
344
345
2234
            for (cury = ystart; cury <= yend; cury++)
346
            {
347

2188
                if ((cury >= ymin) &&
348
                    (cury <= ymax))
349
                {
350
2144
                    Index = (cury - ymin) << 1;
351
2144
                    if (xstart <= pLineEnds[Index])
352
                    {
353
98
                        pLineEnds[Index] = xstart;
354
                    }
355
356
2144
                    if (xstart > pLineEnds[Index + 1])
357
                    {
358
2022
                        pLineEnds[Index + 1] = xstart;
359
                    }
360
                }
361
            }
362
        }
363
        else
364
        {
365
            /* Simple Line. */
366

601
            if (((dx >= dy && (xstart > xend)) ||
367
329
                 ((dy > dx) && ystart > yend)))
368
            {
369
269
                GX_SWAP_VALS(xend, xstart);
370
269
                GX_SWAP_VALS(yend, ystart);
371
            }
372
373
601
            xsign = (xend - xstart) / dx;
374
601
            ysign = (yend - ystart) / dy;
375
376
601
            if (dx >= dy)
377
            {
378
272
                for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
379
12341
                     decision = (dx >> 1); curx <= nextx; curx++, nextx--,
380
12069
                     decision += dy)
381
                {
382
12069
                    if (decision >= dx)
383
                    {
384
7661
                        decision -= dx;
385
7661
                        cury += ysign;
386
7661
                        nexty -= ysign;
387
                    }
388
389

12069
                    if ((cury >= ymin) && (cury <= ymax))
390
                    {
391
10814
                        Index = (cury - ymin) << 1;
392
393
10814
                        if (curx < pLineEnds[Index])
394
                        {
395
5039
                            pLineEnds[Index] = curx;
396
                        }
397
398
10814
                        if (curx > pLineEnds[Index + 1])
399
                        {
400
3139
                            pLineEnds[Index + 1] = curx;
401
                        }
402
                    }
403
404

12069
                    if ((nexty >= ymin) && (nexty <= ymax))
405
                    {
406
11467
                        Index1 = (nexty - ymin) << 1;
407
408
11467
                        if (nextx < pLineEnds[Index1])
409
                        {
410
7765
                            pLineEnds[Index1] = nextx;
411
                        }
412
413
11467
                        if (nextx > pLineEnds[Index1 + 1])
414
                        {
415
1591
                            pLineEnds[Index1 + 1] = nextx;
416
                        }
417
                    }
418
                }
419
            }
420
            else
421
            {
422
329
                for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
423
21225
                     decision = (dy >> 1); cury <= nexty; cury++, nexty--,
424
20896
                     decision += dx)
425
                {
426
20896
                    if (decision >= dy)
427
                    {
428
13195
                        decision -= dy;
429
13195
                        curx += xsign;
430
13195
                        nextx -= xsign;
431
                    }
432
433

20896
                    if ((cury >= ymin) && (cury <= ymax))
434
                    {
435
19640
                        Index = (cury - ymin) << 1;
436
19640
                        if (curx < pLineEnds[Index])
437
                        {
438
7918
                            pLineEnds[Index] = curx;
439
                        }
440
441
19640
                        if (curx > pLineEnds[Index + 1])
442
                        {
443
11211
                            pLineEnds[Index + 1] = curx;
444
                        }
445
                    }
446
447

20896
                    if ((nexty >= ymin) && (nexty <= ymax))
448
                    {
449
20124
                        Index1 = (nexty - ymin) << 1;
450
451
20124
                        if (nextx < pLineEnds[Index1])
452
                        {
453
7764
                            pLineEnds[Index1] = nextx;
454
                        }
455
456
20124
                        if (nextx > pLineEnds[Index1 + 1])
457
                        {
458
11719
                            pLineEnds[Index1 + 1] = nextx;
459
                        }
460
                    }
461
                }
462
            }
463
        }
464
    }
465
466
674
    if (pixelmap)
467
    {
468
        /* Skip the un-draw line.*/
469
295
        if (skip_line > 0)
470
        {
471
184
            skip_line %= info.pixelmap -> gx_pixelmap_height;
472
184
            info.draw = GX_FALSE;
473
1885
            while (skip_line--)
474
            {
475
1701
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, cury, &info);
476
            }
477
        }
478
295
        info.draw = GX_TRUE;
479
    }
480
481
674
    Index = 0;
482
75388
    for (cury = ymin; cury <= ymax; cury++)
483
    {
484
74714
        if (pLineEnds[Index] < clip -> gx_rectangle_left)
485
        {
486
5697
            pLineEnds[Index] = clip -> gx_rectangle_left;
487
        }
488
489
74714
        if (pLineEnds[Index + 1] > clip -> gx_rectangle_right)
490
        {
491
11392
            pLineEnds[Index + 1] = clip -> gx_rectangle_right;
492
        }
493
494
74714
        if (pixelmap)
495
        {
496
            /* Filling arc area with pixelmap. */
497
31160
            info.x_offset = pLineEnds[Index] - xpos;
498
31160
            display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, &info);
499
        }
500
        else
501
        {
502
            /* Fill arc with horizontal lines. */
503
43554
            line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, 1, brush -> gx_brush_fill_color);
504
        }
505
506
74714
        Index += 2;
507
    }
508
}
509
510
#endif
511