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