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_circle_draw PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Kenneth Maxwell, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* Display driver to draw circle arc. */
44 /* */
45 /* INPUT */
46 /* */
47 /* context Drawing context */
48 /* xcenter x-coord of center of circle */
49 /* ycenter y-coord of center of circle */
50 /* r Radius of circle */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* None */
55 /* */
56 /* CALLS */
57 /* */
58 /* [gx_display_driver_pixel_blend] Basic display driver pixel */
59 /* blend function */
60 /* _gx_display_driver_arc_clipping_get */
61 /* Get the clipping rectangles */
62 /* of the circle arc */
63 /* _gx_utility_rectangle_point_detect Detect whether a pixel is */
64 /* inside rectangle */
65 /* [gx_display_driver_pixel_write] Basic display driver pixel */
66 /* write function */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* GUIX Internal Code */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
77 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
78 /* resulting in version 6.1 */
79 /* */
80 /**************************************************************************/
81 #if defined(GX_ARC_DRAWING_SUPPORT)
_gx_display_driver_generic_arc_draw(GX_DRAW_CONTEXT * context,INT xcenter,INT ycenter,UINT r,INT start_angle,INT end_angle)82 VOID _gx_display_driver_generic_arc_draw(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r, INT start_angle, INT end_angle)
83 {
84 /* The arc draw function is implemented by clipping a circle.
85 Calculate the arc clipping first, turn on the pixel on circle when the pixel
86 is inside the arc clipping area. */
87
88 GX_RECTANGLE clip[4];
89 INT x, y;
90 INT d;
91 GX_POINT point;
92 INT sign[4][2] = {{1, 1}, {-1, 1}, {1, -1}, {-1, -1}};
93 INT index;
94 GX_DISPLAY *display = context -> gx_draw_context_display;
95 GX_BRUSH *brush = &context -> gx_draw_context_brush;
96
97 #if defined(GX_BRUSH_ALPHA_SUPPORT)
98 GX_UBYTE brush_alpha = brush -> gx_brush_alpha;
99
100 if (display -> gx_display_driver_pixel_blend == GX_NULL)
101 {
102 /* Pixel blend function is null means alpha isn't supported in this driver.
103 So set alpha value to 0xff to make it draw the original color in case GX_BRUSH_ALPHA_SUPPORT is defined. */
104 brush_alpha = 0xff;
105 }
106 else
107 {
108 if (brush_alpha == 0)
109 /* Nothing to draw here. */
110 return;
111 }
112 #endif
113
114 /* Get the clipping rectangles of the circle arc. */
115 _gx_display_driver_arc_clipping_get(xcenter, ycenter, r, start_angle, end_angle, &clip[0], &clip[1], &clip[2], &clip[3]);
116
117 _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &clip[0], &clip[0]);
118 _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &clip[1], &clip[1]);
119 _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &clip[2], &clip[2]);
120 _gx_utility_rectangle_overlap_detect(context -> gx_draw_context_clip, &clip[3], &clip[3]);
121
122 x = 0;
123 y = (INT)r;
124 d = (INT)(5 - 4 * r);
125
126 #if defined (GX_BRUSH_ALPHA_SUPPORT)
127 if (brush_alpha != 0xff)
128 {
129 while (x <= y)
130 {
131 for (index = 0; index < 4; index++)
132 {
133 point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
134 point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
135
136 if ((_gx_utility_rectangle_point_detect(&clip[0], point)) ||
137 (_gx_utility_rectangle_point_detect(&clip[1], point)) ||
138 (_gx_utility_rectangle_point_detect(&clip[2], point)) ||
139 (_gx_utility_rectangle_point_detect(&clip[3], point)))
140 {
141 display -> gx_display_driver_pixel_blend(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, brush_alpha);
142 }
143
144 point.gx_point_x = (GX_VALUE)(y * sign[index][0] + xcenter);
145 point.gx_point_y = (GX_VALUE)(x * sign[index][1] + ycenter);
146
147 if ((_gx_utility_rectangle_point_detect(&clip[0], point)) ||
148 (_gx_utility_rectangle_point_detect(&clip[1], point)) ||
149 (_gx_utility_rectangle_point_detect(&clip[2], point)) ||
150 (_gx_utility_rectangle_point_detect(&clip[3], point)))
151 {
152 display -> gx_display_driver_pixel_blend(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color, brush_alpha);
153 }
154 }
155
156 if (d < 0)
157 {
158 d += 8 * x + 12;
159 }
160 else
161 {
162 d += 8 * (x - y) + 20;
163 y--;
164 }
165 x++;
166 }
167 }
168 else
169 {
170 #endif
171 while (x <= y)
172 {
173 for (index = 0; index < 4; index++)
174 {
175 point.gx_point_x = (GX_VALUE)(x * sign[index][0] + xcenter);
176 point.gx_point_y = (GX_VALUE)(y * sign[index][1] + ycenter);
177
178 if ((_gx_utility_rectangle_point_detect(&clip[0], point)) ||
179 (_gx_utility_rectangle_point_detect(&clip[1], point)) ||
180 (_gx_utility_rectangle_point_detect(&clip[2], point)) ||
181 (_gx_utility_rectangle_point_detect(&clip[3], point)))
182 {
183 display -> gx_display_driver_pixel_write(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color);
184 }
185
186 point.gx_point_x = (GX_VALUE)(y * sign[index][0] + xcenter);
187 point.gx_point_y = (GX_VALUE)(x * sign[index][1] + ycenter);
188
189 if ((_gx_utility_rectangle_point_detect(&clip[0], point)) ||
190 (_gx_utility_rectangle_point_detect(&clip[1], point)) ||
191 (_gx_utility_rectangle_point_detect(&clip[2], point)) ||
192 (_gx_utility_rectangle_point_detect(&clip[3], point)))
193 {
194 display -> gx_display_driver_pixel_write(context, point.gx_point_x, point.gx_point_y, brush -> gx_brush_line_color);
195 }
196 }
197
198 if (d < 0)
199 {
200 d += 8 * x + 12;
201 }
202 else
203 {
204 d += 8 * (x - y) + 20;
205 y--;
206 }
207 x++;
208 }
209 #if defined (GX_BRUSH_ALPHA_SUPPORT)
210 }
211 #endif
212 }
213 #endif
214
215