GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_16bpp_simple_line_draw.c Lines: 203 203 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
22
23
#define PIXEL_WRITE(loc, val) (*(loc) = ((USHORT)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_16bpp_simple_line_draw           PORTABLE C      */
38
/*                                                           6.3.0        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    Generic 16bpp 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_display_driver_simple_line_alpha_draw                           */
62
/*                                          Display driver basic simpile  */
63
/*                                            line alpha draw function    */
64
/*    _gx_utility_rectangle_point_detect    Detect whether a pixel is     */
65
/*                                            inside rectangle            */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    GUIX Internal Code                                                  */
70
/*                                                                        */
71
/**************************************************************************/
72
566
VOID _gx_display_driver_16bpp_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
73
{
74
INT           curx;
75
INT           cury;
76
INT           x_sign;
77
INT           y_sign;
78
INT           decision;
79
INT           nextx;
80
INT           nexty;
81
INT           y_increment;
82
GX_POINT      end_point;
83
GX_POINT      mid_point;
84
GX_RECTANGLE  half_rectangle;
85
GX_RECTANGLE  half_over;
86
INT           sign;
87
INT           steps;
88
89
USHORT       *put;
90
USHORT       *next_put;
91
92
566
GX_BOOL       clipped = GX_TRUE;
93
566
INT           dx = GX_ABS(xend - xstart);
94
566
INT           dy = GX_ABS(yend - ystart);
95
96
566
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
97
566
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
98
99
#if defined GX_BRUSH_ALPHA_SUPPORT
100
GX_UBYTE alpha;
101
102
566
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
103
566
    if (alpha == 0)
104
    {
105
        /* Nothing to drawn. Just return. */
106
362
        return;
107
    }
108
556
    if (alpha != 0xff)
109
    {
110
352
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
111
352
        return;
112
    }
113
#endif
114
115


204
    if (((dx >= dy && (xstart > xend)) || ((dy > dx) && ystart > yend)))
116
    {
117
83
        GX_SWAP_VALS(xend, xstart);
118
83
        GX_SWAP_VALS(yend, ystart);
119
    }
120
204
    x_sign = (xend - xstart) / dx;
121
204
    y_sign = (yend - ystart) / dy;
122
123
204
    if (y_sign > 0)
124
    {
125
156
        y_increment = context -> gx_draw_context_pitch;
126
    }
127
    else
128
    {
129
48
        y_increment = 0 - context -> gx_draw_context_pitch;
130
    }
131
132
204
    put = (USHORT *)(context -> gx_draw_context_memory);
133
204
    GX_CALCULATE_PUTROW(put, xstart, ystart, context);
134
135
204
    next_put = (USHORT *)(context -> gx_draw_context_memory);
136
204
    GX_CALCULATE_PUTROW(next_put, xend, yend, context);
137
138
139
204
    end_point.gx_point_x = (GX_VALUE)xstart;
140
204
    end_point.gx_point_y = (GX_VALUE)ystart;
141
142
204
    if (_gx_utility_rectangle_point_detect(clip, end_point))
143
    {
144
108
        end_point.gx_point_x = (GX_VALUE)xend;
145
108
        end_point.gx_point_y = (GX_VALUE)yend;
146
147
108
        if (_gx_utility_rectangle_point_detect(clip, end_point))
148
        {
149
52
            clipped = GX_FALSE;
150
        }
151
    }
152
153
204
    if (clipped)
154
    {
155
        /* here if we must do clipping in the inner loop, because one
156
           or both of the end points are outside clipping rectangle */
157
158
        /* Calculate the middle point of the line.  */
159
152
        mid_point.gx_point_x = (GX_VALUE)((xend + xstart) >> 1);
160
152
        mid_point.gx_point_y = (GX_VALUE)((yend + ystart) >> 1);
161
162
        /* Judge the clip in which side.  */
163
152
        if (_gx_utility_rectangle_point_detect(clip, mid_point))
164
        {
165
166
            /* the clip in two sides.  */
167
114
            if (dx >= dy)
168
            {
169
                /* walk out the clipping point.  */
170
3331
                for (curx = xstart, cury = ystart, decision = (dx >> 1); curx < mid_point.gx_point_x;
171
3249
                     curx++, decision += dy)
172
                {
173
3330
                    if (decision >= dx)
174
                    {
175
2139
                        decision -= dx;
176
2139
                        cury += y_sign;
177
2139
                        put += y_increment;
178
                    }
179
180
3330
                    if (curx >= clip -> gx_rectangle_left &&
181
427
                        cury >= clip -> gx_rectangle_top &&
182
355
                        cury <= clip -> gx_rectangle_bottom)
183
                    {
184
81
                        break;
185
                    }
186
3249
                    put++;
187
                }
188
5098
                for (; curx <= mid_point.gx_point_x;
189
5016
                     curx++, decision += dy)
190
                {
191
5016
                    if (decision >= dx)
192
                    {
193
3404
                        decision -= dx;
194
3404
                        cury += y_sign;
195
3404
                        put += y_increment;
196
                    }
197
5016
                    PIXEL_WRITE(put, linecolor);
198
5016
                    put++;
199
                }
200
3097
                for (nextx = xend, nexty = yend, decision = (dx >> 1); nextx > mid_point.gx_point_x;
201
3015
                     nextx--, decision += dy)
202
                {
203
3087
                    if (decision >= dx)
204
                    {
205
1649
                        decision -= dx;
206
1649
                        nexty -= y_sign;
207
1649
                        next_put -= y_increment;
208
                    }
209
3087
                    if (nextx <= clip -> gx_rectangle_right &&
210
174
                        nexty >= clip -> gx_rectangle_top &&
211
127
                        nexty <= clip -> gx_rectangle_bottom)
212
                    {
213
72
                        break;
214
                    }
215
3015
                    next_put--;
216
                }
217
218
5268
                for (; nextx > mid_point.gx_point_x;
219
5186
                     nextx--, decision += dy)
220
                {
221
5186
                    if (decision >= dx)
222
                    {
223
3843
                        decision -= dx;
224
3843
                        nexty -= y_sign;
225
3843
                        next_put -= y_increment;
226
                    }
227
5186
                    PIXEL_WRITE(next_put, linecolor);
228
5186
                    next_put--;
229
                }
230
            }
231
            else
232
            {
233
1762
                for (nextx = xend, nexty = yend, decision = (dy >> 1); nexty > mid_point.gx_point_y;
234
1730
                     nexty--, decision += dx)
235
                {
236
1760
                    if (decision >= dy)
237
                    {
238
821
                        decision -= dy;
239
821
                        nextx -= x_sign;
240
821
                        next_put -= x_sign;
241
                    }
242
1760
                    if (nextx >= clip -> gx_rectangle_left &&
243
1710
                        nextx <= clip -> gx_rectangle_right &&
244
368
                        nexty <= clip -> gx_rectangle_bottom)
245
                    {
246
30
                        break;
247
                    }
248
1730
                    next_put -= context -> gx_draw_context_pitch;
249
                }
250
251
1076
                for (; nexty > mid_point.gx_point_y;
252
1044
                     nexty--, decision += dx)
253
                {
254
1044
                    if (decision >= dy)
255
                    {
256
449
                        decision -= dy;
257
449
                        nextx -= x_sign;
258
449
                        next_put -= x_sign;
259
                    }
260
1044
                    PIXEL_WRITE(next_put, linecolor);
261
1044
                    next_put -= context -> gx_draw_context_pitch;
262
                }
263
264
                /* walk out the clipping point.  */
265
1228
                for (curx = xstart, cury = ystart, decision = (dy >> 1); cury < mid_point.gx_point_y;
266
1196
                     cury++, decision += dx)
267
                {
268
1227
                    if (decision >= dy)
269
                    {
270
609
                        decision -= dy;
271
609
                        curx += x_sign;
272
609
                        put += x_sign;
273
                    }
274
275
1227
                    if (curx >= clip -> gx_rectangle_left &&
276
646
                        curx <= clip -> gx_rectangle_right &&
277
70
                        cury >= clip -> gx_rectangle_top)
278
                    {
279
31
                        break;
280
                    }
281
1196
                    put += context -> gx_draw_context_pitch;
282
                }
283
1640
                for (; cury <= mid_point.gx_point_y;
284
1608
                     cury++, decision += dx)
285
                {
286
1608
                    if (decision >= dy)
287
                    {
288
683
                        decision -= dy;
289
683
                        curx += x_sign;
290
683
                        put += x_sign;
291
                    }
292
1608
                    PIXEL_WRITE(put, linecolor);
293
1608
                    put += context -> gx_draw_context_pitch;
294
                }
295
            }
296
        }
297
        else
298
        {
299
            /* The clip stay at one side.  */
300
38
            if (dx >= dy)
301
            {
302
20
                half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
303
20
                half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
304
20
                if (y_sign == 1)
305
                {
306
11
                    half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
307
11
                    half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
308
                }
309
                else
310
                {
311
9
                    half_rectangle.gx_rectangle_top = mid_point.gx_point_y;
312
9
                    half_rectangle.gx_rectangle_bottom = (GX_VALUE)ystart;
313
                }
314
315
20
                if (_gx_utility_rectangle_overlap_detect(clip, &half_rectangle, &half_over))
316
                {
317
14
                    curx = xstart;
318
14
                    cury = ystart;
319
14
                    steps = mid_point.gx_point_x - curx + 1;
320
14
                    sign = 1;
321
                }
322
                else
323
                {
324
6
                    curx = xend;
325
6
                    cury = yend;
326
6
                    steps = xend - mid_point.gx_point_x;
327
6
                    sign = -1;
328
6
                    y_increment = 0 - y_increment;
329
6
                    y_sign = 0 - y_sign;
330
6
                    put = next_put;
331
                }
332
2104
                for (decision = (dx >> 1); steps > 0; curx += sign, decision += dy, steps--)
333
                {
334
2084
                    if (decision >= dx)
335
                    {
336
922
                        decision -= dx;
337
922
                        cury += y_sign;
338
922
                        put += y_increment;
339
                    }
340
341
2084
                    if (curx >= clip -> gx_rectangle_left &&
342
2073
                        curx <= clip -> gx_rectangle_right &&
343
1284
                        cury >= clip -> gx_rectangle_top &&
344
1171
                        cury <= clip -> gx_rectangle_bottom)
345
                    {
346
1143
                        PIXEL_WRITE(put, linecolor);
347
                    }
348
2084
                    put += sign;
349
                }
350
            }
351
            else
352
            {
353
18
                half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
354
18
                half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
355
18
                if (x_sign == 1)
356
                {
357
9
                    half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
358
9
                    half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
359
                }
360
                else
361
                {
362
9
                    half_rectangle.gx_rectangle_right = (GX_VALUE)xstart;
363
9
                    half_rectangle.gx_rectangle_left = mid_point.gx_point_x;
364
                }
365
366
18
                if (_gx_utility_rectangle_overlap_detect(clip, &half_rectangle, &half_over))
367
                {
368
9
                    curx = xstart;
369
9
                    cury = ystart;
370
9
                    steps = mid_point.gx_point_y - cury + 1;
371
9
                    y_increment = context -> gx_draw_context_pitch;
372
9
                    sign = 1;
373
                }
374
                else
375
                {
376
9
                    curx = xend;
377
9
                    cury = yend;
378
9
                    steps = yend - mid_point.gx_point_y;
379
9
                    sign = -1;
380
9
                    y_increment = 0 - context -> gx_draw_context_pitch;
381
9
                    x_sign = 0 - x_sign;
382
9
                    put = next_put;
383
                }
384
385
1672
                for (decision = (dy >> 1); steps > 0; cury += sign, decision += dx, steps--)
386
                {
387
1654
                    if (decision >= dy)
388
                    {
389
887
                        decision -= dy;
390
887
                        curx += x_sign;
391
887
                        put += x_sign;
392
                    }
393
1654
                    if (curx >= clip -> gx_rectangle_left &&
394
1646
                        curx <= clip -> gx_rectangle_right &&
395
1202
                        cury >= clip -> gx_rectangle_top &&
396
1168
                        cury <= clip -> gx_rectangle_bottom)
397
                    {
398
884
                        PIXEL_WRITE(put, linecolor);
399
                    }
400
1654
                    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
52
        if (dx >= dy)
410
        {
411
28
            put = (USHORT *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
412
28
            next_put = (USHORT *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
413
414
28
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
415
2416
                 decision = (dx >> 1); curx <= nextx; curx++, nextx--,
416
2388
                 decision += dy)
417
            {
418
419
2388
                if (decision >= dx)
420
                {
421
1320
                    decision -= dx;
422
1320
                    cury += y_sign;
423
1320
                    nexty -= y_sign;
424
425
1320
                    put += y_increment;
426
1320
                    next_put -= y_increment;
427
                }
428
2388
                PIXEL_WRITE(put, linecolor);
429
2388
                PIXEL_WRITE(next_put, linecolor);
430
431
2388
                put++;
432
2388
                next_put--;
433
            }
434
        }
435
        else
436
        {
437
438
24
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
439
2260
                 decision = (dy >> 1); cury <= nexty; cury++, nexty--,
440
2236
                 decision += dx)
441
            {
442
2236
                if (decision >= dy)
443
                {
444
708
                    decision -= dy;
445
708
                    curx += x_sign;
446
708
                    nextx -= x_sign;
447
448
708
                    put += x_sign;
449
708
                    next_put -= x_sign;
450
                }
451
2236
                PIXEL_WRITE(put, linecolor);
452
2236
                PIXEL_WRITE(next_put, linecolor);
453
454
2236
                put += context -> gx_draw_context_pitch;
455
2236
                next_put -= context -> gx_draw_context_pitch;
456
            }
457
        }
458
    }
459
}
460