GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_polygon_fill.c Lines: 178 178 100.0 %
Date: 2024-12-05 08:52:37 Branches: 126 126 100.0 %

Line Branch Exec Source
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
/**************************************************************************/
78
848
static VOID _gx_display_driver_polygon_min_max_get(GX_POINT *vertex, INT num, INT *ymin, INT *ymax, INT *xmin)
79
{
80
848
GX_VALUE index = (GX_VALUE)num;
81
INT      y_min;
82
INT      y_max;
83
INT      x_min;
84
85
848
    x_min = vertex[0].gx_point_x;
86
848
    y_min = vertex[0].gx_point_y;
87
848
    y_max = vertex[0].gx_point_y;
88
89
6436
    while (index--)
90
    {
91
5588
        if (vertex[index].gx_point_y < y_min)
92
        {
93
333
            y_min = vertex[index].gx_point_y;
94
        }
95
5255
        else if (vertex[index].gx_point_y > y_max)
96
        {
97
1182
            y_max = vertex[index].gx_point_y;
98
        }
99
100
5588
        if (vertex[index].gx_point_x < x_min)
101
        {
102
105
            x_min = vertex[index].gx_point_x;
103
        }
104
    }
105
106
848
    *ymin = y_min;
107
848
    *ymax = y_max;
108
848
    *xmin = x_min;
109
848
}
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
/**************************************************************************/
155
848
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
848
GX_VALUE        net_index = 0;
164
165
6436
    for (index = 0; index < num; index++)
166
    {
167
5588
        s_point = vertex[index];
168
5588
        e_point = vertex[(index + 1) % num];
169
5588
        ss_point = vertex[(index - 1 + num) % num];
170
5588
        ee_point = vertex[(index + 2) % num];
171
172
        /* Skip horizontal line. */
173
5588
        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
4746
            edge.gx_polygon_edge_dx = GX_ABS(e_point.gx_point_x - s_point.gx_point_x);
178
4746
            edge.gx_polygon_edge_dy = GX_ABS(e_point.gx_point_y - s_point.gx_point_y);
179
180
4746
            if (context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS)
181
            {
182
3150
                edge.gx_polygon_edge_x_decision = 0;
183
            }
184
            else
185
            {
186
1596
                edge.gx_polygon_edge_x_decision = edge.gx_polygon_edge_dy >> 1;
187
            }
188
189

4746
            if (((e_point.gx_point_x > s_point.gx_point_x) && (e_point.gx_point_y > s_point.gx_point_y)) ||
190

3732
                ((e_point.gx_point_x < s_point.gx_point_x) && (e_point.gx_point_y < s_point.gx_point_y)))
191
            {
192
1858
                edge.gx_polygon_edge_sign = 1;
193
            }
194
            else
195
            {
196
2888
                edge.gx_polygon_edge_sign = -1;
197
            }
198
199
4746
            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
2373
                edge.gx_polygon_edge_xi = s_point.gx_point_x;
203
204
                /* Set max y coordinate of the edge. */
205
2373
                edge.gx_polygon_edge_ymax = e_point.gx_point_y;
206
207
2373
                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
837
                    edge.gx_polygon_edge_ymax -= 1;
212
                }
213
214
2373
                edge.gx_polygon_edge_ymin = s_point.gx_point_y;
215
            }
216
            else
217
            {
218
                /* Set xi value. */
219
2373
                edge.gx_polygon_edge_xi = e_point.gx_point_x;
220
221
                /* Set max y coordinate of the edge. */
222
2373
                edge.gx_polygon_edge_ymax = s_point.gx_point_y;
223
224
2373
                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
837
                    edge.gx_polygon_edge_ymax -= 1;
228
                }
229
230
2373
                edge.gx_polygon_edge_ymin = e_point.gx_point_y;
231
            }
232
233
4746
            net[net_index++] = edge;
234
        }
235
    }
236
237
848
    *net_size = net_index;
238
848
}
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
/**************************************************************************/
285
82121
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
82121
GX_VALUE ni = (GX_VALUE)(net_size - 1);
288
GX_VALUE ai;
289
82121
INT      active_edge_table_size = *aet_size;
290
291
540635
    for (ni = 0; ni < net_size; ni++)
292
    {
293
458514
        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
4594
            ai = (GX_VALUE)(active_edge_table_size - 1);
299

8538
            while ((ai >= 0) && (net[ni].gx_polygon_edge_xi < aet[ai].gx_polygon_edge_xi))
300
            {
301
3944
                aet[ai + 1] = aet[ai];
302
3944
                ai--;
303
            }
304
4594
            aet[ai + 1] = net[ni];
305
4594
            active_edge_table_size++;
306
        }
307
    }
308
309
82121
    *aet_size = active_edge_table_size;
310
82121
}
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
/**************************************************************************/
353
82121
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
366849
    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
284728
        if (aet[i].gx_polygon_edge_ymax == y)
363
        {
364
11967
            for (j = i; j < *aet_size - 1; j++)
365
            {
366
7493
                aet[j] = aet[j + 1];
367
            }
368
4474
            (*aet_size)--;
369
4474
            i--;
370
        }
371
    }
372
82121
}
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
/**************************************************************************/
419
19348
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
19348
GX_DISPLAY   *display = context -> gx_draw_context_display;
424
19348
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
425
GX_COLOR      fill_color;
426
427
19348
    fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
428
429
52526
    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
33178
        x1 = aet[index].gx_polygon_edge_xi;
434
33178
        x2 = aet[index + 1].gx_polygon_edge_xi;
435
436

33178
        if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
437
            (x1 != x2))
438
        {
439
21113
            if (aet[index].gx_polygon_edge_x_decision &&
440
11542
                aet[index].gx_polygon_edge_sign > 0)
441
            {
442
4784
                x1 += 1;
443
            }
444
445
21113
            if (aet[index + 1].gx_polygon_edge_x_decision &&
446
11682
                aet[index + 1].gx_polygon_edge_sign < 0)
447
            {
448
4924
                x2 -= 1;
449
            }
450
        }
451
452
        /* Cliping segments x1x2. */
453
33178
        if (x1 < clip -> gx_rectangle_left)
454
        {
455
536
            x1 = clip -> gx_rectangle_left;
456
        }
457
458
33178
        if (x2 > clip -> gx_rectangle_right)
459
        {
460
1562
            x2 = clip -> gx_rectangle_right;
461
        }
462
463
33178
        if (x1 <= x2)
464
        {
465
            /* Filling area between pairs of the intersections. */
466
32401
            display -> gx_display_driver_horizontal_line_draw(context, x1, x2, y, 1, fill_color);
467
        }
468
    }
469
19348
}
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
/**************************************************************************/
519
61749
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
61749
GX_DISPLAY           *display = context -> gx_draw_context_display;
525
61749
GX_RECTANGLE         *clip = context -> gx_draw_context_clip;
526
GX_FILL_PIXELMAP_INFO old_info;
527
61749
GX_BOOL               is_drawn = GX_FALSE;
528
529
    /* Store the ptr info in case that this line will be drawn several times.*/
530
61749
    old_info = (*info);
531
532
169572
    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
107823
        (*info) = old_info;
537
538
        /* Pick up x coordinate value of the pair intersections. */
539
107823
        x1 = aet[index].gx_polygon_edge_xi;
540
107823
        x2 = aet[index + 1].gx_polygon_edge_xi;
541
542

107823
        if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
543
            (x1 != x2))
544
        {
545
67169
            if (aet[index].gx_polygon_edge_x_decision &&
546
37756
                aet[index].gx_polygon_edge_sign > 0)
547
            {
548
16895
                x1 += 1;
549
            }
550
551
67169
            if (aet[index + 1].gx_polygon_edge_x_decision &&
552
38141
                aet[index + 1].gx_polygon_edge_sign < 0)
553
            {
554
17280
                x2 -= 1;
555
            }
556
        }
557
558
        /* Cliping segments x1x2. */
559
107823
        if (x1 < clip -> gx_rectangle_left)
560
        {
561
200
            x1 = clip -> gx_rectangle_left;
562
        }
563
564
107823
        if (x2 > clip -> gx_rectangle_right)
565
        {
566
202
            x2 = clip -> gx_rectangle_right;
567
        }
568
569
107823
        if (x1 > x2)
570
        {
571
46
            continue;
572
        }
573
574
        /* Filling area between pairs of the intersections. */
575
107777
        info -> x_offset = x1 - xpos;
576
107777
        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, x1, x2, y, info);
577
107777
        is_drawn = GX_TRUE;
578
    }
579
580
61749
    if (!is_drawn)
581
    {
582
246
        info -> draw = GX_FALSE;
583
246
        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, y, info);
584
    }
585
61749
}
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
/**************************************************************************/
630
82121
static UINT _gx_display_driver_polygon_active_edge_table_update_and_restore(GX_POLYGON_EDGE *aet, INT aet_size)
631
{
632
82121
GX_VALUE        index = (GX_VALUE)aet_size, xi, yi;
633
GX_POLYGON_EDGE temp;
634
635
    /* Update xi value. */
636
362375
    while (index--)
637
    {
638
280254
        if (aet[index].gx_polygon_edge_dx == 0)
639
        {
640
95706
            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
184548
        aet[index].gx_polygon_edge_x_decision += aet[index].gx_polygon_edge_dx;
647
648
328529
        while (aet[index].gx_polygon_edge_x_decision >= aet[index].gx_polygon_edge_dy)
649
        {
650
143981
            aet[index].gx_polygon_edge_xi += aet[index].gx_polygon_edge_sign;
651
143981
            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
281868
    for (xi = 0; xi < aet_size - 1; xi++)
657
    {
658
754874
        for (yi = (GX_VALUE)(xi + 1); yi < aet_size; yi++)
659
        {
660
555127
            if (aet[xi].gx_polygon_edge_xi > aet[yi].gx_polygon_edge_xi)
661
            {
662
1459
                temp = aet[yi];
663
1459
                aet[yi] = aet[xi];
664
1459
                aet[xi] = temp;
665
            }
666
        }
667
    }
668
669
82121
    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
/**************************************************************************/
713
852
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
852
INT                    aet_size = 0;
723
852
INT                    net_size = num;
724
852
GX_PIXELMAP           *pixelmap = GX_NULL;
725
GX_VALUE               format;
726
GX_FILL_PIXELMAP_INFO  info;
727
852
GX_DISPLAY            *display = context -> gx_draw_context_display;
728
852
GX_RECTANGLE          *clip = context -> gx_draw_context_clip;
729
730
852
    if (num <= GX_POLYGON_MAX_EDGE_NUM)
731
    {
732
        /* Get the top most and bottom most y coordinate of the specified polygon. */
733
848
        _gx_display_driver_polygon_min_max_get(vertex, num, &ymin, &ymax, &xpos);
734
735
        /* Initiate new edge table. */
736
848
        _gx_display_driver_polygon_new_edge_table_init(context, vertex, num, net, &net_size);
737
738
848
        brush = &context -> gx_draw_context_brush;
739
848
        if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
740
        {
741
            /* Pick up brush pixelmap. */
742
638
            pixelmap = brush -> gx_brush_pixelmap;
743
744
638
            if (pixelmap == GX_NULL)
745
            {
746
25
                return;
747
            }
748
749
633
            if (pixelmap -> gx_pixelmap_height <= 0 ||
750
628
                pixelmap -> gx_pixelmap_width <= 0)
751
            {
752
10
                return;
753
            }
754
755
623
            format = context -> gx_draw_context_display -> gx_display_color_format;
756
623
            memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
757
758
            /*Check the pixelmap format is supported in this driver or not.*/
759
623
            if (format >= GX_COLOR_FORMAT_24XRGB)
760
            {
761
                /*32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
762
373
                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
5
                    return;
767
                }
768
            }
769
            else
770
            {
771
250
                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
5
                    return;
776
                }
777
245
                else if (pixelmap -> gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
778
                {
779
5
                    info.mask = 0xf0;
780
                }
781
            }
782
783
613
            info.pixelmap = brush -> gx_brush_pixelmap;
784
613
            info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
785
786
613
            if (pixelmap -> gx_pixelmap_aux_data_size)
787
            {
788
180
                info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
789
            }
790
        }
791
792
823
        if (ymax > clip -> gx_rectangle_bottom)
793
        {
794
18
            ymax = clip -> gx_rectangle_bottom;
795
        }
796
797
        /* Moving scan line from polygon top to bottom. */
798
82944
        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
82121
            _gx_display_driver_polygon_active_edge_insert(aet, net, y, net_size, &aet_size);
803
804
82121
            if (y < clip -> gx_rectangle_top)
805
            {
806
1024
                if (pixelmap)
807
                {
808
                    /* skip the undraw lines. */
809
88
                    info.draw = GX_FALSE;
810
88
                    display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, y, &info);
811
                }
812
            }
813
            else
814
            {
815
81097
                if (pixelmap)
816
                {
817
61749
                    info.draw = GX_TRUE;
818
61749
                    _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
19348
                    _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
82121
            _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
82121
            _gx_display_driver_polygon_active_edge_table_update_and_restore(aet, aet_size);
832
        }
833
    }
834
}
835