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