GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_polygon_fill.c Lines: 212 212 100.0 %
Date: 2024-12-05 08:52:37 Branches: 138 138 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
/**   Display Management (Display)                                        */
18
/**                                                                       */
19
/**************************************************************************/
20
#define GX_SOURCE_CODE
21
22
23
/* Include necessary system files.  */
24
25
#include "gx_api.h"
26
#include "gx_system.h"
27
#include "gx_utility.h"
28
#include "gx_display.h"
29
#include "gx_canvas.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_display_driver_polygon_min_max_get              PORTABLE C      */
37
/*                                                           6.1.3        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Internal helper function that calculates the top most and bottom    */
45
/*    most y coordinate of the specified polygon.                         */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    vertex                            Array of points of the polygon,   */
50
/*                                        terminated by NULL entry        */
51
/*    num                               Number of points of polygon       */
52
/*    xmin                              Retrieved left most x coordinate  */
53
/*    xmax                              Retrieved right most x coordinate */
54
/*    ymin                              Retrieved top most y coordinate   */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    None                                                                */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    None                                                                */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    _gx_display_driver_generic_polygon_fill                             */
67
/*                                                                        */
68
/*  RELEASE HISTORY                                                       */
69
/*                                                                        */
70
/*    DATE              NAME                      DESCRIPTION             */
71
/*                                                                        */
72
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
73
/*                                                                        */
74
/**************************************************************************/
75
508
static VOID _gx_display_driver_polygon_min_max_get(GX_POINT *vertex, INT num, INT *xmin, INT *xmax, INT *ymin)
76
{
77
508
GX_VALUE index = (GX_VALUE)num;
78
INT      x_min;
79
INT      x_max;
80
INT      y_min;
81
82
508
    x_min = vertex[0].gx_point_x;
83
508
    x_max = vertex[0].gx_point_x;
84
508
    y_min = vertex[0].gx_point_y;
85
86
3528
    while (index--)
87
    {
88
3020
        if (vertex[index].gx_point_x < x_min)
89
        {
90
64
            x_min = vertex[index].gx_point_x;
91
        }
92
2956
        else if (vertex[index].gx_point_x > x_max)
93
        {
94
1308
            x_max = vertex[index].gx_point_x;
95
        }
96
97
3020
        if (vertex[index].gx_point_y < y_min)
98
        {
99
216
            y_min = vertex[index].gx_point_y;
100
        }
101
    }
102
103
508
    *xmin = x_min;
104
508
    *xmax = x_max;
105
508
    *ymin = y_min;
106
508
}
107
108
/**************************************************************************/
109
/*                                                                        */
110
/*  FUNCTION                                               RELEASE        */
111
/*                                                                        */
112
/*    _gx_display_driver_polygon_new_edge_table_init_90   PORTABLE C      */
113
/*                                                           6.1.3        */
114
/*  AUTHOR                                                                */
115
/*                                                                        */
116
/*    Kenneth Maxwell, Microsoft Corporation                              */
117
/*                                                                        */
118
/*  DESCRIPTION                                                           */
119
/*                                                                        */
120
/*    Internal helper function that Initiates new edge table, which       */
121
/*    contain all the edges of the specified polygon.                     */
122
/*                                                                        */
123
/*  INPUT                                                                 */
124
/*                                                                        */
125
/*    vertex                            Array of points of the polygon,   */
126
/*                                        terminated by NULL entry        */
127
/*    num                               Number of points of polygon       */
128
/*    net                               Pointer to new edge table         */
129
/*    net_size                          New edge table size               */
130
/*                                                                        */
131
/*  OUTPUT                                                                */
132
/*                                                                        */
133
/*    None                                                                */
134
/*                                                                        */
135
/*  CALLS                                                                 */
136
/*                                                                        */
137
/*    None                                                                */
138
/*                                                                        */
139
/*  CALLED BY                                                             */
140
/*                                                                        */
141
/*    _gx_display_driver_generic_polygon_fill                             */
142
/*                                                                        */
143
/*  RELEASE HISTORY                                                       */
144
/*                                                                        */
145
/*    DATE              NAME                      DESCRIPTION             */
146
/*                                                                        */
147
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
148
/*                                                                        */
149
/**************************************************************************/
150
308
static VOID _gx_display_driver_polygon_new_edge_table_init_90(GX_POINT *vertex, INT num, GX_POLYGON_EDGE *net, INT *net_size)
151
{
152
GX_POLYGON_EDGE edge;
153
INT             index;
154
GX_POINT        s_point;
155
GX_POINT        ss_point;
156
GX_POINT        e_point;
157
GX_POINT        ee_point;
158
308
GX_VALUE        net_index = 0;
159
160
2112
    for (index = 0; index < num; index++)
161
    {
162
1804
        s_point = vertex[index];
163
1804
        e_point = vertex[(index + 1) % num];
164
1804
        ss_point = vertex[(index - 1 + num) % num];
165
1804
        ee_point = vertex[(index + 2) % num];
166
167
        /* Skip vertical line. */
168
1804
        if (s_point.gx_point_x != e_point.gx_point_x)
169
        {
170
            /* Add one edge to new edge table, s_point and e_point are two endpoints of the added edge. */
171
172
1540
            edge.gx_polygon_edge_dx = GX_ABS(e_point.gx_point_x - s_point.gx_point_x);
173
1540
            edge.gx_polygon_edge_dy = GX_ABS(e_point.gx_point_y - s_point.gx_point_y);
174
1540
            edge.gx_polygon_edge_x_decision = edge.gx_polygon_edge_dx >> 1;
175

1540
            if (((e_point.gx_point_x > s_point.gx_point_x) && (e_point.gx_point_y > s_point.gx_point_y)) ||
176

1276
                ((e_point.gx_point_x < s_point.gx_point_x) && (e_point.gx_point_y < s_point.gx_point_y)))
177
            {
178
572
                edge.gx_polygon_edge_sign = -1;
179
            }
180
            else
181
            {
182
968
                edge.gx_polygon_edge_sign = 1;
183
            }
184
185
1540
            if (e_point.gx_point_x > s_point.gx_point_x)
186
            {
187
                /* Set xi value, which is the y coordinate value of the edge's rightmost point. */
188
704
                edge.gx_polygon_edge_xi = e_point.gx_point_y;
189
190
                /* Set min x coordinate of the edge. */
191
704
                edge.gx_polygon_edge_ymax = s_point.gx_point_x;
192
193
704
                if (ss_point.gx_point_x <= s_point.gx_point_x)
194
                {
195
                    /* If e_point isn't the left most point, reset xmin to xmin - 1.
196
                       To avoid producing 2 intersections when scan line comes to the vertex point. */
197
440
                    edge.gx_polygon_edge_ymax += 1;
198
                }
199
200
704
                edge.gx_polygon_edge_ymin = e_point.gx_point_x;
201
            }
202
            else
203
            {
204
                /* Set xi value. */
205
836
                edge.gx_polygon_edge_xi = s_point.gx_point_y;
206
207
                /* Set max x coordinate of the edge. */
208
836
                edge.gx_polygon_edge_ymax = e_point.gx_point_x;
209
210
836
                if (ee_point.gx_point_x <= e_point.gx_point_x)
211
                {
212
                    /* If e_point isn't the left most point, reset xmin to xmin - 1. */
213
572
                    edge.gx_polygon_edge_ymax += 1;
214
                }
215
216
836
                edge.gx_polygon_edge_ymin = s_point.gx_point_x;
217
            }
218
219
1540
            net[net_index++] = edge;
220
        }
221
    }
222
223
308
    *net_size = net_index;
224
308
}
225
226
/**************************************************************************/
227
/*                                                                        */
228
/*  FUNCTION                                               RELEASE        */
229
/*                                                                        */
230
/*    _gx_display_driver_polygon_new_edge_table_init_270  PORTABLE C      */
231
/*                                                           6.1.3        */
232
/*  AUTHOR                                                                */
233
/*                                                                        */
234
/*    Kenneth Maxwell, Microsoft Corporation                              */
235
/*                                                                        */
236
/*  DESCRIPTION                                                           */
237
/*                                                                        */
238
/*    Internal helper function that Initiates new edge table, which       */
239
/*    contain all the edges of the specified polygon.                     */
240
/*                                                                        */
241
/*  INPUT                                                                 */
242
/*                                                                        */
243
/*    vertex                            Array of points of the polygon,   */
244
/*                                        terminated by NULL entry        */
245
/*    num                               Number of points of polygon       */
246
/*    net                               Pointer to new edge table         */
247
/*    net_size                          New edge table size               */
248
/*                                                                        */
249
/*  OUTPUT                                                                */
250
/*                                                                        */
251
/*    None                                                                */
252
/*                                                                        */
253
/*  CALLS                                                                 */
254
/*                                                                        */
255
/*    None                                                                */
256
/*                                                                        */
257
/*  CALLED BY                                                             */
258
/*                                                                        */
259
/*    _gx_display_driver_generic_polygon_fill                             */
260
/*                                                                        */
261
/*  RELEASE HISTORY                                                       */
262
/*                                                                        */
263
/*    DATE              NAME                      DESCRIPTION             */
264
/*                                                                        */
265
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
266
/*                                                                        */
267
/**************************************************************************/
268
200
static VOID _gx_display_driver_polygon_new_edge_table_init_270(GX_POINT *vertex, INT num, GX_POLYGON_EDGE *net, INT *net_size)
269
{
270
GX_POLYGON_EDGE edge;
271
INT             index;
272
GX_POINT        s_point;
273
GX_POINT        ss_point;
274
GX_POINT        e_point;
275
GX_POINT        ee_point;
276
200
GX_VALUE        net_index = 0;
277
278
1416
    for (index = 0; index < num; index++)
279
    {
280
1216
        s_point = vertex[index];
281
1216
        e_point = vertex[(index + 1) % num];
282
1216
        ss_point = vertex[(index - 1 + num) % num];
283
1216
        ee_point = vertex[(index + 2) % num];
284
285
        /* Skip vertical line. */
286
1216
        if (s_point.gx_point_x != e_point.gx_point_x)
287
        {
288
            /* Add one edge to new edge table, s_point and e_point are two endpoints of the added edge. */
289
1024
            edge.gx_polygon_edge_dx = GX_ABS(e_point.gx_point_x - s_point.gx_point_x);
290
1024
            edge.gx_polygon_edge_dy = GX_ABS(e_point.gx_point_y - s_point.gx_point_y);
291
1024
            edge.gx_polygon_edge_x_decision = edge.gx_polygon_edge_dx >> 1;
292

1024
            if (((e_point.gx_point_x > s_point.gx_point_x) && (e_point.gx_point_y > s_point.gx_point_y)) ||
293

832
                ((e_point.gx_point_x < s_point.gx_point_x) && (e_point.gx_point_y < s_point.gx_point_y)))
294
            {
295
392
                edge.gx_polygon_edge_sign = 1;
296
            }
297
            else
298
            {
299
632
                edge.gx_polygon_edge_sign = -1;
300
            }
301
302
1024
            if (e_point.gx_point_x > s_point.gx_point_x)
303
            {
304
                /* Set xi value. */
305
488
                edge.gx_polygon_edge_xi = s_point.gx_point_y;
306
307
                /* Set max x coordinate of the edge. */
308
488
                edge.gx_polygon_edge_ymax = e_point.gx_point_x;
309
310
488
                if (ee_point.gx_point_x >= e_point.gx_point_x)
311
                {
312
                    /* If e_point isn't the right most point, reset xmax to xmax - 1. */
313
320
                    edge.gx_polygon_edge_ymax -= 1;
314
                }
315
316
488
                edge.gx_polygon_edge_ymin = s_point.gx_point_x;
317
            }
318
            else
319
            {
320
                /* Set xi value, which is the y coordinate value of the edge's leftmost point. */
321
536
                edge.gx_polygon_edge_xi = e_point.gx_point_y;
322
323
                /* Set max x coordinate of the edge. */
324
536
                edge.gx_polygon_edge_ymax = s_point.gx_point_x;
325
326
536
                if (ss_point.gx_point_x >= s_point.gx_point_x)
327
                {
328
                    /* If e_point isn't the right most point, reset xmax to xmax - 1.
329
                       To avoid producing 2 intersections when scan line comes to the vertex point. */
330
368
                    edge.gx_polygon_edge_ymax -= 1;
331
                }
332
333
536
                edge.gx_polygon_edge_ymin = e_point.gx_point_x;
334
            }
335
336
1024
            net[net_index++] = edge;
337
        }
338
    }
339
340
200
    *net_size = net_index;
341
200
}
342
343
/**************************************************************************/
344
/*                                                                        */
345
/*  FUNCTION                                               RELEASE        */
346
/*                                                                        */
347
/*    _gx_display_driver_polygon_active_edge_insert       PORTABLE C      */
348
/*                                                           6.1.3        */
349
/*  AUTHOR                                                                */
350
/*                                                                        */
351
/*    Kenneth Maxwell, Microsoft Corporation                              */
352
/*                                                                        */
353
/*  DESCRIPTION                                                           */
354
/*                                                                        */
355
/*    Internal helper function that Inserts an edge from new edge table to*/
356
/*    active edge table.                                                  */
357
/*                                                                        */
358
/*  INPUT                                                                 */
359
/*                                                                        */
360
/*    aet                               Pointer to active edge table      */
361
/*    net                               Pointer to new edge table         */
362
/*    x                                 X coordinate of current scan line */
363
/*    net                               Pointer to new edge table         */
364
/*    net_size                          New edge table size               */
365
/*    aet_size                          Retured active edge table size    */
366
/*                                                                        */
367
/*  OUTPUT                                                                */
368
/*                                                                        */
369
/*    None                                                                */
370
/*                                                                        */
371
/*  CALLS                                                                 */
372
/*                                                                        */
373
/*    None                                                                */
374
/*                                                                        */
375
/*  CALLED BY                                                             */
376
/*                                                                        */
377
/*    _gx_display_driver_generic_polygon_fill                             */
378
/*                                                                        */
379
/*  RELEASE HISTORY                                                       */
380
/*                                                                        */
381
/*    DATE              NAME                      DESCRIPTION             */
382
/*                                                                        */
383
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
384
/*                                                                        */
385
/**************************************************************************/
386
73660
static VOID _gx_display_driver_polygon_active_edge_insert(GX_POLYGON_EDGE *aet, GX_POLYGON_EDGE *net, INT x, INT net_size, INT *aet_size)
387
{
388
73660
GX_VALUE ni = (GX_VALUE)(net_size - 1);
389
GX_VALUE ai;
390
73660
INT      active_edge_table_size = *aet_size;
391
392
445288
    for (ni = 0; ni < net_size; ni++)
393
    {
394
371628
        if (net[ni].gx_polygon_edge_ymin == x)
395
        {
396
            /* If the rightmost x coordinate value of the edge equals to the current scan line x,
397
               Insert the edge to active edge table, and increase aet size by 1. */
398
399
2564
            ai = (GX_VALUE)(active_edge_table_size - 1);
400

3216
            while ((ai >= 0) && (net[ni].gx_polygon_edge_xi < aet[ai].gx_polygon_edge_xi))
401
            {
402
652
                aet[ai + 1] = aet[ai];
403
652
                ai--;
404
            }
405
2564
            aet[ai + 1] = net[ni];
406
2564
            active_edge_table_size++;
407
        }
408
    }
409
410
73660
    *aet_size = active_edge_table_size;
411
73660
}
412
413
/**************************************************************************/
414
/*                                                                        */
415
/*  FUNCTION                                               RELEASE        */
416
/*                                                                        */
417
/*    _gx_display_driver_polygon_non_active_edge_remove   PORTABLE C      */
418
/*                                                           6.1.3        */
419
/*  AUTHOR                                                                */
420
/*                                                                        */
421
/*    Kenneth Maxwell, Microsoft Corporation                              */
422
/*                                                                        */
423
/*  DESCRIPTION                                                           */
424
/*                                                                        */
425
/*    Internal helper function that removes an edge from active edge table*/
426
/*                                                                        */
427
/*  INPUT                                                                 */
428
/*                                                                        */
429
/*    aet                               Pointer to active edge table      */
430
/*    x                                 X coordinate of current scan line */
431
/*    aet_size                          Active edge table size            */
432
/*                                                                        */
433
/*  OUTPUT                                                                */
434
/*                                                                        */
435
/*    None                                                                */
436
/*                                                                        */
437
/*  CALLS                                                                 */
438
/*                                                                        */
439
/*    None                                                                */
440
/*                                                                        */
441
/*  CALLED BY                                                             */
442
/*                                                                        */
443
/*    _gx_display_driver_generic_polygon_fill                             */
444
/*                                                                        */
445
/*  RELEASE HISTORY                                                       */
446
/*                                                                        */
447
/*    DATE              NAME                      DESCRIPTION             */
448
/*                                                                        */
449
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
450
/*                                                                        */
451
/**************************************************************************/
452
73660
static VOID _gx_display_driver_polygon_non_active_edge_remove(GX_POLYGON_EDGE *aet, INT x, INT *aet_size)
453
{
454
INT i;
455
INT j;
456
457
224324
    for (i = 0; i < *aet_size; i++)
458
    {
459
        /* If the bottom most y coordinate value of the edge equals to the current scan line y,
460
           Remove the edge from active edge table, and decrease aet size by 1. */
461
150664
        if (aet[i].gx_polygon_edge_ymax == x)
462
        {
463
3908
            for (j = i; j < *aet_size - 1; j++)
464
            {
465
1344
                aet[j] = aet[j + 1];
466
            }
467
2564
            (*aet_size)--;
468
2564
            i--;
469
        }
470
    }
471
73660
}
472
473
/**************************************************************************/
474
/*                                                                        */
475
/*  FUNCTION                                               RELEASE        */
476
/*                                                                        */
477
/*    _gx_display_driver_polygon_scan_line_draw           PORTABLE C      */
478
/*                                                           6.1.3        */
479
/*  AUTHOR                                                                */
480
/*                                                                        */
481
/*    Kenneth Maxwell, Microsoft Corporation                              */
482
/*                                                                        */
483
/*  DESCRIPTION                                                           */
484
/*                                                                        */
485
/*    Internal helper function that filling area between pair             */
486
/*    intersections.                                                      */
487
/*                                                                        */
488
/*  INPUT                                                                 */
489
/*                                                                        */
490
/*    context                           Drawing context                   */
491
/*    aet                               Pointer to active edge table      */
492
/*    x                                 X coordinate of current scan line */
493
/*    aet_size                          Active edge table size            */
494
/*                                                                        */
495
/*  OUTPUT                                                                */
496
/*                                                                        */
497
/*    None                                                                */
498
/*                                                                        */
499
/*  CALLS                                                                 */
500
/*                                                                        */
501
/*    [gx_display_driver_horizontal_line_draw]                            */
502
/*                                      Basic display driver horizontal   */
503
/*                                        line draw function              */
504
/*                                                                        */
505
/*  CALLED BY                                                             */
506
/*                                                                        */
507
/*    _gx_display_driver_generic_polygon_fill                             */
508
/*                                                                        */
509
/*  RELEASE HISTORY                                                       */
510
/*                                                                        */
511
/*    DATE              NAME                      DESCRIPTION             */
512
/*                                                                        */
513
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
514
/*                                                                        */
515
/**************************************************************************/
516
11900
static VOID _gx_display_driver_polygon_scan_line_draw(GX_DRAW_CONTEXT *context, GX_POLYGON_EDGE *aet, INT x, INT aet_size)
517
{
518
GX_VALUE      index;
519
INT           y1, y2;
520
11900
GX_DISPLAY   *display = context -> gx_draw_context_display;
521
11900
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
522
GX_COLOR      fill_color;
523
524
11900
    fill_color = context -> gx_draw_context_brush.gx_brush_fill_color;
525
526
24118
    for (index = 0; index < aet_size - 1; index = (GX_VALUE)(index + (GX_VALUE)2))
527
    {
528
529
        /* Pick up y coordinate value of the pair intersections. */
530
12218
        y1 = aet[index].gx_polygon_edge_xi;
531
12218
        y2 = aet[index + 1].gx_polygon_edge_xi;
532
533
12218
        if (context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS)
534
        {
535
10473
            if ((aet[index].gx_polygon_edge_dy > aet[index].gx_polygon_edge_dx) &&
536
3279
                (aet[index].gx_polygon_edge_sign < 0))
537
            {
538
1623
                y1 += 1;
539
            }
540
541
10473
            if (aet[index + 1].gx_polygon_edge_dy >= aet[index + 1].gx_polygon_edge_dx)
542
            {
543
4404
                if (aet[index + 1].gx_polygon_edge_sign > 0)
544
                {
545
2112
                    y2 -= 1;
546
                }
547
            }
548
            else
549
            {
550
6069
                y2 -= 1;
551
            }
552
        }
553
554
        /* Cliping segments y1y2. */
555
12218
        if (y1 < clip -> gx_rectangle_top)
556
        {
557
2002
            y1 = clip -> gx_rectangle_top;
558
        }
559
560
12218
        if (y2 > clip -> gx_rectangle_bottom)
561
        {
562
948
            y2 = clip -> gx_rectangle_bottom;
563
        }
564
565
12218
        if (y1 <= y2)
566
        {
567
            /* Filling area between pairs of the intersections. */
568
12118
            display -> gx_display_driver_vertical_line_draw(context, y1, y2, x, 1, fill_color);
569
        }
570
    }
571
11900
}
572
573
/**************************************************************************/
574
/*                                                                        */
575
/*  FUNCTION                                               RELEASE        */
576
/*                                                                        */
577
/*    _gx_display_driver_polygon_pixelmap_scan_line_draw  PORTABLE C      */
578
/*                                                           6.1.3        */
579
/*  AUTHOR                                                                */
580
/*                                                                        */
581
/*    Kenneth Maxwell, Microsoft Corporation                              */
582
/*                                                                        */
583
/*  DESCRIPTION                                                           */
584
/*                                                                        */
585
/*    Internal helper function that filling area between pair             */
586
/*    intersections with pixelmap.                                        */
587
/*                                                                        */
588
/*  INPUT                                                                 */
589
/*                                                                        */
590
/*    context                           Drawing context                   */
591
/*    aet                               Pointer to active edge table      */
592
/*    aet_size                          Active edge table size            */
593
/*    ypos                              Y coord of draw start position    */
594
/*    x                                 X coordinate of current scan line */
595
/*    pixelmap                          Pixelmap to fill                  */
596
/*                                                                        */
597
/*  OUTPUT                                                                */
598
/*                                                                        */
599
/*    None                                                                */
600
/*                                                                        */
601
/*  CALLS                                                                 */
602
/*                                                                        */
603
/*    [gx_display_driver_horizontal_pixelmap_line_draw]                   */
604
/*                                      Basic display driver horizontal   */
605
/*                                        pixelmap line draw function     */
606
/*                                                                        */
607
/*  CALLED BY                                                             */
608
/*                                                                        */
609
/*    _gx_display_driver_generic_polygon_fill                             */
610
/*                                                                        */
611
/*  RELEASE HISTORY                                                       */
612
/*                                                                        */
613
/*    DATE              NAME                      DESCRIPTION             */
614
/*                                                                        */
615
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
616
/*                                                                        */
617
/**************************************************************************/
618
49268
static VOID _gx_display_driver_polygon_pixelmap_scan_line_draw(GX_DRAW_CONTEXT *context, GX_POLYGON_EDGE *aet, INT aet_size,
619
                                                               INT ypos, INT x, GX_FILL_PIXELMAP_INFO *info)
620
{
621
GX_VALUE              index;
622
INT                   y1, y2;
623
49268
GX_DISPLAY           *display = context -> gx_draw_context_display;
624
49268
GX_RECTANGLE         *clip = context -> gx_draw_context_clip;
625
GX_FILL_PIXELMAP_INFO old_info;
626
49268
GX_BOOL               is_drawn = GX_FALSE;
627
628
    /* Store the ptr info in case that this line will be drawn several times.*/
629
49268
    old_info = (*info);
630
631
99934
    for (index = 0; index < aet_size - 1; index = (GX_VALUE)(index + (GX_VALUE)2))
632
    {
633
        /* if aet_size is bigger than 2, it means there's at least two segment in this line.
634
           So it must be drawn this line several times and should always be started from the "correct" position. */
635
50666
        (*info) = old_info;
636
637
        /* Pick up y coordinate value of the pair intersections. */
638
50666
        y1 = aet[index].gx_polygon_edge_xi;
639
50666
        y2 = aet[index + 1].gx_polygon_edge_xi;
640
641
50666
        if (context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS)
642
        {
643
43686
            if ((aet[index].gx_polygon_edge_dy > aet[index].gx_polygon_edge_dx) &&
644
14754
                (aet[index].gx_polygon_edge_sign < 0))
645
            {
646
7272
                y1 += 1;
647
            }
648
649
43686
            if (aet[index + 1].gx_polygon_edge_dy >= aet[index + 1].gx_polygon_edge_dx)
650
            {
651
19548
                if (aet[index + 1].gx_polygon_edge_sign > 0)
652
                {
653
9444
                    y2 -= 1;
654
                }
655
            }
656
            else
657
            {
658
24138
                y2 -= 1;
659
            }
660
        }
661
662
        /* Cliping segments y1y2. */
663
50666
        if (y1 < clip -> gx_rectangle_top)
664
        {
665
7150
            y1 = clip -> gx_rectangle_top;
666
        }
667
668
50666
        if (y2 > clip -> gx_rectangle_bottom)
669
        {
670
4176
            y2 = clip -> gx_rectangle_bottom;
671
        }
672
673
50666
        if (y1 > y2)
674
        {
675
412
            continue;
676
        }
677
678
        /* Filling area between pairs of the intersections. */
679
50254
        info -> x_offset = y1 - ypos;
680
50254
        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, y1, y2, x, info);
681
682
50254
        is_drawn = GX_TRUE;
683
    }
684
685
49268
    if (!is_drawn)
686
    {
687
480
        info -> draw = GX_FALSE;
688
480
        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, info);
689
    }
690
49268
}
691
692
/**************************************************************************/
693
/*                                                                        */
694
/*  FUNCTION                                               RELEASE        */
695
/*                                                                        */
696
/*    _gx_display_driver_polygon_active_edge_table_update_and_restore     */
697
/*                                                        PORTABLE C      */
698
/*                                                           6.1.3        */
699
/*  AUTHOR                                                                */
700
/*                                                                        */
701
/*    Kenneth Maxwell, Microsoft Corporation                              */
702
/*                                                                        */
703
/*  DESCRIPTION                                                           */
704
/*                                                                        */
705
/*    Internal helper function that updates x coordinate of intersection  */
706
/*    according to edge gradient, and sort intersections by increase x    */
707
/*    coordinate value.                                                   */
708
/*                                                                        */
709
/*  INPUT                                                                 */
710
/*                                                                        */
711
/*    aet                               Pointer to active edge table      */
712
/*    aet_size                          Active edge table size            */
713
/*                                                                        */
714
/*  OUTPUT                                                                */
715
/*                                                                        */
716
/*    None                                                                */
717
/*                                                                        */
718
/*  CALLS                                                                 */
719
/*                                                                        */
720
/*    None                                                                */
721
/*                                                                        */
722
/*  CALLED BY                                                             */
723
/*                                                                        */
724
/*    _gx_display_driver_generic_polygon_fill                             */
725
/*                                                                        */
726
/*  RELEASE HISTORY                                                       */
727
/*                                                                        */
728
/*    DATE              NAME                      DESCRIPTION             */
729
/*                                                                        */
730
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
731
/*                                                                        */
732
/**************************************************************************/
733
73660
static UINT _gx_display_driver_polygon_active_edge_table_update_and_restore(GX_POLYGON_EDGE *aet, INT aet_size)
734
{
735
73660
GX_VALUE        index = (GX_VALUE)aet_size, xi, yi;
736
GX_POLYGON_EDGE temp;
737
738
    /* Update xi value. */
739
221760
    while (index--)
740
    {
741
148100
        if (aet[index].gx_polygon_edge_dy == 0)
742
        {
743
77852
            continue;
744
        }
745
746
        /* When scan line move one step from right to left,
747
           we need to update y value of active edges with the delta of the edge,
748
           the following codes equals to y += delta(x). */
749
70248
        aet[index].gx_polygon_edge_x_decision += aet[index].gx_polygon_edge_dy;
750
751
169112
        while (aet[index].gx_polygon_edge_x_decision > aet[index].gx_polygon_edge_dx)
752
        {
753
98864
            aet[index].gx_polygon_edge_xi += aet[index].gx_polygon_edge_sign;
754
98864
            aet[index].gx_polygon_edge_x_decision -= aet[index].gx_polygon_edge_dx;
755
        }
756
    }
757
758
    /* Sort with xi value in ascending order. */
759
148988
    for (xi = 0; xi < aet_size - 1; xi++)
760
    {
761
155900
        for (yi = (GX_VALUE)(xi + 1); yi < aet_size; yi++)
762
        {
763
80572
            if (aet[xi].gx_polygon_edge_xi > aet[yi].gx_polygon_edge_xi)
764
            {
765
324
                temp = aet[yi];
766
324
                aet[yi] = aet[xi];
767
324
                aet[xi] = temp;
768
            }
769
        }
770
    }
771
772
73660
    return GX_SUCCESS;
773
}
774
775
/**************************************************************************/
776
/*                                                                        */
777
/*  FUNCTION                                               RELEASE        */
778
/*                                                                        */
779
/*    _gx_display_driver_generic_rotated_polygon_fill     PORTABLE C      */
780
/*                                                            6.1.3       */
781
/*  AUTHOR                                                                */
782
/*                                                                        */
783
/*    Kenneth Maxwell, Microsoft Corporation                              */
784
/*                                                                        */
785
/*  DESCRIPTION                                                           */
786
/*                                                                        */
787
/*    This fills a polygon.                                               */
788
/*                                                                        */
789
/*  INPUT                                                                 */
790
/*                                                                        */
791
/*    num                               Number of points of polygon       */
792
/*    vertex                            Array of points of the polygon,   */
793
/*                                        terminated by NULL entry.       */
794
/*                                                                        */
795
/*  OUTPUT                                                                */
796
/*                                                                        */
797
/*    status                            Completion status                 */
798
/*                                                                        */
799
/*  CALLS                                                                 */
800
/*                                                                        */
801
/*    _gx_canvas_line_draw              Draw the specified line           */
802
/*                                                                        */
803
/*  CALLED BY                                                             */
804
/*                                                                        */
805
/*    Application Code                                                    */
806
/*                                                                        */
807
/*  RELEASE HISTORY                                                       */
808
/*                                                                        */
809
/*    DATE              NAME                      DESCRIPTION             */
810
/*                                                                        */
811
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
812
/*                                                                        */
813
/**************************************************************************/
814
511
VOID _gx_display_driver_generic_rotated_polygon_fill(GX_DRAW_CONTEXT *context, GX_POINT *vertex, INT num)
815
{
816
INT                    xmin;
817
INT                    xmax;
818
INT                    ypos;
819
INT                    x;
820
INT                    xstart;
821
GX_BYTE                xsign;
822
static GX_POLYGON_EDGE net[GX_POLYGON_MAX_EDGE_NUM]; /* new edge table: obtain all edges of the polygon. */
823
static GX_POLYGON_EDGE aet[GX_POLYGON_MAX_EDGE_NUM]; /* active edge table: obtain all edges that touched by the current scan line. */
824
GX_BRUSH              *brush;
825
511
INT                    aet_size = 0;
826
511
INT                    net_size = num;
827
511
GX_PIXELMAP           *pixelmap = GX_NULL;
828
GX_FILL_PIXELMAP_INFO  info;
829
511
GX_DISPLAY            *display = context -> gx_draw_context_display;
830
511
GX_RECTANGLE          *clip = context -> gx_draw_context_clip;
831
INT                    skip_line;
832
833
511
    if (num <= GX_POLYGON_MAX_EDGE_NUM)
834
    {
835
510
        brush = &context -> gx_draw_context_brush;
836
510
        if (brush -> gx_brush_style & GX_BRUSH_PIXELMAP_FILL)
837
        {
838
412
            if (brush -> gx_brush_pixelmap == GX_NULL)
839
            {
840
2
                return;
841
            }
842
843
            /* Pick up brush pixelmap. */
844
411
            pixelmap = brush -> gx_brush_pixelmap;
845
846
411
            if (pixelmap -> gx_pixelmap_format != display -> gx_display_color_format)
847
            {
848
                /* Display driver only support its native format pixelmap.*/
849
                /* Nothing should be drawn if pixelmap format isn't support. */
850
1
                return;
851
            }
852
853
410
            memset(&info, 0, sizeof(GX_FILL_PIXELMAP_INFO));
854
855
410
            info.pixelmap = brush -> gx_brush_pixelmap;
856
410
            info.current_pixel_ptr = (GX_UBYTE *)info.pixelmap -> gx_pixelmap_data;
857
858
410
            if (pixelmap -> gx_pixelmap_aux_data_size)
859
            {
860
162
                info.current_aux_ptr = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
861
            }
862
        }
863
864
        /* Get the top most and bottom most y coordinate of the specified polygon. */
865
508
        _gx_display_driver_polygon_min_max_get(vertex, num, &xmin, &xmax, &ypos);
866
867
508
        if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
868
        {
869
            /* Initiate new edge table. */
870
308
            _gx_display_driver_polygon_new_edge_table_init_90(vertex, num, net, &net_size);
871
872
308
            if (pixelmap)
873
            {
874
238
                skip_line = (xmax - xmin + 1) % pixelmap -> gx_pixelmap_width;
875
876
238
                if (skip_line)
877
                {
878
218
                    skip_line = pixelmap -> gx_pixelmap_width - skip_line;
879
880
218
                    info.draw = GX_FALSE;
881
18234
                    while (skip_line--)
882
                    {
883
18016
                        display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
884
                    }
885
                }
886
            }
887
        }
888
        else
889
        {
890
200
            _gx_display_driver_polygon_new_edge_table_init_270(vertex, num, net, &net_size);
891
        }
892
893
508
        if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
894
        {
895
308
            xstart = xmax;
896
308
            xsign = -1;
897
        }
898
        else
899
        {
900
200
            xstart = xmin;
901
200
            xsign = 1;
902
        }
903
904
        /* Moving scan line from polygon top to bottom. */
905
74168
        for (x = xmin; x <= xmax; x++)
906
        {
907
            /* This function will check if the scan line comes to the top most y coordinate of any edges in net table.
908
               If it is true, add it to the aet table. */
909
73660
            _gx_display_driver_polygon_active_edge_insert(aet, net, xstart, net_size, &aet_size);
910
911
73660
            if ((xstart < clip -> gx_rectangle_left) ||
912
73584
                (xstart > clip -> gx_rectangle_right))
913
            {
914
12492
                if (pixelmap)
915
                {
916
                    /* skip the undraw lines. */
917
9762
                    info.draw = GX_FALSE;
918
9762
                    display -> gx_display_driver_horizontal_pixelmap_line_draw(context, 0, 0, 0, &info);
919
                }
920
            }
921
            else
922
            {
923
61168
                if (pixelmap)
924
                {
925
49268
                    info.draw = GX_TRUE;
926
49268
                    _gx_display_driver_polygon_pixelmap_scan_line_draw(context, aet, aet_size, ypos, xstart, &info);
927
                }
928
                else
929
                {
930
                    /* Filling the polygon area that touched by scan line. */
931
11900
                    _gx_display_driver_polygon_scan_line_draw(context, aet, xstart, aet_size);
932
                }
933
            }
934
            /* This function will check if the scan line comes to the bottom most y coordinate of any edges in aet table.
935
               If it is true, remove it from aet table. */
936
73660
            _gx_display_driver_polygon_non_active_edge_remove(aet, xstart, &aet_size);
937
938
            /* Update x coordinate of intersections between polygon and scan line, and sort them by increase x coordinate value. */
939
73660
            _gx_display_driver_polygon_active_edge_table_update_and_restore(aet, aet_size);
940
941
73660
            xstart += xsign;
942
        }
943
    }
944
}
945