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_display.h"
28 #include "gx_system.h"
29 #include "gx_utility.h"
30
31 #if defined(GX_ARC_DRAWING_SUPPORT)
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _gx_display_driver_generic_circle_fill PORTABLE C */
38 /* 6.1 */
39 /* AUTHOR */
40 /* */
41 /* Kenneth Maxwell, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* Display driver fill circle. */
46 /* */
47 /* INPUT */
48 /* */
49 /* context Drawing context */
50 /* xcenter x-coord of center of circle */
51 /* ycenter y-coord of center of circle */
52 /* r Radius of circle */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* None */
57 /* */
58 /* CALLS */
59 /* */
60 /* [gx_display_driver_horizontal_line_draw] */
61 /* Basic display driver */
62 /* horizontal line draw routine*/
63 /* [gx_display_driver_horizontal_pixelmap_line_draw] */
64 /* Basic display driver */
65 /* horizontal pixelmap line */
66 /* draw function */
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 /**************************************************************************/
_gx_display_driver_generic_circle_fill(GX_DRAW_CONTEXT * context,INT xcenter,INT ycenter,UINT r)80 VOID _gx_display_driver_generic_circle_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r)
81 {
82 GX_DISPLAY *display;
83 GX_BRUSH *brush;
84 GX_RECTANGLE *clip;
85 INT xpos;
86 INT curx;
87 INT cury;
88 INT ymin;
89 INT ymax;
90 INT yi;
91 INT x1;
92 INT x2;
93 INT y1;
94 INT height;
95 INT loop;
96 GX_VALUE format;
97 INT skip_line;
98 GX_PIXELMAP *pixelmap = GX_NULL;
99 GX_FILL_PIXELMAP_INFO info;
100 INT *pLineEnds;
101 INT Index;
102 INT sign[4][2] = {{1, 1}, {1, -1}, {1, 1}, {1, -1}};
103 INT error;
104 GX_COLOR fill_color;
105
106 display = context -> gx_draw_context_display;
107 clip = context -> gx_draw_context_clip;
108 brush = &context -> gx_draw_context_brush;
109
110 if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
111 {
112 pixelmap = brush -> gx_brush_pixelmap;
113 if (pixelmap == GX_NULL)
114 {
115 /* Nothing should be drawn if pixelmap isn't set with GX_BRUSH_PIXELMAP_FILL style. */
116 return;
117 }
118 if (pixelmap -> gx_pixelmap_height <= 0 ||
119 pixelmap -> gx_pixelmap_width <= 0)
120 {
121 return;
122 }
123 format = display -> gx_display_color_format;
124 memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
125
126 /*Check the pixelmap format is supported in this driver or not.*/
127 if (format >= GX_COLOR_FORMAT_24XRGB)
128 {
129 /*32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
130 if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
131 {
132 /* Display driver only support its native format pixelmap.*/
133 /* Nothing should be drawn if pixelmap format isn't support. */
134 return;
135 }
136 }
137 else
138 {
139 if (pixelmap -> gx_pixelmap_format != format)
140 {
141 /* Display driver only support its native format pixelmap.*/
142 /* Nothing should be drawn if pixelmap format isn't support. */
143 return;
144 }
145 }
146
147 if (format == GX_COLOR_FORMAT_4BIT_GRAY)
148 {
149 info.mask = 0xf0;
150 }
151
152 /* If filling pixelmap, set fill pixelmap info. */
153 info.pixelmap = pixelmap;
154 info.current_pixel_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_data;
155 if (pixelmap -> gx_pixelmap_aux_data_size)
156 {
157 info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
158 }
159 }
160
161 xpos = xcenter - (INT)r;
162 ymin = ycenter - (INT)r;
163 ymax = ycenter + (INT)r;
164
165 /* Calculate minimum y line. */
166 if (clip -> gx_rectangle_top > ymin)
167 {
168 skip_line = clip -> gx_rectangle_top - ymin;
169 ymin = clip -> gx_rectangle_top;
170 }
171 else
172 {
173 skip_line = 0;
174 }
175
176 /* Calculat maximum y line. */
177 if (clip -> gx_rectangle_bottom < ymax)
178 {
179 ymax = clip -> gx_rectangle_bottom;
180 }
181
182 height = ymax - ymin + 1;
183 pLineEnds = _gx_system_scratchpad;
184
185 /* default the point array to being off the screen on both sides: */
186 for (loop = 0; loop < height * 2; loop += 2)
187 {
188 pLineEnds[loop] = 2000;
189 pLineEnds[loop + 1] = 0;
190 }
191
192 curx = 0;
193 cury = (INT)r;
194 error = 0;
195
196 /* For shapes pixelmap-fill driver function, it must fill shapes line by line from up to bottom.
197 So this contains two steps here: first, calculate the boudary point of circle; Second, draw pixelmap line by line. */
198 while (curx <= cury)
199 {
200 for (loop = 0; loop < 4; loop++)
201 {
202 /* Upper half part. */
203 if (loop < 2)
204 {
205 x1 = curx * sign[loop][0];
206 y1 = (cury - 1) * sign[loop][1];
207 }
208 /* lower half part. */
209 else
210 {
211 x1 = (cury - 1) * sign[loop][0];
212 y1 = curx * sign[loop][1];
213 }
214
215 x2 = -x1;
216 x1 += xcenter;
217 x2 += xcenter;
218 y1 += ycenter;
219
220 if ((y1 >= ymin) && (y1 <= ymax))
221 {
222 if (x1 > x2)
223 {
224 GX_SWAP_VALS(x1, x2);
225 }
226
227 if (x1 < clip -> gx_rectangle_left)
228 {
229 x1 = clip -> gx_rectangle_left;
230 }
231
232 if (x2 > clip -> gx_rectangle_right)
233 {
234 x2 = clip -> gx_rectangle_right;
235 }
236
237 Index = (y1 - ymin) << 1;
238 pLineEnds[Index] = x1;
239 pLineEnds[Index + 1] = x2;
240 }
241 }
242
243 curx++;
244 yi = (INT)(r * r) - curx * curx;
245 error = (cury << 8) - (INT)(_gx_utility_math_sqrt((UINT)(yi << 10)) << 3);
246
247 while (error >= 255)
248 {
249 error -= 255;
250 cury--;
251 }
252 }
253
254 Index = 0;
255
256 if (pixelmap)
257 {
258 skip_line = (skip_line % info.pixelmap -> gx_pixelmap_height);
259 if (skip_line)
260 {
261 info.draw = GX_FALSE;
262 while (skip_line--)
263 {
264 display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
265 }
266 }
267
268 info.draw = GX_TRUE;
269
270 for (cury = ymin; cury <= ymax; cury++)
271 {
272 if (pLineEnds[Index] <= pLineEnds[Index + 1])
273 {
274 info.x_offset = pLineEnds[Index] - xpos;
275 display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, &info);
276 }
277 Index += 2;
278 }
279 }
280 else
281 {
282 fill_color = brush -> gx_brush_fill_color;
283
284 for (cury = ymin; cury <= ymax; cury++)
285 {
286 if (pLineEnds[Index] <= pLineEnds[Index + 1])
287 {
288 display -> gx_display_driver_horizontal_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, 1, fill_color);
289 }
290 Index += 2;
291 }
292 }
293 }
294 #endif
295
296