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_rotated_circle_fill PORTABLE C */
38 /* 6.1.3 */
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 /* 12-31-2020 Kenneth Maxwell Initial Version 6.1.3 */
76 /* */
77 /**************************************************************************/
_gx_display_driver_generic_rotated_circle_fill(GX_DRAW_CONTEXT * context,INT xcenter,INT ycenter,UINT r)78 VOID _gx_display_driver_generic_rotated_circle_fill(GX_DRAW_CONTEXT *context, INT xcenter, INT ycenter, UINT r)
79 {
80 GX_DISPLAY *display;
81 GX_BRUSH *brush;
82 GX_RECTANGLE *clip;
83 INT ypos;
84 INT curx;
85 INT cury;
86 INT xmin;
87 INT xmax;
88 INT yi;
89 INT x1;
90 INT y1;
91 INT y2;
92 INT width;
93 INT loop;
94 INT skip_line;
95 GX_PIXELMAP *pixelmap = GX_NULL;
96 GX_FILL_PIXELMAP_INFO info;
97 INT *pLineEnds;
98 INT Index;
99 GX_BYTE sign[4][2] = {{1, 1}, {-1, 1}, {1, 1}, {-1, 1}};
100 INT error;
101 GX_COLOR fill_color;
102 GX_BYTE xsign;
103
104 display = context -> gx_draw_context_display;
105 clip = context -> gx_draw_context_clip;
106 brush = &context -> gx_draw_context_brush;
107
108 if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
109 {
110 if (brush -> gx_brush_pixelmap == GX_NULL)
111 {
112 /* Nothing should be drawn if pixelmap isn't set with GX_BRUSH_PIXELMAP_FILL style. */
113 return;
114 }
115
116 pixelmap = brush -> gx_brush_pixelmap;
117 if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
118 {
119 /* Display driver only support its native format pixelmap.*/
120 /* Nothing should be drawn if pixelmap format isn't support. */
121 return;
122 }
123
124 memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
125
126 /* If filling pixelmap, set fill pixelmap info. */
127 info.pixelmap = pixelmap;
128 info.current_pixel_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_data;
129 if (pixelmap -> gx_pixelmap_aux_data_size)
130 {
131 info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
132 }
133 }
134
135 xmin = xcenter - (INT)r;
136 xmax = xcenter + (INT)r;
137
138 /* Calculate minimum y line. */
139 if (clip -> gx_rectangle_left > xmin)
140 {
141 xmin = clip -> gx_rectangle_left;
142 }
143
144 /* Calculat maximum y line. */
145 if (clip -> gx_rectangle_right < xmax)
146 {
147 xmax = clip -> gx_rectangle_right;
148 }
149
150 width = xmax - xmin + 1;
151 pLineEnds = _gx_system_scratchpad;
152
153 /* default the point array to being off the screen on both sides: */
154 for (loop = 0; loop < width * 2; loop += 2)
155 {
156 pLineEnds[loop] = 2000;
157 pLineEnds[loop + 1] = 0;
158 }
159
160 curx = 0;
161 cury = (INT)r;
162 error = 0;
163
164 /* For shapes pixelmap-fill driver function, it must fill shapes line by line from up to bottom.
165 So this contains two steps here: first, calculate the boudary point of circle; Second, draw pixelmap line by line. */
166 while (curx <= cury)
167 {
168 for (loop = 0; loop < 4; loop++)
169 {
170 /* Upper half part. */
171 if (loop < 2)
172 {
173 x1 = curx * sign[loop][0];
174 y1 = (cury - 1) * sign[loop][1];
175 }
176 /* lower half part. */
177 else
178 {
179 x1 = (cury - 1) * sign[loop][0];
180 y1 = curx * sign[loop][1];
181 }
182
183 y2 = -y1;
184 y1 += ycenter;
185 y2 += ycenter;
186 x1 += xcenter;
187
188 if ((x1 >= xmin) && (x1 <= xmax))
189 {
190 if (y1 > y2)
191 {
192 GX_SWAP_VALS(y1, y2);
193 }
194
195 if (y1 < clip -> gx_rectangle_top)
196 {
197 y1 = clip -> gx_rectangle_top;
198 }
199
200 if (y2 > clip -> gx_rectangle_bottom)
201 {
202 y2 = clip -> gx_rectangle_bottom;
203 }
204
205 Index = (x1 - xmin) << 1;
206 pLineEnds[Index] = y1;
207 pLineEnds[Index + 1] = y2;
208 }
209 }
210
211 curx++;
212 yi = (INT)(r * r) - curx * curx;
213 error = (cury << 8) - (INT)(_gx_utility_math_sqrt((UINT)(yi << 10)) << 3);
214
215 while (error >= 255)
216 {
217 error -= 255;
218 cury--;
219 }
220 }
221
222 if (pixelmap)
223 {
224 if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
225 {
226 skip_line = (xmax - (xcenter - (INT)r) + 1) % pixelmap -> gx_pixelmap_width;
227
228 if (skip_line)
229 {
230 skip_line = pixelmap -> gx_pixelmap_width - skip_line;
231 }
232
233 x1 = xmax;
234 xsign = -1;
235 Index = (width - 1) * 2;
236 }
237 else
238 {
239 skip_line = (xmin - clip -> gx_rectangle_left);
240
241 x1 = xmin;
242 xsign = 1;
243 Index = 0;
244 }
245
246 if (skip_line)
247 {
248
249 info.draw = GX_FALSE;
250 while (skip_line--)
251 {
252 display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
253 }
254 }
255
256 info.draw = GX_TRUE;
257 ypos = ycenter - (INT)r;
258
259 for (curx = xmin; curx <= xmax; curx++)
260 {
261 if (pLineEnds[Index] <= pLineEnds[Index + 1])
262 {
263 info.x_offset = pLineEnds[Index] - ypos;
264 display -> gx_display_driver_horizontal_pixelmap_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], x1, &info);
265 }
266
267 x1 += xsign;
268 Index += xsign;
269 Index += xsign;
270 }
271 }
272 else
273 {
274 Index = 0;
275 fill_color = brush -> gx_brush_fill_color;
276
277 for (curx = xmin; curx <= xmax; curx++)
278 {
279 if (pLineEnds[Index] <= pLineEnds[Index + 1])
280 {
281 display -> gx_display_driver_vertical_line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], curx, 1, fill_color);
282 }
283 Index += 2;
284 }
285 }
286 }
287 #endif
288
289