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