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 /* Internal scratch area. */
32 static GX_FIXED_POINT LinePoints[5];
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _gx_display_driver_generic_wide_line_points_calculate               */
39 /*                                                        PORTABLE C      */
40 /*                                                           6.1          */
41 /*                                                                        */
42 /*  AUTHOR                                                                */
43 /*                                                                        */
44 /*    Kenneth Maxwell, Microsoft Corporation                              */
45 /*                                                                        */
46 /*  DESCRIPTION                                                           */
47 /*                                                                        */
48 /*    Calculate corners of wide line. Used by all versions (anti-aliased  */
49 /*    or not, square or round ends) of wide line drawinggeneric display   */
50 /*    driver wide line drawing function.                                  */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    context                               Drawing context               */
55 /*    xStart                                x-coord of endpoint           */
56 /*    yStart                                y-coord of endpoint           */
57 /*    xEnd                                  x-coord of endpoint           */
58 /*    yEnd                                  y-coord of endpoint           */
59 /*    outline                               Whether or not to draw        */
60 /*                                            outline                     */
61 /*                                                                        */
62 /*  OUTPUT                                                                */
63 /*                                                                        */
64 /*    GX_POINT*                             Calculated end points         */
65 /*                                                                        */
66 /*  CALLS                                                                 */
67 /*                                                                        */
68 /*    GX_ABS                                Compute the absolute value    */
69 /*    GX_SWAP_VALS                          Swap two values               */
70 /*    GX_FIXED_VAL_MAKE                                                   */
71 /*    GX_FIXED_VAL_RND                                                    */
72 /*    _gx_utility_math_sqrt                 Compute the square root value */
73 /*    [gx_display_driver_anti_aliased_line_draw                           */
74 /*                                          Driver function that draws    */
75 /*                                            anti-aliased lines.         */
76 /*                                                                        */
77 /*  CALLED BY                                                             */
78 /*                                                                        */
79 /*    _gx_display_driver_generic_simple_wide_line_draw                    */
80 /*    _gx_display_driver_generic_aliased_wide_line_draw                   */
81 /*                                                                        */
82 /*  RELEASE HISTORY                                                       */
83 /*                                                                        */
84 /*    DATE              NAME                      DESCRIPTION             */
85 /*                                                                        */
86 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
87 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
88 /*                                            resulting in version 6.1    */
89 /*                                                                        */
90 /**************************************************************************/
_gx_display_driver_generic_wide_line_points_calculate(GX_DRAW_CONTEXT * context,INT xStart,INT yStart,INT xEnd,INT yEnd,INT brush_width,GX_BOOL outline)91 GX_FIXED_POINT *_gx_display_driver_generic_wide_line_points_calculate(GX_DRAW_CONTEXT *context, INT xStart, INT yStart,
92                                                                       INT xEnd, INT yEnd, INT brush_width, GX_BOOL outline)
93 {
94 GX_FIXED_VAL   distance;
95 GX_FIXED_VAL   brush_distance;
96 GX_FIXED_POINT FixedPoints[5];
97 INT            LineDirection[4];
98 int            xsign;
99 int            ysign;
100 int            xside;
101 int            yside;
102 VOID           (*aliased_line)(GX_DRAW_CONTEXT *context, GX_FIXED_VAL x1, GX_FIXED_VAL y1, GX_FIXED_VAL x2, GX_FIXED_VAL y2);
103 
104 int            dx = GX_ABS(xEnd - xStart);
105 int            dy = GX_ABS(yEnd - yStart);
106 
107     if (((dx >= dy && (xStart > xEnd)) || ((dy > dx) && yStart > yEnd)))
108     {
109         GX_SWAP_VALS(xEnd, xStart);
110         GX_SWAP_VALS(yEnd, yStart);
111     }
112 
113     distance = (GX_FIXED_VAL)_gx_utility_math_sqrt((UINT)(GX_FIXED_VAL_MAKE(dx * dx) + GX_FIXED_VAL_MAKE(dy * dy)));
114     distance <<= (GX_FIXED_VAL_SHIFT >> 1);
115     brush_distance = GX_FIXED_VAL_MAKE(brush_width - 1);
116     brush_distance >>= 1;
117     xsign = ysign = 1;
118 
119     if (dx)
120     {
121         xsign = (xEnd - xStart) / dx;
122     }
123     if (dy)
124     {
125         ysign = (yEnd - yStart) / dy;
126     }
127 
128     xside = dy;
129     xside *= brush_distance;
130     xside /= (distance >> GX_FIXED_VAL_SHIFT);
131     xside *= xsign;
132 
133     yside = dx;
134     yside *= brush_distance;
135     yside /= (distance >> GX_FIXED_VAL_SHIFT);
136     yside *= ysign;
137 
138     LineDirection[0] = 0;
139     LineDirection[1] = 1;
140     LineDirection[2] = 2;
141     LineDirection[3] = 3;
142 
143     if (yEnd < yStart)
144     {
145         LineDirection[1] = 3;
146         LineDirection[3] = 1;
147     }
148 
149     if (xEnd < xStart)
150     {
151         LineDirection[0] = 2;
152         LineDirection[2] = 0;
153     }
154 
155     FixedPoints[LineDirection[0]].x = GX_FIXED_VAL_MAKE(xStart) - xside;
156     FixedPoints[LineDirection[0]].y = GX_FIXED_VAL_MAKE(yStart) + yside;
157     FixedPoints[LineDirection[1]].x = GX_FIXED_VAL_MAKE(xStart) + xside;
158     FixedPoints[LineDirection[1]].y = GX_FIXED_VAL_MAKE(yStart) - yside;
159     FixedPoints[LineDirection[2]].x = GX_FIXED_VAL_MAKE(xEnd) + xside;
160     FixedPoints[LineDirection[2]].y = GX_FIXED_VAL_MAKE(yEnd) - yside;
161     FixedPoints[LineDirection[3]].x = GX_FIXED_VAL_MAKE(xEnd) - xside;
162     FixedPoints[LineDirection[3]].y = GX_FIXED_VAL_MAKE(yEnd) + yside;
163 
164     LinePoints[0] = FixedPoints[0];
165     LinePoints[1] = FixedPoints[1];
166     LinePoints[2] = FixedPoints[2];
167     LinePoints[3] = FixedPoints[3];
168 
169     if (outline)
170     {
171         aliased_line = _gx_display_driver_generic_aliased_fixed_point_line_draw;
172 
173         aliased_line(context, FixedPoints[0].x,
174                      FixedPoints[0].y,
175                      FixedPoints[1].x,
176                      FixedPoints[1].y);
177 
178         aliased_line(context, FixedPoints[1].x,
179                      FixedPoints[1].y,
180                      FixedPoints[2].x,
181                      FixedPoints[2].y);
182 
183         aliased_line(context, FixedPoints[2].x,
184                      FixedPoints[2].y,
185                      FixedPoints[3].x,
186                      FixedPoints[3].y);
187 
188         aliased_line(context, FixedPoints[3].x,
189                      FixedPoints[3].y,
190                      FixedPoints[0].x,
191                      FixedPoints[0].y);
192     }
193 
194     /* close the polygon */
195     LinePoints[4] = LinePoints[0];
196 
197     return(LinePoints);
198 }
199 
200