GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_arc_fill.c Lines: 184 184 100.0 %
Date: 2024-12-05 08:52:37 Branches: 158 158 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_system.h"
28
#include "gx_utility.h"
29
#include "gx_display.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_display_driver_generic_rotated_arc_fill         PORTABLE C      */
37
/*                                                           6.1.3        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Display driver to fill circle sector.                               */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    context                               Drawing context               */
49
/*    xcenter                               x-coord of center of circle   */
50
/*    ycenter                               y-coord of center of circle   */
51
/*    r                                     Radius of circle              */
52
/*    start_angle                           The start angle of circle arc */
53
/*    end_angle                             The end angle of circle arc   */
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_arc_clipping_get   Get an arc clipping.          */
65
/*    _gx_utility_rectangle_point_detect    Detect whether a pixel is     */
66
/*                                            inside rectangle            */
67
/*    _gx_display_driver_circle_point_get   Get point coord on a circle   */
68
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
69
/*                                          Basic display driver          */
70
/*                                            horizontal pixelmap line    */
71
/*                                            draw function               */
72
/*                                                                        */
73
/*  CALLED BY                                                             */
74
/*                                                                        */
75
/*    _gx_display_driver_generic_arc_draw                                 */
76
/*                                                                        */
77
/*  RELEASE HISTORY                                                       */
78
/*                                                                        */
79
/*    DATE              NAME                      DESCRIPTION             */
80
/*                                                                        */
81
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
82
/*                                                                        */
83
/**************************************************************************/
84
#if defined(GX_ARC_DRAWING_SUPPORT)
85
144
VOID _gx_display_driver_generic_rotated_arc_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
86
{
87
88
GX_DISPLAY           *display;
89
GX_RECTANGLE         *clip;
90
GX_RECTANGLE          arc_clip[4];
91
GX_BRUSH             *brush;
92
GX_POINT              point;
93
144
INT                   sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
94
INT                  *pLineEnds;
95
INT                   xmin;
96
INT                   xmax;
97
INT                   xstart;
98
INT                   xend;
99
INT                   ystart;
100
INT                   yend;
101
INT                   curx;
102
INT                   cury;
103
INT                   nextx;
104
INT                   nexty;
105
INT                   dx;
106
INT                   dy;
107
INT                   Index;
108
INT                   Index1;
109
INT                   width;
110
INT                   xsign;
111
INT                   ysign;
112
INT                   decision;
113
VOID                  (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
114
144
GX_PIXELMAP          *pixelmap = GX_NULL;
115
INT                   ypos;
116
INT                   skip_line;
117
GX_FILL_PIXELMAP_INFO info;
118
INT                   inner_offset;
119
120
144
    display = context -> gx_draw_context_display;
121
144
    brush = &context -> gx_draw_context_brush;
122
144
    inner_offset = brush -> gx_brush_width;
123
144
    line_draw = display -> gx_display_driver_vertical_line_draw;
124
144
    clip = context -> gx_draw_context_clip;
125
126
144
    if (inner_offset)
127
    {
128
143
        inner_offset -= 1;
129
143
        inner_offset >>= 1;
130
    }
131
132
144
    if (r <= (UINT)inner_offset)
133
    {
134
3
        return;
135
    }
136
137
143
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
138
    {
139
97
        if (brush -> gx_brush_pixelmap == GX_NULL)
140
        {
141
1
            return;
142
        }
143
144
        /* Pick up brush pixelmap. */
145
96
        pixelmap = brush -> gx_brush_pixelmap;
146
147
96
        if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
148
        {
149
            /* Display driver only support its native format pixelmap.*/
150
            /* Nothing should be drawn if pixelmap format isn't support. */
151
1
            return;
152
        }
153
154
95
        memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
155
156
95
        info.pixelmap = brush -> gx_brush_pixelmap;
157
95
        info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
158
159
95
        if (pixelmap -> gx_pixelmap_aux_data_size)
160
        {
161
24
            info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
162
        }
163
    }
164
165
141
    r = (UINT)(r - (UINT)(inner_offset >> 1));
166
167
141
    xmax = xcenter + (INT)r;
168
141
    xmin = xcenter - (INT)r;
169
170
    /* Get two endpoint of the arc. */
171
141
    _gx_utility_circle_point_get(xcenter, ycenter, r, start_angle, &point);
172
173
141
    xstart = point.gx_point_x;
174
141
    ystart = point.gx_point_y;
175
176
141
    _gx_utility_circle_point_get(xcenter, ycenter, r, end_angle, &point);
177
178
141
    xend = point.gx_point_x;
179
141
    yend = point.gx_point_y;
180
181
141
    skip_line = 0;
182
183
    /* Calculate minimum y line. */
184

141
    if (((start_angle < 180) && (end_angle < 180)) ||
185
16
        ((start_angle > 180) && (end_angle < 540)))
186
    {
187
39
        if (xstart > xend)
188
        {
189
35
            xmin = xend;
190
        }
191
        else
192
        {
193
4
            xmin = xstart;
194
        }
195
    }
196
197
141
    if (clip -> gx_rectangle_left > xmin)
198
    {
199
37
        xmin = clip -> gx_rectangle_left;
200
    }
201
202
    /* Calculate maximum y line. */
203
141
    if (end_angle < 360)
204
    {
205
117
        if (xstart > xend)
206
        {
207
105
            xmax = xstart;
208
        }
209
        else
210
        {
211
12
            xmax = xend;
212
        }
213
    }
214
215
141
    if (clip -> gx_rectangle_right < xmax)
216
    {
217
20
        xmax = clip -> gx_rectangle_right;
218
    }
219
220
141
    width = xmax - xmin + 1;
221
222
    /* default the point array to being off the screen on both sides: */
223
141
    pLineEnds = _gx_system_scratchpad;
224
225
33013
    for (Index = 0; Index < width * 2; Index += 2)
226
    {
227
32872
        pLineEnds[Index] = 2000;
228
32872
        pLineEnds[Index + 1] = 0;
229
    }
230
231
    /* Get the clipping rectangles of the circle arc. */
232
141
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle, &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
233
234
141
    curx = 0;
235
141
    cury = (INT)r;
236
141
    decision = (INT)(5 - 4 * r);
237
238
22679
    while (curx <= cury)
239
    {
240
112690
        for (Index = 0; Index < 4; Index++)
241
        {
242
90152
            point.gx_point_x = (GX_VALUE)(curx * sign[Index][0] + xcenter);
243
90152
            point.gx_point_y = (GX_VALUE)(cury * sign[Index][1] + ycenter);
244
245
90152
            if ((point.gx_point_x >= xmin) &&
246
68832
                (point.gx_point_x <= xmax))
247
            {
248

93329
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
249
64973
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
250
47116
                    _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
251
21776
                    _gx_utility_rectangle_point_detect(&arc_clip[3], point))
252
                {
253
32236
                    Index1 = (point.gx_point_x - xmin) << 1;
254
32236
                    if (point.gx_point_y < pLineEnds[Index1])
255
                    {
256
30520
                        pLineEnds[Index1] = point.gx_point_y;
257
                    }
258
259
32236
                    if (point.gx_point_y > pLineEnds[Index1 + 1])
260
                    {
261
23280
                        pLineEnds[Index1 + 1] = point.gx_point_y;
262
                    }
263
                }
264
            }
265
266
90152
            point.gx_point_x = (GX_VALUE)(cury * sign[Index][0] + xcenter);
267
90152
            point.gx_point_y = (GX_VALUE)(curx * sign[Index][1] + ycenter);
268
269
90152
            if ((point.gx_point_x >= xmin) &&
270
61424
                (point.gx_point_x <= xmax))
271
            {
272

46526
                if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
273
32569
                    _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
274
17653
                    _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
275
6120
                    _gx_utility_rectangle_point_detect(&arc_clip[3], point))
276
                {
277
19650
                    Index1 = (point.gx_point_x - xmin) << 1;
278
19650
                    if (point.gx_point_y < pLineEnds[Index1])
279
                    {
280
14496
                        pLineEnds[Index1] = point.gx_point_y;
281
                    }
282
283
19650
                    if (point.gx_point_y > pLineEnds[Index1 + 1])
284
                    {
285
11059
                        pLineEnds[Index1 + 1] = point.gx_point_y;
286
                    }
287
                }
288
            }
289
        }
290
291
22538
        if (decision < 0)
292
        {
293
13115
            decision += 8 * curx + 12;
294
        }
295
        else
296
        {
297
9423
            decision += 8 * (curx - cury) + 20;
298
9423
            cury--;
299
        }
300
22538
        curx++;
301
    }
302
303
    /* Fill in the point array by using Breshenhams line for
304
       the line that connect two endpoints of the arc. */
305
306
141
    dx = GX_ABS(xend - xstart);
307
141
    dy = GX_ABS(yend - ystart);
308
309
141
    if (xstart != xend)
310
    {
311
        /* Horizontal Line. */
312
137
        if (ystart == yend)
313
        {
314
12
            if (xstart > xend)
315
            {
316
8
                GX_SWAP_VALS(xstart, xend);
317
8
                GX_SWAP_VALS(ystart, yend);
318
            }
319
320
4480
            for (curx = xstart; curx <= xend; curx++)
321
            {
322

4468
                if ((curx >= xmin) &&
323
                    (curx <= xmax))
324
                {
325
3640
                    Index = (curx - xmin) << 1;
326
3640
                    if (ystart <= pLineEnds[Index])
327
                    {
328
1276
                        pLineEnds[Index] = ystart;
329
                    }
330
331
3640
                    if (ystart > pLineEnds[Index + 1])
332
                    {
333
2356
                        pLineEnds[Index + 1] = ystart;
334
                    }
335
                }
336
            }
337
        }
338
        else
339
        {
340
            /* Simple Line. */
341

125
            if (((dx >= dy && (xstart > xend)) ||
342
24
                 ((dy > dx) && ystart > yend)))
343
            {
344
97
                GX_SWAP_VALS(xend, xstart);
345
97
                GX_SWAP_VALS(yend, ystart);
346
            }
347
348
125
            xsign = (xend - xstart) / dx;
349
125
            ysign = (yend - ystart) / dy;
350
351
125
            if (dx >= dy)
352
            {
353
101
                for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
354
11294
                     decision = (dx >> 1); curx <= nextx; curx++, nextx--,
355
11193
                     decision += dy)
356
                {
357
11193
                    if (decision >= dx)
358
                    {
359
6649
                        decision -= dx;
360
6649
                        cury += ysign;
361
6649
                        nexty -= ysign;
362
                    }
363
364

11193
                    if ((curx >= xmin) && (curx <= xmax))
365
                    {
366
9838
                        Index = (curx - xmin) << 1;
367
368
9838
                        if (cury < pLineEnds[Index])
369
                        {
370
316
                            pLineEnds[Index] = cury;
371
                        }
372
373
9838
                        if (cury > pLineEnds[Index + 1])
374
                        {
375
9247
                            pLineEnds[Index + 1] = cury;
376
                        }
377
                    }
378
379

11193
                    if ((nextx >= xmin) && (nextx <= xmax))
380
                    {
381
9645
                        Index1 = (nextx - xmin) << 1;
382
383
9645
                        if (nexty < pLineEnds[Index1])
384
                        {
385
312
                            pLineEnds[Index1] = nexty;
386
                        }
387
388
9645
                        if (nexty > pLineEnds[Index1 + 1])
389
                        {
390
9170
                            pLineEnds[Index1 + 1] = nexty;
391
                        }
392
                    }
393
                }
394
            }
395
            else
396
            {
397
24
                for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
398
5844
                     decision = (dy >> 1); cury <= nexty; cury++, nexty--,
399
5820
                     decision += dx)
400
                {
401
5820
                    if (decision >= dy)
402
                    {
403
1816
                        decision -= dy;
404
1816
                        curx += xsign;
405
1816
                        nextx -= xsign;
406
                    }
407
408

5820
                    if ((curx >= xmin) && (curx <= xmax))
409
                    {
410
2440
                        Index = (curx - xmin) << 1;
411
2440
                        if (cury < pLineEnds[Index])
412
                        {
413
436
                            pLineEnds[Index] = cury;
414
                        }
415
416
2440
                        if (cury > pLineEnds[Index + 1])
417
                        {
418
1660
                            pLineEnds[Index + 1] = cury;
419
                        }
420
                    }
421
422

5820
                    if ((nextx >= xmin) && (nextx <= xmax))
423
                    {
424
3572
                        Index1 = (nextx - xmin) << 1;
425
426
3572
                        if (nexty < pLineEnds[Index1])
427
                        {
428
756
                            pLineEnds[Index1] = nexty;
429
                        }
430
431
3572
                        if (nexty > pLineEnds[Index1 + 1])
432
                        {
433
620
                            pLineEnds[Index1 + 1] = nexty;
434
                        }
435
                    }
436
                }
437
            }
438
        }
439
    }
440
441
141
    if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
442
    {
443
95
        if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
444
        {
445
67
            skip_line = (xmax - (xcenter - (INT)r) + 1) % pixelmap -> gx_pixelmap_width;
446
447
            /* Skip the un-draw line.*/
448
67
            if (skip_line)
449
            {
450
65
                skip_line = pixelmap -> gx_pixelmap_width - skip_line;
451
            }
452
453
67
            xstart = xmax;
454
67
            Index = (width - 1) * 2;
455
67
            xsign = -1;
456
        }
457
        else
458
        {
459
28
            skip_line = (xmin - clip -> gx_rectangle_left);
460
461
28
            xstart = xmin;
462
28
            Index = 0;
463
28
            xsign = 1;
464
        }
465
466
        /* Skip the un-draw line.*/
467
95
        if (skip_line)
468
        {
469
93
            info.draw = GX_FALSE;
470
8343
            while (skip_line--)
471
            {
472
8250
                display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, cury, &info);
473
            }
474
        }
475
476
95
        info.draw = GX_TRUE;
477
95
        ypos = ycenter - (INT)r;
478
479
21490
        for (curx = xmin; curx <= xmax; curx++)
480
        {
481
21395
            if (pLineEnds[Index] < clip -> gx_rectangle_top)
482
            {
483
3466
                pLineEnds[Index] = clip -> gx_rectangle_top;
484
            }
485
486
21395
            if (pLineEnds[Index + 1] > clip -> gx_rectangle_bottom)
487
            {
488
2738
                pLineEnds[Index + 1] = clip -> gx_rectangle_bottom;
489
            }
490
491
            /* Filling arc area with pixelmap. */
492
21395
            info.x_offset = pLineEnds[Index] - ypos;
493
21395
            display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], xstart, &info);
494
495
21395
            xstart += xsign;
496
21395
            Index += xsign;
497
21395
            Index += xsign;
498
        }
499
    }
500
    else
501
    {
502
46
        Index = 0;
503
504
11523
        for (curx = xmin; curx <= xmax; curx++)
505
        {
506
11477
            if (pLineEnds[Index] < clip -> gx_rectangle_top)
507
            {
508
3466
                pLineEnds[Index] = clip -> gx_rectangle_top;
509
            }
510
511
11477
            if (pLineEnds[Index + 1] > clip -> gx_rectangle_bottom)
512
            {
513
2738
                pLineEnds[Index + 1] = clip -> gx_rectangle_bottom;
514
            }
515
516
            /* Fill arc with horizontal lines. */
517
11477
            line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], curx, 1, brush -> gx_brush_fill_color);
518
519
11477
            Index += 2;
520
        }
521
    }
522
}
523
524
#endif
525