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