GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_wide_ellipse_draw.c Lines: 108 108 100.0 %
Date: 2026-03-06 19:21:09 Branches: 80 80 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_utility.h"
29
#include "gx_display.h"
30
#include "gx_system.h"
31
32
#if defined(GX_ARC_DRAWING_SUPPORT)
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_display_driver_generic_wide_ellipse_draw        PORTABLE C      */
38
/*                                                           6.1          */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    Display driver function to draw ellipse with wide outline.          */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    context                               Drawing context               */
50
/*    xcenter                               x-coord of center of ellipse  */
51
/*    ycenter                               y-coord of center of ellipse  */
52
/*    a                                     Length of the Semi-major Axis */
53
/*    b                                     Length of the Semi-minor Axis */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    None                                                                */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    [gx_display_driver_horizontal_line_draw]                            */
62
/*                                          The display driver horizontal */
63
/*                                            line drawing function       */
64
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    GUIX Internal Code                                                  */
68
/*                                                                        */
69
/**************************************************************************/
70
775
VOID _gx_display_driver_generic_wide_ellipse_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, INT a, INT b)
71
{
72
/* The ellipse draw function is implemented from midpoint ellipse algorithm. */
73
74
GX_DISPLAY   *display;
75
GX_RECTANGLE *clip;
76
GX_BRUSH     *brush;
77
INT           brush_width;
78
INT           x;
79
INT           x2;
80
INT           y;
81
INT           y2;
82
INT           d;
83
775
INT           sign[2] = {1, -1};
84
INT           index;
85
INT           aa;
86
INT           bb;
87
INT          *pLineEnds;
88
INT           ymin;
89
INT           ymax;
90
INT           height;
91
INT           loop;
92
93
#if defined(GX_BRUSH_ALPHA_SUPPORT)
94
GX_UBYTE old_alpha;
95
775
    old_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
96
775
    context -> gx_draw_context_brush.gx_brush_alpha = GX_ALPHA_VALUE_OPAQUE;
97
#endif
98
775
    display = context -> gx_draw_context_display;
99
775
    clip = context -> gx_draw_context_clip;
100
775
    brush = &context -> gx_draw_context_brush;
101
775
    brush_width = brush -> gx_brush_width;
102
103
775
    if ((a <= ((brush_width - 1) >> 1)) ||
104
695
        (b <= ((brush_width - 1) >> 1)))
105
    {
106
81
        return;
107
    }
108
109
694
    pLineEnds = _gx_system_scratchpad;
110
111
694
    ymin = ycenter - b - (brush_width >> 1);
112
694
    ymax = ycenter + b + (brush_width >> 1);
113
114
694
    if (ymin < clip -> gx_rectangle_top)
115
    {
116
20
        ymin = clip -> gx_rectangle_top;
117
    }
118
119
694
    if (ymax > clip -> gx_rectangle_bottom)
120
    {
121
3
        ymax = clip -> gx_rectangle_bottom;
122
    }
123
124
694
    height = ymax - ymin + 1;
125
126
142700
    for (y = 0; y <= height * 2; y += 2)
127
    {
128
142006
        pLineEnds[y] = 2000;
129
142006
        pLineEnds[y + 1] = 0;
130
    }
131
132
694
    y2 = ycenter - b - (brush_width >> 1);
133
8058
    for (y = y2; y < y2 + brush_width; y++)
134
    {
135

7364
        if ((y >= ymin) && (y <= ymax))
136
        {
137
7211
            pLineEnds[(y - ymin) << 1] = 0;
138
        }
139
    }
140
141
694
    y2 = ycenter + b - ((brush_width - 1) >> 1);
142
8058
    for (y = y2; y < y2 + brush_width; y++)
143
    {
144

7364
        if ((y >= ymin) && (y <= ymax))
145
        {
146
7330
            pLineEnds[(y - ymin) << 1] = 0;
147
        }
148
    }
149
150
694
    a -= ((brush_width - 1) >> 1);
151
694
    b -= ((brush_width - 1) >> 1);
152
153
694
    aa = a * a;
154
694
    bb = b * b;
155
694
    x = 0;
156
694
    y = b;
157
694
    d = (bb << 2) + aa * (1 - (b << 1));
158
159
    /* Region I of the first quarter of the inner ellipse.  */
160
49747
    while ((bb << 1) * (x + 1) < aa * (2 * y - 1))
161
    {
162
147159
        for (loop = 0; loop < 2; loop++)
163
        {
164
98106
            y2 = y * sign[loop] + ycenter;
165
166

98106
            if ((y2 >= ymin) && (y2 <= ymax))
167
            {
168
97734
                index = (y2 - ymin) << 1;
169
170
97734
                if (x < pLineEnds[index])
171
                {
172
32405
                    pLineEnds[index] = x;
173
                }
174
            }
175
        }
176
177
49053
        if (d < 0)
178
        {
179
32169
            d += (bb << 1) * ((x << 1) + 3);
180
        }
181
        else
182
        {
183
16884
            d += (bb << 1) * ((x << 1) + 3) + (aa << 2) * (1 - y);
184
16884
            y--;
185
        }
186
49053
        x++;
187
    }
188
189
694
    d = bb * x * (x + 1) + aa * y * (y - 1) - aa * bb;
190
191
    /* Region II of the first quarter of the inner ellipse.  */
192
48732
    while (y >= 0)
193
    {
194
144114
        for (loop = 0; loop < 2; loop++)
195
        {
196
96076
            y2 = y * sign[loop] + ycenter;
197
198

96076
            if ((y2 >= ymin) && (y2 <= ymax))
199
            {
200
95224
                index = (y2 - ymin) << 1;
201
202
95224
                if (x < pLineEnds[index])
203
                {
204
94366
                    pLineEnds[index] = x;
205
                }
206
            }
207
        }
208
209
48038
        if (d < 0)
210
        {
211
15085
            d += (bb << 1) * (x + 1) + aa * (3 - (y << 1));
212
15085
            x++;
213
        }
214
        else
215
        {
216
32953
            d += aa * (3 - (y << 1));
217
        }
218
48038
        y--;
219
    }
220
221
694
    a += brush_width - 1;
222
694
    b += brush_width - 1;
223
694
    aa = a * a;
224
694
    bb = b * b;
225
694
    x = 0;
226
694
    y = b;
227
694
    d = (bb << 2) + (aa << 2) * (1 - b);
228
229
    /* Region I of the first quarter of the outer ellipse.  */
230
54006
    while ((bb << 1) * (x + 1) < aa * (2 * y - 1))
231
    {
232
159936
        for (loop = 0; loop < 2; loop++)
233
        {
234
106624
            y2 = y * sign[loop] + ycenter;
235
236

106624
            if ((y2 >= ymin) && (y2 <= ymax))
237
            {
238
105713
                index = (y2 - ymin) << 1;
239
240
105713
                if (x > pLineEnds[index + 1])
241
                {
242
104388
                    pLineEnds[index + 1] = x;
243
                }
244
            }
245
        }
246
247
53312
        if (d < 0)
248
        {
249
34404
            d += bb * ((x << 3) + 12);
250
        }
251
        else
252
        {
253
18908
            d += bb * ((x << 3) + 12) + (aa << 3) * (1 - y);
254
18908
            y--;
255
        }
256
53312
        x++;
257
    }
258
259
694
    d = (b << 1) * ((x << 1) + 1) + (a << 1) * (y - 1) - (a << 1) * b;
260
261
    /* Region II of the first quarter of the outer ellipse.  */
262
53378
    while (y >= 0)
263
    {
264
158052
        for (loop = 0; loop < 2; loop++)
265
        {
266
105368
            y2 = y * sign[loop] + ycenter;
267
268

105368
            if ((y2 >= ymin) && (y2 <= ymax))
269
            {
270
104457
                index = (y2 - ymin) << 1;
271
272
104457
                if (x > pLineEnds[index + 1])
273
                {
274
103685
                    pLineEnds[index + 1] = x;
275
                }
276
            }
277
        }
278
279
52684
        if (d < 0)
280
        {
281
17869
            x++;
282
17869
            d += (bb << 1) * (x + 1) - aa * (1 + (y << 1));
283
        }
284
        else
285
        {
286
34815
            d += aa * (-1 - (y << 1));
287
        }
288
52684
        y--;
289
    }
290
291
    /* Filling outlines with horizontal line. */
292
694
    index = 0;
293
142006
    for (y = ymin; y <= ymax; y++)
294
    {
295
423936
        for (loop = 0; loop < 2; loop++)
296
        {
297
282624
            x = pLineEnds[index] * sign[loop] + xcenter;
298
282624
            x2 = pLineEnds[index + 1] * sign[loop] + xcenter;
299
300
282624
            if (loop)
301
            {
302
141312
                GX_SWAP_VALS(x, x2);
303
            }
304
305
282624
            if (x < clip -> gx_rectangle_left)
306
            {
307
6014
                x = clip -> gx_rectangle_left;
308
            }
309
310
282624
            if (x2 > clip -> gx_rectangle_right)
311
            {
312
8635
                x2 = clip -> gx_rectangle_right;
313
            }
314
315
282624
            display -> gx_display_driver_horizontal_line_draw(context, x, x2, y, 1,
316
                                                              brush -> gx_brush_line_color);
317
        }
318
319
141312
        index += 2;
320
    }
321
#if defined(GX_BRUSH_ALPHA_SUPPORT)
322
694
    context -> gx_draw_context_brush.gx_brush_alpha = old_alpha;
323
#endif
324
}
325
#endif
326