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

7364
        if ((y >= ymin) && (y <= ymax))
143
        {
144
7211
            pLineEnds[(y - ymin) << 1] = 0;
145
        }
146
    }
147
148
694
    y2 = ycenter + b - ((brush_width - 1) >> 1);
149
8058
    for (y = y2; y < y2 + brush_width; y++)
150
    {
151

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

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

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

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

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