GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_aliased_arc_draw.c Lines: 66 66 100.0 %
Date: 2026-03-06 19:21:09 Branches: 52 52 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Display Management (Display)                                        */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_system.h"
29
#include "gx_utility.h"
30
#include "gx_display.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_display_driver_generic_aliased_arc_draw         PORTABLE C      */
37
/*                                                           6.1          */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Display driver to draw aliased circle arc.                          */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    xcenter                               x-coord of center of circle   */
49
/*                                            arc                         */
50
/*    ycenter                               y-coord of center of circle   */
51
/*                                            arc                         */
52
/*    r                                     Radius of circle arc          */
53
/*    start_angle                           The start angle of circle arc */
54
/*    end_angle                             The end angle of circle arc   */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    None                                                                */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    _gx_display_driver_arc_clipping_get   Get an arc clipping.          */
63
/*    _gx_utility_rectangle_overlap_detect  Detect two rectangles being   */
64
/*                                            overlap to each other       */
65
/*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
66
/*                                            blend function              */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    GUIX Internal Code                                                  */
71
/*                                                                        */
72
/**************************************************************************/
73
#if defined(GX_ARC_DRAWING_SUPPORT)
74
494
VOID _gx_display_driver_generic_aliased_arc_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
75
{
76
/* The arc draw function is implemented by clipping a circle.
77
   Calculate the arc clipping first, turn on the pixel on circle when the pixel
78
   is inside the arc clipping area.                                             */
79
80
GX_DISPLAY  *display;
81
GX_RECTANGLE arc_clip[4];
82
GX_BRUSH    *brush;
83
INT          x;
84
INT          y;
85
GX_POINT     point;
86
494
INT          sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
87
INT          index;
88
INT          error;
89
INT          realval;
90
GX_UBYTE     alpha1;
91
GX_UBYTE     alpha2;
92
VOID         (*blend_func)(GX_DRAW_CONTEXT *context,
93
                           INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
94
95
#if defined(GX_BRUSH_ALPHA_SUPPORT)
96
GX_UBYTE brush_alpha;
97
98
494
    brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
99
100
494
    if (brush_alpha == 0)
101
    {
102
        /* Nothing to draw here. */
103
143
        return;
104
    }
105
#endif
106
107
352
    display = context -> gx_draw_context_display;
108
352
    blend_func = display -> gx_display_driver_pixel_blend;
109
110
352
    if (blend_func == GX_NULL)
111
    {
112
1
        return;
113
    }
114
115
351
    brush = &context -> gx_draw_context_brush;
116
117
118
    /* Get the clipping rectangles of the circle arc. */
119
351
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle,
120
                                        &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
121
122
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[0], &arc_clip[0]);
123
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[1], &arc_clip[1]);
124
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[2], &arc_clip[2]);
125
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[3], &arc_clip[3]);
126
127
351
    x = 0;
128
351
    y = (INT)r;
129
351
    error = 0;
130
131
    /* Process anti-aliased circle drawing. */
132
17734
    while (x < y)
133
    {
134
86915
        for (index = 0; index < 4; index++)
135
        {
136
69532
            alpha1 = (GX_UBYTE)(255 - error);
137
69532
            alpha2 = (GX_UBYTE)error;
138
#if defined(GX_BRUSH_ALPHA_SUPPORT)
139
69532
            alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
140
69532
            alpha2 = (GX_UBYTE)(alpha2 * brush_alpha / 255);
141
#endif
142
143
69532
            point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
144
69532
            point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
145
146

134080
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
147
126068
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
148
122319
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
149
60799
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
150
            {
151
8803
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
152
            }
153
154
69532
            point.gx_point_y = (GX_VALUE)((y - 1) * sign[index][1] + ycenter);
155
156

133997
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
157
125658
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
158
121507
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
159
60314
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
160
            {
161
9288
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
162
            }
163
164
69532
            point.gx_point_x = (GX_VALUE)(y * sign[index][0] + xcenter);
165
69532
            point.gx_point_y = (GX_VALUE)(x * sign[index][1] + ycenter);
166
167

134687
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
168
127365
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
169
123738
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
170
61528
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
171
            {
172
8108
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
173
            }
174
175
69532
            point.gx_point_x = (GX_VALUE)((y - 1) * sign[index][0] + xcenter);
176
177

134549
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
178
126820
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
179
122773
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
180
60970
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
181
            {
182
8666
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
183
            }
184
        }
185
186
17383
        x++;
187
188
17383
        realval = (INT)(r * r) - x * x;
189
17383
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
190
191
24692
        while (error >= 255)
192
        {
193
7309
            error -= 255;
194
7309
            y--;
195
        }
196
    }
197
198
351
    alpha1 = (GX_UBYTE)(255 - error);
199
#if defined(GX_BRUSH_ALPHA_SUPPORT)
200
351
    alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
201
#endif
202
203
1755
    for (index = 0; index < 4; index++)
204
    {
205
206
1404
        point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
207
1404
        point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
208
209

2472
        if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
210
1980
            _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
211
1803
            _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
212
891
            _gx_utility_rectangle_point_detect(&arc_clip[3], point))
213
        {
214
514
            blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
215
        }
216
    }
217
}
218
#endif
219