GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_pie_fill.c Lines: 204 204 100.0 %
Date: 2024-12-05 08:52:37 Branches: 160 160 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_rotated_simple_pie_fill  PORTABLE C      */
35
/*                                                           6.1.5        */
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_display_driver_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
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
82
/*  03-02-2021     Ting Zhu                 Modified comment(s),          */
83
/*                                            improved logic,             */
84
/*                                            resulting in version 6.1.5  */
85
/*                                                                        */
86
/**************************************************************************/
87
#if defined(GX_ARC_DRAWING_SUPPORT)
88
89
504
static VOID _gx_display_driver_generic_rotated_simple_pie_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter,
90
                                                               UINT r, INT start_angle, INT end_angle, GX_BOOL skip_end)
91
{
92
/* The function will only fill a pie with both start angle and end angle are
93
   between 0 and 180 or beween 180 and 360.*/
94
95
GX_DISPLAY           *display;
96
GX_BRUSH             *brush;
97
GX_RECTANGLE         *clip;
98
GX_RECTANGLE          arc_clip[4];
99
GX_POINT              point;
100
GX_POINT              points[3];
101
504
INT                   sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
102
INT                  *pLineEnds;
103
GX_POINT             *pGet;
104
INT                   xmin;
105
INT                   xmax;
106
INT                   xstart;
107
INT                   xend;
108
INT                   ystart;
109
INT                   yend;
110
INT                   curx;
111
INT                   cury;
112
INT                   nextx;
113
INT                   nexty;
114
INT                   dx;
115
INT                   dy;
116
INT                   Index;
117
INT                   loop;
118
INT                   width;
119
INT                   xsign;
120
INT                   ysign;
121
INT                   decision;
122
int                   fillingwards;
123
VOID                  (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
124
504
INT                   xpos = 0;
125
504
GX_PIXELMAP          *pixelmap = GX_NULL;
126
INT                   skip_line;
127
GX_FILL_PIXELMAP_INFO info;
128
129
504
    display = context -> gx_draw_context_display;
130
504
    brush = &context -> gx_draw_context_brush;
131
504
    line_draw = display -> gx_display_driver_vertical_line_draw;
132
133
504
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
134
    {
135
407
        if (brush -> gx_brush_pixelmap == GX_NULL)
136
        {
137
2
            return;
138
        }
139
140
        /* Pick up brush pixelmap. */
141
406
        pixelmap = brush -> gx_brush_pixelmap;
142
143
406
        if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
144
        {
145
            /* Display driver only support its native format pixelmap.*/
146
            /* Nothing should be drawn if pixelmap format isn't support. */
147
1
            return;
148
        }
149
150
405
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
151
152
405
        info.pixelmap = pixelmap;
153
405
        info.current_pixel_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_data;
154
405
        if (pixelmap -> gx_pixelmap_aux_data_size)
155
        {
156
150
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
157
        }
158
    }
159
160
502
    pGet = points;
161
162
502
    points[1].gx_point_x = (GX_VALUE)xcenter;
163
502
    points[1].gx_point_y = (GX_VALUE)ycenter;
164
165
502
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &points[0]);
166
502
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &points[2]);
167
168
502
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle,
169
                                        &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
170
171
    /* Pie is in left side. */
172
502
    xmin = points[0].gx_point_x;
173
502
    xmax = points[2].gx_point_x;
174
175
502
    if (xmin > xmax)
176
    {
177
264
        GX_SWAP_VALS(xmin, xmax);
178
    }
179
180
502
    if (xmax < xcenter)
181
    {
182
154
        xmax = xcenter;
183
    }
184
348
    else if (xmin > xcenter)
185
    {
186
156
        xmin = xcenter;
187
    }
188
189
502
    clip = context -> gx_draw_context_clip;
190
191
502
    if (clip -> gx_rectangle_left > xmin)
192
    {
193
14
        xmin = clip -> gx_rectangle_left;
194
    }
195
196
502
    if (clip -> gx_rectangle_right < xmax)
197
    {
198
10
        xmax = clip -> gx_rectangle_right;
199
    }
200
201
502
    width = xmax - xmin + 1;
202
203
502
    pLineEnds = _gx_system_scratchpad;
204
205
    /* default the point array to being off the screen on both sides: */
206
207
93532
    for (loop = 0; loop < width * 2; loop += 2)
208
    {
209
93030
        pLineEnds[loop] = 2000;
210
93030
        pLineEnds[loop + 1] = 0;
211
    }
212
213
502
    curx = 0;
214
502
    cury = (INT)r;
215
502
    decision = 5 - (INT)(4 * r);
216
217
62262
    while (curx <= cury)
218
    {
219
308800
        for (loop = 0; loop < 4; loop++)
220
        {
221
247040
            point.gx_point_x = (GX_VALUE)(curx * sign[loop][0] + xcenter);
222
247040
            point.gx_point_y = (GX_VALUE)(cury * sign[loop][1] + ycenter);
223
224

247040
            if ((point.gx_point_x >= xmin) && (point.gx_point_x <= xmax))
225
            {
226

264820
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
227
117136
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point))
228
                {
229
47090
                    Index = (point.gx_point_x - xmin) << 1;
230
47090
                    if (point.gx_point_y < pLineEnds[Index])
231
                    {
232
46898
                        pLineEnds[Index] = point.gx_point_y;
233
                    }
234
235
47090
                    if (point.gx_point_y > pLineEnds[Index + 1])
236
                    {
237
37662
                        pLineEnds[Index + 1] = point.gx_point_y;
238
                    }
239
                }
240
            }
241
242
247040
            point.gx_point_x = (GX_VALUE)(cury * sign[loop][0] + xcenter);
243
247040
            point.gx_point_y = (GX_VALUE)(curx * sign[loop][1] + ycenter);
244
245

247040
            if ((point.gx_point_x >= xmin) && (point.gx_point_x <= xmax))
246
            {
247

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

53766
                if ((curx >= xmin) && (curx <= xmax))
313
                {
314
52778
                    Index = (curx - xmin) << 1;
315
52778
                    if (ystart < pLineEnds[Index])
316
                    {
317
32684
                        pLineEnds[Index] = ystart;
318
                    }
319
320
52778
                    if (ystart > pLineEnds[Index + 1])
321
                    {
322
37910
                        pLineEnds[Index + 1] = ystart;
323
                    }
324
                }
325
            }
326
326
            continue;
327
        }
328
329
        /* Simple Line. */
330

674
        if (((dx >= dy && (xstart > xend)) ||
331
362
             ((dy > dx) && ystart > yend)))
332
        {
333
338
            GX_SWAP_VALS(xend, xstart);
334
338
            GX_SWAP_VALS(yend, ystart);
335
        }
336
337
674
        xsign = (xend - xstart) / dx;
338
674
        ysign = (yend - ystart) / dy;
339
340
674
        if (dx >= dy)
341
        {
342
312
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
343
23896
                 decision = (dx >> 1); curx <= nextx; curx++, nextx--,
344
23584
                 decision += dy)
345
            {
346
23584
                if (decision >= dx)
347
                {
348
10772
                    decision -= dx;
349
10772
                    cury += ysign;
350
10772
                    nexty -= ysign;
351
                }
352
353

23584
                if ((curx >= xmin) && (curx <= xmax))
354
                {
355
23056
                    Index = (curx - xmin) << 1;
356
357
23056
                    if (cury < pLineEnds[Index])
358
                    {
359
11218
                        pLineEnds[Index] = cury;
360
                    }
361
362
23056
                    if (cury - 1 > pLineEnds[Index + 1])
363
                    {
364
16768
                        pLineEnds[Index + 1] = cury - 1;
365
                    }
366
                }
367
368

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

31066
                if ((curx - 1 + fillingwards >= xmin) && (curx - 1 + fillingwards <= xmax))
421
                {
422
30544
                    Index = (curx - 1 + fillingwards - xmin) << 1;
423
424
30544
                    if (cury < pLineEnds[Index])
425
                    {
426
5990
                        pLineEnds[Index] = cury;
427
                    }
428
429
30544
                    if (cury > pLineEnds[Index + 1])
430
                    {
431
15788
                        pLineEnds[Index + 1] = cury;
432
                    }
433
                }
434
435

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