GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_32bpp_simple_line_draw.c Lines: 201 201 100.0 %
Date: 2024-12-05 08:52:37 Branches: 124 124 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
#define PIXEL_WRITE(loc, val) (*(loc) = (val))
21
22
#define GX_SOURCE_CODE
23
24
/* Include necessary system files.  */
25
26
#include "gx_api.h"
27
#include "gx_utility.h"
28
#include "gx_display.h"
29
30
/**************************************************************************/
31
/*                                                                        */
32
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _gx_display_driver_32bpp_simple_line_draw           PORTABLE C      */
35
/*                                                           6.1          */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Kenneth Maxwell, Microsoft Corporation                              */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    Generic 32bpp color format line draw function.                      */
43
/*                                                                        */
44
/*  INPUT                                                                 */
45
/*                                                                        */
46
/*    context                               Drawing context               */
47
/*    xstart                                x-coord of endpoint           */
48
/*    ystart                                y-coord of endpoint           */
49
/*    xend                                  x-coord of endpoint           */
50
/*    yend                                  y-coord of endpoint           */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _gx_display_driver_simple_line_alpha_draw                           */
59
/*                                          Basic display driver line     */
60
/*                                            alpha draw function         */
61
/*                                                                        */
62
/*  CALLED BY                                                             */
63
/*                                                                        */
64
/*    GUIX Internal Code                                                  */
65
/*                                                                        */
66
/*  RELEASE HISTORY                                                       */
67
/*                                                                        */
68
/*    DATE              NAME                      DESCRIPTION             */
69
/*                                                                        */
70
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
71
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
72
/*                                            resulting in version 6.1    */
73
/*                                                                        */
74
/**************************************************************************/
75
187
VOID _gx_display_driver_32bpp_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
76
{
77
INT           curx;
78
INT           cury;
79
INT           x_sign;
80
INT           y_sign;
81
INT           decision;
82
INT           nextx;
83
INT           nexty;
84
INT           y_increment;
85
GX_POINT      end_point;
86
GX_POINT      mid_point;
87
GX_RECTANGLE  half_rectangle;
88
GX_RECTANGLE  half_over;
89
INT           sign;
90
INT           steps;
91
92
ULONG        *put;
93
ULONG        *next_put;
94
95
187
GX_BOOL       clipped = GX_TRUE;
96
187
INT           dx = GX_ABS(xend - xstart);
97
187
INT           dy = GX_ABS(yend - ystart);
98
99
187
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
100
187
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
101
#if defined GX_BRUSH_ALPHA_SUPPORT
102
GX_UBYTE      alpha;
103
104
187
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
105
187
    if (alpha == 0)
106
    {
107
        /* Nothing to drawn. Just return. */
108
68
        return;
109
    }
110
163
    if (alpha != 0xff)
111
    {
112
44
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
113
44
        return;
114
    }
115
#endif
116
117


119
    if (((dx >= dy && (xstart > xend)) || ((dy > dx) && ystart > yend)))
118
    {
119
16
        GX_SWAP_VALS(xend, xstart);
120
16
        GX_SWAP_VALS(yend, ystart);
121
    }
122
119
    x_sign = (xend - xstart) / dx;
123
119
    y_sign = (yend - ystart) / dy;
124
125
119
    if (y_sign > 0)
126
    {
127
102
        y_increment = context -> gx_draw_context_pitch;
128
    }
129
    else
130
    {
131
17
        y_increment = 0 - context -> gx_draw_context_pitch;
132
    }
133
134
119
    put = (ULONG *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
135
119
    next_put = (ULONG *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
136
137
138
119
    end_point.gx_point_x = (GX_VALUE)xstart;
139
119
    end_point.gx_point_y = (GX_VALUE)ystart;
140
141
119
    if (_gx_utility_rectangle_point_detect(clip, end_point))
142
    {
143
73
        end_point.gx_point_x = (GX_VALUE)xend;
144
73
        end_point.gx_point_y = (GX_VALUE)yend;
145
146
73
        if (_gx_utility_rectangle_point_detect(clip, end_point))
147
        {
148
53
            clipped = GX_FALSE;
149
        }
150
    }
151
152
119
    if (clipped)
153
    {
154
        /* here if we must do clipping in the inner loop, because one
155
        or both of the end points are outside clipping rectangle */
156
157
        /* Calculate the middle point of the line.  */
158
66
        mid_point.gx_point_x = (GX_VALUE)(xend + xstart) >> 1;
159
66
        mid_point.gx_point_y = (GX_VALUE)(yend + ystart) >> 1;
160
161
        /* Judge the clip in which side.  */
162
66
        if (_gx_utility_rectangle_point_detect(clip, mid_point))
163
        {
164
165
            /* the clip in two sides.  */
166
52
            if (dx >= dy)
167
            {
168
                /* walk out the clipping point.  */
169
1649
                for (curx = xstart, cury = ystart, decision = (dx >> 1); curx < mid_point.gx_point_x;
170
1614
                    curx++, decision += dy)
171
                {
172
1648
                    if (decision >= dx)
173
                    {
174
884
                        decision -= dx;
175
884
                        cury += y_sign;
176
884
                        put += y_increment;
177
                    }
178
179
1648
                    if (curx >= clip -> gx_rectangle_left &&
180
77
                        cury >= clip -> gx_rectangle_top &&
181
44
                        cury <= clip -> gx_rectangle_bottom)
182
                    {
183
34
                        break;
184
                    }
185
1614
                    put++;
186
                }
187
1139
                for (; curx <= mid_point.gx_point_x;
188
1104
                    curx++, decision += dy)
189
                {
190
1104
                    if (decision >= dx)
191
                    {
192
584
                        decision -= dx;
193
584
                        cury += y_sign;
194
584
                        put += y_increment;
195
                    }
196
1104
                    PIXEL_WRITE(put, linecolor);
197
1104
                    put++;
198
                }
199
1725
                for (nextx = xend, nexty = yend, decision = (dx >> 1); nextx > mid_point.gx_point_x;
200
1690
                    nextx--, decision += dy)
201
                {
202
1715
                    if (decision >= dx)
203
                    {
204
914
                        decision -= dx;
205
914
                        nexty -= y_sign;
206
914
                        next_put -= y_increment;
207
                    }
208
1715
                    if (nextx <= clip -> gx_rectangle_right &&
209
70
                        nexty >= clip -> gx_rectangle_top &&
210
44
                        nexty <= clip -> gx_rectangle_bottom)
211
                    {
212
25
                        break;
213
                    }
214
1690
                    next_put--;
215
                }
216
217
1029
                for (; nextx > mid_point.gx_point_x;
218
994
                    nextx--, decision += dy)
219
                {
220
994
                    if (decision >= dx)
221
                    {
222
533
                        decision -= dx;
223
533
                        nexty -= y_sign;
224
533
                        next_put -= y_increment;
225
                    }
226
994
                    PIXEL_WRITE(next_put, linecolor);
227
994
                    next_put--;
228
                }
229
            }
230
            else
231
            {
232
844
                for (nextx = xend, nexty = yend, decision = (dy >> 1); nexty > mid_point.gx_point_y;
233
827
                    nexty--, decision += dx)
234
                {
235
842
                    if (decision >= dy)
236
                    {
237
293
                        decision -= dy;
238
293
                        nextx -= x_sign;
239
293
                        next_put -= x_sign;
240
                    }
241
842
                    if (nextx >= clip -> gx_rectangle_left &&
242
791
                        nextx <= clip -> gx_rectangle_right &&
243
25
                        nexty <= clip -> gx_rectangle_bottom)
244
                    {
245
15
                        break;
246
                    }
247
827
                    next_put -= context -> gx_draw_context_pitch;
248
                }
249
250
748
                for (; nexty > mid_point.gx_point_y;
251
731
                    nexty--, decision += dx)
252
                {
253
731
                    if (decision >= dy)
254
                    {
255
211
                        decision -= dy;
256
211
                        nextx -= x_sign;
257
211
                        next_put -= x_sign;
258
                    }
259
731
                    PIXEL_WRITE(next_put, linecolor);
260
731
                    next_put -= context -> gx_draw_context_pitch;
261
                }
262
263
                /* walk out the clipping point.  */
264
694
                for (curx = xstart, cury = ystart, decision = (dy >> 1); cury < mid_point.gx_point_y;
265
677
                    cury++, decision += dx)
266
                {
267
693
                    if (decision >= dy)
268
                    {
269
278
                        decision -= dy;
270
278
                        curx += x_sign;
271
278
                        put += x_sign;
272
                    }
273
274
693
                    if (curx >= clip -> gx_rectangle_left &&
275
117
                        curx <= clip -> gx_rectangle_right &&
276
45
                        cury >= clip -> gx_rectangle_top)
277
                    {
278
16
                        break;
279
                    }
280
677
                    put += context -> gx_draw_context_pitch;
281
                }
282
912
                for (; cury <= mid_point.gx_point_y;
283
895
                    cury++, decision += dx)
284
                {
285
895
                    if (decision >= dy)
286
                    {
287
232
                        decision -= dy;
288
232
                        curx += x_sign;
289
232
                        put += x_sign;
290
                    }
291
895
                    PIXEL_WRITE(put, linecolor);
292
895
                    put += context -> gx_draw_context_pitch;
293
                }
294
            }   /**/
295
                /*context   ->  gx_draw_context_display  ->  gx_display_driver_pixel_write(context, mid_point.gx_point_x,mid_point.gx_point_y, GX_COLOR_RED);*/
296
        }
297
        else
298
        {
299
            /* The clip stay at one side.  */
300
14
            if (dx >= dy)
301
            {
302
8
                half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
303
8
                half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
304
8
                if (y_sign == 1)
305
                {
306
5
                    half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
307
5
                    half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
308
                }
309
                else
310
                {
311
3
                    half_rectangle.gx_rectangle_top = mid_point.gx_point_y;
312
3
                    half_rectangle.gx_rectangle_bottom = (GX_VALUE)ystart;
313
                }
314
315
8
                if (_gx_utility_rectangle_overlap_detect(clip, &half_rectangle, &half_over))
316
                {
317
4
                    curx = xstart;
318
4
                    cury = ystart;
319
4
                    steps = mid_point.gx_point_x - curx + 1;
320
4
                    sign = 1;
321
                }
322
                else
323
                {
324
4
                    curx = xend;
325
4
                    cury = yend;
326
4
                    steps = xend - mid_point.gx_point_x;
327
4
                    sign = -1;
328
4
                    y_increment = 0 - y_increment;
329
4
                    y_sign = 0 - y_sign;
330
4
                    put = next_put;
331
                }
332
765
                for (decision = (dx >> 1); steps > 0; curx += sign, decision += dy, steps--)
333
                {
334
757
                    if (decision >= dx)
335
                    {
336
278
                        decision -= dx;
337
278
                        cury += y_sign;
338
278
                        put += y_increment;
339
                    }
340
341
757
                    if (curx >= clip -> gx_rectangle_left &&
342
751
                        curx <= clip -> gx_rectangle_right &&
343
266
                        cury >= clip -> gx_rectangle_top &&
344
235
                        cury <= clip -> gx_rectangle_bottom)
345
                    {
346
223
                        PIXEL_WRITE(put, linecolor);
347
                    }
348
757
                    put += sign;
349
                }
350
            }
351
            else
352
            {
353
6
                half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
354
6
                half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
355
6
                if (x_sign == 1)
356
                {
357
4
                    half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
358
4
                    half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
359
                }
360
                else
361
                {
362
2
                    half_rectangle.gx_rectangle_right = (GX_VALUE)xstart;
363
2
                    half_rectangle.gx_rectangle_left = mid_point.gx_point_x;
364
                }
365
366
6
                if (_gx_utility_rectangle_overlap_detect(clip, &half_rectangle, &half_over))
367
                {
368
4
                    curx = xstart;
369
4
                    cury = ystart;
370
4
                    steps = mid_point.gx_point_y - cury + 1;
371
4
                    y_increment = context -> gx_draw_context_pitch;
372
4
                    sign = 1;
373
                }
374
                else
375
                {
376
2
                    curx = xend;
377
2
                    cury = yend;
378
2
                    steps = yend - mid_point.gx_point_y;
379
2
                    sign = -1;
380
2
                    y_increment = 0 - context -> gx_draw_context_pitch;
381
2
                    x_sign = 0 - x_sign;
382
2
                    put = next_put;
383
                }
384
385
658
                for (decision = (dy >> 1); steps > 0; cury += sign, decision += dx, steps--)
386
                {
387
652
                    if (decision >= dy)
388
                    {
389
339
                        decision -= dy;
390
339
                        curx += x_sign;
391
339
                        put += x_sign;
392
                    }
393
652
                    if (curx >= clip -> gx_rectangle_left &&
394
646
                        curx <= clip -> gx_rectangle_right &&
395
484
                        cury >= clip -> gx_rectangle_top &&
396
474
                        cury <= clip -> gx_rectangle_bottom)
397
                    {
398
246
                        PIXEL_WRITE(put, linecolor);
399
                    }
400
652
                    put += y_increment;
401
                }
402
            }
403
        }
404
    }
405
    else
406
    {
407
        /* here if both line ends lie within clipping rectangle, we can
408
        run a faster inner loop */
409
53
        if (dx >= dy)
410
        {
411
31
            put = (ULONG *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
412
31
            next_put = (ULONG *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
413
414
31
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
415
2650
                decision = (dx >> 1); curx <= nextx; curx++, nextx--,
416
2619
                decision += dy)
417
            {
418
419
2619
                if (decision >= dx)
420
                {
421
1430
                    decision -= dx;
422
1430
                    cury += y_sign;
423
1430
                    nexty -= y_sign;
424
425
1430
                    put += y_increment;
426
1430
                    next_put -= y_increment;
427
                }
428
2619
                PIXEL_WRITE(put, linecolor);
429
2619
                PIXEL_WRITE(next_put, linecolor);
430
431
2619
                put++;
432
2619
                next_put--;
433
            }
434
        }
435
        else
436
        {
437
438
22
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
439
2126
                decision = (dy >> 1); cury <= nexty; cury++, nexty--,
440
2104
                decision += dx)
441
            {
442
2104
                if (decision >= dy)
443
                {
444
460
                    decision -= dy;
445
460
                    curx += x_sign;
446
460
                    nextx -= x_sign;
447
448
460
                    put += x_sign;
449
460
                    next_put -= x_sign;
450
                }
451
2104
                PIXEL_WRITE(put, linecolor);
452
2104
                PIXEL_WRITE(next_put, linecolor);
453
454
2104
                put += context -> gx_draw_context_pitch;
455
2104
                next_put -= context -> gx_draw_context_pitch;
456
            }
457
        }
458
    }
459
}