1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** GUIX Component */
17 /** */
18 /** Display Management (Display) */
19 /** */
20 /**************************************************************************/
21
22
23
24 #define GX_SOURCE_CODE
25
26
27 /* Include necessary system files. */
28
29 #include "gx_api.h"
30 #include "gx_utility.h"
31 #include "gx_display.h"
32 #include "gx_system.h"
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _gx_display_driver_generic_rotated_wide_line_fill PORTABLE C */
39 /* 6.1.3 */
40 /* AUTHOR */
41 /* */
42 /* Kenneth Maxwell, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* Fill a wide line after the four corner points have been calculated. */
47 /* */
48 /* INPUT */
49 /* */
50 /* context Drawing context */
51 /* pPoints Pre-computed end points */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* None */
56 /* */
57 /* CALLS */
58 /* */
59 /* GX_ABS Compute the absolute value */
60 /* GX_SWAP_VALUE Swap two values */
61 /* [_gx_display_driver_horizontal_line_draw] */
62 /* Driver for horizontal line */
63 /* draw */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* _gx_display_driver_generic_simple_wide_line_draw */
68 /* _gx_display_driver_generic_aliased_wide_line_draw */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 12-31-2020 Kenneth Maxwell Initial Version 6.1.3 */
75 /* */
76 /**************************************************************************/
_gx_display_driver_generic_rotated_wide_line_fill(GX_DRAW_CONTEXT * context,GX_FIXED_POINT * pPoints)77 VOID _gx_display_driver_generic_rotated_wide_line_fill(GX_DRAW_CONTEXT *context, GX_FIXED_POINT *pPoints)
78 {
79 /*
80 Use Breshenham's line to compute the points along each line that bounds
81 the wide line and save the points to an array. Then draw horizontal lines
82 to connect the points.
83 */
84
85 GX_FIXED_POINT *pGet = pPoints;
86 INT *pLineEnds;
87 INT xmin;
88 INT xmax;
89 INT xstart;
90 INT xend;
91 INT ystart;
92 INT yend;
93 INT curx;
94 INT cury;
95 INT test;
96 GX_FIXED_VAL dx;
97 GX_FIXED_VAL dy;
98 INT Index;
99 INT loop;
100 INT width;
101 INT xsign;
102 INT ysign;
103 INT decision;
104 INT shift;
105 VOID (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
106 GX_RECTANGLE *clip = context -> gx_draw_context_clip;
107 GX_COLOR linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
108 GX_BOOL aliased = GX_FALSE;
109 INT x_fraction;
110 INT y_fraction;
111
112 if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
113 context -> gx_draw_context_display -> gx_display_driver_pixel_blend)
114 {
115 aliased = GX_TRUE;
116 }
117
118 xmin = GX_FIXED_VAL_TO_INT(pPoints[0].x);
119 xmax = GX_FIXED_VAL_RND_UP(pPoints[2].x);
120
121 if (xmin < clip -> gx_rectangle_left)
122 {
123 xmin = clip -> gx_rectangle_left;
124 }
125
126 if (xmax > clip -> gx_rectangle_right)
127 {
128 xmax = clip -> gx_rectangle_right;
129 }
130
131 width = xmax - xmin + 1;
132
133 pLineEnds = _gx_system_scratchpad;
134
135 /* default the point array to being off the screen on both sides: */
136
137 for (loop = 0; loop < width * 2; loop += 2)
138 {
139 pLineEnds[loop] = 2000;
140 pLineEnds[loop + 1] = 0;
141 }
142
143 /* Fill in the point array by using Breshenhams line for
144 all 4 sides of the bounding rectangle
145 */
146
147 for (loop = 0; loop < 4; loop++)
148 {
149 xstart = pGet -> x;
150 ystart = pGet -> y;
151 pGet++;
152 xend = pGet -> x;
153 yend = pGet -> y;
154 dx = GX_ABS(xend - xstart);
155 dy = GX_ABS(yend - ystart);
156
157 xsign = ysign = 1;
158
159 if (((dx >= dy && (xstart > xend)) ||
160 ((dy > dx) && ystart > yend)))
161 {
162 GX_SWAP_VALS(xend, xstart);
163 GX_SWAP_VALS(yend, ystart);
164 }
165 if (dx)
166 {
167 xsign = (xend - xstart) / dx;
168 }
169 if (dy)
170 {
171 ysign = (yend - ystart) / dy;
172 }
173
174 x_fraction = (xstart & GX_FIXED_VAL_FRACTION_MASK);
175 y_fraction = (ystart & GX_FIXED_VAL_FRACTION_MASK);
176
177 shift = 0;
178
179 if (dx >= dy)
180 {
181 if (ysign < 0)
182 {
183 cury = GX_FIXED_VAL_RND_UP(ystart);
184
185 if (y_fraction)
186 {
187 y_fraction = GX_FIXED_VAL_ONE - y_fraction;
188 }
189 }
190 else
191 {
192 cury = GX_FIXED_VAL_TO_INT(ystart);
193 }
194
195 decision = (y_fraction * dx - x_fraction * dy) / GX_FIXED_VAL_ONE;
196
197 if (decision < 0)
198 {
199 decision += dx;
200 cury -= ysign;
201 }
202
203 xstart = GX_FIXED_VAL_TO_INT(xstart);
204
205 if (aliased)
206 {
207 xend = GX_FIXED_VAL_TO_INT(xend);
208
209 if (x_fraction)
210 {
211 xstart++;
212 decision += dy;
213 }
214
215 if (dy)
216 {
217 if ((loop == 1) || (loop == 2))
218 {
219 shift = ysign;
220 }
221 }
222 }
223 else
224 {
225 xend = GX_FIXED_VAL_RND(xend);
226
227 if (x_fraction >= GX_FIXED_VAL_HALF)
228 {
229 xstart++;
230 decision += dy;
231 }
232
233 decision += (dx >> 1);
234 if (decision >= dx)
235 {
236 decision -= dx;
237 cury += ysign;
238 }
239 }
240
241 for (curx = xstart; curx <= xend; curx++, decision += dy)
242 {
243 if (decision >= dx)
244 {
245 decision -= dx;
246 cury += ysign;
247 }
248
249 if ((curx >= xmin) && (curx <= xmax))
250 {
251 Index = (curx - xmin) << 1;
252
253 test = cury + shift;
254 if (test < pLineEnds[Index])
255 {
256 pLineEnds[Index] = test;
257 }
258
259 if (test > pLineEnds[Index + 1])
260 {
261 pLineEnds[Index + 1] = test;
262 }
263 }
264 }
265 }
266 else
267 {
268 if (xsign < 0)
269 {
270 curx = GX_FIXED_VAL_RND_UP(xstart);
271
272 if (x_fraction)
273 {
274 x_fraction = GX_FIXED_VAL_FRACTION_MASK - x_fraction;
275 }
276 }
277 else
278 {
279 curx = GX_FIXED_VAL_TO_INT(xstart);
280 }
281
282 decision = (x_fraction * dy - y_fraction * dx) / GX_FIXED_VAL_ONE;
283
284 if (decision < 0)
285 {
286 decision += dy;
287 curx -= xsign;
288 }
289
290 ystart = GX_FIXED_VAL_TO_INT(ystart);
291
292 if (aliased)
293 {
294 yend = GX_FIXED_VAL_TO_INT(yend);
295
296 if (y_fraction)
297 {
298 ystart++;
299 decision += dx;
300 }
301
302 if (dx)
303 {
304 if (loop == 2 || loop == 3)
305 {
306 shift = xsign;
307 }
308 }
309 }
310 else
311 {
312 yend = GX_FIXED_VAL_RND(yend);
313
314 if (y_fraction >= GX_FIXED_VAL_HALF)
315 {
316 ystart++;
317 decision += dx;
318 }
319
320 decision += (dy >> 1);
321
322 if (decision >= dy)
323 {
324 decision -= dy;
325 curx += xsign;
326 }
327 }
328
329 for (cury = ystart; cury <= yend; cury++, decision += dx)
330 {
331 if (decision >= dy)
332 {
333 decision -= dy;
334 curx += xsign;
335 }
336
337 test = curx + shift;
338
339 if ((test >= xmin) && (test <= xmax))
340 {
341 Index = (test - xmin) << 1;
342
343 if (cury < pLineEnds[Index])
344 {
345 pLineEnds[Index] = cury;
346 }
347
348 if (cury > pLineEnds[Index + 1])
349 {
350 pLineEnds[Index + 1] = cury;
351 }
352 }
353 }
354 }
355 }
356
357 Index = 0;
358 line_draw = context -> gx_draw_context_display -> gx_display_driver_vertical_line_draw;
359
360 for (curx = xmin; curx <= xmax; curx++)
361 {
362 if (pLineEnds[Index] < clip -> gx_rectangle_top)
363 {
364 pLineEnds[Index] = clip -> gx_rectangle_top;
365 }
366
367 if (pLineEnds[Index + 1] > clip -> gx_rectangle_bottom)
368 {
369 pLineEnds[Index + 1] = clip -> gx_rectangle_bottom;
370 }
371
372 if (pLineEnds[Index] <= pLineEnds[Index + 1])
373 {
374 line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], curx, 1, linecolor);
375 }
376 Index += 2;
377 }
378 }
379
380