GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_aliased_ellipse_draw.c Lines: 65 65 100.0 %
Date: 2024-12-05 08:52:37 Branches: 30 30 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_utility.h"
28
#include "gx_display.h"
29
30
/**************************************************************************/
31
/*                                                                        */
32
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _gx_display_driver_generic_aliased_ellipse_draw     PORTABLE C      */
35
/*                                                           6.1          */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Kenneth Maxwell, Microsoft Corporation                              */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    Display driver to draw anti-alised ellipse.                         */
43
/*                                                                        */
44
/*  INPUT                                                                 */
45
/*                                                                        */
46
/*    context                               Drawing context               */
47
/*    xcenter                               x-coord of center of ellipse  */
48
/*    ycenter                               y-coord of center of ellipse  */
49
/*    a                                     Length of the Semi-major Axis */
50
/*    b                                     Length of the Semi-minor Axis */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _gx_utility_rectangle_overlap_detect  Detect two rectangles being   */
59
/*                                            overlap to each other       */
60
/*    _gx_utility_math_sqrt                 Compute the square root value */
61
/*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
62
/*                                            blend function              */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    GUIX Internal Code                                                  */
67
/*                                                                        */
68
/*  RELEASE HISTORY                                                       */
69
/*                                                                        */
70
/*    DATE              NAME                      DESCRIPTION             */
71
/*                                                                        */
72
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
73
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
74
/*                                            resulting in version 6.1    */
75
/*                                                                        */
76
/**************************************************************************/
77
395
VOID _gx_display_driver_generic_aliased_ellipse_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, INT a, INT b)
78
{
79
/* The ellipse draw function is implemented from midpoint ellipse algorithm. */
80
81
GX_DISPLAY   *display;
82
GX_RECTANGLE *clip;
83
GX_BRUSH     *brush;
84
INT           x;
85
INT           y;
86
GX_POINT      point;
87
395
INT           sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
88
INT           index;
89
INT           aa;
90
INT           bb;
91
INT           realval;
92
INT           error;
93
GX_UBYTE      alpha1;
94
GX_UBYTE      alpha2;
95
96
VOID          (*blend_func)(GX_DRAW_CONTEXT *context,
97
                            INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
98
99
#if defined(GX_BRUSH_ALPHA_SUPPORT)
100
GX_UBYTE brush_alpha;
101
102
395
    brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
103
104
395
    if (brush_alpha == 0)
105
    {
106
        /* Nothing to draw here. */
107
128
        return;
108
    }
109
#endif
110
111
268
    display = context -> gx_draw_context_display;
112
268
    clip = context -> gx_draw_context_clip;
113
268
    brush = &context -> gx_draw_context_brush;
114
115
268
    blend_func = display -> gx_display_driver_pixel_blend;
116
117
268
    if (blend_func == GX_NULL)
118
    {
119
1
        return;
120
    }
121
122
267
    aa = a * a;
123
267
    bb = b * b;
124
267
    x = 0;
125
267
    y = b;
126
267
    error = 0;
127
128
    /* Region I of the first quarter of the ellipse.  */
129
16661
    while (2 * bb * (x + 1) < aa * (2 * y - 1))
130
    {
131
16411
        alpha1 = (GX_UBYTE)(255 - error);
132
16411
        alpha2 = (GX_UBYTE)error;
133
#if defined(GX_BRUSH_ALPHA_SUPPORT)
134
16411
        alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
135
16411
        alpha2 = (GX_UBYTE)(alpha2 * brush_alpha / 255);
136
#endif
137
        /* calculate error of next pixel. */
138
16411
        realval = bb - bb * (x + 1) * (x + 1) / aa;
139
16411
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
140
141
16411
        if (error >= 510)
142
        {
143
            /* The slope in point(x + 1, y) is greater than -1,
144
               make point(x, y) the delimit pixel, break here. */
145
17
            realval = bb - bb * x * x / aa;
146
17
            error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
147
17
            break;
148
        }
149
150
81970
        for (index = 0; index < 4; index++)
151
        {
152
65576
            point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
153
65576
            point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
154
155
65576
            if (_gx_utility_rectangle_point_detect(clip, point))
156
            {
157
64504
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
158
            }
159
160
65576
            point.gx_point_y = (GX_VALUE)((y - 1) * sign[index][1] + ycenter);
161
162
65576
            if (_gx_utility_rectangle_point_detect(clip, point))
163
            {
164
64504
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
165
            }
166
        }
167
168
16394
        if (error >= 255)
169
        {
170
2742
            error -= 255;
171
2742
            y--;
172
        }
173
174
16394
        x++;
175
    }
176
177
267
    alpha1 = (GX_UBYTE)(255 - error);
178
#if defined(GX_BRUSH_ALPHA_SUPPORT)
179
267
    alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
180
#endif
181
182
    /* Draw delimit pixel where delta x equals to delta y.  */
183
1335
    for (index = 0; index < 4; index++)
184
    {
185
1068
        point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
186
1068
        point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
187
188
1068
        if (_gx_utility_rectangle_point_detect(clip, point))
189
        {
190
1016
            blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
191
        }
192
    }
193
194
    /* Region II of the first quarter of the ellipse.  */
195
17925
    while (y > 0)
196
    {
197
17658
        y--;
198
199
17658
        realval = aa - aa * y * y / bb;
200
17658
        error = (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3) - (x << 8);
201
202
20528
        while (error >= 255)
203
        {
204
2870
            error -= 255;
205
2870
            x++;
206
        }
207
17658
        alpha1 = (GX_UBYTE)(255 - error);
208
17658
        alpha2 = (GX_UBYTE)error;
209
#if defined(GX_BRUSH_ALPHA_SUPPORT)
210
17658
        alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
211
17658
        alpha2 = (GX_UBYTE)(alpha2 * brush_alpha / 255);
212
#endif
213
214
88290
        for (index = 0; index < 4; index++)
215
        {
216
70632
            point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
217
70632
            point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
218
219
220
70632
            if (_gx_utility_rectangle_point_detect(clip, point))
221
            {
222
63100
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
223
            }
224
225
70632
            point.gx_point_x = (GX_VALUE)((x + 1) * sign[index][0] + xcenter);
226
227
70632
            if (_gx_utility_rectangle_point_detect(clip, point))
228
            {
229
62984
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
230
            }
231
        }
232
    }
233
}
234