GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_polygon_fill.c Lines: 178 178 100.0 %
Date: 2026-03-06 19:21:09 Branches: 126 126 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Canvas Management (Canvas)                                          */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_system.h"
29
#include "gx_utility.h"
30
#include "gx_display.h"
31
#include "gx_canvas.h"
32
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_display_driver_polygon_min_max_get              PORTABLE C      */
39
/*                                                           6.1          */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Kenneth Maxwell, Microsoft Corporation                              */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*    Internal helper function that calculates the top most and bottom    */
47
/*    most y coordinate of the specified polygon.                         */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    vertex                            Array of points of the polygon,   */
52
/*                                        terminated by NULL entry        */
53
/*    num                               Number of points of polygon       */
54
/*    ymin                              Retrieved top most y coordinate   */
55
/*    ymax                              Retrieved bottom most y coordinate*/
56
/*    xmin                              Retrieved left most x coordinate  */
57
/*                                                                        */
58
/*  OUTPUT                                                                */
59
/*                                                                        */
60
/*    None                                                                */
61
/*                                                                        */
62
/*  CALLS                                                                 */
63
/*                                                                        */
64
/*    None                                                                */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    _gx_display_driver_generic_polygon_fill                             */
69
/*                                                                        */
70
/**************************************************************************/
71
848
static VOID _gx_display_driver_polygon_min_max_get(GX_POINT *vertex, INT num, INT *ymin, INT *ymax, INT *xmin)
72
{
73
848
GX_VALUE index = (GX_VALUE)num;
74
INT      y_min;
75
INT      y_max;
76
INT      x_min;
77
78
848
    x_min = vertex[0].gx_point_x;
79
848
    y_min = vertex[0].gx_point_y;
80
848
    y_max = vertex[0].gx_point_y;
81
82
6436
    while (index--)
83
    {
84
5588
        if (vertex[index].gx_point_y < y_min)
85
        {
86
333
            y_min = vertex[index].gx_point_y;
87
        }
88
5255
        else if (vertex[index].gx_point_y > y_max)
89
        {
90
1182
            y_max = vertex[index].gx_point_y;
91
        }
92
93
5588
        if (vertex[index].gx_point_x < x_min)
94
        {
95
105
            x_min = vertex[index].gx_point_x;
96
        }
97
    }
98
99
848
    *ymin = y_min;
100
848
    *ymax = y_max;
101
848
    *xmin = x_min;
102
848
}
103
104
/**************************************************************************/
105
/*                                                                        */
106
/*  FUNCTION                                               RELEASE        */
107
/*                                                                        */
108
/*    _gx_display_driver_polygon_new_edge_table_init      PORTABLE C      */
109
/*                                                           6.1          */
110
/*  AUTHOR                                                                */
111
/*                                                                        */
112
/*    Kenneth Maxwell, Microsoft Corporation                              */
113
/*                                                                        */
114
/*  DESCRIPTION                                                           */
115
/*                                                                        */
116
/*    Internal helper function that Initiates new edge table, which       */
117
/*    contain all the edges of the specified polygon.                     */
118
/*                                                                        */
119
/*  INPUT                                                                 */
120
/*                                                                        */
121
/*    vertex                            Array of points of the polygon,   */
122
/*                                        terminated by NULL entry        */
123
/*    num                               Number of points of polygon       */
124
/*    net                               Pointer to new edge table         */
125
/*    net_size                          New edge table size               */
126
/*                                                                        */
127
/*  OUTPUT                                                                */
128
/*                                                                        */
129
/*    None                                                                */
130
/*                                                                        */
131
/*  CALLS                                                                 */
132
/*                                                                        */
133
/*    None                                                                */
134
/*                                                                        */
135
/*  CALLED BY                                                             */
136
/*                                                                        */
137
/*    _gx_display_driver_generic_polygon_fill                             */
138
/*                                                                        */
139
/**************************************************************************/
140
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)
141
{
142
GX_POLYGON_EDGE edge;
143
INT             index;
144
GX_POINT        s_point;
145
GX_POINT        ss_point;
146
GX_POINT        e_point;
147
GX_POINT        ee_point;
148
848
GX_VALUE        net_index = 0;
149
150
6436
    for (index = 0; index < num; index++)
151
    {
152
5588
        s_point = vertex[index];
153
5588
        e_point = vertex[(index + 1) % num];
154
5588
        ss_point = vertex[(index - 1 + num) % num];
155
5588
        ee_point = vertex[(index + 2) % num];
156
157
        /* Skip horizontal line. */
158
5588
        if (s_point.gx_point_y != e_point.gx_point_y)
159
        {
160
            /* Add one edge to new edge table, s_point and e_point are two endpoints of the added edge. */
161
162
4746
            edge.gx_polygon_edge_dx = GX_ABS(e_point.gx_point_x - s_point.gx_point_x);
163
4746
            edge.gx_polygon_edge_dy = GX_ABS(e_point.gx_point_y - s_point.gx_point_y);
164
165
4746
            if (context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS)
166
            {
167
3150
                edge.gx_polygon_edge_x_decision = 0;
168
            }
169
            else
170
            {
171
1596
                edge.gx_polygon_edge_x_decision = edge.gx_polygon_edge_dy >> 1;
172
            }
173
174

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

3732
                ((e_point.gx_point_x < s_point.gx_point_x) && (e_point.gx_point_y < s_point.gx_point_y)))
176
            {
177
1858
                edge.gx_polygon_edge_sign = 1;
178
            }
179
            else
180
            {
181
2888
                edge.gx_polygon_edge_sign = -1;
182
            }
183
184
4746
            if (e_point.gx_point_y > s_point.gx_point_y)
185
            {
186
                /* Set xi value, which is the x coordinate value of the edge's toppest point. */
187
2373
                edge.gx_polygon_edge_xi = s_point.gx_point_x;
188
189
                /* Set max y coordinate of the edge. */
190
2373
                edge.gx_polygon_edge_ymax = e_point.gx_point_y;
191
192
2373
                if (ee_point.gx_point_y >= e_point.gx_point_y)
193
                {
194
                    /* If e_point isn't the bottom most point, reset ymax to ymax - 1.
195
                       To avoid producing 2 intersections when scan line comes to the vertex point. */
196
837
                    edge.gx_polygon_edge_ymax -= 1;
197
                }
198
199
2373
                edge.gx_polygon_edge_ymin = s_point.gx_point_y;
200
            }
201
            else
202
            {
203
                /* Set xi value. */
204
2373
                edge.gx_polygon_edge_xi = e_point.gx_point_x;
205
206
                /* Set max y coordinate of the edge. */
207
2373
                edge.gx_polygon_edge_ymax = s_point.gx_point_y;
208
209
2373
                if (ss_point.gx_point_y >= s_point.gx_point_y)
210
                {
211
                    /* If e_point isn't the bottom most point, reset ymax to ymax - 1. */
212
837
                    edge.gx_polygon_edge_ymax -= 1;
213
                }
214
215
2373
                edge.gx_polygon_edge_ymin = e_point.gx_point_y;
216
            }
217
218
4746
            net[net_index++] = edge;
219
        }
220
    }
221
222
848
    *net_size = net_index;
223
848
}
224
225
/**************************************************************************/
226
/*                                                                        */
227
/*  FUNCTION                                               RELEASE        */
228
/*                                                                        */
229
/*    _gx_display_driver_polygon_active_edge_insert       PORTABLE C      */
230
/*                                                           6.1          */
231
/*  AUTHOR                                                                */
232
/*                                                                        */
233
/*    Kenneth Maxwell, Microsoft Corporation                              */
234
/*                                                                        */
235
/*  DESCRIPTION                                                           */
236
/*                                                                        */
237
/*    Internal helper function that Inserts an edge from new edge table to*/
238
/*    active edge table.                                                  */
239
/*                                                                        */
240
/*  INPUT                                                                 */
241
/*                                                                        */
242
/*    aet                               Pointer to active edge table      */
243
/*    net                               Pointer to new edge table         */
244
/*    y                                 Y coordinate of current scan line */
245
/*    net                               Pointer to new edge table         */
246
/*    net_size                          New edge table size               */
247
/*    aet_size                          Retured active 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
/**************************************************************************/
262
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)
263
{
264
82121
GX_VALUE ni = (GX_VALUE)(net_size - 1);
265
GX_VALUE ai;
266
82121
INT      active_edge_table_size = *aet_size;
267
268
540635
    for (ni = 0; ni < net_size; ni++)
269
    {
270
458514
        if (net[ni].gx_polygon_edge_ymin == y)
271
        {
272
            /* If the toppest y coordinate value of the edge equals to the current scan line y,
273
               Insert the edge to active edge table, and increase aet size by 1. */
274
275
4594
            ai = (GX_VALUE)(active_edge_table_size - 1);
276

8538
            while ((ai >= 0) && (net[ni].gx_polygon_edge_xi < aet[ai].gx_polygon_edge_xi))
277
            {
278
3944
                aet[ai + 1] = aet[ai];
279
3944
                ai--;
280
            }
281
4594
            aet[ai + 1] = net[ni];
282
4594
            active_edge_table_size++;
283
        }
284
    }
285
286
82121
    *aet_size = active_edge_table_size;
287
82121
}
288
289
/**************************************************************************/
290
/*                                                                        */
291
/*  FUNCTION                                               RELEASE        */
292
/*                                                                        */
293
/*    _gx_display_driver_polygon_non_active_edge_remove   PORTABLE C      */
294
/*                                                           6.1          */
295
/*  AUTHOR                                                                */
296
/*                                                                        */
297
/*    Kenneth Maxwell, Microsoft Corporation                              */
298
/*                                                                        */
299
/*  DESCRIPTION                                                           */
300
/*                                                                        */
301
/*    Internal helper function that removes an edge from active edge table*/
302
/*                                                                        */
303
/*  INPUT                                                                 */
304
/*                                                                        */
305
/*    aet                               Pointer to active edge table      */
306
/*    y                                 Y coordinate of current scan line */
307
/*    aet_size                          Active edge table size            */
308
/*                                                                        */
309
/*  OUTPUT                                                                */
310
/*                                                                        */
311
/*    None                                                                */
312
/*                                                                        */
313
/*  CALLS                                                                 */
314
/*                                                                        */
315
/*    None                                                                */
316
/*                                                                        */
317
/*  CALLED BY                                                             */
318
/*                                                                        */
319
/*    _gx_display_driver_generic_polygon_fill                             */
320
/*                                                                        */
321
/**************************************************************************/
322
82121
static VOID _gx_display_driver_polygon_non_active_edge_remove(GX_POLYGON_EDGE *aet, INT y, INT *aet_size)
323
{
324
INT i;
325
INT j;
326
327
366849
    for (i = 0; i < *aet_size; i++)
328
    {
329
        /* If the bottom most y coordinate value of the edge equals to the current scan line y,
330
           Remove the edge from active edge table, and decrease aet size by 1. */
331
284728
        if (aet[i].gx_polygon_edge_ymax == y)
332
        {
333
11967
            for (j = i; j < *aet_size - 1; j++)
334
            {
335
7493
                aet[j] = aet[j + 1];
336
            }
337
4474
            (*aet_size)--;
338
4474
            i--;
339
        }
340
    }
341
82121
}
342
343
/**************************************************************************/
344
/*                                                                        */
345
/*  FUNCTION                                               RELEASE        */
346
/*                                                                        */
347
/*    _gx_display_driver_polygon_scan_line_draw           PORTABLE C      */
348
/*                                                           6.1          */
349
/*  AUTHOR                                                                */
350
/*                                                                        */
351
/*    Kenneth Maxwell, Microsoft Corporation                              */
352
/*                                                                        */
353
/*  DESCRIPTION                                                           */
354
/*                                                                        */
355
/*    Internal helper function that filling area between pair             */
356
/*    intersections.                                                      */
357
/*                                                                        */
358
/*  INPUT                                                                 */
359
/*                                                                        */
360
/*    context                           Drawing context                   */
361
/*    aet                               Pointer to active edge table      */
362
/*    y                                 Y coordinate of current scan line */
363
/*    aet_size                          Active edge table size            */
364
/*                                                                        */
365
/*  OUTPUT                                                                */
366
/*                                                                        */
367
/*    None                                                                */
368
/*                                                                        */
369
/*  CALLS                                                                 */
370
/*                                                                        */
371
/*    [gx_display_driver_horizontal_line_draw]                            */
372
/*                                      Basic display driver horizontal   */
373
/*                                        line draw function              */
374
/*                                                                        */
375
/*  CALLED BY                                                             */
376
/*                                                                        */
377
/*    _gx_display_driver_generic_polygon_fill                             */
378
/*                                                                        */
379
/**************************************************************************/
380
19348
static VOID _gx_display_driver_polygon_scan_line_draw(GX_DRAW_CONTEXT *context, GX_POLYGON_EDGE *aet, INT y, INT aet_size)
381
{
382
GX_VALUE      index;
383
INT           x1, x2;
384
19348
GX_DISPLAY   *display = context -> gx_draw_context_display;
385
19348
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
386
GX_COLOR      fill_color;
387
388
19348
    fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
389
390
52526
    for (index = 0; index < aet_size - 1; index = (GX_VALUE)(index + (GX_VALUE)2))
391
    {
392
393
        /* Pick up x coordinate value of the pair intersections. */
394
33178
        x1 = aet[index].gx_polygon_edge_xi;
395
33178
        x2 = aet[index + 1].gx_polygon_edge_xi;
396
397

33178
        if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
398
            (x1 != x2))
399
        {
400
21113
            if (aet[index].gx_polygon_edge_x_decision &&
401
11542
                aet[index].gx_polygon_edge_sign > 0)
402
            {
403
4784
                x1 += 1;
404
            }
405
406
21113
            if (aet[index + 1].gx_polygon_edge_x_decision &&
407
11682
                aet[index + 1].gx_polygon_edge_sign < 0)
408
            {
409
4924
                x2 -= 1;
410
            }
411
        }
412
413
        /* Cliping segments x1x2. */
414
33178
        if (x1 < clip -> gx_rectangle_left)
415
        {
416
536
            x1 = clip -> gx_rectangle_left;
417
        }
418
419
33178
        if (x2 > clip -> gx_rectangle_right)
420
        {
421
1562
            x2 = clip -> gx_rectangle_right;
422
        }
423
424
33178
        if (x1 <= x2)
425
        {
426
            /* Filling area between pairs of the intersections. */
427
32401
            display -> gx_display_driver_horizontal_line_draw(context, x1, x2, y, 1, fill_color);
428
        }
429
    }
430
19348
}
431
432
/**************************************************************************/
433
/*                                                                        */
434
/*  FUNCTION                                               RELEASE        */
435
/*                                                                        */
436
/*    _gx_display_driver_polygon_pixelmap_scan_line_draw  PORTABLE C      */
437
/*                                                           6.1          */
438
/*  AUTHOR                                                                */
439
/*                                                                        */
440
/*    Kenneth Maxwell, Microsoft Corporation                              */
441
/*                                                                        */
442
/*  DESCRIPTION                                                           */
443
/*                                                                        */
444
/*    Internal helper function that filling area between pair             */
445
/*    intersections with pixelmap.                                        */
446
/*                                                                        */
447
/*  INPUT                                                                 */
448
/*                                                                        */
449
/*    context                           Drawing context                   */
450
/*    aet                               Pointer to active edge table      */
451
/*    aet_size                          Active edge table size            */
452
/*    xpos                              X coord of draw start position    */
453
/*    y                                 Y coordinate of current scan line */
454
/*    pixelmap                          Pixelmap to fill                  */
455
/*                                                                        */
456
/*  OUTPUT                                                                */
457
/*                                                                        */
458
/*    None                                                                */
459
/*                                                                        */
460
/*  CALLS                                                                 */
461
/*                                                                        */
462
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
463
/*                                      Basic display driver horizontal   */
464
/*                                        pixelmap line draw function     */
465
/*                                                                        */
466
/*  CALLED BY                                                             */
467
/*                                                                        */
468
/*    _gx_display_driver_generic_polygon_fill                             */
469
/*                                                                        */
470
/**************************************************************************/
471
61749
static VOID _gx_display_driver_polygon_pixelmap_scan_line_draw(GX_DRAW_CONTEXT *context, GX_POLYGON_EDGE *aet, INT aet_size,
472
                                                               INT xpos, INT y, GX_FILL_PIXELMAP_INFO *info)
473
{
474
GX_VALUE              index;
475
INT                   x1, x2;
476
61749
GX_DISPLAY           *display = context -> gx_draw_context_display;
477
61749
GX_RECTANGLE         *clip = context -> gx_draw_context_clip;
478
GX_FILL_PIXELMAP_INFO old_info;
479
61749
GX_BOOL               is_drawn = GX_FALSE;
480
481
    /* Store the ptr info in case that this line will be drawn several times.*/
482
61749
    old_info = (*info);
483
484
169572
    for (index = 0; index < aet_size - 1; index = (GX_VALUE)(index + (GX_VALUE)2))
485
    {
486
        /* if aet_size is bigger than 2, it means there's at least two segment in this line.
487
           So it must be drawn this line several times and should always be started from the "correct" position. */
488
107823
        (*info) = old_info;
489
490
        /* Pick up x coordinate value of the pair intersections. */
491
107823
        x1 = aet[index].gx_polygon_edge_xi;
492
107823
        x2 = aet[index + 1].gx_polygon_edge_xi;
493
494

107823
        if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
495
            (x1 != x2))
496
        {
497
67169
            if (aet[index].gx_polygon_edge_x_decision &&
498
37756
                aet[index].gx_polygon_edge_sign > 0)
499
            {
500
16895
                x1 += 1;
501
            }
502
503
67169
            if (aet[index + 1].gx_polygon_edge_x_decision &&
504
38141
                aet[index + 1].gx_polygon_edge_sign < 0)
505
            {
506
17280
                x2 -= 1;
507
            }
508
        }
509
510
        /* Cliping segments x1x2. */
511
107823
        if (x1 < clip -> gx_rectangle_left)
512
        {
513
200
            x1 = clip -> gx_rectangle_left;
514
        }
515
516
107823
        if (x2 > clip -> gx_rectangle_right)
517
        {
518
202
            x2 = clip -> gx_rectangle_right;
519
        }
520
521
107823
        if (x1 > x2)
522
        {
523
46
            continue;
524
        }
525
526
        /* Filling area between pairs of the intersections. */
527
107777
        info -> x_offset = x1 - xpos;
528
107777
        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, x1, x2, y, info);
529
107777
        is_drawn = GX_TRUE;
530
    }
531
532
61749
    if (!is_drawn)
533
    {
534
246
        info -> draw = GX_FALSE;
535
246
        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, y, info);
536
    }
537
61749
}
538
539
/**************************************************************************/
540
/*                                                                        */
541
/*  FUNCTION                                               RELEASE        */
542
/*                                                                        */
543
/*    _gx_display_driver_polygon_active_edge_table_update_and_restore     */
544
/*                                                        PORTABLE C      */
545
/*                                                           6.1          */
546
/*  AUTHOR                                                                */
547
/*                                                                        */
548
/*    Kenneth Maxwell, Microsoft Corporation                              */
549
/*                                                                        */
550
/*  DESCRIPTION                                                           */
551
/*                                                                        */
552
/*    Internal helper function that updates x coordinate of intersection  */
553
/*    according to edge gradient, and sort intersections by increase x    */
554
/*    coordinate value.                                                   */
555
/*                                                                        */
556
/*  INPUT                                                                 */
557
/*                                                                        */
558
/*    aet                               Pointer to active edge table      */
559
/*    aet_size                          Active edge table size            */
560
/*                                                                        */
561
/*  OUTPUT                                                                */
562
/*                                                                        */
563
/*    None                                                                */
564
/*                                                                        */
565
/*  CALLS                                                                 */
566
/*                                                                        */
567
/*    None                                                                */
568
/*                                                                        */
569
/*  CALLED BY                                                             */
570
/*                                                                        */
571
/*    _gx_display_driver_generic_polygon_fill                             */
572
/*                                                                        */
573
/**************************************************************************/
574
82121
static UINT _gx_display_driver_polygon_active_edge_table_update_and_restore(GX_POLYGON_EDGE *aet, INT aet_size)
575
{
576
82121
GX_VALUE        index = (GX_VALUE)aet_size, xi, yi;
577
GX_POLYGON_EDGE temp;
578
579
    /* Update xi value. */
580
362375
    while (index--)
581
    {
582
280254
        if (aet[index].gx_polygon_edge_dx == 0)
583
        {
584
95706
            continue;
585
        }
586
587
        /* When scan line move one step from top to bottom,
588
           we need to update x value of active edges with the delta of the edge,
589
           the following codes equals to x += delta(y). */
590
184548
        aet[index].gx_polygon_edge_x_decision += aet[index].gx_polygon_edge_dx;
591
592
328529
        while (aet[index].gx_polygon_edge_x_decision >= aet[index].gx_polygon_edge_dy)
593
        {
594
143981
            aet[index].gx_polygon_edge_xi += aet[index].gx_polygon_edge_sign;
595
143981
            aet[index].gx_polygon_edge_x_decision -= aet[index].gx_polygon_edge_dy;
596
        }
597
    }
598
599
    /* Sort with xi value in ascending order. */
600
281868
    for (xi = 0; xi < aet_size - 1; xi++)
601
    {
602
754874
        for (yi = (GX_VALUE)(xi + 1); yi < aet_size; yi++)
603
        {
604
555127
            if (aet[xi].gx_polygon_edge_xi > aet[yi].gx_polygon_edge_xi)
605
            {
606
1459
                temp = aet[yi];
607
1459
                aet[yi] = aet[xi];
608
1459
                aet[xi] = temp;
609
            }
610
        }
611
    }
612
613
82121
    return GX_SUCCESS;
614
}
615
616
/**************************************************************************/
617
/*                                                                        */
618
/*  FUNCTION                                               RELEASE        */
619
/*                                                                        */
620
/*    _gx_display_driver_generic_polygon_scan_line_fill   PORTABLE C      */
621
/*                                                           6.1          */
622
/*  AUTHOR                                                                */
623
/*                                                                        */
624
/*    Kenneth Maxwell, Microsoft Corporation                              */
625
/*                                                                        */
626
/*  DESCRIPTION                                                           */
627
/*                                                                        */
628
/*    This fills a polygon.                                               */
629
/*                                                                        */
630
/*  INPUT                                                                 */
631
/*                                                                        */
632
/*    num                               Number of points of polygon       */
633
/*    vertex                            Array of points of the polygon,   */
634
/*                                        terminated by NULL entry.       */
635
/*                                                                        */
636
/*  OUTPUT                                                                */
637
/*                                                                        */
638
/*    status                            Completion status                 */
639
/*                                                                        */
640
/*  CALLS                                                                 */
641
/*                                                                        */
642
/*    _gx_canvas_line_draw              Draw the specified line           */
643
/*                                                                        */
644
/*  CALLED BY                                                             */
645
/*                                                                        */
646
/*    Application Code                                                    */
647
/*                                                                        */
648
/**************************************************************************/
649
852
VOID _gx_display_driver_generic_polygon_fill(GX_DRAW_CONTEXT *context, GX_POINT *vertex, INT num)
650
{
651
INT                    ymin;
652
INT                    ymax;
653
INT                    xpos;
654
INT                    y;
655
static GX_POLYGON_EDGE net[GX_POLYGON_MAX_EDGE_NUM]; /* new edge table: obtain all edges of the polygon. */
656
static GX_POLYGON_EDGE aet[GX_POLYGON_MAX_EDGE_NUM]; /* active edge table: obtain all edges that touched by the current scan line. */
657
GX_BRUSH              *brush;
658
852
INT                    aet_size = 0;
659
852
INT                    net_size = num;
660
852
GX_PIXELMAP           *pixelmap = GX_NULL;
661
GX_VALUE               format;
662
GX_FILL_PIXELMAP_INFO  info;
663
852
GX_DISPLAY            *display = context -> gx_draw_context_display;
664
852
GX_RECTANGLE          *clip = context -> gx_draw_context_clip;
665
666
852
    if (num <= GX_POLYGON_MAX_EDGE_NUM)
667
    {
668
        /* Get the top most and bottom most y coordinate of the specified polygon. */
669
848
        _gx_display_driver_polygon_min_max_get(vertex, num, &ymin, &ymax, &xpos);
670
671
        /* Initiate new edge table. */
672
848
        _gx_display_driver_polygon_new_edge_table_init(context, vertex, num, net, &net_size);
673
674
848
        brush = &context -> gx_draw_context_brush;
675
848
        if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
676
        {
677
            /* Pick up brush pixelmap. */
678
638
            pixelmap = brush -> gx_brush_pixelmap;
679
680
638
            if (pixelmap == GX_NULL)
681
            {
682
25
                return;
683
            }
684
685
633
            if (pixelmap -> gx_pixelmap_height <= 0 ||
686
628
                pixelmap -> gx_pixelmap_width <= 0)
687
            {
688
10
                return;
689
            }
690
691
623
            format = context -> gx_draw_context_display -> gx_display_color_format;
692
623
            memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
693
694
            /*Check the pixelmap format is supported in this driver or not.*/
695
623
            if (format >= GX_COLOR_FORMAT_24XRGB)
696
            {
697
                /*32ARGB FORMAT use 24xrgb driver for now. So this is a special case.*/
698
373
                if (pixelmap -> gx_pixelmap_format < GX_COLOR_FORMAT_24XRGB)
699
                {
700
                    /* Display driver only support its native format pixelmap. */
701
                    /* Nothing should be drawn if pixelmap format isn't support. */
702
5
                    return;
703
                }
704
            }
705
            else
706
            {
707
250
                if (pixelmap -> gx_pixelmap_format != format)
708
                {
709
                    /* Display driver only support its native format pixelmap. */
710
                    /* Nothing should be drawn if pixelmap format isn't support. */
711
5
                    return;
712
                }
713
245
                else if (pixelmap -> gx_pixelmap_format == GX_COLOR_FORMAT_4BIT_GRAY)
714
                {
715
5
                    info.mask = 0xf0;
716
                }
717
            }
718
719
613
            info.pixelmap = brush -> gx_brush_pixelmap;
720
613
            info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
721
722
613
            if (pixelmap -> gx_pixelmap_aux_data_size)
723
            {
724
180
                info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
725
            }
726
        }
727
728
823
        if (ymax > clip -> gx_rectangle_bottom)
729
        {
730
18
            ymax = clip -> gx_rectangle_bottom;
731
        }
732
733
        /* Moving scan line from polygon top to bottom. */
734
82944
        for (y = ymin; y <= ymax; y++)
735
        {
736
            /* This function will check if the scan line comes to the top most y coordinate of any edges in net table.
737
               If it is true, add it to the aet table. */
738
82121
            _gx_display_driver_polygon_active_edge_insert(aet, net, y, net_size, &aet_size);
739
740
82121
            if (y < clip -> gx_rectangle_top)
741
            {
742
1024
                if (pixelmap)
743
                {
744
                    /* skip the undraw lines. */
745
88
                    info.draw = GX_FALSE;
746
88
                    display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, y, &info);
747
                }
748
            }
749
            else
750
            {
751
81097
                if (pixelmap)
752
                {
753
61749
                    info.draw = GX_TRUE;
754
61749
                    _gx_display_driver_polygon_pixelmap_scan_line_draw(context, aet, aet_size, xpos, y, &info);
755
                }
756
                else
757
                {
758
                    /* Filling the polygon area that touched by scan line. */
759
19348
                    _gx_display_driver_polygon_scan_line_draw(context, aet, y, aet_size);
760
                }
761
            }
762
            /* This function will check if the scan line comes to the bottom most y coordinate of any edges in aet table.
763
               If it is true, remove it from aet table. */
764
82121
            _gx_display_driver_polygon_non_active_edge_remove(aet, y, &aet_size);
765
766
            /* Update x coordinate of intersections between polygon and scan line, and sort them by increase x coordinate value. */
767
82121
            _gx_display_driver_polygon_active_edge_table_update_and_restore(aet, aet_size);
768
        }
769
    }
770
}
771