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

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

793532
            if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
243
            {
244

549742
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
245
241472
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point))
246
                {
247
96345
                    Index = (point.gx_point_y - ymin) << 1;
248
96345
                    if (point.gx_point_x < pLineEnds[Index])
249
                    {
250
65921
                        pLineEnds[Index] = point.gx_point_x;
251
                    }
252
253
96345
                    if (point.gx_point_x > pLineEnds[Index + 1])
254
                    {
255
61617
                        pLineEnds[Index + 1] = point.gx_point_x;
256
                    }
257
                }
258
            }
259
260
793532
            point.gx_point_x = (GX_VALUE)(cury * sign[loop][0] + xcenter);
261
793532
            point.gx_point_y = (GX_VALUE)(curx * sign[loop][1] + ycenter);
262
263

793532
            if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
264
            {
265

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

4254
                if ((cury >= ymin) && (cury <= ymax))
332
                {
333
1516
                    Index = (cury - ymin) << 1;
334
1516
                    if (xstart <= pLineEnds[Index])
335
                    {
336
1420
                        pLineEnds[Index] = xstart;
337
                    }
338
339
1516
                    if (xstart > pLineEnds[Index + 1])
340
                    {
341
641
                        pLineEnds[Index + 1] = xstart;
342
                    }
343
                }
344
            }
345
529
            continue;
346
        }
347
348
        /* Simple Line. */
349

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

98520
                if ((cury - 1 + fillingwards >= ymin) && (cury - 1 + fillingwards <= ymax))
396
                {
397
95880
                    Index = (cury - 1 + fillingwards - ymin) << 1;
398
399
95880
                    if (curx < pLineEnds[Index])
400
                    {
401
21007
                        pLineEnds[Index] = curx;
402
                    }
403
404
95880
                    if (curx > pLineEnds[Index + 1])
405
                    {
406
58329
                        pLineEnds[Index + 1] = curx;
407
                    }
408
                }
409
410

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

71155
                if ((cury >= ymin) && (cury <= ymax))
440
                {
441
69569
                    Index = (cury - ymin) << 1;
442
443
69569
                    if (curx < pLineEnds[Index])
444
                    {
445
41219
                        pLineEnds[Index] = curx;
446
                    }
447
448
69569
                    if (curx - 1 > pLineEnds[Index + 1])
449
                    {
450
39527
                        pLineEnds[Index + 1] = curx - 1;
451
                    }
452
                }
453
454

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