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_wide_line_fill PORTABLE C */
39 /* 6.1 */
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 /* 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 /**************************************************************************/
_gx_display_driver_generic_wide_line_fill(GX_DRAW_CONTEXT * context,GX_FIXED_POINT * pPoints)79 VOID _gx_display_driver_generic_wide_line_fill(GX_DRAW_CONTEXT *context, GX_FIXED_POINT *pPoints)
80 {
81 /*
82 Use Breshenham's line to compute the points along each line that bounds
83 the wide line and save the points to an array. Then draw horizontal lines
84 to connect the points.
85 */
86
87 GX_FIXED_POINT *pGet = pPoints;
88 INT *pLineEnds;
89 INT ymin;
90 INT ymax;
91 INT xstart;
92 INT xend;
93 INT ystart;
94 INT yend;
95 INT curx;
96 INT cury;
97 INT test;
98 GX_FIXED_VAL dx;
99 GX_FIXED_VAL dy;
100 INT Index;
101 INT loop;
102 INT height;
103 INT xsign;
104 INT ysign;
105 INT decision;
106 INT shift;
107 VOID (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
108 GX_RECTANGLE *clip = context -> gx_draw_context_clip;
109 GX_COLOR linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
110 GX_BOOL aliased = GX_FALSE;
111 INT x_fraction;
112 INT y_fraction;
113
114 if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
115 context -> gx_draw_context_display -> gx_display_driver_pixel_blend)
116 {
117 aliased = GX_TRUE;
118 }
119
120 ymin = GX_FIXED_VAL_TO_INT(pPoints[1].y);
121 ymax = GX_FIXED_VAL_RND_UP(pPoints[3].y);
122
123 if (ymin < clip -> gx_rectangle_top)
124 {
125 ymin = clip -> gx_rectangle_top;
126 }
127
128 if (ymax > clip -> gx_rectangle_bottom)
129 {
130 ymax = clip -> gx_rectangle_bottom;
131 }
132
133 height = ymax - ymin + 1;
134
135 pLineEnds = _gx_system_scratchpad;
136
137 /* default the point array to being off the screen on both sides: */
138
139 for (loop = 0; loop < height * 2; loop += 2)
140 {
141 pLineEnds[loop] = 2000;
142 pLineEnds[loop + 1] = 0;
143 }
144
145 /* Fill in the point array by using Breshenhams line for
146 all 4 sides of the bounding rectangle
147 */
148
149 for (loop = 0; loop < 4; loop++)
150 {
151 xstart = pGet -> x;
152 ystart = pGet -> y;
153 pGet++;
154 xend = pGet -> x;
155 yend = pGet -> y;
156 dx = GX_ABS(xend - xstart);
157 dy = GX_ABS(yend - ystart);
158
159 xsign = ysign = 1;
160
161 if (((dx >= dy && (xstart > xend)) ||
162 ((dy > dx) && ystart > yend)))
163 {
164 GX_SWAP_VALS(xend, xstart);
165 GX_SWAP_VALS(yend, ystart);
166 }
167 if (dx)
168 {
169 xsign = (xend - xstart) / dx;
170 }
171 if (dy)
172 {
173 ysign = (yend - ystart) / dy;
174 }
175
176 x_fraction = (xstart & GX_FIXED_VAL_FRACTION_MASK);
177 y_fraction = (ystart & GX_FIXED_VAL_FRACTION_MASK);
178
179 shift = 0;
180
181 if (dx >= dy)
182 {
183 if (ysign < 0)
184 {
185 cury = GX_FIXED_VAL_RND_UP(ystart);
186
187 if (y_fraction)
188 {
189 y_fraction = GX_FIXED_VAL_ONE - y_fraction;
190 }
191 }
192 else
193 {
194 cury = GX_FIXED_VAL_TO_INT(ystart);
195 }
196
197 decision = (y_fraction * dx - x_fraction * dy) / GX_FIXED_VAL_ONE;
198
199 if (decision < 0)
200 {
201 decision += dx;
202 cury -= ysign;
203 }
204
205 xstart = GX_FIXED_VAL_TO_INT(xstart);
206
207 if (aliased)
208 {
209 xend = GX_FIXED_VAL_TO_INT(xend);
210
211 if (x_fraction)
212 {
213 xstart++;
214 decision += dy;
215 }
216
217 if (dy)
218 {
219 if ((loop == 1) || (loop == 2))
220 {
221 shift = ysign;
222 }
223 }
224 }
225 else
226 {
227 xend = GX_FIXED_VAL_RND(xend);
228
229 if (x_fraction >= GX_FIXED_VAL_HALF)
230 {
231 xstart++;
232 decision += dy;
233 }
234
235 decision += (dx >> 1);
236 if (decision >= dx)
237 {
238 decision -= dx;
239 cury += ysign;
240 }
241 }
242
243 for (curx = xstart; curx <= xend; curx++, decision += dy)
244 {
245 if (decision >= dx)
246 {
247 decision -= dx;
248 cury += ysign;
249 }
250
251 test = cury + shift;
252
253 if ((test >= ymin) && (test <= ymax))
254 {
255 Index = (test - ymin) << 1;
256
257 if (curx < pLineEnds[Index])
258 {
259 pLineEnds[Index] = curx;
260 }
261
262 if (curx > pLineEnds[Index + 1])
263 {
264 pLineEnds[Index + 1] = curx;
265 }
266 }
267 }
268
269 }
270 else
271 {
272 if (xsign < 0)
273 {
274 curx = GX_FIXED_VAL_RND_UP(xstart);
275
276 if (x_fraction)
277 {
278 x_fraction = GX_FIXED_VAL_FRACTION_MASK - x_fraction;
279 }
280 }
281 else
282 {
283 curx = GX_FIXED_VAL_TO_INT(xstart);
284 }
285
286 decision = (x_fraction * dy - y_fraction * dx) / GX_FIXED_VAL_ONE;
287
288 if (decision < 0)
289 {
290 decision += dy;
291 curx -= xsign;
292 }
293
294 ystart = GX_FIXED_VAL_TO_INT(ystart);
295
296 if (aliased)
297 {
298 yend = GX_FIXED_VAL_TO_INT(yend);
299
300 if (y_fraction)
301 {
302 ystart++;
303 decision += dx;
304 }
305
306 if (dx)
307 {
308 if (loop == 2 || loop == 3)
309 {
310 shift = xsign;
311 }
312 }
313 }
314 else
315 {
316 yend = GX_FIXED_VAL_RND(yend);
317
318 if (y_fraction >= GX_FIXED_VAL_HALF)
319 {
320 ystart++;
321 decision += dx;
322 }
323
324 decision += (dy >> 1);
325
326 if (decision >= dy)
327 {
328 decision -= dy;
329 curx += xsign;
330 }
331 }
332
333 for (cury = ystart; cury <= yend; cury++, decision += dx)
334 {
335 if (decision >= dy)
336 {
337 decision -= dy;
338 curx += xsign;
339 }
340
341 if ((cury >= ymin) && (cury <= ymax))
342 {
343 Index = (cury - ymin) << 1;
344
345 test = curx + shift;
346 if (test < pLineEnds[Index])
347 {
348 pLineEnds[Index] = test;
349 }
350
351 if (test > pLineEnds[Index + 1])
352 {
353 pLineEnds[Index + 1] = test;
354 }
355 }
356 }
357 }
358 }
359
360 Index = 0;
361 line_draw = context -> gx_draw_context_display -> gx_display_driver_horizontal_line_draw;
362
363 for (cury = ymin; cury <= ymax; cury++)
364 {
365 if (pLineEnds[Index] < clip -> gx_rectangle_left)
366 {
367 pLineEnds[Index] = clip -> gx_rectangle_left;
368 }
369
370 if (pLineEnds[Index + 1] > clip -> gx_rectangle_right)
371 {
372 pLineEnds[Index + 1] = clip -> gx_rectangle_right;
373 }
374
375 if (pLineEnds[Index] <= pLineEnds[Index + 1])
376 {
377 line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, 1, linecolor);
378 }
379 Index += 2;
380 }
381 }
382
383