GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_ellipse_fill.c Lines: 119 119 100.0 %
Date: 2024-12-05 08:52:37 Branches: 70 70 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_rotated_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
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
78
/*  04-02-2021     Ting Zhu                 Modified comment(s),          */
79
/*                                            modified algorithm to make  */
80
/*                                            it fit one-width antialiaed */
81
/*                                            ellipse outline,            */
82
/*                                            resulting in version 6.1.6  */
83
/*                                                                        */
84
/**************************************************************************/
85
86
VOID _gx_display_driver_generic_rotated_ellipse_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, INT a, INT b)
86
{
87
/* The ellipse fill function follows Bresenham ellipse algorithm while
88
   connecting the two point that symmetric with respect to y-axis. */
89
90
GX_DISPLAY           *display;
91
GX_RECTANGLE         *clip;
92
GX_BRUSH             *brush;
93
INT                   x1;
94
INT                   x;
95
INT                   y;
96
INT                   y0;
97
INT                   y1;
98
86
INT                   sign[2] = {1, -1};
99
INT                  *pLineEnds;
100
INT                   index;
101
INT                   width;
102
INT                   Index;
103
INT                   aa;
104
INT                   bb;
105
INT                   ypos;
106
INT                   xmin;
107
INT                   xmax;
108
INT                   skip_line;
109
86
GX_PIXELMAP          *pixelmap = GX_NULL;
110
GX_COLOR              fill_color;
111
GX_FILL_PIXELMAP_INFO info;
112
GX_BYTE               xsign;
113
INT                   error;
114
INT                   realval;
115
GX_BOOL               record;
116
117
86
    display = context -> gx_draw_context_display;
118
86
    clip = context -> gx_draw_context_clip;
119
86
    brush = &context -> gx_draw_context_brush;
120
121
86
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
122
    {
123
68
        if (brush -> gx_brush_pixelmap == GX_NULL)
124
        {
125
            /* Nothing should be drawn if pixelmap isn't set with GX_BRUSH_PIXELMAP_FILL style. */
126
2
            return;
127
        }
128
129
67
        pixelmap = brush -> gx_brush_pixelmap;
130
131
67
        if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
132
        {
133
            /* Display driver only support its native format pixelmap.*/
134
            /* Nothing should be drawn if pixelmap format isn't support. */
135
1
            return;
136
        }
137
138
66
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
139
140
66
        info.pixelmap = brush -> gx_brush_pixelmap;
141
66
        info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
142
143
66
        if (pixelmap -> gx_pixelmap_aux_data_size)
144
        {
145
24
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
146
        }
147
    }
148
149
84
    xmin = xcenter - a;
150
84
    xmax = xcenter + a;
151
152
    /* Calculate minimum y line. */
153
84
    if (clip -> gx_rectangle_left > xmin)
154
    {
155
2
        xmin = clip -> gx_rectangle_left;
156
    }
157
158
    /* Calculate maximum y line. */
159
84
    if (clip -> gx_rectangle_right < xmax)
160
    {
161
4
        xmax = clip -> gx_rectangle_right;
162
    }
163
164
84
    width = (xmax - xmin + 1);
165
84
    pLineEnds = _gx_system_scratchpad;
166
167
    /* default the point array to being off the screen on both sides: */
168
26288
    for (Index = 0; Index < width * 2; Index += 2)
169
    {
170
26204
        pLineEnds[Index] = 2000;
171
26204
        pLineEnds[Index + 1] = 0;
172
    }
173
174
84
    aa = a * a;
175
84
    bb = b * b;
176
84
    x = 0;
177
84
    y = b;
178
84
    error = 0;
179
180
    /* Region I of the first quarter of the ellipse.  */
181
11290
    while (2 * bb * (x + 1) < aa * (2 * y - 1))
182
    {
183
        /* calculate error of next pixel. */
184
11208
        realval = bb - bb * (x + 1) * (x + 1) / aa;
185
11208
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
186
187
11208
        if (error >= 510)
188
        {
189
            /* The slope in point(x + 1, y) is greater than -1,
190
               make point(x, y) the delimit pixel, break here. */
191
2
            realval = bb - bb * x * x / aa;
192
2
            error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
193
2
            break;
194
        }
195
196
11206
        y0 = ycenter - (y - 1);
197
11206
        y1 = ycenter + (y - 1);
198
199
11206
        if (y0 < clip -> gx_rectangle_top)
200
        {
201
62
            y0 = clip -> gx_rectangle_top;
202
        }
203
204
11206
        if (y1 > clip -> gx_rectangle_bottom)
205
        {
206
62
            y1 = clip -> gx_rectangle_bottom;
207
        }
208
209
33618
        for (index = 0; index < 2; index++)
210
        {
211
22412
            x1 = x * sign[index] + xcenter;
212
213

22412
            if ((x1 >= xmin) && (x1 <= xmax))
214
            {
215
22058
                Index = (x1 - xmin) << 1;
216
22058
                pLineEnds[Index] = y0;
217
22058
                pLineEnds[Index + 1] = y1;
218
            }
219
        }
220
221
11206
        if (error >= 255)
222
        {
223
3812
            y--;
224
        }
225
226
11206
        x++;
227
    }
228
229
84
    record = GX_TRUE;
230
231
84
    y0 = ycenter - y;
232
84
    y1 = ycenter + y;
233
234
84
    if (y0 < clip -> gx_rectangle_top)
235
    {
236
2
        y0 = clip -> gx_rectangle_top;
237
    }
238
239
84
    if (y1 > clip -> gx_rectangle_bottom)
240
    {
241
2
        y1 = clip -> gx_rectangle_bottom;
242
    }
243
244
252
    for (index = 0; index < 2; index++)
245
    {
246
168
        x1 = x * sign[index] + xcenter;
247
248

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

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