GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_aliased_wide_circle_draw.c Lines: 86 86 100.0 %
Date: 2026-03-06 19:21:09 Branches: 54 54 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_wide_circle_draw PORTABLE C      */
37
/*                                                           6.1.7        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Display driver function to draw anti-aliased circle with            */
45
/*    specified outline width.                                            */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    context                               Drawing context               */
50
/*    xcenter                               x-coord of center of circle   */
51
/*    ycenter                               y-coord of center of circle   */
52
/*    r                                     Radius of circle              */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    None                                                                */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
61
/*                                            blend function              */
62
/*    _gx_utility_rectangle_point_detect    Detect whether a pixel is     */
63
/*                                            inside rectangle            */
64
/*    [gx_display_driver_horizontal_line_draw]                            */
65
/*                                          Basic display driver          */
66
/*                                            horizontal line draw routine*/
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    GUIX Internal Code                                                  */
71
/*                                                                        */
72
/**************************************************************************/
73
#if defined(GX_ARC_DRAWING_SUPPORT)
74
4049
VOID _gx_display_driver_generic_aliased_wide_circle_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r)
75
{
76
/* The circle draw function is implemented from midpoint circle algorithm. */
77
78
GX_DISPLAY   *display;
79
GX_RECTANGLE *clip;
80
GX_BRUSH     *brush;
81
INT           brush_width;
82
4049
INT           x = 0;
83
INT           x2;
84
INT           y;
85
INT           y2;
86
GX_POINT      point;
87
4049
INT           sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
88
INT           index;
89
4049
INT           error = 0;
90
INT           loop;
91
INT          *pLineEnds;
92
INT           ymin;
93
INT           ymax;
94
INT           height;
95
GX_UBYTE      alpha1;
96
GX_UBYTE      alpha2;
97
VOID          (*blend_func)(GX_DRAW_CONTEXT *context,
98
                            INT x, INT y, GX_COLOR color, GX_UBYTE error);
99
100
#if defined(GX_BRUSH_ALPHA_SUPPORT)
101
GX_UBYTE temp_alpha;
102
4049
    temp_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
103
4049
    context -> gx_draw_context_brush.gx_brush_alpha = GX_ALPHA_VALUE_OPAQUE;
104
#endif
105
106
4049
    display = context -> gx_draw_context_display;
107
4049
    clip = context -> gx_draw_context_clip;
108
4049
    brush = &context -> gx_draw_context_brush;
109
4049
    brush_width = brush -> gx_brush_width;
110
111
4049
    if (r <= (UINT)((brush_width - 1) >> 1))
112
    {
113
199
        return;
114
    }
115
116
3851
    blend_func = display -> gx_display_driver_pixel_blend;
117
118
3851
    if (blend_func == GX_NULL)
119
    {
120
1
        return;
121
    }
122
123
3850
    ymin = ycenter - (INT)r - (brush_width >> 1);
124
3850
    ymax = ycenter + (INT)r + (brush_width >> 1);
125
126
3850
    if (ymin < clip -> gx_rectangle_top)
127
    {
128
165
        ymin = clip -> gx_rectangle_top;
129
    }
130
131
3850
    if (ymax > clip -> gx_rectangle_bottom)
132
    {
133
243
        ymax = clip -> gx_rectangle_bottom;
134
    }
135
136
3850
    height = ymax - ymin + 1;
137
3850
    pLineEnds = _gx_system_scratchpad;
138
139
486687
    for (y = 0; y <= height * 2; y += 2)
140
    {
141
482837
        pLineEnds[y] = 0;
142
482837
        pLineEnds[y + 1] = 0;
143
    }
144
145
    /* loop = 0: draw inner circle, and save the point array.
146
       loop = 1: draw outer circle, and save the point array.  */
147
11550
    for (loop = 0; loop < 2; loop++)
148
    {
149
7700
        if (loop == 0)
150
        {
151
            /* Calculate the inner circle radius.  */
152
3850
            r = (UINT)(r - (UINT)((brush_width - 1) >> 1));
153
        }
154
        else
155
        {
156
            /* Calculate the outer circle radious.  */
157
3850
            r += (UINT)(brush_width - 1);
158
        }
159
160
7700
        x = 0;
161
7700
        y = (INT)r;
162
7700
        error = 0;
163
164
326873
        while (x < y)
165
        {
166
167
957519
            for (index = 0; index < 2; index++)
168
            {
169
638346
                x2 = y;
170
638346
                y2 = x * sign[index][0] + ycenter;
171
172

638346
                if ((y2 >= ymin) && (y2 <= ymax))
173
                {
174
638300
                    pLineEnds[((y2 - ymin) << 1) + loop] = x2 - loop;
175
                }
176
            }
177
178
319173
            alpha1 = (GX_UBYTE)(255 - error);
179
319173
            alpha2 = (GX_UBYTE)error;
180
181
1595865
            for (index = 0; index < 4; index++)
182
            {
183
1276692
                point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
184
1276692
                point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
185
186
1276692
                if (_gx_utility_rectangle_point_detect(clip, point))
187
                {
188
                    /* Draw point(x, y).  */
189
1181152
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
190
                }
191
192
1276692
                point.gx_point_y = (GX_VALUE)((y - 1) * sign[index][1] + ycenter);
193
194
1276692
                if (_gx_utility_rectangle_point_detect(clip, point))
195
                {
196
                    /* Draw point(x, y - 1). */
197
1188240
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, (GX_UBYTE)alpha2);
198
                }
199
200
1276692
                point.gx_point_x = (GX_VALUE)(y * sign[index][0] + xcenter);
201
1276692
                point.gx_point_y = (GX_VALUE)(x * sign[index][1] + ycenter);
202
203
1276692
                if (_gx_utility_rectangle_point_detect(clip, point))
204
                {
205
                    /* Draw point (y, x). */
206
1149504
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
207
                }
208
209
1276692
                point.gx_point_x = (GX_VALUE)((y - 1) * sign[index][0] + xcenter);
210
211
1276692
                if (_gx_utility_rectangle_point_detect(clip, point))
212
                {
213
                    /* Draw point (y - 1, x. )*/
214
1154196
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
215
                }
216
            }
217
218
319173
            x++;
219
220
319173
            y2 = (INT)(r * r) - x * x;
221
222
            /* error is the distance from mathmatical point to
223
               drawing point, which is used to determin alpha value.  */
224
319173
            error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(y2 << 10)) << 3);
225
226
449683
            while (error >= 255)
227
            {
228
130510
                error -= 255;
229
130510
                y--;
230
231
391530
                for (index = 0; index < 2; index++)
232
                {
233
261020
                    x2 = x;
234
261020
                    y2 = y * sign[index][0] + ycenter;
235
236

261020
                    if ((y2 >= ymin) && (y2 <= ymax))
237
                    {
238
249988
                        pLineEnds[((y2 - ymin) << 1) + loop] = x2 - loop;
239
                    }
240
                }
241
            }
242
        }
243
    }
244
245
19250
    for (index = 0; index < 4; index++)
246
    {
247
15400
        point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
248
15400
        point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
249
250
15400
        if (_gx_utility_rectangle_point_detect(clip, point))
251
        {
252
15396
            blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, (GX_UBYTE)(255 - error));
253
        }
254
    }
255
256
3850
    index = 0;
257
258
    /* Filling outlines with horizontal line. */
259
482837
    for (y = ymin; y <= ymax; y++)
260
    {
261
1436961
        for (loop = 0; loop < 2; loop++)
262
        {
263
957974
            x = pLineEnds[index] * sign[loop][0] + xcenter;
264
957974
            x2 = pLineEnds[index + 1] * sign[loop][0] + xcenter;
265
266
957974
            if (x > x2)
267
            {
268
444575
                GX_SWAP_VALS(x, x2);
269
            }
270
271
957974
            if (x < clip -> gx_rectangle_left)
272
            {
273
38232
                x = clip -> gx_rectangle_left;
274
            }
275
276
957974
            if (x2 > clip -> gx_rectangle_right)
277
            {
278
36180
                x2 = clip -> gx_rectangle_right;
279
            }
280
281
957974
            display -> gx_display_driver_horizontal_line_draw(context, x, x2, y, 1,
282
                                                              brush -> gx_brush_line_color);
283
        }
284
478987
        index += 2;
285
    }
286
287
#if defined(GX_BRUSH_ALPHA_SUPPORT)
288
3850
    context -> gx_draw_context_brush.gx_brush_alpha = temp_alpha;
289
#endif
290
}
291
#endif
292