GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_8bpp_simple_line_draw.c Lines: 203 203 100.0 %
Date: 2026-03-06 19:21:09 Branches: 126 126 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
#define PIXEL_WRITE(loc, val) (*(loc) = ((GX_UBYTE)val))
24
25
#define GX_SOURCE_CODE
26
27
/* Include necessary system files.  */
28
29
#include "gx_api.h"
30
#include "gx_utility.h"
31
#include "gx_display.h"
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_display_driver_8bpp_simple_line_draw            PORTABLE C      */
38
/*                                                           6.1          */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    Generic 8bpp color format line draw function.                       */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    context                               Drawing context               */
50
/*    xstart                                x-coord of endpoint           */
51
/*    ystart                                y-coord of endpoint           */
52
/*    xend                                  x-coord of endpoint           */
53
/*    yend                                  y-coord of endpoint           */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    None                                                                */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    GX_ABS                                Compute the absolute value    */
62
/*    GX_SWAP_VALUE                         Swap two values               */
63
/*    [PIXEL_WRITE]                         Driver level pixel write      */
64
/*                                            routine                     */
65
/*    _gx_display_driver_simple_line_alpha_draw                           */
66
/*                                          Basic display driver simple   */
67
/*                                            alpha line draw function    */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    GUIX Internal Code                                                  */
72
/*                                                                        */
73
/**************************************************************************/
74
721
VOID _gx_display_driver_8bpp_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
75
{
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
GX_UBYTE     *put;
93
GX_UBYTE     *next_put;
94
95
721
GX_BOOL       clipped = GX_TRUE;
96
721
INT           dx = GX_ABS(xend - xstart);
97
721
INT           dy = GX_ABS(yend - ystart);
98
99
721
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
100
721
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
721
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
105
721
    if (alpha == 0)
106
    {
107
        /* Nothing to drawn. Just return. */
108
51
        return;
109
    }
110
709
    if (alpha != 0xff)
111
    {
112
39
        if (context -> gx_draw_context_display -> gx_display_color_format != GX_COLOR_FORMAT_8BIT_PACKED_PIXEL)
113
        {
114
            /* Alpha blend is not supported for palette driver. */
115
12
            return;
116
        }
117
118
27
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
119
27
        return;
120
    }
121
#endif
122
123


670
    if (((dx >= dy && (xstart > xend)) || ((dy > dx) && ystart > yend)))
124
    {
125
203
        GX_SWAP_VALS(xend, xstart);
126
203
        GX_SWAP_VALS(yend, ystart);
127
    }
128
670
    x_sign = (xend - xstart) / dx;
129
670
    y_sign = (yend - ystart) / dy;
130
131
670
    if (y_sign > 0)
132
    {
133
459
        y_increment = context -> gx_draw_context_pitch;
134
    }
135
    else
136
    {
137
211
        y_increment = 0 - context -> gx_draw_context_pitch;
138
    }
139
140
670
    put = (GX_UBYTE *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
141
670
    next_put = (GX_UBYTE *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
142
143
144
670
    end_point.gx_point_x = (GX_VALUE)xstart;
145
670
    end_point.gx_point_y = (GX_VALUE)ystart;
146
147
670
    if (_gx_utility_rectangle_point_detect(clip, end_point))
148
    {
149
625
        end_point.gx_point_x = (GX_VALUE)xend;
150
625
        end_point.gx_point_y = (GX_VALUE)yend;
151
152
625
        if (_gx_utility_rectangle_point_detect(clip, end_point))
153
        {
154
496
            clipped = GX_FALSE;
155
        }
156
    }
157
158
670
    if (clipped)
159
    {
160
        /* here if we must do clipping in the inner loop, because one
161
        or both of the end points are outside clipping rectangle */
162
163
        /* Calculate the middle point of the line.  */
164
174
        mid_point.gx_point_x = (GX_VALUE)(xend + xstart) >> 1;
165
174
        mid_point.gx_point_y = (GX_VALUE)(yend + ystart) >> 1;
166
167
        /* Judge the clip in which side.  */
168
174
        if (_gx_utility_rectangle_point_detect(clip, mid_point))
169
        {
170
171
            /* the clip in two sides.  */
172
154
            if (dx >= dy)
173
            {
174
                /* walk out the clipping point.  */
175
1414
                for (curx = xstart, cury = ystart, decision = (dx >> 1); curx < mid_point.gx_point_x;
176
1272
                    curx++, decision += dy)
177
                {
178
1413
                    if (decision >= dx)
179
                    {
180
970
                        decision -= dx;
181
970
                        cury += y_sign;
182
970
                        put += y_increment;
183
                    }
184
185
1413
                    if (curx >= clip -> gx_rectangle_left &&
186
444
                        cury >= clip -> gx_rectangle_top &&
187
409
                        cury <= clip -> gx_rectangle_bottom)
188
                    {
189
141
                        break;
190
                    }
191
1272
                    put++;
192
                }
193
12514
                for (; curx <= mid_point.gx_point_x;
194
12372
                    curx++, decision += dy)
195
                {
196
12372
                    if (decision >= dx)
197
                    {
198
3272
                        decision -= dx;
199
3272
                        cury += y_sign;
200
3272
                        put += y_increment;
201
                    }
202
12372
                    PIXEL_WRITE(put, linecolor);
203
12372
                    put++;
204
                }
205
1327
                for (nextx = xend, nexty = yend, decision = (dx >> 1); nextx > mid_point.gx_point_x;
206
1185
                    nextx--, decision += dy)
207
                {
208
1326
                    if (decision >= dx)
209
                    {
210
500
                        decision -= dx;
211
500
                        nexty -= y_sign;
212
500
                        next_put -= y_increment;
213
                    }
214
1326
                    if (nextx <= clip -> gx_rectangle_right &&
215
184
                        nexty >= clip -> gx_rectangle_top &&
216
161
                        nexty <= clip -> gx_rectangle_bottom)
217
                    {
218
141
                        break;
219
                    }
220
1185
                    next_put--;
221
                }
222
223
12517
                for (; nextx > mid_point.gx_point_x;
224
12375
                    nextx--, decision += dy)
225
                {
226
12375
                    if (decision >= dx)
227
                    {
228
3675
                        decision -= dx;
229
3675
                        nexty -= y_sign;
230
3675
                        next_put -= y_increment;
231
                    }
232
12375
                    PIXEL_WRITE(next_put, linecolor);
233
12375
                    next_put--;
234
                }
235
            }
236
            else
237
            {
238
681
                for (nextx = xend, nexty = yend, decision = (dy >> 1); nexty > mid_point.gx_point_y;
239
669
                    nexty--, decision += dx)
240
                {
241
680
                    if (decision >= dy)
242
                    {
243
383
                        decision -= dy;
244
383
                        nextx -= x_sign;
245
383
                        next_put -= x_sign;
246
                    }
247
680
                    if (nextx >= clip -> gx_rectangle_left &&
248
642
                        nextx <= clip -> gx_rectangle_right &&
249
374
                        nexty <= clip -> gx_rectangle_bottom)
250
                    {
251
11
                        break;
252
                    }
253
669
                    next_put -= context -> gx_draw_context_pitch;
254
                }
255
256
237
                for (; nexty > mid_point.gx_point_y;
257
225
                    nexty--, decision += dx)
258
                {
259
225
                    if (decision >= dy)
260
                    {
261
87
                        decision -= dy;
262
87
                        nextx -= x_sign;
263
87
                        next_put -= x_sign;
264
                    }
265
225
                    PIXEL_WRITE(next_put, linecolor);
266
225
                    next_put -= context -> gx_draw_context_pitch;
267
                }
268
269
                /* walk out the clipping point.  */
270
334
                for (curx = xstart, cury = ystart, decision = (dy >> 1); cury < mid_point.gx_point_y;
271
322
                    cury++, decision += dx)
272
                {
273
333
                    if (decision >= dy)
274
                    {
275
184
                        decision -= dy;
276
184
                        curx += x_sign;
277
184
                        put += x_sign;
278
                    }
279
280
333
                    if (curx >= clip -> gx_rectangle_left &&
281
307
                        curx <= clip -> gx_rectangle_right &&
282
39
                        cury >= clip -> gx_rectangle_top)
283
                    {
284
11
                        break;
285
                    }
286
322
                    put += context -> gx_draw_context_pitch;
287
                }
288
592
                for (; cury <= mid_point.gx_point_y;
289
580
                    cury++, decision += dx)
290
                {
291
580
                    if (decision >= dy)
292
                    {
293
294
                        decision -= dy;
294
294
                        curx += x_sign;
295
294
                        put += x_sign;
296
                    }
297
580
                    PIXEL_WRITE(put, linecolor);
298
580
                    put += context -> gx_draw_context_pitch;
299
                }
300
            }   /**/
301
                /*context  -> gx_draw_context_display -> gx_display_driver_pixel_write(context, mid_point.gx_point_x,mid_point.gx_point_y, GX_COLOR_RED);*/
302
        }
303
        else
304
        {
305
            /* The clip stay at one side.  */
306
20
            if (dx >= dy)
307
            {
308
10
                half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
309
10
                half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
310
10
                if (y_sign == 1)
311
                {
312
5
                    half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
313
5
                    half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
314
                }
315
                else
316
                {
317
5
                    half_rectangle.gx_rectangle_top = mid_point.gx_point_y;
318
5
                    half_rectangle.gx_rectangle_bottom = (GX_VALUE)ystart;
319
                }
320
321
10
                if (_gx_utility_rectangle_overlap_detect(clip, &half_rectangle, &half_over))
322
                {
323
6
                    curx = xstart;
324
6
                    cury = ystart;
325
6
                    steps = mid_point.gx_point_x - curx + 1;
326
6
                    sign = 1;
327
                }
328
                else
329
                {
330
4
                    curx = xend;
331
4
                    cury = yend;
332
4
                    steps = xend - mid_point.gx_point_x;
333
4
                    sign = -1;
334
4
                    y_increment = 0 - y_increment;
335
4
                    y_sign = 0 - y_sign;
336
4
                    put = next_put;
337
                }
338
938
                for (decision = (dx >> 1); steps > 0; curx += sign, decision += dy, steps--)
339
                {
340
928
                    if (decision >= dx)
341
                    {
342
470
                        decision -= dx;
343
470
                        cury += y_sign;
344
470
                        put += y_increment;
345
                    }
346
347
928
                    if (curx >= clip -> gx_rectangle_left &&
348
915
                        curx <= clip -> gx_rectangle_right &&
349
442
                        cury >= clip -> gx_rectangle_top &&
350
421
                        cury <= clip -> gx_rectangle_bottom)
351
                    {
352
409
                        PIXEL_WRITE(put, linecolor);
353
                    }
354
928
                    put += sign;
355
                }
356
            }
357
            else
358
            {
359
10
                half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
360
10
                half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
361
10
                if (x_sign == 1)
362
                {
363
5
                    half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
364
5
                    half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
365
                }
366
                else
367
                {
368
5
                    half_rectangle.gx_rectangle_right = (GX_VALUE)xstart;
369
5
                    half_rectangle.gx_rectangle_left = mid_point.gx_point_x;
370
                }
371
372
10
                if (_gx_utility_rectangle_overlap_detect(clip, &half_rectangle, &half_over))
373
                {
374
5
                    curx = xstart;
375
5
                    cury = ystart;
376
5
                    steps = mid_point.gx_point_y - cury + 1;
377
5
                    y_increment = context -> gx_draw_context_pitch;
378
5
                    sign = 1;
379
                }
380
                else
381
                {
382
5
                    curx = xend;
383
5
                    cury = yend;
384
5
                    steps = yend - mid_point.gx_point_y;
385
5
                    sign = -1;
386
5
                    y_increment = 0 - context -> gx_draw_context_pitch;
387
5
                    x_sign = 0 - x_sign;
388
5
                    put = next_put;
389
                }
390
391
880
                for (decision = (dy >> 1); steps > 0; cury += sign, decision += dx, steps--)
392
                {
393
870
                    if (decision >= dy)
394
                    {
395
447
                        decision -= dy;
396
447
                        curx += x_sign;
397
447
                        put += x_sign;
398
                    }
399
870
                    if (curx >= clip -> gx_rectangle_left &&
400
865
                        curx <= clip -> gx_rectangle_right &&
401
714
                        cury >= clip -> gx_rectangle_top &&
402
709
                        cury <= clip -> gx_rectangle_bottom)
403
                    {
404
387
                        PIXEL_WRITE(put, linecolor);
405
                    }
406
870
                    put += y_increment;
407
                }
408
            }
409
        }
410
    }
411
    else
412
    {
413
        /* here if both line ends lie within clipping rectangle, we can
414
        run a faster inner loop */
415
496
        if (dx >= dy)
416
        {
417
224
            put = (GX_UBYTE *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
418
224
            next_put = (GX_UBYTE *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
419
420
224
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
421
13436
                decision = (dx >> 1); curx <= nextx; curx++, nextx--,
422
13212
                decision += dy)
423
            {
424
425
13212
                if (decision >= dx)
426
                {
427
8708
                    decision -= dx;
428
8708
                    cury += y_sign;
429
8708
                    nexty -= y_sign;
430
431
8708
                    put += y_increment;
432
8708
                    next_put -= y_increment;
433
                }
434
13212
                PIXEL_WRITE(put, linecolor);
435
13212
                PIXEL_WRITE(next_put, linecolor);
436
437
13212
                put++;
438
13212
                next_put--;
439
            }
440
        }
441
        else
442
        {
443
444
272
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
445
20096
                decision = (dy >> 1); cury <= nexty; cury++, nexty--,
446
19824
                decision += dx)
447
            {
448
19824
                if (decision >= dy)
449
                {
450
6000
                    decision -= dy;
451
6000
                    curx += x_sign;
452
6000
                    nextx -= x_sign;
453
454
6000
                    put += x_sign;
455
6000
                    next_put -= x_sign;
456
                }
457
19824
                PIXEL_WRITE(put, linecolor);
458
19824
                PIXEL_WRITE(next_put, linecolor);
459
460
19824
                put += context -> gx_draw_context_pitch;
461
19824
                next_put -= context -> gx_draw_context_pitch;
462
            }
463
        }
464
    }
465
}