GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_wide_line_fill.c Lines: 125 125 100.0 %
Date: 2026-03-06 19:21:09 Branches: 98 98 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
22
23
24
#define GX_SOURCE_CODE
25
26
27
/* Include necessary system files.  */
28
29
#include "gx_api.h"
30
#include "gx_utility.h"
31
#include "gx_display.h"
32
#include "gx_system.h"
33
34
/**************************************************************************/
35
/*                                                                        */
36
/*  FUNCTION                                               RELEASE        */
37
/*                                                                        */
38
/*    _gx_display_driver_generic_wide_line_fill           PORTABLE C      */
39
/*                                                           6.1          */
40
/*  AUTHOR                                                                */
41
/*                                                                        */
42
/*    Kenneth Maxwell, Microsoft Corporation                              */
43
/*                                                                        */
44
/*  DESCRIPTION                                                           */
45
/*                                                                        */
46
/*   Fill a wide line after the four corner points have been calculated.  */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    context                               Drawing context               */
51
/*    pPoints                               Pre-computed end points       */
52
/*                                                                        */
53
/*  OUTPUT                                                                */
54
/*                                                                        */
55
/*    None                                                                */
56
/*                                                                        */
57
/*  CALLS                                                                 */
58
/*                                                                        */
59
/*    GX_ABS                                Compute the absolute value    */
60
/*    GX_SWAP_VALUE                         Swap two values               */
61
/*    [_gx_display_driver_horizontal_line_draw]                           */
62
/*                                          Driver for horizontal line    */
63
/*                                            draw                        */
64
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    _gx_display_driver_generic_simple_wide_line_draw                    */
68
/*    _gx_display_driver_generic_aliased_wide_line_draw                   */
69
/*                                                                        */
70
/**************************************************************************/
71
7834
VOID _gx_display_driver_generic_wide_line_fill(GX_DRAW_CONTEXT *context, GX_FIXED_POINT *pPoints)
72
{
73
/*
74
   Use Breshenham's line to compute the points along each line that bounds
75
   the wide line and save the points to an array. Then draw horizontal lines
76
   to connect the points.
77
 */
78
79
7834
GX_FIXED_POINT *pGet = pPoints;
80
INT            *pLineEnds;
81
INT             ymin;
82
INT             ymax;
83
INT             xstart;
84
INT             xend;
85
INT             ystart;
86
INT             yend;
87
INT             curx;
88
INT             cury;
89
INT             test;
90
GX_FIXED_VAL    dx;
91
GX_FIXED_VAL    dy;
92
INT             Index;
93
INT             loop;
94
INT             height;
95
INT             xsign;
96
INT             ysign;
97
INT             decision;
98
INT             shift;
99
VOID            (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
100
7834
GX_RECTANGLE   *clip = context -> gx_draw_context_clip;
101
7834
GX_COLOR        linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
102
7834
GX_BOOL         aliased = GX_FALSE;
103
INT             x_fraction;
104
INT             y_fraction;
105
106
7834
    if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
107
4580
        context -> gx_draw_context_display -> gx_display_driver_pixel_blend)
108
    {
109
3122
        aliased = GX_TRUE;
110
    }
111
112
7834
    ymin = GX_FIXED_VAL_TO_INT(pPoints[1].y);
113
7834
    ymax = GX_FIXED_VAL_RND_UP(pPoints[3].y);
114
115
7834
    if (ymin < clip -> gx_rectangle_top)
116
    {
117
7
        ymin = clip -> gx_rectangle_top;
118
    }
119
120
7834
    if (ymax > clip -> gx_rectangle_bottom)
121
    {
122
728
        ymax = clip -> gx_rectangle_bottom;
123
    }
124
125
7834
    height = ymax - ymin + 1;
126
127
7834
    pLineEnds = _gx_system_scratchpad;
128
129
    /* default the point array to being off the screen on both sides: */
130
131
730214
    for (loop = 0; loop < height * 2; loop += 2)
132
    {
133
722380
        pLineEnds[loop] = 2000;
134
722380
        pLineEnds[loop + 1] = 0;
135
    }
136
137
    /* Fill in the point array by using Breshenhams line for
138
       all 4 sides of the bounding rectangle
139
     */
140
141
39170
    for (loop = 0; loop < 4; loop++)
142
    {
143
31336
        xstart = pGet -> x;
144
31336
        ystart = pGet -> y;
145
31336
        pGet++;
146
31336
        xend = pGet -> x;
147
31336
        yend = pGet -> y;
148
31336
        dx = GX_ABS(xend - xstart);
149
31336
        dy = GX_ABS(yend - ystart);
150
151
31336
        xsign = ysign = 1;
152
153

31336
        if (((dx >= dy && (xstart > xend)) ||
154
14460
             ((dy > dx) && ystart > yend)))
155
        {
156
15668
            GX_SWAP_VALS(xend, xstart);
157
15668
            GX_SWAP_VALS(yend, ystart);
158
        }
159
31336
        if (dx)
160
        {
161
31332
            xsign = (xend - xstart) / dx;
162
        }
163
31336
        if (dy)
164
        {
165
31332
            ysign = (yend - ystart) / dy;
166
        }
167
168
31336
        x_fraction = (xstart & GX_FIXED_VAL_FRACTION_MASK);
169
31336
        y_fraction = (ystart & GX_FIXED_VAL_FRACTION_MASK);
170
171
31336
        shift = 0;
172
173
31336
        if (dx >= dy)
174
        {
175
16876
            if (ysign < 0)
176
            {
177
9080
                cury = GX_FIXED_VAL_RND_UP(ystart);
178
179
9080
                if (y_fraction)
180
                {
181
8938
                    y_fraction = GX_FIXED_VAL_ONE - y_fraction;
182
                }
183
            }
184
            else
185
            {
186
7796
                cury = GX_FIXED_VAL_TO_INT(ystart);
187
            }
188
189
16876
            decision = (y_fraction * dx - x_fraction * dy) / GX_FIXED_VAL_ONE;
190
191
16876
            if (decision < 0)
192
            {
193
4116
                decision += dx;
194
4116
                cury -= ysign;
195
            }
196
197
16876
            xstart = GX_FIXED_VAL_TO_INT(xstart);
198
199
16876
            if (aliased)
200
            {
201
6584
                xend = GX_FIXED_VAL_TO_INT(xend);
202
203
6584
                if (x_fraction)
204
                {
205
6376
                    xstart++;
206
6376
                    decision += dy;
207
                }
208
209
6584
                if (dy)
210
                {
211

6580
                    if ((loop == 1) || (loop == 2))
212
                    {
213
3290
                        shift = ysign;
214
                    }
215
                }
216
            }
217
            else
218
            {
219
10292
                xend = GX_FIXED_VAL_RND(xend);
220
221
10292
                if (x_fraction >= GX_FIXED_VAL_HALF)
222
                {
223
5173
                    xstart++;
224
5173
                    decision += dy;
225
                }
226
227
10292
                decision += (dx >> 1);
228
10292
                if (decision >= dx)
229
                {
230
7604
                    decision -= dx;
231
7604
                    cury += ysign;
232
                }
233
            }
234
235
1081210
            for (curx = xstart; curx <= xend; curx++, decision += dy)
236
            {
237
1064334
                if (decision >= dx)
238
                {
239
570564
                    decision -= dx;
240
570564
                    cury += ysign;
241
                }
242
243
1064334
                test = cury + shift;
244
245

1064334
                if ((test >= ymin) && (test <= ymax))
246
                {
247
1021885
                    Index = (test - ymin) << 1;
248
249
1021885
                    if (curx < pLineEnds[Index])
250
                    {
251
427089
                        pLineEnds[Index] = curx;
252
                    }
253
254
1021885
                    if (curx > pLineEnds[Index + 1])
255
                    {
256
693235
                        pLineEnds[Index + 1] = curx;
257
                    }
258
                }
259
            }
260
261
        }
262
        else
263
        {
264
14460
            if (xsign < 0)
265
            {
266
6584
                curx = GX_FIXED_VAL_RND_UP(xstart);
267
268
6584
                if (x_fraction)
269
                {
270
6350
                    x_fraction = GX_FIXED_VAL_FRACTION_MASK - x_fraction;
271
                }
272
            }
273
            else
274
            {
275
7876
                curx = GX_FIXED_VAL_TO_INT(xstart);
276
            }
277
278
14460
            decision = (x_fraction * dy - y_fraction * dx) / GX_FIXED_VAL_ONE;
279
280
14460
            if (decision < 0)
281
            {
282
3766
                decision += dy;
283
3766
                curx -= xsign;
284
            }
285
286
14460
            ystart = GX_FIXED_VAL_TO_INT(ystart);
287
288
14460
            if (aliased)
289
            {
290
5904
                yend = GX_FIXED_VAL_TO_INT(yend);
291
292
5904
                if (y_fraction)
293
                {
294
5614
                    ystart++;
295
5614
                    decision += dx;
296
                }
297
298
5904
                if (dx)
299
                {
300

5900
                    if (loop == 2 || loop == 3)
301
                    {
302
2950
                        shift = xsign;
303
                    }
304
                }
305
            }
306
            else
307
            {
308
8556
                yend = GX_FIXED_VAL_RND(yend);
309
310
8556
                if (y_fraction >= GX_FIXED_VAL_HALF)
311
                {
312
4282
                    ystart++;
313
4282
                    decision += dx;
314
                }
315
316
8556
                decision += (dy >> 1);
317
318
8556
                if (decision >= dy)
319
                {
320
6126
                    decision -= dy;
321
6126
                    curx += xsign;
322
                }
323
            }
324
325
934812
            for (cury = ystart; cury <= yend; cury++, decision += dx)
326
            {
327
920352
                if (decision >= dy)
328
                {
329
387094
                    decision -= dy;
330
387094
                    curx += xsign;
331
                }
332
333

920352
                if ((cury >= ymin) && (cury <= ymax))
334
                {
335
876189
                    Index = (cury - ymin) << 1;
336
337
876189
                    test = curx + shift;
338
876189
                    if (test < pLineEnds[Index])
339
                    {
340
719466
                        pLineEnds[Index] = test;
341
                    }
342
343
876189
                    if (test > pLineEnds[Index + 1])
344
                    {
345
563136
                        pLineEnds[Index + 1] = test;
346
                    }
347
                }
348
            }
349
        }
350
    }
351
352
7834
    Index = 0;
353
7834
    line_draw = context -> gx_draw_context_display -> gx_display_driver_horizontal_line_draw;
354
355
730214
    for (cury = ymin; cury <= ymax; cury++)
356
    {
357
722380
        if (pLineEnds[Index] < clip -> gx_rectangle_left)
358
        {
359
25347
            pLineEnds[Index] = clip -> gx_rectangle_left;
360
        }
361
362
722380
        if (pLineEnds[Index + 1] > clip -> gx_rectangle_right)
363
        {
364
60210
            pLineEnds[Index + 1] = clip -> gx_rectangle_right;
365
        }
366
367
722380
        if (pLineEnds[Index] <= pLineEnds[Index + 1])
368
        {
369
641619
            line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], cury, 1, linecolor);
370
        }
371
722380
        Index += 2;
372
    }
373
7834
}
374