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