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

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

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

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

832
                ((e_point.gx_point_x < s_point.gx_point_x) && (e_point.gx_point_y < s_point.gx_point_y)))
277
            {
278
392
                edge.gx_polygon_edge_sign = 1;
279
            }
280
            else
281
            {
282
632
                edge.gx_polygon_edge_sign = -1;
283
            }
284
285
1024
            if (e_point.gx_point_x > s_point.gx_point_x)
286
            {
287
                /* Set xi value. */
288
488
                edge.gx_polygon_edge_xi = s_point.gx_point_y;
289
290
                /* Set max x coordinate of the edge. */
291
488
                edge.gx_polygon_edge_ymax = e_point.gx_point_x;
292
293
488
                if (ee_point.gx_point_x >= e_point.gx_point_x)
294
                {
295
                    /* If e_point isn't the right most point, reset xmax to xmax - 1. */
296
320
                    edge.gx_polygon_edge_ymax -= 1;
297
                }
298
299
488
                edge.gx_polygon_edge_ymin = s_point.gx_point_x;
300
            }
301
            else
302
            {
303
                /* Set xi value, which is the y coordinate value of the edge's leftmost point. */
304
536
                edge.gx_polygon_edge_xi = e_point.gx_point_y;
305
306
                /* Set max x coordinate of the edge. */
307
536
                edge.gx_polygon_edge_ymax = s_point.gx_point_x;
308
309
536
                if (ss_point.gx_point_x >= s_point.gx_point_x)
310
                {
311
                    /* If e_point isn't the right most point, reset xmax to xmax - 1.
312
                       To avoid producing 2 intersections when scan line comes to the vertex point. */
313
368
                    edge.gx_polygon_edge_ymax -= 1;
314
                }
315
316
536
                edge.gx_polygon_edge_ymin = e_point.gx_point_x;
317
            }
318
319
1024
            net[net_index++] = edge;
320
        }
321
    }
322
323
200
    *net_size = net_index;
324
200
}
325
326
/**************************************************************************/
327
/*                                                                        */
328
/*  FUNCTION                                               RELEASE        */
329
/*                                                                        */
330
/*    _gx_display_driver_polygon_active_edge_insert       PORTABLE C      */
331
/*                                                           6.1.3        */
332
/*  AUTHOR                                                                */
333
/*                                                                        */
334
/*    Kenneth Maxwell, Microsoft Corporation                              */
335
/*                                                                        */
336
/*  DESCRIPTION                                                           */
337
/*                                                                        */
338
/*    Internal helper function that Inserts an edge from new edge table to*/
339
/*    active edge table.                                                  */
340
/*                                                                        */
341
/*  INPUT                                                                 */
342
/*                                                                        */
343
/*    aet                               Pointer to active edge table      */
344
/*    net                               Pointer to new edge table         */
345
/*    x                                 X coordinate of current scan line */
346
/*    net                               Pointer to new edge table         */
347
/*    net_size                          New edge table size               */
348
/*    aet_size                          Retured active edge table size    */
349
/*                                                                        */
350
/*  OUTPUT                                                                */
351
/*                                                                        */
352
/*    None                                                                */
353
/*                                                                        */
354
/*  CALLS                                                                 */
355
/*                                                                        */
356
/*    None                                                                */
357
/*                                                                        */
358
/*  CALLED BY                                                             */
359
/*                                                                        */
360
/*    _gx_display_driver_generic_polygon_fill                             */
361
/*                                                                        */
362
/**************************************************************************/
363
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)
364
{
365
73660
GX_VALUE ni = (GX_VALUE)(net_size - 1);
366
GX_VALUE ai;
367
73660
INT      active_edge_table_size = *aet_size;
368
369
445288
    for (ni = 0; ni < net_size; ni++)
370
    {
371
371628
        if (net[ni].gx_polygon_edge_ymin == x)
372
        {
373
            /* If the rightmost x coordinate value of the edge equals to the current scan line x,
374
               Insert the edge to active edge table, and increase aet size by 1. */
375
376
2564
            ai = (GX_VALUE)(active_edge_table_size - 1);
377

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