GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_aliased_wide_arc_draw.c Lines: 298 298 100.0 %
Date: 2024-12-05 08:52:37 Branches: 246 246 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
#include "gx_canvas.h"
31
32
#if defined(GX_ARC_DRAWING_SUPPORT)
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_display_driver_generic_simple_aliased_wide_arc_draw             */
39
/*                                                        PORTABLE C      */
40
/*                                                           6.1          */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    Kenneth Maxwell, Microsoft Corporation                              */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    Innner help function that draw an aliased wide arc between [90, 180]*/
48
/*     or [270, 540].                                                     */
49
/*                                                                        */
50
/*  INPUT                                                                 */
51
/*                                                                        */
52
/*    context                               Drawing context               */
53
/*    xcenter                               curx-coord of center of circle*/
54
/*    ycenter                               cury-coord of center of circle*/
55
/*    r                                     Radius of circle              */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    None                                                                */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
64
/*                                            blend function              */
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_line_draw]                            */
70
/*                                          Basic display driver          */
71
/*                                            horizontal line draw routine*/
72
/*                                                                        */
73
/*  CALLED BY                                                             */
74
/*                                                                        */
75
/*    _gx_display_driver_generic_aliased_wide_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
10243
static VOID _gx_display_driver_generic_simple_aliased_wide_arc_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
87
{
88
/* The function draw a wide arc between 90 and 270 or beween 270 and 450.*/
89
GX_DISPLAY   *display;
90
GX_BRUSH     *brush;
91
GX_RECTANGLE *clip;
92
GX_RECTANGLE  arc_clip[4];
93
GX_POINT      point;
94
GX_POINT      inner_start;
95
GX_POINT      inner_end;
96
GX_POINT      outer_start;
97
GX_POINT      outer_end;
98
10243
INT           sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
99
INT          *pLineEnds;
100
INT           ymin;
101
INT           ymax;
102
INT           xstart;
103
INT           xend;
104
INT           ystart;
105
INT           yend;
106
INT           curx;
107
INT           cury;
108
INT           nextx;
109
INT           nexty;
110
INT           dx;
111
INT           dy;
112
INT           Index;
113
INT           Index1;
114
INT           loop;
115
INT           height;
116
INT           xsign;
117
INT           ysign;
118
INT           error;
119
INT           decision;
120
INT           brush_width;
121
GX_UBYTE      alpha1;
122
GX_UBYTE      alpha2;
123
VOID          (*blend_func)(GX_DRAW_CONTEXT *, INT, INT, GX_COLOR, GX_UBYTE);
124
10243
GX_BOOL       right = GX_TRUE;
125
INT           test;
126
INT           cur_shift;
127
INT           next_shift;
128
129

10243
    if ((start_angle >= 90) &&
130
7087
        (start_angle <= 270) &&
131
        (end_angle <= 270))
132
    {
133
3738
        right = GX_FALSE;
134
    }
135
136
10243
    display = context -> gx_draw_context_display;
137
10243
    brush = &context -> gx_draw_context_brush;
138
10243
    brush_width = brush -> gx_brush_width;
139
10243
    blend_func = display -> gx_display_driver_pixel_blend;
140
141
10243
    if (blend_func == GX_NULL)
142
    {
143
50
        return;
144
    }
145
146
10241
    clip = context -> gx_draw_context_clip;
147
10241
    pLineEnds = _gx_system_scratchpad;
148
149
10241
    if (r <= (UINT)((brush_width - 1) >> 1))
150
    {
151
48
        return;
152
    }
153
154
    /* Calculate the ridius of the inner circle.  */
155
10193
    r = (UINT)(r - (UINT)((brush_width - 1) >> 1));
156
157
    /* Get end points. */
158
10193
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &inner_start);
159
10193
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &inner_end);
160
10193
    _gx_utility_circle_point_get(xcenter, ycenter, (UINT)(r + (UINT)brush_width - 1), start_angle, &outer_start);
161
10193
    _gx_utility_circle_point_get(xcenter, ycenter, (UINT)(r + (UINT)brush_width - 1), end_angle, &outer_end);
162
163
10193
    ymin = ycenter - (INT)r - brush_width + 1;
164
10193
    ymax = ycenter + (INT)r + brush_width - 1;
165
166

10193
    if (((start_angle < 90) && (end_angle < 90)) ||
167
6634
        ((start_angle > 90) && (end_angle < 450)))
168
    {
169
3971
        if (outer_start.gx_point_y < outer_end.gx_point_y)
170
        {
171
3016
            ymin = outer_start.gx_point_y;
172
        }
173
        else
174
        {
175
955
            ymin = outer_end.gx_point_y;
176
        }
177
178
3971
        if (inner_start.gx_point_y < ymin)
179
        {
180
387
            ymin = inner_start.gx_point_y;
181
        }
182
183
3971
        if (inner_end.gx_point_y < ymin)
184
        {
185
401
            ymin = inner_end.gx_point_y;
186
        }
187
    }
188
189
10193
    if (clip -> gx_rectangle_top > ymin)
190
    {
191
37
        ymin = clip -> gx_rectangle_top;
192
    }
193
194
    /* Calculate maximum y line. */
195

10193
    if (((start_angle < 270) && (end_angle < 270)) || (start_angle > 270))
196
    {
197
4094
        if (outer_start.gx_point_y > outer_end.gx_point_y)
198
        {
199
3156
            ymax = outer_start.gx_point_y;
200
        }
201
        else
202
        {
203
938
            ymax = outer_end.gx_point_y;
204
        }
205
206
4094
        if (inner_start.gx_point_y > ymax)
207
        {
208
2737
            ymax = inner_start.gx_point_y;
209
        }
210
211
4094
        if (inner_end.gx_point_y > ymax)
212
        {
213
350
            ymax = inner_end.gx_point_y;
214
        }
215
    }
216
217
10193
    if (clip -> gx_rectangle_bottom < ymax)
218
    {
219
33
        ymax = clip -> gx_rectangle_bottom;
220
    }
221
222
10193
    height = ymax - ymin + 1;
223
224
    /* default the point array to being off the screen on both sides: */
225
226
597993
    for (loop = 0; loop < height * 2; loop += 2)
227
    {
228
587800
        pLineEnds[loop] = 2000;
229
587800
        pLineEnds[loop + 1] = 0;
230
    }
231
232
    /* Get point array of inner arc and outer arc. */
233
30579
    for (Index1 = 0; Index1 < 2; Index1++)
234
    {
235
20386
        if (Index1 == 1)
236
        {
237
10193
            r += (UINT)(brush_width - 1);
238
        }
239
240
20386
        _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle,
241
                                            &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
242
243
20386
        curx = 0;
244
20386
        cury = (INT)r;
245
20386
        error = 0;
246
247
795945
        while (curx < cury)
248
        {
249
775559
            alpha1 = (GX_UBYTE)(255 - error);
250
775559
            alpha2 = (GX_UBYTE)error;
251
252
3877795
            for (loop = 0; loop < 4; loop++)
253
            {
254
3102236
                point.gx_point_x = (GX_VALUE)(curx * sign[loop][0] + xcenter);
255
3102236
                point.gx_point_y = (GX_VALUE)(cury * sign[loop][1] + ycenter);
256
257

5589351
                if ((_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
258
3311234
                     _gx_utility_rectangle_point_detect(&arc_clip[1], point)) &&
259
824119
                    _gx_utility_rectangle_point_detect(clip, point))
260
                {
261
                    /* Draw point(curx, cury).  */
262
776167
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
263
                }
264
265
3102236
                point.gx_point_y = (GX_VALUE)((cury - 1) * sign[loop][1] + ycenter);
266
267

5589705
                if ((_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
268
3311728
                     _gx_utility_rectangle_point_detect(&arc_clip[1], point)) &&
269
824259
                    _gx_utility_rectangle_point_detect(clip, point))
270
                {
271
776393
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, (GX_UBYTE)alpha2);
272
                }
273
274
3102236
                point.gx_point_x = (GX_VALUE)(cury * sign[loop][0] + xcenter);
275
3102236
                point.gx_point_y = (GX_VALUE)(curx * sign[loop][1] + ycenter);
276
277

5694312
                if ((_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
278
3370133
                     _gx_utility_rectangle_point_detect(&arc_clip[1], point)) &&
279
778057
                    _gx_utility_rectangle_point_detect(clip, point))
280
                {
281
                    /* Draw point(cury, curx).  */
282
738823
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color,  alpha1);
283
                }
284
285

3102236
                if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
286
                {
287

2572185
                    if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
288
1038259
                        _gx_utility_rectangle_point_detect(&arc_clip[1], point))
289
                    {
290
756529
                        Index = (point.gx_point_y - ymin) << 1;
291
292
756529
                        if (right)
293
                        {
294
448249
                            if (Index1 == 0)
295
                            {
296
202110
                                pLineEnds[Index] = cury * sign[loop][0] + xcenter;
297
                            }
298
                            else
299
                            {
300
246139
                                pLineEnds[Index + 1] = (cury - 1) * sign[loop][0] + xcenter;
301
                            }
302
                        }
303
                        else
304
                        {
305
308280
                            if (Index1 == 0)
306
                            {
307
145613
                                pLineEnds[Index + 1] = cury * sign[loop][0] + xcenter;
308
                            }
309
                            else
310
                            {
311
162667
                                pLineEnds[Index] = (cury - 1) * sign[loop][0] + xcenter;
312
                            }
313
                        }
314
                    }
315
                }
316
317
3102236
                point.gx_point_x = (GX_VALUE)((cury - 1) * sign[loop][0] + xcenter);
318
319

5693448
                if ((_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
320
3369757
                     _gx_utility_rectangle_point_detect(&arc_clip[1], point)) &&
321
778545
                    _gx_utility_rectangle_point_detect(clip, point))
322
                {
323
                    /* Draw point(cury - 1, curx).  */
324
739376
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, (GX_UBYTE)alpha2);
325
                }
326
327

3102236
                if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
328
                {
329

2571318
                    if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
330
1037392
                        _gx_utility_rectangle_point_detect(&arc_clip[1], point))
331
                    {
332
757020
                        Index = (point.gx_point_y - ymin) << 1;
333
334
757020
                        if (right)
335
                        {
336
448475
                            if (Index1 == 0)
337
                            {
338
202218
                                pLineEnds[Index] = cury * sign[loop][0] + xcenter;
339
                            }
340
                            else
341
                            {
342
246257
                                pLineEnds[Index + 1] = (cury - 1) * sign[loop][0] + xcenter;
343
                            }
344
                        }
345
                        else
346
                        {
347
308545
                            if (Index1 == 0)
348
                            {
349
145617
                                pLineEnds[Index + 1] = cury * sign[loop][0] + xcenter;
350
                            }
351
                            else
352
                            {
353
162928
                                pLineEnds[Index] = (cury - 1) * sign[loop][0] + xcenter;
354
                            }
355
                        }
356
                    }
357
                }
358
            }
359
360
            /* Calculate the distance between mathmatical point to drawing poing,
361
               which is used to blending pixel.  */
362
775559
            curx++;
363
775559
            nexty = (INT)(r * r) - curx * curx;
364
775559
            error = (cury << 8) - (INT)(_gx_utility_math_sqrt((UINT)(nexty << 10)) << 3);
365
366
1092893
            while (error >= 255)
367
            {
368
317334
                error -= 255;
369
317334
                cury--;
370
371
1586670
                for (loop = 0; loop < 4; loop++)
372
                {
373
1269336
                    point.gx_point_x = (GX_VALUE)(curx * sign[loop][0] + xcenter);
374
1269336
                    point.gx_point_y = (GX_VALUE)(cury * sign[loop][1] + ycenter);
375
376

1269336
                    if ((point.gx_point_y >= ymin) && (point.gx_point_y <= ymax))
377
                    {
378

1053822
                        if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
379
413398
                            _gx_utility_rectangle_point_detect(&arc_clip[1], point))
380
                        {
381
309718
                            Index = (point.gx_point_y - ymin) << 1;
382
383
309718
                            if (right)
384
                            {
385
194124
                                if (Index1 == 0)
386
                                {
387
86035
                                    pLineEnds[Index] = curx * sign[loop][0] + xcenter;
388
                                }
389
                                else
390
                                {
391
108089
                                    pLineEnds[Index + 1] = (curx - 1) * sign[loop][0] + xcenter;
392
                                }
393
                            }
394
                            else
395
                            {
396
115594
                                if (Index1 == 0)
397
                                {
398
53521
                                    pLineEnds[Index + 1] = curx * sign[loop][0] + xcenter;
399
                                }
400
                                else
401
                                {
402
62073
                                    pLineEnds[Index] = (curx - 1) * sign[loop][0] + xcenter;
403
                                }
404
                            }
405
                        }
406
                    }
407
                }
408
            }
409
        }
410
411
20386
        alpha1 = (GX_UBYTE)(255 - error);
412
413
101930
        for (loop = 0; loop < 4; loop++)
414
        {
415
416
81544
            point.gx_point_x = (GX_VALUE)(curx * sign[loop][0] + xcenter);
417
81544
            point.gx_point_y = (GX_VALUE)(cury * sign[loop][1] + ycenter);
418
419

145241
            if ((_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
420
88453
                 _gx_utility_rectangle_point_detect(&arc_clip[1], point)) &&
421
24756
                _gx_utility_rectangle_point_detect(clip, point))
422
            {
423
24676
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color,  alpha1);
424
            }
425
        }
426
    }
427
428
    /* Fill in the point array by using Breshenhams line for
429
       2 lines of the arc end.
430
     */
431
432
30579
    for (loop = 0; loop < 2; loop++)
433
    {
434
20386
        if (loop == 0)
435
        {
436
10193
            xstart = inner_start.gx_point_x;
437
10193
            ystart = inner_start.gx_point_y;
438
10193
            xend = outer_start.gx_point_x;
439
10193
            yend = outer_start.gx_point_y;
440
        }
441
        else
442
        {
443
10193
            xstart = inner_end.gx_point_x;
444
10193
            ystart = inner_end.gx_point_y;
445
10193
            xend = outer_end.gx_point_x;
446
10193
            yend = outer_end.gx_point_y;
447
        }
448
449
20386
        dx = GX_ABS(xend - xstart);
450
20386
        dy = GX_ABS(yend - ystart);
451
452
        /* Horizontal Line. */
453
20386
        if (ystart == yend)
454
        {
455
2814
            continue;
456
        }
457
458
        /* Vertical Line. */
459
17572
        if (xstart == xend)
460
        {
461
12755
            if (ystart > yend)
462
            {
463
6470
                GX_SWAP_VALS(xstart, xend);
464
6470
                GX_SWAP_VALS(ystart, yend);
465
            }
466
467
114596
            for (cury = ystart; cury <= yend; cury++)
468
            {
469

101841
                if ((cury >= ymin) && (cury <= ymax))
470
                {
471
101354
                    Index = (cury - ymin) << 1;
472
101354
                    if (xstart <= pLineEnds[Index])
473
                    {
474
78741
                        pLineEnds[Index] = xstart;
475
                    }
476
477
101354
                    if (xstart > pLineEnds[Index + 1])
478
                    {
479
36922
                        pLineEnds[Index + 1] = xstart;
480
                    }
481
                }
482
            }
483
12755
            continue;
484
        }
485
486
        /* Simple Line. */
487

4817
        if (((dx >= dy && (xstart > xend)) ||
488
1162
             ((dy > dx) && ystart > yend)))
489
        {
490
1620
            GX_SWAP_VALS(xend, xstart);
491
1620
            GX_SWAP_VALS(yend, ystart);
492
        }
493
494
4817
        xsign = (xend - xstart) / dx;
495
4817
        ysign = (yend - ystart) / dy;
496
497
4817
        cur_shift = 0;
498
4817
        next_shift = 0;
499
500
4817
        if (dx >= dy)
501
        {
502

3655
            if ((right && loop == 1) ||
503
918
                (!right && loop == 0))
504
            {
505
726
                if (ysign > 0)
506
                {
507
362
                    cur_shift = 1;
508
                }
509
                else
510
                {
511
364
                    next_shift = 1;
512
                }
513
            }
514
            else
515
            {
516
2929
                if (ysign > 0)
517
                {
518
312
                    next_shift = -1;
519
                }
520
                else
521
                {
522
2617
                    cur_shift = -1;
523
                }
524
            }
525
526
3655
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
527
20724
                 decision = 0; curx <= nextx; curx++, nextx--,
528
17069
                 decision += dy)
529
            {
530
17069
                if (decision >= dx)
531
                {
532
2661
                    decision -= dx;
533
2661
                    cury += ysign;
534
2661
                    nexty -= ysign;
535
                }
536
537
17069
                test = cury + cur_shift;
538
539

17069
                if ((test >= ymin) && (test <= ymax))
540
                {
541
17053
                    Index = (test - ymin) << 1;
542
543
17053
                    if (curx < pLineEnds[Index])
544
                    {
545
1614
                        pLineEnds[Index] = curx;
546
                    }
547
548
17053
                    if (curx > pLineEnds[Index + 1])
549
                    {
550
3878
                        pLineEnds[Index + 1] = curx;
551
                    }
552
                }
553
554
17069
                test = nexty + next_shift;
555
556

17069
                if ((test >= ymin) && (test <= ymax))
557
                {
558
17053
                    Index1 = (test - ymin) << 1;
559
560
17053
                    if (nextx < pLineEnds[Index1])
561
                    {
562
2827
                        pLineEnds[Index1] = nextx;
563
                    }
564
565
17053
                    if (nextx > pLineEnds[Index1 + 1])
566
                    {
567
4105
                        pLineEnds[Index1 + 1] = nextx;
568
                    }
569
                }
570
            }
571
        }
572
        else
573
        {
574

1162
            if ((right && loop == 1) ||
575
394
                (!right && loop == 0))
576
            {
577
608
                next_shift = -xsign;
578
            }
579
            else
580
            {
581
554
                cur_shift = xsign;
582
            }
583
584
1162
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
585
7861
                 decision = 0; cury <= nexty; cury++, nexty--,
586
6699
                 decision += dx)
587
            {
588
6699
                if (decision >= dy)
589
                {
590
1689
                    decision -= dy;
591
1689
                    curx += xsign;
592
1689
                    nextx -= xsign;
593
                }
594
595

6699
                if ((cury >= ymin) && (cury <= ymax))
596
                {
597
598
6678
                    Index = (cury - ymin) << 1;
599
6678
                    test = curx + cur_shift;
600
601
6678
                    if (test < pLineEnds[Index])
602
                    {
603
3589
                        pLineEnds[Index] = test;
604
                    }
605
606
6678
                    if (test > pLineEnds[Index + 1])
607
                    {
608
3873
                        pLineEnds[Index + 1] = test;
609
                    }
610
                }
611
612

6699
                if ((nexty >= ymin) && (nexty <= ymax))
613
                {
614
6678
                    Index1 = (nexty - ymin) << 1;
615
6678
                    test = nextx + next_shift;
616
617
6678
                    if (test < pLineEnds[Index1])
618
                    {
619
2894
                        pLineEnds[Index1] = test;
620
                    }
621
622
6678
                    if (test > pLineEnds[Index1 + 1])
623
                    {
624
3667
                        pLineEnds[Index1 + 1] = test;
625
                    }
626
                }
627
            }
628
        }
629
    }
630
631
    /* Filling the outline area with horizontal line. */
632
633
10193
    Index = 0;
634
597993
    for (cury = ymin; cury <= ymax; cury++)
635
    {
636
587800
        if (pLineEnds[Index] <= pLineEnds[Index + 1])
637
        {
638
582428
            if (pLineEnds[Index] < clip -> gx_rectangle_left)
639
            {
640
4855
                pLineEnds[Index] = clip -> gx_rectangle_left;
641
            }
642
643
582428
            if (pLineEnds[Index + 1] > clip -> gx_rectangle_right)
644
            {
645
2980
                pLineEnds[Index + 1] = clip -> gx_rectangle_right;
646
            }
647
648
582428
            display -> gx_display_driver_horizontal_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, 1,
649
                                                              brush -> gx_brush_line_color);
650
        }
651
587800
        Index += 2;
652
    }
653
}
654
655
/**************************************************************************/
656
/*                                                                        */
657
/*  FUNCTION                                               RELEASE        */
658
/*                                                                        */
659
/*    _gx_display_driver_generic_aliased_wide_arc_draw    PORTABLE C      */
660
/*                                                           6.1          */
661
/*  AUTHOR                                                                */
662
/*                                                                        */
663
/*    Kenneth Maxwell, Microsoft Corporation                              */
664
/*                                                                        */
665
/*  DESCRIPTION                                                           */
666
/*                                                                        */
667
/*    Display driver function to draw wide anti-aliased circular arc.     */
668
/*                                                                        */
669
/*  INPUT                                                                 */
670
/*                                                                        */
671
/*    context                             Drawing context                 */
672
/*    xcenter                             curx-coord of center of circle  */
673
/*    ycenter                             cury-coord of center of circle  */
674
/*    r                                   Radius of circle                */
675
/*                                                                        */
676
/*  OUTPUT                                                                */
677
/*                                                                        */
678
/*    None                                                                */
679
/*                                                                        */
680
/*  CALLS                                                                 */
681
/*                                                                        */
682
/*    [gx_display_driver_generic_simple_wide_arc_draw]                    */
683
/*                                          Real display driver wide arc  */
684
/*                                            draw function               */
685
/*    _gx_utility_circle_point_get          Get point coord on a circle   */
686
/*    _gx_canvas_circle_draw                Draw circle into a canvas     */
687
/*    [gx_display_driver_anti_aliased_line_draw]                          */
688
/*                                          Basic driver-level aliased    */
689
/*                                            line draw function          */
690
/*                                                                        */
691
/*  CALLED BY                                                             */
692
/*                                                                        */
693
/*    GUIX Internal Code                                                  */
694
/*                                                                        */
695
/*  RELEASE HISTORY                                                       */
696
/*                                                                        */
697
/*    DATE              NAME                      DESCRIPTION             */
698
/*                                                                        */
699
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
700
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
701
/*                                            resulting in version 6.1    */
702
/*                                                                        */
703
/**************************************************************************/
704
6794
VOID _gx_display_driver_generic_aliased_wide_arc_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
705
{
706
GX_BRUSH   *brush;
707
INT         brush_width;
708
GX_POINT    startp;
709
GX_POINT    endp;
710
GX_DISPLAY *display;
711
GX_COLOR    old_fill;
712
UINT        old_style;
713
714
#if defined(GX_BRUSH_ALPHA_SUPPORT)
715
GX_UBYTE old_alpha;
716
717
6794
    old_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
718
6794
    context -> gx_draw_context_brush.gx_brush_alpha = GX_ALPHA_VALUE_OPAQUE;
719
#endif
720
721
6794
    brush = &context -> gx_draw_context_brush;
722
6794
    brush_width = brush -> gx_brush_width;
723
6794
    display = context -> gx_draw_context_display;
724
725
6794
    if (start_angle < 90)
726
    {
727
2838
        if (end_angle <= 90)
728
        {
729
2305
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, end_angle);
730
        }
731
533
        else if (end_angle <= 270)
732
        {
733
399
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, 90);
734
399
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 90, end_angle);
735
        }
736
        else
737
        {
738
134
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, 90);
739
134
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 90, 270);
740
134
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 270, end_angle);
741
        }
742
    }
743
3956
    else if (start_angle < 270)
744
    {
745
3067
        if (end_angle <= 270)
746
        {
747
453
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, end_angle);
748
        }
749
2614
        else if (end_angle <= 450)
750
        {
751
2533
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, 270);
752
2533
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 270, end_angle);
753
        }
754
        else
755
        {
756
81
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, 270);
757
81
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 270, 450);
758
81
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 90, end_angle - 360);
759
        }
760
    }
761
    else
762
    {
763
889
        if (end_angle <= 450)
764
        {
765
832
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, end_angle);
766
        }
767
57
        else if (end_angle <= 630)
768
        {
769
27
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, 450);
770
27
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 90, end_angle - 360);
771
        }
772
        else
773
        {
774
30
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, start_angle, 450);
775
30
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 90, 270);
776
30
            _gx_display_driver_generic_simple_aliased_wide_arc_draw(context, xcenter, ycenter, r, 270, end_angle - 360);
777
        }
778
    }
779
780
6794
    old_fill = brush -> gx_brush_fill_color;
781
6794
    old_style = brush -> gx_brush_style;
782
783
6794
    brush -> gx_brush_width = 1;
784
6794
    brush -> gx_brush_fill_color = brush -> gx_brush_line_color;
785
6794
    brush -> gx_brush_style |= GX_BRUSH_SOLID_FILL;
786
787
6794
    r = (UINT)(r - (UINT)((brush_width - 1) >> 1));
788
6794
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &startp);
789
6794
    _gx_utility_circle_point_get(xcenter, ycenter, r + (UINT)brush_width - 1, start_angle, &endp);
790
791
6794
    if (brush -> gx_brush_style & GX_BRUSH_ROUND)
792
    {
793
6379
        brush -> gx_brush_style &= (ULONG)(~GX_BRUSH_PIXELMAP_FILL);
794
795
6379
        _gx_display_driver_generic_aliased_filled_circle_draw(context,
796
6379
                                                              GX_FIXED_VAL_MAKE(startp.gx_point_x + endp.gx_point_x) >> 1,
797
6379
                                                              GX_FIXED_VAL_MAKE(startp.gx_point_y + endp.gx_point_y) >> 1,
798
6379
                                                              GX_FIXED_VAL_MAKE(brush_width) >> 1);
799
    }
800
    else
801
    {
802
415
        display -> gx_display_driver_anti_aliased_line_draw(context,
803
415
                                                            startp.gx_point_x,
804
415
                                                            startp.gx_point_y,
805
415
                                                            endp.gx_point_x,
806
415
                                                            endp.gx_point_y);
807
    }
808
809
6794
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &startp);
810
6794
    _gx_utility_circle_point_get(xcenter, ycenter, r + (UINT)brush_width - 1, end_angle, &endp);
811
812
6794
    if (brush -> gx_brush_style & GX_BRUSH_ROUND)
813
    {
814
6379
        brush -> gx_brush_style &= (ULONG)(~GX_BRUSH_PIXELMAP_FILL);
815
816
6379
        _gx_display_driver_generic_aliased_filled_circle_draw(context,
817
6379
                                                              GX_FIXED_VAL_MAKE(startp.gx_point_x + endp.gx_point_x) >> 1,
818
6379
                                                              GX_FIXED_VAL_MAKE(startp.gx_point_y + endp.gx_point_y) >> 1,
819
6379
                                                              GX_FIXED_VAL_MAKE(brush_width) >> 1);
820
    }
821
    else
822
    {
823
415
        display -> gx_display_driver_anti_aliased_line_draw(context,
824
415
                                                            startp.gx_point_x,
825
415
                                                            startp.gx_point_y,
826
415
                                                            endp.gx_point_x,
827
415
                                                            endp.gx_point_y);
828
    }
829
830
6794
    brush -> gx_brush_width = (GX_VALUE)brush_width;
831
6794
    brush -> gx_brush_fill_color = old_fill;
832
6794
    brush -> gx_brush_style = old_style;
833
834
#if defined(GX_BRUSH_ALPHA_SUPPORT)
835
6794
    context -> gx_draw_context_brush.gx_brush_alpha = old_alpha;
836
#endif
837
6794
}
838
#endif
839