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