GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_generic_rotated_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_rotated_wide_line_fill   PORTABLE C      */
38
/*                                                           6.1.3        */
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
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
74
/*                                                                        */
75
/**************************************************************************/
76
4731
VOID _gx_display_driver_generic_rotated_wide_line_fill(GX_DRAW_CONTEXT *context, GX_FIXED_POINT *pPoints)
77
{
78
/*
79
   Use Breshenham's line to compute the points along each line that bounds
80
   the wide line and save the points to an array. Then draw horizontal lines
81
   to connect the points.
82
 */
83
84
4731
GX_FIXED_POINT *pGet = pPoints;
85
INT            *pLineEnds;
86
INT             xmin;
87
INT             xmax;
88
INT             xstart;
89
INT             xend;
90
INT             ystart;
91
INT             yend;
92
INT             curx;
93
INT             cury;
94
INT             test;
95
GX_FIXED_VAL    dx;
96
GX_FIXED_VAL    dy;
97
INT             Index;
98
INT             loop;
99
INT             width;
100
INT             xsign;
101
INT             ysign;
102
INT             decision;
103
INT             shift;
104
VOID            (*line_draw)(GX_DRAW_CONTEXT *context, INT x1, INT x2, INT ypos, INT width, GX_COLOR color);
105
4731
GX_RECTANGLE   *clip = context -> gx_draw_context_clip;
106
4731
GX_COLOR        linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
107
4731
GX_BOOL         aliased = GX_FALSE;
108
INT             x_fraction;
109
INT             y_fraction;
110
111
4731
    if ((context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_ALIAS) &&
112
2092
        context -> gx_draw_context_display -> gx_display_driver_pixel_blend)
113
    {
114
2090
        aliased = GX_TRUE;
115
    }
116
117
4731
    xmin = GX_FIXED_VAL_TO_INT(pPoints[0].x);
118
4731
    xmax = GX_FIXED_VAL_RND_UP(pPoints[2].x);
119
120
4731
    if (xmin < clip -> gx_rectangle_left)
121
    {
122
418
        xmin = clip -> gx_rectangle_left;
123
    }
124
125
4731
    if (xmax > clip -> gx_rectangle_right)
126
    {
127
164
        xmax = clip -> gx_rectangle_right;
128
    }
129
130
4731
    width = xmax - xmin + 1;
131
132
4731
    pLineEnds = _gx_system_scratchpad;
133
134
    /* default the point array to being off the screen on both sides: */
135
136
448543
    for (loop = 0; loop < width * 2; loop += 2)
137
    {
138
443812
        pLineEnds[loop] = 2000;
139
443812
        pLineEnds[loop + 1] = 0;
140
    }
141
142
    /* Fill in the point array by using Breshenhams line for
143
       all 4 sides of the bounding rectangle
144
     */
145
146
23655
    for (loop = 0; loop < 4; loop++)
147
    {
148
18924
        xstart = pGet -> x;
149
18924
        ystart = pGet -> y;
150
18924
        pGet++;
151
18924
        xend = pGet -> x;
152
18924
        yend = pGet -> y;
153
18924
        dx = GX_ABS(xend - xstart);
154
18924
        dy = GX_ABS(yend - ystart);
155
156
18924
        xsign = ysign = 1;
157
158

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

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

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

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

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