GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_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_rotated_wide_line_fill   PORTABLE C      */
39
/*                                                           6.1.3        */
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
4731
VOID _gx_display_driver_generic_rotated_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
4731
GX_FIXED_POINT *pGet = pPoints;
80
INT            *pLineEnds;
81
INT             xmin;
82
INT             xmax;
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             width;
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
4731
GX_RECTANGLE   *clip = context -> gx_draw_context_clip;
101
4731
GX_COLOR        linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
102
4731
GX_BOOL         aliased = GX_FALSE;
103
INT             x_fraction;
104
INT             y_fraction;
105
106
4731
    if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
107
2092
        context -> gx_draw_context_display -> gx_display_driver_pixel_blend)
108
    {
109
2090
        aliased = GX_TRUE;
110
    }
111
112
4731
    xmin = GX_FIXED_VAL_TO_INT(pPoints[0].x);
113
4731
    xmax = GX_FIXED_VAL_RND_UP(pPoints[2].x);
114
115
4731
    if (xmin < clip -> gx_rectangle_left)
116
    {
117
418
        xmin = clip -> gx_rectangle_left;
118
    }
119
120
4731
    if (xmax > clip -> gx_rectangle_right)
121
    {
122
164
        xmax = clip -> gx_rectangle_right;
123
    }
124
125
4731
    width = xmax - xmin + 1;
126
127
4731
    pLineEnds = _gx_system_scratchpad;
128
129
    /* default the point array to being off the screen on both sides: */
130
131
448543
    for (loop = 0; loop < width * 2; loop += 2)
132
    {
133
443812
        pLineEnds[loop] = 2000;
134
443812
        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
23655
    for (loop = 0; loop < 4; loop++)
142
    {
143
18924
        xstart = pGet -> x;
144
18924
        ystart = pGet -> y;
145
18924
        pGet++;
146
18924
        xend = pGet -> x;
147
18924
        yend = pGet -> y;
148
18924
        dx = GX_ABS(xend - xstart);
149
18924
        dy = GX_ABS(yend - ystart);
150
151
18924
        xsign = ysign = 1;
152
153

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

4440
                    if ((loop == 1) || (loop == 2))
212
                    {
213
2220
                        shift = ysign;
214
                    }
215
                }
216
            }
217
            else
218
            {
219
5418
                xend = GX_FIXED_VAL_RND(xend);
220
221
5418
                if (x_fraction >= GX_FIXED_VAL_HALF)
222
                {
223
3487
                    xstart++;
224
3487
                    decision += dy;
225
                }
226
227
5418
                decision += (dx >> 1);
228
5418
                if (decision >= dx)
229
                {
230
3886
                    decision -= dx;
231
3886
                    cury += ysign;
232
                }
233
            }
234
235
648194
            for (curx = xstart; curx <= xend; curx++, decision += dy)
236
            {
237
638332
                if (decision >= dx)
238
                {
239
278454
                    decision -= dx;
240
278454
                    cury += ysign;
241
                }
242
243

638332
                if ((curx >= xmin) && (curx <= xmax))
244
                {
245
590554
                    Index = (curx - xmin) << 1;
246
247
590554
                    test = cury + shift;
248
590554
                    if (test < pLineEnds[Index])
249
                    {
250
294413
                        pLineEnds[Index] = test;
251
                    }
252
253
590554
                    if (test > pLineEnds[Index + 1])
254
                    {
255
534258
                        pLineEnds[Index + 1] = test;
256
                    }
257
                }
258
            }
259
        }
260
        else
261
        {
262
9062
            if (xsign < 0)
263
            {
264
4468
                curx = GX_FIXED_VAL_RND_UP(xstart);
265
266
4468
                if (x_fraction)
267
                {
268
4454
                    x_fraction = GX_FIXED_VAL_FRACTION_MASK - x_fraction;
269
                }
270
            }
271
            else
272
            {
273
4594
                curx = GX_FIXED_VAL_TO_INT(xstart);
274
            }
275
276
9062
            decision = (x_fraction * dy - y_fraction * dx) / GX_FIXED_VAL_ONE;
277
278
9062
            if (decision < 0)
279
            {
280
1703
                decision += dy;
281
1703
                curx -= xsign;
282
            }
283
284
9062
            ystart = GX_FIXED_VAL_TO_INT(ystart);
285
286
9062
            if (aliased)
287
            {
288
3916
                yend = GX_FIXED_VAL_TO_INT(yend);
289
290
3916
                if (y_fraction)
291
                {
292
3914
                    ystart++;
293
3914
                    decision += dx;
294
                }
295
296
3916
                if (dx)
297
                {
298

3912
                    if (loop == 2 || loop == 3)
299
                    {
300
1956
                        shift = xsign;
301
                    }
302
                }
303
            }
304
            else
305
            {
306
5146
                yend = GX_FIXED_VAL_RND(yend);
307
308
5146
                if (y_fraction >= GX_FIXED_VAL_HALF)
309
                {
310
3267
                    ystart++;
311
3267
                    decision += dx;
312
                }
313
314
5146
                decision += (dy >> 1);
315
316
5146
                if (decision >= dy)
317
                {
318
3687
                    decision -= dy;
319
3687
                    curx += xsign;
320
                }
321
            }
322
323
644546
            for (cury = ystart; cury <= yend; cury++, decision += dx)
324
            {
325
635484
                if (decision >= dy)
326
                {
327
291190
                    decision -= dy;
328
291190
                    curx += xsign;
329
                }
330
331
635484
                test = curx + shift;
332
333

635484
                if ((test >= xmin) && (test <= xmax))
334
                {
335
604444
                    Index = (test - xmin) << 1;
336
337
604444
                    if (cury < pLineEnds[Index])
338
                    {
339
143263
                        pLineEnds[Index] = cury;
340
                    }
341
342
604444
                    if (cury > pLineEnds[Index + 1])
343
                    {
344
510750
                        pLineEnds[Index + 1] = cury;
345
                    }
346
                }
347
            }
348
        }
349
    }
350
351
4731
    Index = 0;
352
4731
    line_draw = context -> gx_draw_context_display -> gx_display_driver_vertical_line_draw;
353
354
448543
    for (curx = xmin; curx <= xmax; curx++)
355
    {
356
443812
        if (pLineEnds[Index] < clip -> gx_rectangle_top)
357
        {
358
9866
            pLineEnds[Index] = clip -> gx_rectangle_top;
359
        }
360
361
443812
        if (pLineEnds[Index + 1] > clip -> gx_rectangle_bottom)
362
        {
363
13079
            pLineEnds[Index + 1] = clip -> gx_rectangle_bottom;
364
        }
365
366
443812
        if (pLineEnds[Index] <= pLineEnds[Index + 1])
367
        {
368
422714
            line_draw(context, pLineEnds[Index], pLineEnds[Index + 1], curx, 1, linecolor);
369
        }
370
443812
        Index += 2;
371
    }
372
4731
}
373