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

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

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

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

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

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