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_utility.h"
28 #include "gx_display.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _gx_display_driver_generic_aliased_wide_line_draw   PORTABLE C      */
36 /*                                                           6.1.3        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Kenneth Maxwell, Microsoft Corporation                              */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*   Generic display driver function for aliased wide line.               */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    context                               Drawing context               */
48 /*    xstart                                x-coord of endpoint           */
49 /*    ystart                                y-coord of endpoint           */
50 /*    xend                                  x-coord of endpoint           */
51 /*    yend                                  y-coord of endpoint           */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    None                                                                */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    [gx_display_driver_simple_wide_line_draw]                           */
60 /*                                          Basic display driver wide     */
61 /*                                            line draw function          */
62 /*    _gx_display_driver_generic_wide_line_points_calculate               */
63 /*                                          Calculate corners of wide line*/
64 /*    _gx_display_driver_generic_aliased_filled_circle_draw               */
65 /*                                          Basic display driver aliased  */
66 /*                                            circle fill function        */
67 /*    _gx_display_driver_generic_wide_line_fill                           */
68 /*                                          Basic display driver wide line*/
69 /*                                            draw function               */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    GUIX Internal Code                                                  */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
80 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*  12-31-2020     Kenneth Maxwell          Modified comment(s),          */
83 /*                                            supported display rotation, */
84 /*                                            resulting in version 6.1.3  */
85 /*                                                                        */
86 /**************************************************************************/
_gx_display_driver_generic_aliased_wide_line_draw(GX_DRAW_CONTEXT * context,INT xstart,INT ystart,INT xend,INT yend)87 VOID _gx_display_driver_generic_aliased_wide_line_draw(GX_DRAW_CONTEXT *context, INT xstart,
88                                                        INT ystart, INT xend, INT yend)
89 {
90 GX_DISPLAY     *display = context -> gx_draw_context_display;
91 INT             brush_width = context -> gx_draw_context_brush.gx_brush_width;
92 GX_FIXED_POINT *line_points;
93 GX_FIXED_VAL    sxcenter;
94 GX_FIXED_VAL    sycenter;
95 GX_FIXED_VAL    excenter;
96 GX_FIXED_VAL    eycenter;
97 GX_RECTANGLE    clip_rect;
98 
99 #if defined(GX_BRUSH_ALPHA_SUPPORT)
100 GX_UBYTE old_alpha;
101     old_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
102     context -> gx_draw_context_brush.gx_brush_alpha = GX_ALPHA_VALUE_OPAQUE;
103 #endif
104     /* calculate the corners of this line, save them
105        to our points array
106      */
107     if (!(context -> gx_draw_context_display -> gx_display_driver_pixel_blend))
108     {
109         display -> gx_display_driver_simple_wide_line_draw(context, xstart, ystart, xend, yend);
110         return;
111     }
112 
113     if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ROUND) &&
114         (brush_width > 2))
115     {
116         sxcenter = GX_FIXED_VAL_MAKE(xstart);
117         sycenter = GX_FIXED_VAL_MAKE(ystart);
118         excenter = GX_FIXED_VAL_MAKE(xend);
119         eycenter = GX_FIXED_VAL_MAKE(yend);
120 
121         if (!(brush_width & 0x01))
122         {
123             if (ystart == yend)
124             {
125                 /* Horizontal line. */
126                 sycenter -= GX_FIXED_VAL_HALF;
127                 eycenter -= GX_FIXED_VAL_HALF;
128             }
129             else if (xstart == xend)
130             {
131                 /* Vertical line. */
132                 sxcenter -= GX_FIXED_VAL_HALF;
133                 excenter -= GX_FIXED_VAL_HALF;
134             }
135         }
136 
137         _gx_display_driver_generic_aliased_filled_circle_draw(context, sxcenter, sycenter,
138                                                               GX_FIXED_VAL_MAKE(brush_width) >> 1);
139 
140         _gx_display_driver_generic_aliased_filled_circle_draw(context, excenter, eycenter,
141                                                               GX_FIXED_VAL_MAKE(brush_width) >> 1);
142     }
143 
144     if (ystart == yend)
145     {
146         /* Horizontal line. */
147 
148         if (xstart > xend)
149         {
150             GX_SWAP_VALS(xstart, xend);
151         }
152 
153         clip_rect.gx_rectangle_left = (GX_VALUE)xstart;
154         clip_rect.gx_rectangle_right = (GX_VALUE)xend;
155         clip_rect.gx_rectangle_top = (GX_VALUE)(ystart - (brush_width >> 1));
156         clip_rect.gx_rectangle_bottom = (GX_VALUE)(clip_rect.gx_rectangle_top + brush_width - 1);
157 
158         if (_gx_utility_rectangle_overlap_detect(&clip_rect, context -> gx_draw_context_clip, &clip_rect))
159         {
160             display -> gx_display_driver_horizontal_line_draw(context,
161                                                               clip_rect.gx_rectangle_left,
162                                                               clip_rect.gx_rectangle_right,
163                                                               clip_rect.gx_rectangle_top,
164                                                               clip_rect.gx_rectangle_bottom - clip_rect.gx_rectangle_top + 1,
165                                                               context -> gx_draw_context_brush.gx_brush_line_color);
166         }
167     }
168     else if (xstart == xend)
169     {
170         /* Vertical line. */
171 
172         if (ystart > yend)
173         {
174             GX_SWAP_VALS(ystart, yend);
175         }
176 
177         clip_rect.gx_rectangle_left = (GX_VALUE)(xstart - (brush_width >> 1));
178         clip_rect.gx_rectangle_right = (GX_VALUE)(clip_rect.gx_rectangle_left + brush_width - 1);
179         clip_rect.gx_rectangle_top = (GX_VALUE)ystart;
180         clip_rect.gx_rectangle_bottom = (GX_VALUE)yend;
181 
182         if (_gx_utility_rectangle_overlap_detect(&clip_rect, context -> gx_draw_context_clip, &clip_rect))
183         {
184             display -> gx_display_driver_vertical_line_draw(context,
185                                                             clip_rect.gx_rectangle_top,
186                                                             clip_rect.gx_rectangle_bottom,
187                                                             clip_rect.gx_rectangle_left,
188                                                             clip_rect.gx_rectangle_right - clip_rect.gx_rectangle_left + 1,
189                                                             context -> gx_draw_context_brush.gx_brush_line_color);
190         }
191     }
192     else
193     {
194         line_points = _gx_display_driver_generic_wide_line_points_calculate(context, xstart, ystart,
195                                                                             xend, yend, brush_width, GX_TRUE);
196 
197         if (display -> gx_display_rotation_angle)
198         {
199             _gx_display_driver_generic_rotated_wide_line_fill(context, line_points);
200         }
201         else
202         {
203             _gx_display_driver_generic_wide_line_fill(context, line_points);
204         }
205     }
206 
207 #if defined(GX_BRUSH_ALPHA_SUPPORT)
208     context -> gx_draw_context_brush.gx_brush_alpha = old_alpha;
209 #endif
210 }
211 
212