GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_aliased_arc_draw.c Lines: 66 66 100.0 %
Date: 2024-12-05 08:52:37 Branches: 52 52 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
/*  FUNCTION                                               RELEASE        */
34
/*                                                                        */
35
/*    _gx_display_driver_generic_aliased_arc_draw         PORTABLE C      */
36
/*                                                           6.1          */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Kenneth Maxwell, Microsoft Corporation                              */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    Display driver to draw aliased circle arc.                          */
44
/*                                                                        */
45
/*  INPUT                                                                 */
46
/*                                                                        */
47
/*    xcenter                               x-coord of center of circle   */
48
/*                                            arc                         */
49
/*    ycenter                               y-coord of center of circle   */
50
/*                                            arc                         */
51
/*    r                                     Radius of circle arc          */
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_arc_clipping_get   Get an arc clipping.          */
62
/*    _gx_utility_rectangle_overlap_detect  Detect two rectangles being   */
63
/*                                            overlap to each other       */
64
/*    [gx_display_driver_pixel_blend]       Basic display driver pixel    */
65
/*                                            blend function              */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    GUIX Internal Code                                                  */
70
/*                                                                        */
71
/*  RELEASE HISTORY                                                       */
72
/*                                                                        */
73
/*    DATE              NAME                      DESCRIPTION             */
74
/*                                                                        */
75
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
76
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
77
/*                                            resulting in version 6.1    */
78
/*                                                                        */
79
/**************************************************************************/
80
#if defined(GX_ARC_DRAWING_SUPPORT)
81
494
VOID _gx_display_driver_generic_aliased_arc_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
82
{
83
/* The arc draw function is implemented by clipping a circle.
84
   Calculate the arc clipping first, turn on the pixel on circle when the pixel
85
   is inside the arc clipping area.                                             */
86
87
GX_DISPLAY  *display;
88
GX_RECTANGLE arc_clip[4];
89
GX_BRUSH    *brush;
90
INT          x;
91
INT          y;
92
GX_POINT     point;
93
494
INT          sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
94
INT          index;
95
INT          error;
96
INT          realval;
97
GX_UBYTE     alpha1;
98
GX_UBYTE     alpha2;
99
VOID         (*blend_func)(GX_DRAW_CONTEXT *context,
100
                           INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
101
102
#if defined(GX_BRUSH_ALPHA_SUPPORT)
103
GX_UBYTE brush_alpha;
104
105
494
    brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
106
107
494
    if (brush_alpha == 0)
108
    {
109
        /* Nothing to draw here. */
110
143
        return;
111
    }
112
#endif
113
114
352
    display = context -> gx_draw_context_display;
115
352
    blend_func = display -> gx_display_driver_pixel_blend;
116
117
352
    if (blend_func == GX_NULL)
118
    {
119
1
        return;
120
    }
121
122
351
    brush = &context -> gx_draw_context_brush;
123
124
125
    /* Get the clipping rectangles of the circle arc. */
126
351
    _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle,
127
                                        &arc_clip[0], &arc_clip[1], &arc_clip[2], &arc_clip[3]);
128
129
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[0], &arc_clip[0]);
130
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[1], &arc_clip[1]);
131
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[2], &arc_clip[2]);
132
351
    _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &arc_clip[3], &arc_clip[3]);
133
134
351
    x = 0;
135
351
    y = (INT)r;
136
351
    error = 0;
137
138
    /* Process anti-aliased circle drawing. */
139
17734
    while (x < y)
140
    {
141
86915
        for (index = 0; index < 4; index++)
142
        {
143
69532
            alpha1 = (GX_UBYTE)(255 - error);
144
69532
            alpha2 = (GX_UBYTE)error;
145
#if defined(GX_BRUSH_ALPHA_SUPPORT)
146
69532
            alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
147
69532
            alpha2 = (GX_UBYTE)(alpha2 * brush_alpha / 255);
148
#endif
149
150
69532
            point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
151
69532
            point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
152
153

134080
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
154
126068
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
155
122319
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
156
60799
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
157
            {
158
8803
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
159
            }
160
161
69532
            point.gx_point_y = (GX_VALUE)((y - 1) * sign[index][1] + ycenter);
162
163

133997
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
164
125658
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
165
121507
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
166
60314
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
167
            {
168
9288
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
169
            }
170
171
69532
            point.gx_point_x = (GX_VALUE)(y * sign[index][0] + xcenter);
172
69532
            point.gx_point_y = (GX_VALUE)(x * sign[index][1] + ycenter);
173
174

134687
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
175
127365
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
176
123738
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
177
61528
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
178
            {
179
8108
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
180
            }
181
182
69532
            point.gx_point_x = (GX_VALUE)((y - 1) * sign[index][0] + xcenter);
183
184

134549
            if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
185
126820
                _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
186
122773
                _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
187
60970
                _gx_utility_rectangle_point_detect(&arc_clip[3], point))
188
            {
189
8666
                blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha2);
190
            }
191
        }
192
193
17383
        x++;
194
195
17383
        realval = (INT)(r * r) - x * x;
196
17383
        error = (y << 8) - (INT)(_gx_utility_math_sqrt((UINT)(realval << 10)) << 3);
197
198
24692
        while (error >= 255)
199
        {
200
7309
            error -= 255;
201
7309
            y--;
202
        }
203
    }
204
205
351
    alpha1 = (GX_UBYTE)(255 - error);
206
#if defined(GX_BRUSH_ALPHA_SUPPORT)
207
351
    alpha1 = (GX_UBYTE)(alpha1 * brush_alpha / 255);
208
#endif
209
210
1755
    for (index = 0; index < 4; index++)
211
    {
212
213
1404
        point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
214
1404
        point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
215
216

2472
        if (_gx_utility_rectangle_point_detect(&arc_clip[0], point) ||
217
1980
            _gx_utility_rectangle_point_detect(&arc_clip[1], point) ||
218
1803
            _gx_utility_rectangle_point_detect(&arc_clip[2], point) ||
219
891
            _gx_utility_rectangle_point_detect(&arc_clip[3], point))
220
        {
221
514
            blend_func(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, alpha1);
222
        }
223
    }
224
}
225
#endif
226