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

674
    if (((start_angle < 90) && (end_angle < 90)) ||
214
393
        ((start_angle > 90) && (end_angle < 450)))
215
    {
216
474
        if (ystart > yend)
217
        {
218
276
            ymin = yend;
219
        }
220
        else
221
        {
222
198
            ymin = ystart;
223
        }
224
    }
225
226
674
    if (clip -> gx_rectangle_top > ymin)
227
    {
228
18
        ymin = clip -> gx_rectangle_top;
229
    }
230
674
    skip_line = ymin - ypos;
231
232
    /* Calculate maximum y line. */
233

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

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

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

2188
                if ((cury >= ymin) &&
355
                    (cury <= ymax))
356
                {
357
2144
                    Index = (cury - ymin) << 1;
358
2144
                    if (xstart <= pLineEnds[Index])
359
                    {
360
98
                        pLineEnds[Index] = xstart;
361
                    }
362
363
2144
                    if (xstart > pLineEnds[Index + 1])
364
                    {
365
2022
                        pLineEnds[Index + 1] = xstart;
366
                    }
367
                }
368
            }
369
        }
370
        else
371
        {
372
            /* Simple Line. */
373

601
            if (((dx >= dy && (xstart > xend)) ||
374
329
                 ((dy > dx) && ystart > yend)))
375
            {
376
269
                GX_SWAP_VALS(xend, xstart);
377
269
                GX_SWAP_VALS(yend, ystart);
378
            }
379
380
601
            xsign = (xend - xstart) / dx;
381
601
            ysign = (yend - ystart) / dy;
382
383
601
            if (dx >= dy)
384
            {
385
272
                for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
386
12341
                     decision = (dx >> 1); curx <= nextx; curx++, nextx--,
387
12069
                     decision += dy)
388
                {
389
12069
                    if (decision >= dx)
390
                    {
391
7661
                        decision -= dx;
392
7661
                        cury += ysign;
393
7661
                        nexty -= ysign;
394
                    }
395
396

12069
                    if ((cury >= ymin) && (cury <= ymax))
397
                    {
398
10814
                        Index = (cury - ymin) << 1;
399
400
10814
                        if (curx < pLineEnds[Index])
401
                        {
402
5039
                            pLineEnds[Index] = curx;
403
                        }
404
405
10814
                        if (curx > pLineEnds[Index + 1])
406
                        {
407
3139
                            pLineEnds[Index + 1] = curx;
408
                        }
409
                    }
410
411

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

20896
                    if ((cury >= ymin) && (cury <= ymax))
441
                    {
442
19640
                        Index = (cury - ymin) << 1;
443
19640
                        if (curx < pLineEnds[Index])
444
                        {
445
7918
                            pLineEnds[Index] = curx;
446
                        }
447
448
19640
                        if (curx > pLineEnds[Index + 1])
449
                        {
450
11211
                            pLineEnds[Index + 1] = curx;
451
                        }
452
                    }
453
454

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