GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_ellipse_fill.c Lines: 102 102 100.0 %
Date: 2024-12-05 08:52:37 Branches: 64 64 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_system.h"
29
#include "gx_display.h"
30
31
#if defined(GX_ARC_DRAWING_SUPPORT)
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_display_driver_generic_ellipse_fill             PORTABLE C      */
38
/*                                                           6.1.6        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    Display driver to draw a filled ellipse.                            */
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
/*                                          Basic display driver          */
63
/*                                            horizontal line draw routine*/
64
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
65
/*                                          Basic display driver          */
66
/*                                            horizontal pixelmap line    */
67
/*                                            draw function               */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    GUIX Internal Code                                                  */
72
/*                                                                        */
73
/*  RELEASE HISTORY                                                       */
74
/*                                                                        */
75
/*    DATE              NAME                      DESCRIPTION             */
76
/*                                                                        */
77
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
78
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
79
/*                                            resulting in version 6.1    */
80
/*  04-02-2021     Kenneth Maxwell          Modified comment(s),          */
81
/*                                            modified algorithm to make  */
82
/*                                            it fit one-width antialiaed */
83
/*                                            ellipse outline,            */
84
/*                                            resulting in version 6.1.6  */
85
/*                                                                        */
86
/**************************************************************************/
87
2319
VOID _gx_display_driver_generic_ellipse_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, INT a, INT b)
88
{
89
/* The ellipse fill function follows midpoint ellipse algorithm while
90
   connecting the two point that symmetric with respect to y-axis. */
91
92
GX_DISPLAY           *display;
93
GX_RECTANGLE         *clip;
94
GX_BRUSH             *brush;
95
INT                   x0;
96
INT                   x1;
97
INT                   x;
98
INT                   y;
99
INT                   y1;
100
2319
INT                   sign[2] = {1, -1};
101
INT                  *pLineEnds;
102
INT                   index;
103
INT                   height;
104
INT                   Index;
105
INT                   aa;
106
INT                   bb;
107
INT                   xpos;
108
INT                   ymin;
109
INT                   ymax;
110
INT                   skip_line;
111
2319
GX_PIXELMAP          *pixelmap = GX_NULL;
112
GX_VALUE              format;
113
GX_COLOR              fill_color;
114
GX_FILL_PIXELMAP_INFO info;
115
INT                   error;
116
INT                   realval;
117
118
119
2319
    display = context -> gx_draw_context_display;
120
2319
    clip = context -> gx_draw_context_clip;
121
2319
    brush = &context -> gx_draw_context_brush;
122
123
2319
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
124
    {
125
        /* Pick up pixelmap. */
126
1758
        pixelmap = brush -> gx_brush_pixelmap;
127
1758
        if (pixelmap == GX_NULL)
128
        {
129
            /* Nothing should be drawn if pixelmap isn't set with GX_BRUSH_PIXELMAP_FILL style. */
130
8
            return;
131
        }
132
1756
        if (pixelmap -> gx_pixelmap_height <= 0 ||
133
1755
            pixelmap -> gx_pixelmap_width <= 0)
134
        {
135
2
            return;
136
        }
137
138
1754
        format = display -> gx_display_color_format;
139
1754
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
140
141
1754
        if (format >= GX_COLOR_FORMAT_24XRGB)
142
        {
143
            /* 32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
144
887
            if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
145
            {
146
                /* Display driver only support its native format pixelmap.*/
147
                /* Nothing should be drawn if pixelmap format isn't support. */
148
1
                return;
149
            }
150
        }
151
        else
152
        {
153
867
            if (pixelmap -> gx_pixelmap_format != format)
154
            {
155
                /* Display driver only support its native format pixelmap.*/
156
                /* Nothing should be drawn if pixelmap format isn't support. */
157
3
                return;
158
            }
159
        }
160
161
1750
        if (format == GX_COLOR_FORMAT_4BIT_GRAY)
162
        {
163
224
            info.mask = 0xf0;
164
        }
165
166
1750
        info.pixelmap = brush -> gx_brush_pixelmap;
167
1750
        info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
168
169
1750
        if (pixelmap -> gx_pixelmap_aux_data_size)
170
        {
171
574
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
172
        }
173
    }
174
175
2311
    xpos = xcenter - a;
176
2311
    ymin = ycenter - b;
177
2311
    ymax = ycenter + b;
178
179
    /* Calculate minimum y line. */
180
2311
    if (clip -> gx_rectangle_top > ymin)
181
    {
182
5
        skip_line = clip -> gx_rectangle_top - ymin;
183
5
        ymin = clip -> gx_rectangle_top;
184
    }
185
    else
186
    {
187
2306
        skip_line = 0;
188
    }
189
190
    /* Calculate maximum y line. */
191
2311
    if (clip -> gx_rectangle_bottom < ymax)
192
    {
193
5
        ymax = clip -> gx_rectangle_bottom;
194
    }
195
196
2311
    height = (ymax - ymin + 1);
197
2311
    pLineEnds = _gx_system_scratchpad;
198
199
    /* default the point array to being off the screen on both sides: */
200
436602
    for (Index = 0; Index < height * 2; Index += 2)
201
    {
202
434291
        pLineEnds[Index] = 2000;
203
434291
        pLineEnds[Index + 1] = 0;
204
    }
205
206
2311
    aa = a * a;
207
2311
    bb = b * b;
208
2311
    x = 0;
209
2311
    y = b;
210
2311
    error = 0;
211
212
    /* Region I of the first quarter of the ellipse.  */
213
157963
    while (2 * bb * (x + 1) < aa * (2 * y - 1))
214
    {
215
        /* calculate error of next pixel. */
216
155680
        realval = bb - bb * (x + 1) * (x + 1) / aa;
217
155680
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
218
219
155680
        if (error >= 510)
220
        {
221
            /* The slope in point(x + 1, y) is greater than -1,
222
               make point(x, y) the delimit pixel, break here. */
223
28
            realval = bb - bb * x * x / aa;
224
28
            break;
225
        }
226
227
155652
        x0 = xcenter - x;
228
155652
        x1 = xcenter + x;
229
230
155652
        if (x0 < clip -> gx_rectangle_left)
231
        {
232
80
            x0 = clip -> gx_rectangle_left;
233
        }
234
235
155652
        if (x1 > clip -> gx_rectangle_right)
236
        {
237
178
            x1 = clip -> gx_rectangle_right;
238
        }
239
240
466956
        for (index = 0; index < 2; index++)
241
        {
242
311304
            y1 = (y - 1) * sign[index] + ycenter;
243
244

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

339820
            if ((y1 >= ymin) && (y1 <= ymax))
293
            {
294
336182
                Index = (y1 - ymin) << 1;
295
336182
                pLineEnds[Index] = x0;
296
336182
                pLineEnds[Index + 1] = x1;
297
            }
298
        }
299
    }
300
301
2311
    Index = 0;
302
2311
    if (pixelmap != GX_NULL)
303
    {
304
1750
        skip_line = (skip_line % info.pixelmap -> gx_pixelmap_height);
305
1750
        if (skip_line)
306
        {
307
1
            info.draw = GX_FALSE;
308
12
            while (skip_line--)
309
            {
310
11
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
311
            }
312
        }
313
314
1750
        info.draw = GX_TRUE;
315
316
329965
        for (y = ymin; y <= ymax; y++)
317
        {
318
328215
            info.x_offset = pLineEnds[Index] - xpos;
319
328215
            display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], y, &info);
320
328215
            Index += 2;
321
        }
322
    }
323
    else
324
    {
325
561
        fill_color = brush -> gx_brush_fill_color;
326
327
106637
        for (y = ymin; y <= ymax; y++)
328
        {
329
106076
            display -> gx_display_driver_horizontal_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], y, 1, fill_color);
330
106076
            Index += 2;
331
        }
332
    }
333
}
334
#endif
335