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