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