GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_ellipse_fill.c Lines: 119 119 100.0 %
Date: 2026-03-06 19:21:09 Branches: 70 70 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_system.h"
30
#include "gx_display.h"
31
32
#if defined(GX_ARC_DRAWING_SUPPORT)
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_display_driver_generic_rotated_ellipse_fill     PORTABLE C      */
39
/*                                                           6.1.6        */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Kenneth Maxwell, Microsoft Corporation                              */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    Display driver to draw a filled ellipse.                            */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    context                               Drawing context               */
51
/*    xcenter                               x-coord of center of ellipse  */
52
/*    ycenter                               y-coord of center of ellipse  */
53
/*    a                                     Length of the Semi-major Axis */
54
/*    b                                     Length of the Semi-minor Axis */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    None                                                                */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    [gx_display_driver_horizontal_line_draw]                            */
63
/*                                          Basic display driver          */
64
/*                                            horizontal line draw routine*/
65
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
66
/*                                          Basic display driver          */
67
/*                                            horizontal pixelmap line    */
68
/*                                            draw function               */
69
/*                                                                        */
70
/*  CALLED BY                                                             */
71
/*                                                                        */
72
/*    GUIX Internal Code                                                  */
73
/*                                                                        */
74
/**************************************************************************/
75
86
VOID _gx_display_driver_generic_rotated_ellipse_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, INT a, INT b)
76
{
77
/* The ellipse fill function follows Bresenham ellipse algorithm while
78
   connecting the two point that symmetric with respect to y-axis. */
79
80
GX_DISPLAY           *display;
81
GX_RECTANGLE         *clip;
82
GX_BRUSH             *brush;
83
INT                   x1;
84
INT                   x;
85
INT                   y;
86
INT                   y0;
87
INT                   y1;
88
86
INT                   sign[2] = {1, -1};
89
INT                  *pLineEnds;
90
INT                   index;
91
INT                   width;
92
INT                   Index;
93
INT                   aa;
94
INT                   bb;
95
INT                   ypos;
96
INT                   xmin;
97
INT                   xmax;
98
INT                   skip_line;
99
86
GX_PIXELMAP          *pixelmap = GX_NULL;
100
GX_COLOR              fill_color;
101
GX_FILL_PIXELMAP_INFO info;
102
GX_BYTE               xsign;
103
INT                   error;
104
INT                   realval;
105
GX_BOOL               record;
106
107
86
    display = context -> gx_draw_context_display;
108
86
    clip = context -> gx_draw_context_clip;
109
86
    brush = &context -> gx_draw_context_brush;
110
111
86
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
112
    {
113
68
        if (brush -> gx_brush_pixelmap == GX_NULL)
114
        {
115
            /* Nothing should be drawn if pixelmap isn't set with GX_BRUSH_PIXELMAP_FILL style. */
116
2
            return;
117
        }
118
119
67
        pixelmap = brush -> gx_brush_pixelmap;
120
121
67
        if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
122
        {
123
            /* Display driver only support its native format pixelmap.*/
124
            /* Nothing should be drawn if pixelmap format isn't support. */
125
1
            return;
126
        }
127
128
66
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
129
130
66
        info.pixelmap = brush -> gx_brush_pixelmap;
131
66
        info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
132
133
66
        if (pixelmap -> gx_pixelmap_aux_data_size)
134
        {
135
24
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
136
        }
137
    }
138
139
84
    xmin = xcenter - a;
140
84
    xmax = xcenter + a;
141
142
    /* Calculate minimum y line. */
143
84
    if (clip -> gx_rectangle_left > xmin)
144
    {
145
2
        xmin = clip -> gx_rectangle_left;
146
    }
147
148
    /* Calculate maximum y line. */
149
84
    if (clip -> gx_rectangle_right < xmax)
150
    {
151
4
        xmax = clip -> gx_rectangle_right;
152
    }
153
154
84
    width = (xmax - xmin + 1);
155
84
    pLineEnds = _gx_system_scratchpad;
156
157
    /* default the point array to being off the screen on both sides: */
158
26288
    for (Index = 0; Index < width * 2; Index += 2)
159
    {
160
26204
        pLineEnds[Index] = 2000;
161
26204
        pLineEnds[Index + 1] = 0;
162
    }
163
164
84
    aa = a * a;
165
84
    bb = b * b;
166
84
    x = 0;
167
84
    y = b;
168
84
    error = 0;
169
170
    /* Region I of the first quarter of the ellipse.  */
171
11290
    while (2 * bb * (x + 1) < aa * (2 * y - 1))
172
    {
173
        /* calculate error of next pixel. */
174
11208
        realval = bb - bb * (x + 1) * (x + 1) / aa;
175
11208
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
176
177
11208
        if (error >= 510)
178
        {
179
            /* The slope in point(x + 1, y) is greater than -1,
180
               make point(x, y) the delimit pixel, break here. */
181
2
            realval = bb - bb * x * x / aa;
182
2
            error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
183
2
            break;
184
        }
185
186
11206
        y0 = ycenter - (y - 1);
187
11206
        y1 = ycenter + (y - 1);
188
189
11206
        if (y0 < clip -> gx_rectangle_top)
190
        {
191
62
            y0 = clip -> gx_rectangle_top;
192
        }
193
194
11206
        if (y1 > clip -> gx_rectangle_bottom)
195
        {
196
62
            y1 = clip -> gx_rectangle_bottom;
197
        }
198
199
33618
        for (index = 0; index < 2; index++)
200
        {
201
22412
            x1 = x * sign[index] + xcenter;
202
203

22412
            if ((x1 >= xmin) && (x1 <= xmax))
204
            {
205
22058
                Index = (x1 - xmin) << 1;
206
22058
                pLineEnds[Index] = y0;
207
22058
                pLineEnds[Index + 1] = y1;
208
            }
209
        }
210
211
11206
        if (error >= 255)
212
        {
213
3812
            y--;
214
        }
215
216
11206
        x++;
217
    }
218
219
84
    record = GX_TRUE;
220
221
84
    y0 = ycenter - y;
222
84
    y1 = ycenter + y;
223
224
84
    if (y0 < clip -> gx_rectangle_top)
225
    {
226
2
        y0 = clip -> gx_rectangle_top;
227
    }
228
229
84
    if (y1 > clip -> gx_rectangle_bottom)
230
    {
231
2
        y1 = clip -> gx_rectangle_bottom;
232
    }
233
234
252
    for (index = 0; index < 2; index++)
235
    {
236
168
        x1 = x * sign[index] + xcenter;
237
238

168
        if ((x1 >= xmin) && (x1 <= xmax))
239
        {
240
164
            Index = (x1 - xmin) << 1;
241
164
            pLineEnds[Index] = y0;
242
164
            pLineEnds[Index + 1] = y1;
243
        }
244
    }
245
246
    /* Region II of the first quarter of the ellipse.  */
247
4922
    while (y > 0)
248
    {
249
4838
        y--;
250
251
4838
        realval = aa - aa * y * y / bb;
252
4838
        error = (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3) - (x << 8);
253
254
6902
        while (error >= 255)
255
        {
256
2064
            error -= 255;
257
2064
            x++;
258
259
2064
            record = GX_TRUE;
260
        }
261
262
4838
        if (record)
263
        {
264
2148
            record = GX_FALSE;
265
266
2148
            y0 = ycenter - y;
267
2148
            y1 = ycenter + y;
268
269
2148
            if (y0 < clip -> gx_rectangle_top)
270
            {
271
74
                y0 = clip -> gx_rectangle_top;
272
            }
273
274
2148
            if (y1 > clip -> gx_rectangle_bottom)
275
            {
276
104
                y1 = clip -> gx_rectangle_bottom;
277
            }
278
279
6444
            for (index = 0; index < 2; index++)
280
            {
281
4296
                x1 = x * sign[index] + xcenter;
282
283

4296
                if ((x1 >= xmin) && (x1 <= xmax))
284
                {
285
4230
                    Index = (x1 - xmin) << 1;
286
4230
                    pLineEnds[Index] = y0;
287
4230
                    pLineEnds[Index + 1] = y1;
288
                }
289
            }
290
        }
291
    }
292
293
84
    if (pixelmap != GX_NULL)
294
    {
295
66
        if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
296
        {
297
38
            skip_line = (xmax - (xcenter - a) + 1) % pixelmap -> gx_pixelmap_width;
298
299
38
            if (skip_line)
300
            {
301
37
                skip_line = pixelmap -> gx_pixelmap_width - skip_line;
302
            }
303
304
38
            x1 = xmax;
305
38
            xsign = -1;
306
38
            Index = (width - 1) * 2;
307
        }
308
        else
309
        {
310
28
            skip_line = (xmin - clip -> gx_rectangle_left);
311
312
28
            x1 = xmin;
313
28
            xsign = 1;
314
28
            Index = 0;
315
        }
316
317
66
        if (skip_line)
318
        {
319
65
            info.draw = GX_FALSE;
320
2891
            while (skip_line--)
321
            {
322
2826
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
323
            }
324
        }
325
326
66
        info.draw = GX_TRUE;
327
66
        ypos = ycenter - b;
328
329
20872
        for (x = xmin; x <= xmax; x++)
330
        {
331
20806
            info.x_offset = pLineEnds[Index] - ypos;
332
20806
            display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], x1, &info);
333
334
20806
            x1 += xsign;
335
20806
            Index += xsign;
336
20806
            Index += xsign;
337
        }
338
    }
339
    else
340
    {
341
18
        Index = 0;
342
18
        fill_color = brush -> gx_brush_fill_color;
343
344
5416
        for (x = xmin; x <= xmax; x++)
345
        {
346
5398
            display -> gx_display_driver_vertical_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], x, 1, fill_color);
347
5398
            Index += 2;
348
        }
349
    }
350
}
351
#endif
352