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 /**   Canvas Management (Canvas)                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29 #include "gx_display.h"
30 #include "gx_canvas.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _gx_display_driver_polygon_min_max_get              PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Kenneth Maxwell, Microsoft Corporation                              */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    Internal helper function that calculates the top most and bottom    */
46 /*    most y coordinate of the specified polygon.                         */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    vertex                            Array of points of the polygon,   */
51 /*                                        terminated by NULL entry        */
52 /*    num                               Number of points of polygon       */
53 /*    ymin                              Retrieved top most y coordinate   */
54 /*    ymax                              Retrieved bottom most y coordinate*/
55 /*    xmin                              Retrieved left most x coordinate  */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    None                                                                */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    None                                                                */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _gx_display_driver_generic_polygon_fill                             */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
74 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
75 /*                                            resulting in version 6.1    */
76 /*                                                                        */
77 /**************************************************************************/
_gx_display_driver_polygon_min_max_get(GX_POINT * vertex,INT num,INT * ymin,INT * ymax,INT * xmin)78 static VOID _gx_display_driver_polygon_min_max_get(GX_POINT *vertex, INT num, INT *ymin, INT *ymax, INT *xmin)
79 {
80 GX_VALUE index = (GX_VALUE)num;
81 INT      y_min;
82 INT      y_max;
83 INT      x_min;
84 
85     x_min = vertex[0].gx_point_x;
86     y_min = vertex[0].gx_point_y;
87     y_max = vertex[0].gx_point_y;
88 
89     while (index--)
90     {
91         if (vertex[index].gx_point_y < y_min)
92         {
93             y_min = vertex[index].gx_point_y;
94         }
95         else if (vertex[index].gx_point_y > y_max)
96         {
97             y_max = vertex[index].gx_point_y;
98         }
99 
100         if (vertex[index].gx_point_x < x_min)
101         {
102             x_min = vertex[index].gx_point_x;
103         }
104     }
105 
106     *ymin = y_min;
107     *ymax = y_max;
108     *xmin = x_min;
109 }
110 
111 /**************************************************************************/
112 /*                                                                        */
113 /*  FUNCTION                                               RELEASE        */
114 /*                                                                        */
115 /*    _gx_display_driver_polygon_new_edge_table_init      PORTABLE C      */
116 /*                                                           6.1          */
117 /*  AUTHOR                                                                */
118 /*                                                                        */
119 /*    Kenneth Maxwell, Microsoft Corporation                              */
120 /*                                                                        */
121 /*  DESCRIPTION                                                           */
122 /*                                                                        */
123 /*    Internal helper function that Initiates new edge table, which       */
124 /*    contain all the edges of the specified polygon.                     */
125 /*                                                                        */
126 /*  INPUT                                                                 */
127 /*                                                                        */
128 /*    vertex                            Array of points of the polygon,   */
129 /*                                        terminated by NULL entry        */
130 /*    num                               Number of points of polygon       */
131 /*    net                               Pointer to new edge table         */
132 /*    net_size                          New edge table size               */
133 /*                                                                        */
134 /*  OUTPUT                                                                */
135 /*                                                                        */
136 /*    None                                                                */
137 /*                                                                        */
138 /*  CALLS                                                                 */
139 /*                                                                        */
140 /*    None                                                                */
141 /*                                                                        */
142 /*  CALLED BY                                                             */
143 /*                                                                        */
144 /*    _gx_display_driver_generic_polygon_fill                             */
145 /*                                                                        */
146 /*  RELEASE HISTORY                                                       */
147 /*                                                                        */
148 /*    DATE              NAME                      DESCRIPTION             */
149 /*                                                                        */
150 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
151 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
152 /*                                            resulting in version 6.1    */
153 /*                                                                        */
154 /**************************************************************************/
_gx_display_driver_polygon_new_edge_table_init(GX_DRAW_CONTEXT * context,GX_POINT * vertex,INT num,GX_POLYGON_EDGE * net,INT * net_size)155 static VOID _gx_display_driver_polygon_new_edge_table_init(GX_DRAW_CONTEXT *context, GX_POINT *vertex, INT num, GX_POLYGON_EDGE *net, INT *net_size)
156 {
157 GX_POLYGON_EDGE edge;
158 INT             index;
159 GX_POINT        s_point;
160 GX_POINT        ss_point;
161 GX_POINT        e_point;
162 GX_POINT        ee_point;
163 GX_VALUE        net_index = 0;
164 
165     for (index = 0; index < num; index++)
166     {
167         s_point = vertex[index];
168         e_point = vertex[(index + 1) % num];
169         ss_point = vertex[(index - 1 + num) % num];
170         ee_point = vertex[(index + 2) % num];
171 
172         /* Skip horizontal line. */
173         if (s_point.gx_point_y != e_point.gx_point_y)
174         {
175             /* Add one edge to new edge table, s_point and e_point are two endpoints of the added edge. */
176 
177             edge.gx_polygon_edge_dx = GX_ABS(e_point.gx_point_x - s_point.gx_point_x);
178             edge.gx_polygon_edge_dy = GX_ABS(e_point.gx_point_y - s_point.gx_point_y);
179 
180             if (context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS)
181             {
182                 edge.gx_polygon_edge_x_decision = 0;
183             }
184             else
185             {
186                 edge.gx_polygon_edge_x_decision = edge.gx_polygon_edge_dy >> 1;
187             }
188 
189             if (((e_point.gx_point_x > s_point.gx_point_x) && (e_point.gx_point_y > s_point.gx_point_y)) ||
190                 ((e_point.gx_point_x < s_point.gx_point_x) && (e_point.gx_point_y < s_point.gx_point_y)))
191             {
192                 edge.gx_polygon_edge_sign = 1;
193             }
194             else
195             {
196                 edge.gx_polygon_edge_sign = -1;
197             }
198 
199             if (e_point.gx_point_y > s_point.gx_point_y)
200             {
201                 /* Set xi value, which is the x coordinate value of the edge's toppest point. */
202                 edge.gx_polygon_edge_xi = s_point.gx_point_x;
203 
204                 /* Set max y coordinate of the edge. */
205                 edge.gx_polygon_edge_ymax = e_point.gx_point_y;
206 
207                 if (ee_point.gx_point_y >= e_point.gx_point_y)
208                 {
209                     /* If e_point isn't the bottom most point, reset ymax to ymax - 1.
210                        To avoid producing 2 intersections when scan line comes to the vertex point. */
211                     edge.gx_polygon_edge_ymax -= 1;
212                 }
213 
214                 edge.gx_polygon_edge_ymin = s_point.gx_point_y;
215             }
216             else
217             {
218                 /* Set xi value. */
219                 edge.gx_polygon_edge_xi = e_point.gx_point_x;
220 
221                 /* Set max y coordinate of the edge. */
222                 edge.gx_polygon_edge_ymax = s_point.gx_point_y;
223 
224                 if (ss_point.gx_point_y >= s_point.gx_point_y)
225                 {
226                     /* If e_point isn't the bottom most point, reset ymax to ymax - 1. */
227                     edge.gx_polygon_edge_ymax -= 1;
228                 }
229 
230                 edge.gx_polygon_edge_ymin = e_point.gx_point_y;
231             }
232 
233             net[net_index++] = edge;
234         }
235     }
236 
237     *net_size = net_index;
238 }
239 
240 /**************************************************************************/
241 /*                                                                        */
242 /*  FUNCTION                                               RELEASE        */
243 /*                                                                        */
244 /*    _gx_display_driver_polygon_active_edge_insert       PORTABLE C      */
245 /*                                                           6.1          */
246 /*  AUTHOR                                                                */
247 /*                                                                        */
248 /*    Kenneth Maxwell, Microsoft Corporation                              */
249 /*                                                                        */
250 /*  DESCRIPTION                                                           */
251 /*                                                                        */
252 /*    Internal helper function that Inserts an edge from new edge table to*/
253 /*    active edge table.                                                  */
254 /*                                                                        */
255 /*  INPUT                                                                 */
256 /*                                                                        */
257 /*    aet                               Pointer to active edge table      */
258 /*    net                               Pointer to new edge table         */
259 /*    y                                 Y coordinate of current scan line */
260 /*    net                               Pointer to new edge table         */
261 /*    net_size                          New edge table size               */
262 /*    aet_size                          Retured active edge table size    */
263 /*                                                                        */
264 /*  OUTPUT                                                                */
265 /*                                                                        */
266 /*    None                                                                */
267 /*                                                                        */
268 /*  CALLS                                                                 */
269 /*                                                                        */
270 /*    None                                                                */
271 /*                                                                        */
272 /*  CALLED BY                                                             */
273 /*                                                                        */
274 /*    _gx_display_driver_generic_polygon_fill                             */
275 /*                                                                        */
276 /*  RELEASE HISTORY                                                       */
277 /*                                                                        */
278 /*    DATE              NAME                      DESCRIPTION             */
279 /*                                                                        */
280 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
281 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
282 /*                                            resulting in version 6.1    */
283 /*                                                                        */
284 /**************************************************************************/
_gx_display_driver_polygon_active_edge_insert(GX_POLYGON_EDGE * aet,GX_POLYGON_EDGE * net,INT y,INT net_size,INT * aet_size)285 static VOID _gx_display_driver_polygon_active_edge_insert(GX_POLYGON_EDGE *aet, GX_POLYGON_EDGE *net, INT y, INT net_size, INT *aet_size)
286 {
287 GX_VALUE ni = (GX_VALUE)(net_size - 1);
288 GX_VALUE ai;
289 INT      active_edge_table_size = *aet_size;
290 
291     for (ni = 0; ni < net_size; ni++)
292     {
293         if (net[ni].gx_polygon_edge_ymin == y)
294         {
295             /* If the toppest y coordinate value of the edge equals to the current scan line y,
296                Insert the edge to active edge table, and increase aet size by 1. */
297 
298             ai = (GX_VALUE)(active_edge_table_size - 1);
299             while ((ai >= 0) && (net[ni].gx_polygon_edge_xi < aet[ai].gx_polygon_edge_xi))
300             {
301                 aet[ai + 1] = aet[ai];
302                 ai--;
303             }
304             aet[ai + 1] = net[ni];
305             active_edge_table_size++;
306         }
307     }
308 
309     *aet_size = active_edge_table_size;
310 }
311 
312 /**************************************************************************/
313 /*                                                                        */
314 /*  FUNCTION                                               RELEASE        */
315 /*                                                                        */
316 /*    _gx_display_driver_polygon_non_active_edge_remove   PORTABLE C      */
317 /*                                                           6.1          */
318 /*  AUTHOR                                                                */
319 /*                                                                        */
320 /*    Kenneth Maxwell, Microsoft Corporation                              */
321 /*                                                                        */
322 /*  DESCRIPTION                                                           */
323 /*                                                                        */
324 /*    Internal helper function that removes an edge from active edge table*/
325 /*                                                                        */
326 /*  INPUT                                                                 */
327 /*                                                                        */
328 /*    aet                               Pointer to active edge table      */
329 /*    y                                 Y coordinate of current scan line */
330 /*    aet_size                          Active edge table size            */
331 /*                                                                        */
332 /*  OUTPUT                                                                */
333 /*                                                                        */
334 /*    None                                                                */
335 /*                                                                        */
336 /*  CALLS                                                                 */
337 /*                                                                        */
338 /*    None                                                                */
339 /*                                                                        */
340 /*  CALLED BY                                                             */
341 /*                                                                        */
342 /*    _gx_display_driver_generic_polygon_fill                             */
343 /*                                                                        */
344 /*  RELEASE HISTORY                                                       */
345 /*                                                                        */
346 /*    DATE              NAME                      DESCRIPTION             */
347 /*                                                                        */
348 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
349 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
350 /*                                            resulting in version 6.1    */
351 /*                                                                        */
352 /**************************************************************************/
_gx_display_driver_polygon_non_active_edge_remove(GX_POLYGON_EDGE * aet,INT y,INT * aet_size)353 static VOID _gx_display_driver_polygon_non_active_edge_remove(GX_POLYGON_EDGE *aet, INT y, INT *aet_size)
354 {
355 INT i;
356 INT j;
357 
358     for (i = 0; i < *aet_size; i++)
359     {
360         /* If the bottom most y coordinate value of the edge equals to the current scan line y,
361            Remove the edge from active edge table, and decrease aet size by 1. */
362         if (aet[i].gx_polygon_edge_ymax == y)
363         {
364             for (j = i; j < *aet_size - 1; j++)
365             {
366                 aet[j] = aet[j + 1];
367             }
368             (*aet_size)--;
369             i--;
370         }
371     }
372 }
373 
374 /**************************************************************************/
375 /*                                                                        */
376 /*  FUNCTION                                               RELEASE        */
377 /*                                                                        */
378 /*    _gx_display_driver_polygon_scan_line_draw           PORTABLE C      */
379 /*                                                           6.1          */
380 /*  AUTHOR                                                                */
381 /*                                                                        */
382 /*    Kenneth Maxwell, Microsoft Corporation                              */
383 /*                                                                        */
384 /*  DESCRIPTION                                                           */
385 /*                                                                        */
386 /*    Internal helper function that filling area between pair             */
387 /*    intersections.                                                      */
388 /*                                                                        */
389 /*  INPUT                                                                 */
390 /*                                                                        */
391 /*    context                           Drawing context                   */
392 /*    aet                               Pointer to active edge table      */
393 /*    y                                 Y coordinate of current scan line */
394 /*    aet_size                          Active edge table size            */
395 /*                                                                        */
396 /*  OUTPUT                                                                */
397 /*                                                                        */
398 /*    None                                                                */
399 /*                                                                        */
400 /*  CALLS                                                                 */
401 /*                                                                        */
402 /*    [gx_display_driver_horizontal_line_draw]                            */
403 /*                                      Basic display driver horizontal   */
404 /*                                        line draw function              */
405 /*                                                                        */
406 /*  CALLED BY                                                             */
407 /*                                                                        */
408 /*    _gx_display_driver_generic_polygon_fill                             */
409 /*                                                                        */
410 /*  RELEASE HISTORY                                                       */
411 /*                                                                        */
412 /*    DATE              NAME                      DESCRIPTION             */
413 /*                                                                        */
414 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
415 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
416 /*                                            resulting in version 6.1    */
417 /*                                                                        */
418 /**************************************************************************/
_gx_display_driver_polygon_scan_line_draw(GX_DRAW_CONTEXT * context,GX_POLYGON_EDGE * aet,INT y,INT aet_size)419 static VOID _gx_display_driver_polygon_scan_line_draw(GX_DRAW_CONTEXT *context, GX_POLYGON_EDGE *aet, INT y, INT aet_size)
420 {
421 GX_VALUE      index;
422 INT           x1, x2;
423 GX_DISPLAY   *display = context -> gx_draw_context_display;
424 GX_RECTANGLE *clip = context -> gx_draw_context_clip;
425 GX_COLOR      fill_color;
426 
427     fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
428 
429     for (index = 0; index < aet_size - 1; index = (GX_VALUE)(index + (GX_VALUE)2))
430     {
431 
432         /* Pick up x coordinate value of the pair intersections. */
433         x1 = aet[index].gx_polygon_edge_xi;
434         x2 = aet[index + 1].gx_polygon_edge_xi;
435 
436         if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
437             (x1 != x2))
438         {
439             if (aet[index].gx_polygon_edge_x_decision &&
440                 aet[index].gx_polygon_edge_sign > 0)
441             {
442                 x1 += 1;
443             }
444 
445             if (aet[index + 1].gx_polygon_edge_x_decision &&
446                 aet[index + 1].gx_polygon_edge_sign < 0)
447             {
448                 x2 -= 1;
449             }
450         }
451 
452         /* Cliping segments x1x2. */
453         if (x1 < clip -> gx_rectangle_left)
454         {
455             x1 = clip -> gx_rectangle_left;
456         }
457 
458         if (x2 > clip -> gx_rectangle_right)
459         {
460             x2 = clip -> gx_rectangle_right;
461         }
462 
463         if (x1 <= x2)
464         {
465             /* Filling area between pairs of the intersections. */
466             display -> gx_display_driver_horizontal_line_draw(context, x1, x2, y, 1, fill_color);
467         }
468     }
469 }
470 
471 /**************************************************************************/
472 /*                                                                        */
473 /*  FUNCTION                                               RELEASE        */
474 /*                                                                        */
475 /*    _gx_display_driver_polygon_pixelmap_scan_line_draw  PORTABLE C      */
476 /*                                                           6.1          */
477 /*  AUTHOR                                                                */
478 /*                                                                        */
479 /*    Kenneth Maxwell, Microsoft Corporation                              */
480 /*                                                                        */
481 /*  DESCRIPTION                                                           */
482 /*                                                                        */
483 /*    Internal helper function that filling area between pair             */
484 /*    intersections with pixelmap.                                        */
485 /*                                                                        */
486 /*  INPUT                                                                 */
487 /*                                                                        */
488 /*    context                           Drawing context                   */
489 /*    aet                               Pointer to active edge table      */
490 /*    aet_size                          Active edge table size            */
491 /*    xpos                              X coord of draw start position    */
492 /*    y                                 Y coordinate of current scan line */
493 /*    pixelmap                          Pixelmap to fill                  */
494 /*                                                                        */
495 /*  OUTPUT                                                                */
496 /*                                                                        */
497 /*    None                                                                */
498 /*                                                                        */
499 /*  CALLS                                                                 */
500 /*                                                                        */
501 /*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
502 /*                                      Basic display driver horizontal   */
503 /*                                        pixelmap line draw function     */
504 /*                                                                        */
505 /*  CALLED BY                                                             */
506 /*                                                                        */
507 /*    _gx_display_driver_generic_polygon_fill                             */
508 /*                                                                        */
509 /*  RELEASE HISTORY                                                       */
510 /*                                                                        */
511 /*    DATE              NAME                      DESCRIPTION             */
512 /*                                                                        */
513 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
514 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
515 /*                                            removed use of memcpy,      */
516 /*                                            resulting in version 6.1    */
517 /*                                                                        */
518 /**************************************************************************/
_gx_display_driver_polygon_pixelmap_scan_line_draw(GX_DRAW_CONTEXT * context,GX_POLYGON_EDGE * aet,INT aet_size,INT xpos,INT y,GX_FILL_PIXELMAP_INFO * info)519 static VOID _gx_display_driver_polygon_pixelmap_scan_line_draw(GX_DRAW_CONTEXT *context, GX_POLYGON_EDGE *aet, INT aet_size,
520                                                                INT xpos, INT y, GX_FILL_PIXELMAP_INFO *info)
521 {
522 GX_VALUE              index;
523 INT                   x1, x2;
524 GX_DISPLAY           *display = context -> gx_draw_context_display;
525 GX_RECTANGLE         *clip = context -> gx_draw_context_clip;
526 GX_FILL_PIXELMAP_INFO old_info;
527 GX_BOOL               is_drawn = GX_FALSE;
528 
529     /* Store the ptr info in case that this line will be drawn several times.*/
530     old_info = (*info);
531 
532     for (index = 0; index < aet_size - 1; index = (GX_VALUE)(index + (GX_VALUE)2))
533     {
534         /* if aet_size is bigger than 2, it means there's at least two segment in this line.
535            So it must be drawn this line several times and should always be started from the "correct" position. */
536         (*info) = old_info;
537 
538         /* Pick up x coordinate value of the pair intersections. */
539         x1 = aet[index].gx_polygon_edge_xi;
540         x2 = aet[index + 1].gx_polygon_edge_xi;
541 
542         if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
543             (x1 != x2))
544         {
545             if (aet[index].gx_polygon_edge_x_decision &&
546                 aet[index].gx_polygon_edge_sign > 0)
547             {
548                 x1 += 1;
549             }
550 
551             if (aet[index + 1].gx_polygon_edge_x_decision &&
552                 aet[index + 1].gx_polygon_edge_sign < 0)
553             {
554                 x2 -= 1;
555             }
556         }
557 
558         /* Cliping segments x1x2. */
559         if (x1 < clip -> gx_rectangle_left)
560         {
561             x1 = clip -> gx_rectangle_left;
562         }
563 
564         if (x2 > clip -> gx_rectangle_right)
565         {
566             x2 = clip -> gx_rectangle_right;
567         }
568 
569         if (x1 > x2)
570         {
571             continue;
572         }
573 
574         /* Filling area between pairs of the intersections. */
575         info -> x_offset = x1 - xpos;
576         display -> gx_display_driver_horizontal_pixelmap_line_draw(context, x1, x2, y, info);
577         is_drawn = GX_TRUE;
578     }
579 
580     if (!is_drawn)
581     {
582         info -> draw = GX_FALSE;
583         display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, y, info);
584     }
585 }
586 
587 /**************************************************************************/
588 /*                                                                        */
589 /*  FUNCTION                                               RELEASE        */
590 /*                                                                        */
591 /*    _gx_display_driver_polygon_active_edge_table_update_and_restore     */
592 /*                                                        PORTABLE C      */
593 /*                                                           6.1          */
594 /*  AUTHOR                                                                */
595 /*                                                                        */
596 /*    Kenneth Maxwell, Microsoft Corporation                              */
597 /*                                                                        */
598 /*  DESCRIPTION                                                           */
599 /*                                                                        */
600 /*    Internal helper function that updates x coordinate of intersection  */
601 /*    according to edge gradient, and sort intersections by increase x    */
602 /*    coordinate value.                                                   */
603 /*                                                                        */
604 /*  INPUT                                                                 */
605 /*                                                                        */
606 /*    aet                               Pointer to active edge table      */
607 /*    aet_size                          Active edge table size            */
608 /*                                                                        */
609 /*  OUTPUT                                                                */
610 /*                                                                        */
611 /*    None                                                                */
612 /*                                                                        */
613 /*  CALLS                                                                 */
614 /*                                                                        */
615 /*    None                                                                */
616 /*                                                                        */
617 /*  CALLED BY                                                             */
618 /*                                                                        */
619 /*    _gx_display_driver_generic_polygon_fill                             */
620 /*                                                                        */
621 /*  RELEASE HISTORY                                                       */
622 /*                                                                        */
623 /*    DATE              NAME                      DESCRIPTION             */
624 /*                                                                        */
625 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
626 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
627 /*                                            resulting in version 6.1    */
628 /*                                                                        */
629 /**************************************************************************/
_gx_display_driver_polygon_active_edge_table_update_and_restore(GX_POLYGON_EDGE * aet,INT aet_size)630 static UINT _gx_display_driver_polygon_active_edge_table_update_and_restore(GX_POLYGON_EDGE *aet, INT aet_size)
631 {
632 GX_VALUE        index = (GX_VALUE)aet_size, xi, yi;
633 GX_POLYGON_EDGE temp;
634 
635     /* Update xi value. */
636     while (index--)
637     {
638         if (aet[index].gx_polygon_edge_dx == 0)
639         {
640             continue;
641         }
642 
643         /* When scan line move one step from top to bottom,
644            we need to update x value of active edges with the delta of the edge,
645            the following codes equals to x += delta(y). */
646         aet[index].gx_polygon_edge_x_decision += aet[index].gx_polygon_edge_dx;
647 
648         while (aet[index].gx_polygon_edge_x_decision >= aet[index].gx_polygon_edge_dy)
649         {
650             aet[index].gx_polygon_edge_xi += aet[index].gx_polygon_edge_sign;
651             aet[index].gx_polygon_edge_x_decision -= aet[index].gx_polygon_edge_dy;
652         }
653     }
654 
655     /* Sort with xi value in ascending order. */
656     for (xi = 0; xi < aet_size - 1; xi++)
657     {
658         for (yi = (GX_VALUE)(xi + 1); yi < aet_size; yi++)
659         {
660             if (aet[xi].gx_polygon_edge_xi > aet[yi].gx_polygon_edge_xi)
661             {
662                 temp = aet[yi];
663                 aet[yi] = aet[xi];
664                 aet[xi] = temp;
665             }
666         }
667     }
668 
669     return GX_SUCCESS;
670 }
671 
672 /**************************************************************************/
673 /*                                                                        */
674 /*  FUNCTION                                               RELEASE        */
675 /*                                                                        */
676 /*    _gx_display_driver_generic_polygon_scan_line_fill   PORTABLE C      */
677 /*                                                           6.1          */
678 /*  AUTHOR                                                                */
679 /*                                                                        */
680 /*    Kenneth Maxwell, Microsoft Corporation                              */
681 /*                                                                        */
682 /*  DESCRIPTION                                                           */
683 /*                                                                        */
684 /*    This fills a polygon.                                               */
685 /*                                                                        */
686 /*  INPUT                                                                 */
687 /*                                                                        */
688 /*    num                               Number of points of polygon       */
689 /*    vertex                            Array of points of the polygon,   */
690 /*                                        terminated by NULL entry.       */
691 /*                                                                        */
692 /*  OUTPUT                                                                */
693 /*                                                                        */
694 /*    status                            Completion status                 */
695 /*                                                                        */
696 /*  CALLS                                                                 */
697 /*                                                                        */
698 /*    _gx_canvas_line_draw              Draw the specified line           */
699 /*                                                                        */
700 /*  CALLED BY                                                             */
701 /*                                                                        */
702 /*    Application Code                                                    */
703 /*                                                                        */
704 /*  RELEASE HISTORY                                                       */
705 /*                                                                        */
706 /*    DATE              NAME                      DESCRIPTION             */
707 /*                                                                        */
708 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
709 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
710 /*                                            resulting in version 6.1    */
711 /*                                                                        */
712 /**************************************************************************/
_gx_display_driver_generic_polygon_fill(GX_DRAW_CONTEXT * context,GX_POINT * vertex,INT num)713 VOID _gx_display_driver_generic_polygon_fill(GX_DRAW_CONTEXT *context, GX_POINT *vertex, INT num)
714 {
715 INT                    ymin;
716 INT                    ymax;
717 INT                    xpos;
718 INT                    y;
719 static GX_POLYGON_EDGE net[GX_POLYGON_MAX_EDGE_NUM]; /* new edge table: obtain all edges of the polygon. */
720 static GX_POLYGON_EDGE aet[GX_POLYGON_MAX_EDGE_NUM]; /* active edge table: obtain all edges that touched by the current scan line. */
721 GX_BRUSH              *brush;
722 INT                    aet_size = 0;
723 INT                    net_size = num;
724 GX_PIXELMAP           *pixelmap = GX_NULL;
725 GX_VALUE               format;
726 GX_FILL_PIXELMAP_INFO  info;
727 GX_DISPLAY            *display = context -> gx_draw_context_display;
728 GX_RECTANGLE          *clip = context -> gx_draw_context_clip;
729 
730     if (num <= GX_POLYGON_MAX_EDGE_NUM)
731     {
732         /* Get the top most and bottom most y coordinate of the specified polygon. */
733         _gx_display_driver_polygon_min_max_get(vertex, num, &ymin, &ymax, &xpos);
734 
735         /* Initiate new edge table. */
736         _gx_display_driver_polygon_new_edge_table_init(context, vertex, num, net, &net_size);
737 
738         brush = &context -> gx_draw_context_brush;
739         if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
740         {
741             /* Pick up brush pixelmap. */
742             pixelmap = brush -> gx_brush_pixelmap;
743 
744             if (pixelmap == GX_NULL)
745             {
746                 return;
747             }
748 
749             if (pixelmap -> gx_pixelmap_height <= 0 ||
750                 pixelmap -> gx_pixelmap_width <= 0)
751             {
752                 return;
753             }
754 
755             format = context -> gx_draw_context_display -> gx_display_color_format;
756             memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
757 
758             /*Check the pixelmap format is supported in this driver or not.*/
759             if (format >= GX_COLOR_FORMAT_24XRGB)
760             {
761                 /*32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
762                 if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
763                 {
764                     /* Display driver only support its native format pixelmap. */
765                     /* Nothing should be drawn if pixelmap format isn't support. */
766                     return;
767                 }
768             }
769             else
770             {
771                 if (pixelmap -> gx_pixelmap_format != format)
772                 {
773                     /* Display driver only support its native format pixelmap. */
774                     /* Nothing should be drawn if pixelmap format isn't support. */
775                     return;
776                 }
777                 else if (pixelmap -> gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
778                 {
779                     info.mask = 0xf0;
780                 }
781             }
782 
783             info.pixelmap = brush -> gx_brush_pixelmap;
784             info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
785 
786             if (pixelmap -> gx_pixelmap_aux_data_size)
787             {
788                 info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
789             }
790         }
791 
792         if (ymax > clip -> gx_rectangle_bottom)
793         {
794             ymax = clip -> gx_rectangle_bottom;
795         }
796 
797         /* Moving scan line from polygon top to bottom. */
798         for (y = ymin; y <= ymax; y++)
799         {
800             /* This function will check if the scan line comes to the top most y coordinate of any edges in net table.
801                If it is true, add it to the aet table. */
802             _gx_display_driver_polygon_active_edge_insert(aet, net, y, net_size, &aet_size);
803 
804             if (y < clip -> gx_rectangle_top)
805             {
806                 if (pixelmap)
807                 {
808                     /* skip the undraw lines. */
809                     info.draw = GX_FALSE;
810                     display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, y, &info);
811                 }
812             }
813             else
814             {
815                 if (pixelmap)
816                 {
817                     info.draw = GX_TRUE;
818                     _gx_display_driver_polygon_pixelmap_scan_line_draw(context, aet, aet_size, xpos, y, &info);
819                 }
820                 else
821                 {
822                     /* Filling the polygon area that touched by scan line. */
823                     _gx_display_driver_polygon_scan_line_draw(context, aet, y, aet_size);
824                 }
825             }
826             /* This function will check if the scan line comes to the bottom most y coordinate of any edges in aet table.
827                If it is true, remove it from aet table. */
828             _gx_display_driver_polygon_non_active_edge_remove(aet, y, &aet_size);
829 
830             /* Update x coordinate of intersections between polygon and scan line, and sort them by increase x coordinate value. */
831             _gx_display_driver_polygon_active_edge_table_update_and_restore(aet, aet_size);
832         }
833     }
834 }
835 
836