GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_aliased_filled_circle_draw.c Lines: 92 92 100.0 %
Date: 2024-12-05 08:52:37 Branches: 53 54 98.1 %

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_display.h"
28
#include "gx_utility.h"
29
30
/**************************************************************************/
31
/*                                                                        */
32
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _gx_display_driver_generic_aliased_filled_circle_draw               */
35
/*                                                        PORTABLE C      */
36
/*                                                           6.1.7        */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Kenneth Maxwell, Microsoft Corporation                              */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    Display driver to draw filled circals with anti-aliased edge.       */
44
/*                                                                        */
45
/*  INPUT                                                                 */
46
/*                                                                        */
47
/*    context                               Drawing context               */
48
/*    xcenter                               x-coord of center of circle   */
49
/*    ycenter                               y-coord of center of circle   */
50
/*    r                                     Radius of circle              */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    [gx_display_driver_pixel_blend]       Driver-level pixel blend      */
59
/*    [gx_display_driver_horizontal_line_draw]                            */
60
/*                                          Driver-level horizontal line  */
61
/*                                            draw function               */
62
/*                                                                        */
63
/*  CALLED BY                                                             */
64
/*                                                                        */
65
/*    _gx_display_driver_generic_aliased_wide_line_draw                   */
66
/*                                                                        */
67
/*  RELEASE HISTORY                                                       */
68
/*                                                                        */
69
/*    DATE              NAME                      DESCRIPTION             */
70
/*                                                                        */
71
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
72
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
73
/*                                            resulting in version 6.1    */
74
/*  06-02-2021     Kenneth Maxwell          Modified comment(s),          */
75
/*                                            removed unused variable     */
76
/*                                            assignment,                 */
77
/*                                            resulting in version 6.1.7  */
78
/*                                                                        */
79
/**************************************************************************/
80
15561
VOID _gx_display_driver_generic_aliased_filled_circle_draw(GX_DRAW_CONTEXT *context, GX_FIXED_VAL xcenter, GX_FIXED_VAL ycenter, GX_FIXED_VAL r)
81
{
82
/* The circle draw function is implemented from midpoint circle algorithm. */
83
84
GX_DISPLAY   *display;
85
GX_RECTANGLE *clip;
86
GX_BRUSH     *brush;
87
INT           x;
88
INT           y;
89
GX_POINT      point;
90
15561
GX_BYTE       ysign[2] = {1, -1};
91
INT           index;
92
INT           error;
93
INT           yi;
94
GX_VALUE      xstart;
95
GX_VALUE      xend;
96
GX_UBYTE      alpha1;
97
GX_FIXED_VAL  xfraction;
98
GX_FIXED_VAL  yfraction;
99
INT           rr;
100
INT           half_shift;
101
VOID          (*blend_func)(GX_DRAW_CONTEXT *context,
102
                            INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
103
104
#if defined(GX_BRUSH_ALPHA_SUPPORT)
105
GX_UBYTE brush_alpha;
106
107
15561
    brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
108
109
15561
    if (brush_alpha == 0)
110
    {
111
        /* Nothing to draw here. */
112
2
        return;
113
    }
114
#endif
115
116
15561
    display = context -> gx_draw_context_display;
117
15561
    clip = context -> gx_draw_context_clip;
118
15561
    brush = &context -> gx_draw_context_brush;
119
120
15561
    blend_func = display -> gx_display_driver_pixel_blend;
121
122
15561
    if (blend_func == GX_NULL)
123
    {
124
2
        return;
125
    }
126
127
15559
    xfraction = (xcenter & GX_FIXED_VAL_FRACTION_MASK);
128
15559
    yfraction = (ycenter & GX_FIXED_VAL_FRACTION_MASK);
129
130
15559
    r -= GX_FIXED_VAL_HALF;
131
132
15559
    if (xfraction)
133
    {
134
3974
        x = GX_FIXED_VAL_ONE - xfraction;
135
    }
136
    else
137
    {
138
11585
        x = 0;
139
    }
140
15559
    y = GX_FIXED_VAL_RND_UP(r + yfraction);
141
15559
    y = GX_FIXED_VAL_MAKE(y) - yfraction;
142
143
15559
    half_shift = (GX_FIXED_VAL_SHIFT >> 1);
144
15559
    rr = (r >> half_shift) * (r >> half_shift);
145
146
66282
    while (x < y)
147
    {
148
55055
        yi = rr - ((x >> half_shift) * (x >> half_shift));
149
150
55055
        error = (INT)_gx_utility_math_sqrt((UINT)yi);
151
55055
        error <<= 8;
152
55055
        error >>= half_shift;
153
55055
        error = GX_FIXED_VAL_TO_INT((y << 8)) - error;
154
155
69603
        while (error >= 255)
156
        {
157
14548
            error -= 255;
158
14548
            y -= GX_FIXED_VAL_ONE;
159
        }
160
161
55055
        if (x > y)
162
        {
163
4332
            break;
164
        }
165
166
50723
        alpha1 = (GX_UBYTE)(255 - error);
167
#if defined(GX_BRUSH_ALPHA_SUPPORT)
168
50723
        alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
169
#endif
170
171
152169
        for (index = 0; index < 2; index++)
172
        {
173
101446
            point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xcenter + x);
174
101446
            point.gx_point_y = (GX_VALUE)GX_FIXED_VAL_TO_INT(ycenter + y * ysign[index]);
175
176
101446
            xend = point.gx_point_x;
177
178
            /* draw pixel(x, y). */
179
101446
            if (_gx_utility_rectangle_point_detect(clip, point))
180
            {
181
99310
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
182
            }
183
184
101446
            point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xcenter - x);
185
186
101446
            xstart = point.gx_point_x;
187
188
101446
            yi = GX_FIXED_VAL_TO_INT(ycenter + (y - GX_FIXED_VAL_ONE) * ysign[index]);
189
190
101446
            if (xstart < clip -> gx_rectangle_left)
191
            {
192
1084
                xstart = clip -> gx_rectangle_left;
193
            }
194
195
101446
            if (xend > clip -> gx_rectangle_right)
196
            {
197
676
                xend = clip -> gx_rectangle_right;
198
            }
199
200
101446
            if (xstart <= xend &&
201
100058
                yi >= clip -> gx_rectangle_top &&
202
99563
                yi <= clip -> gx_rectangle_bottom)
203
            {
204
99394
                display -> gx_display_driver_horizontal_line_draw(context, xstart, xend, yi, 1, brush -> gx_brush_line_color);
205
            }
206
207
101446
            if (x)
208
            {
209
                /* draw pixel(-x, y). */
210
78276
                if (_gx_utility_rectangle_point_detect(clip, point))
211
                {
212
76858
                    blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
213
                }
214
            }
215
        }
216
217
50723
        x += GX_FIXED_VAL_ONE;
218
    }
219
220
15559
    x = GX_FIXED_VAL_RND_UP(r + xfraction);
221
15559
    x = GX_FIXED_VAL_MAKE(x) - xfraction;
222
223
15559
    if (yfraction)
224
    {
225
7086
        y = yfraction;
226
    }
227
    else
228
    {
229
8473
        y = 0;
230
    }
231
232
66369
    while (x > y)
233
    {
234
51856
        yi = rr - ((y >> half_shift) * (y >> half_shift));
235
236
51856
        error = (INT)_gx_utility_math_sqrt((UINT)yi);
237
51856
        error <<= 8;
238
51856
        error >>= half_shift;
239
51856
        error = GX_FIXED_VAL_TO_INT((x << 8)) - error;
240
241
66516
        while (error >= 255)
242
        {
243
14660
            error -= 255;
244
14660
            x -= GX_FIXED_VAL_ONE;
245
        }
246
247
51856
        if (x < y)
248
        {
249
1046
            break;
250
        }
251
252
50810
        alpha1 = (GX_UBYTE)(255 - error);
253
#if defined(GX_BRUSH_ALPHA_SUPPORT)
254
50810
        alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
255
#endif
256
257
152430
        for (index = 0; index < 2; index++)
258
        {
259
101620
            point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xcenter + x);
260
101620
            point.gx_point_y = (GX_VALUE)GX_FIXED_VAL_TO_INT(ycenter + y * ysign[index]);
261
262
101620
            xend = (GX_VALUE)(point.gx_point_x - 1);
263
264
            /* draw pixel(x, y). */
265
101620
            if (_gx_utility_rectangle_point_detect(clip, point))
266
            {
267
99486
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
268
            }
269
270
271
101620
            point.gx_point_x = (GX_VALUE)GX_FIXED_VAL_TO_INT(xcenter - x);
272
101620
            xstart = (GX_VALUE)(point.gx_point_x + 1);
273
274
101620
            if (xstart < clip -> gx_rectangle_left)
275
            {
276
1172
                xstart = clip -> gx_rectangle_left;
277
            }
278
279
101620
            if (xend > clip -> gx_rectangle_right)
280
            {
281
700
                xend = clip -> gx_rectangle_right;
282
            }
283
284
101620
            if (xstart <= xend &&
285
99450
                point.gx_point_y >= clip -> gx_rectangle_top &&
286
99073
                point.gx_point_y <= clip -> gx_rectangle_bottom)
287
            {
288
98912
                display -> gx_display_driver_horizontal_line_draw(context, xstart, xend, point.gx_point_y, 1, brush -> gx_brush_line_color);
289
            }
290
291
            /* draw pixel(-x, y). */
292
101620
            if (_gx_utility_rectangle_point_detect(clip, point))
293
            {
294
99614
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
295
            }
296
        }
297
298
50810
        y += GX_FIXED_VAL_ONE;
299
    }
300
}
301