GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_ellipse_fill.c Lines: 102 102 100.0 %
Date: 2026-03-06 19:21:09 Branches: 64 64 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_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
2319
VOID _gx_display_driver_generic_ellipse_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, INT a, INT b)
76
{
77
/* The ellipse fill function follows midpoint 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                   x0;
84
INT                   x1;
85
INT                   x;
86
INT                   y;
87
INT                   y1;
88
2319
INT                   sign[2] = {1, -1};
89
INT                  *pLineEnds;
90
INT                   index;
91
INT                   height;
92
INT                   Index;
93
INT                   aa;
94
INT                   bb;
95
INT                   xpos;
96
INT                   ymin;
97
INT                   ymax;
98
INT                   skip_line;
99
2319
GX_PIXELMAP          *pixelmap = GX_NULL;
100
GX_VALUE              format;
101
GX_COLOR              fill_color;
102
GX_FILL_PIXELMAP_INFO info;
103
INT                   error;
104
INT                   realval;
105
106
107
2319
    display = context -> gx_draw_context_display;
108
2319
    clip = context -> gx_draw_context_clip;
109
2319
    brush = &context -> gx_draw_context_brush;
110
111
2319
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
112
    {
113
        /* Pick up pixelmap. */
114
1758
        pixelmap = brush -> gx_brush_pixelmap;
115
1758
        if (pixelmap == GX_NULL)
116
        {
117
            /* Nothing should be drawn if pixelmap isn't set with GX_BRUSH_PIXELMAP_FILL style. */
118
8
            return;
119
        }
120
1756
        if (pixelmap -> gx_pixelmap_height <= 0 ||
121
1755
            pixelmap -> gx_pixelmap_width <= 0)
122
        {
123
2
            return;
124
        }
125
126
1754
        format = display -> gx_display_color_format;
127
1754
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
128
129
1754
        if (format >= GX_COLOR_FORMAT_24XRGB)
130
        {
131
            /* 32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
132
887
            if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
133
            {
134
                /* Display driver only support its native format pixelmap.*/
135
                /* Nothing should be drawn if pixelmap format isn't support. */
136
1
                return;
137
            }
138
        }
139
        else
140
        {
141
867
            if (pixelmap -> gx_pixelmap_format != format)
142
            {
143
                /* Display driver only support its native format pixelmap.*/
144
                /* Nothing should be drawn if pixelmap format isn't support. */
145
3
                return;
146
            }
147
        }
148
149
1750
        if (format == GX_COLOR_FORMAT_4BIT_GRAY)
150
        {
151
224
            info.mask = 0xf0;
152
        }
153
154
1750
        info.pixelmap = brush -> gx_brush_pixelmap;
155
1750
        info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
156
157
1750
        if (pixelmap -> gx_pixelmap_aux_data_size)
158
        {
159
574
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
160
        }
161
    }
162
163
2311
    xpos = xcenter - a;
164
2311
    ymin = ycenter - b;
165
2311
    ymax = ycenter + b;
166
167
    /* Calculate minimum y line. */
168
2311
    if (clip -> gx_rectangle_top > ymin)
169
    {
170
5
        skip_line = clip -> gx_rectangle_top - ymin;
171
5
        ymin = clip -> gx_rectangle_top;
172
    }
173
    else
174
    {
175
2306
        skip_line = 0;
176
    }
177
178
    /* Calculate maximum y line. */
179
2311
    if (clip -> gx_rectangle_bottom < ymax)
180
    {
181
5
        ymax = clip -> gx_rectangle_bottom;
182
    }
183
184
2311
    height = (ymax - ymin + 1);
185
2311
    pLineEnds = _gx_system_scratchpad;
186
187
    /* default the point array to being off the screen on both sides: */
188
436602
    for (Index = 0; Index < height * 2; Index += 2)
189
    {
190
434291
        pLineEnds[Index] = 2000;
191
434291
        pLineEnds[Index + 1] = 0;
192
    }
193
194
2311
    aa = a * a;
195
2311
    bb = b * b;
196
2311
    x = 0;
197
2311
    y = b;
198
2311
    error = 0;
199
200
    /* Region I of the first quarter of the ellipse.  */
201
157963
    while (2 * bb * (x + 1) < aa * (2 * y - 1))
202
    {
203
        /* calculate error of next pixel. */
204
155680
        realval = bb - bb * (x + 1) * (x + 1) / aa;
205
155680
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
206
207
155680
        if (error >= 510)
208
        {
209
            /* The slope in point(x + 1, y) is greater than -1,
210
               make point(x, y) the delimit pixel, break here. */
211
28
            realval = bb - bb * x * x / aa;
212
28
            break;
213
        }
214
215
155652
        x0 = xcenter - x;
216
155652
        x1 = xcenter + x;
217
218
155652
        if (x0 < clip -> gx_rectangle_left)
219
        {
220
80
            x0 = clip -> gx_rectangle_left;
221
        }
222
223
155652
        if (x1 > clip -> gx_rectangle_right)
224
        {
225
178
            x1 = clip -> gx_rectangle_right;
226
        }
227
228
466956
        for (index = 0; index < 2; index++)
229
        {
230
311304
            y1 = (y - 1) * sign[index] + ycenter;
231
232

311304
            if ((y1 >= ymin) && (y1 <= ymax))
233
            {
234
310725
                Index = (y1 - ymin) << 1;
235
310725
                pLineEnds[Index] = x0;
236
310725
                pLineEnds[Index + 1] = x1;
237
            }
238
        }
239
240
155652
        if (error >= 255)
241
        {
242
48013
            error -= 255;
243
48013
            y--;
244
        }
245
246
155652
        x++;
247
    }
248
249
    /* Region II of the first quarter of the ellipse.  */
250
172221
    while (y > 0)
251
    {
252
169910
        y--;
253
254
169910
        realval = aa - aa * y * y / bb;
255
169910
        error = (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3) - (x << 8);
256
257
216050
        while (error >= 255)
258
        {
259
46140
            error -= 255;
260
46140
            x++;
261
        }
262
263
169910
        x0 = xcenter - x;
264
169910
        x1 = xcenter + x;
265
266
169910
        if (x0 < clip -> gx_rectangle_left)
267
        {
268
3374
            x0 = clip -> gx_rectangle_left;
269
        }
270
271
169910
        if (x1 > clip -> gx_rectangle_right)
272
        {
273
7618
            x1 = clip -> gx_rectangle_right;
274
        }
275
276
509730
        for (index = 0; index < 2; index++)
277
        {
278
339820
            y1 = y * sign[index] + ycenter;
279
280

339820
            if ((y1 >= ymin) && (y1 <= ymax))
281
            {
282
336182
                Index = (y1 - ymin) << 1;
283
336182
                pLineEnds[Index] = x0;
284
336182
                pLineEnds[Index + 1] = x1;
285
            }
286
        }
287
    }
288
289
2311
    Index = 0;
290
2311
    if (pixelmap != GX_NULL)
291
    {
292
1750
        skip_line = (skip_line % info.pixelmap -> gx_pixelmap_height);
293
1750
        if (skip_line)
294
        {
295
1
            info.draw = GX_FALSE;
296
12
            while (skip_line--)
297
            {
298
11
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
299
            }
300
        }
301
302
1750
        info.draw = GX_TRUE;
303
304
329965
        for (y = ymin; y <= ymax; y++)
305
        {
306
328215
            info.x_offset = pLineEnds[Index] - xpos;
307
328215
            display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], y, &info);
308
328215
            Index += 2;
309
        }
310
    }
311
    else
312
    {
313
561
        fill_color = brush -> gx_brush_fill_color;
314
315
106637
        for (y = ymin; y <= ymax; y++)
316
        {
317
106076
            display -> gx_display_driver_horizontal_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], y, 1, fill_color);
318
106076
            Index += 2;
319
        }
320
    }
321
}
322
#endif
323