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


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