GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_16bpp_rotated_simple_line_draw.c Lines: 216 216 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) = ((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_rotated_simple_line_draw   PORTABLE C      */
38
/*                                                           6.1.3        */
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
/*                                          Generic line draw with alpha  */
63
/*    _gx_display_driver_16bpp_simple_line_draw                           */
64
/*                                          Generic 16bpp line draw       */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    GUIX Internal Code                                                  */
69
/*                                                                        */
70
/**************************************************************************/
71
604
VOID _gx_display_driver_16bpp_rotated_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
72
{
73
INT           curx;
74
INT           cury;
75
INT           x_sign;
76
INT           y_sign;
77
INT           decision;
78
INT           nextx;
79
INT           nexty;
80
INT           y_increment;
81
GX_POINT      end_point;
82
GX_POINT      mid_point;
83
GX_RECTANGLE  half_rectangle;
84
GX_RECTANGLE  half_over;
85
INT           sign;
86
INT           steps;
87
88
USHORT       *put;
89
USHORT       *next_put;
90
91
604
GX_BOOL       clipped = GX_TRUE;
92
INT           dx;
93
INT           dy;
94
95
GX_RECTANGLE *clip;
96
GX_RECTANGLE  rotated_clip;
97
GX_COLOR      linecolor;
98
99
#if defined GX_BRUSH_ALPHA_SUPPORT
100
GX_UBYTE alpha;
101
102
604
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
103
604
    if (alpha == 0)
104
    {
105
        /* Nothing to drawn. Just return. */
106
60
        return;
107
    }
108
574
    if (alpha != 0xff)
109
    {
110
30
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
111
30
        return;
112
    }
113
#endif
114
115
544
    GX_SWAP_VALS(xstart, ystart);
116
544
    GX_SWAP_VALS(xend, yend);
117
544
    clip = context -> gx_draw_context_clip;
118
119
544
    if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
120
    {
121
277
        ystart = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - ystart - 1;
122
277
        yend = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - yend - 1;
123
124
277
        rotated_clip.gx_rectangle_left = clip -> gx_rectangle_top;
125
277
        rotated_clip.gx_rectangle_right = clip -> gx_rectangle_bottom;
126
277
        rotated_clip.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_right - 1);
127
277
        rotated_clip.gx_rectangle_bottom = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_left - 1);
128
    }
129
    else
130
    {
131
267
        xstart = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xstart - 1;
132
267
        xend = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xend - 1;
133
134
267
        rotated_clip.gx_rectangle_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_bottom - 1);
135
267
        rotated_clip.gx_rectangle_right = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_top - 1);
136
267
        rotated_clip.gx_rectangle_top = clip -> gx_rectangle_left;
137
267
        rotated_clip.gx_rectangle_bottom = clip -> gx_rectangle_right;
138
    }
139
140
544
    dx = GX_ABS(xend - xstart);
141
544
    dy = GX_ABS(yend - ystart);
142
143
144
544
    linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
145
146


544
    if (((dx >= dy && (xstart > xend)) || ((dy > dx) && ystart > yend)))
147
    {
148
271
        GX_SWAP_VALS(xend, xstart);
149
271
        GX_SWAP_VALS(yend, ystart);
150
    }
151
544
    x_sign = (xend - xstart) / dx;
152
544
    y_sign = (yend - ystart) / dy;
153
154
544
    if (y_sign > 0)
155
    {
156
374
        y_increment = context -> gx_draw_context_pitch;
157
    }
158
    else
159
    {
160
170
        y_increment = 0 - context -> gx_draw_context_pitch;
161
    }
162
163
544
    put = (USHORT *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
164
544
    next_put = (USHORT *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
165
166
167
544
    end_point.gx_point_x = (GX_VALUE)xstart;
168
544
    end_point.gx_point_y = (GX_VALUE)ystart;
169
170
544
    if (_gx_utility_rectangle_point_detect(&rotated_clip, end_point))
171
    {
172
523
        end_point.gx_point_x = (GX_VALUE)xend;
173
523
        end_point.gx_point_y = (GX_VALUE)yend;
174
175
523
        if (_gx_utility_rectangle_point_detect(&rotated_clip, end_point))
176
        {
177
514
            clipped = GX_FALSE;
178
        }
179
    }
180
181
544
    if (clipped)
182
    {
183
        /* here if we must do clipping in the inner loop, because one
184
           or both of the end points are outside clipping rectangle */
185
186
        /* Calculate the middle point of the line.  */
187
30
        mid_point.gx_point_x = (GX_VALUE)((xend + xstart) >> 1);
188
30
        mid_point.gx_point_y = (GX_VALUE)((yend + ystart) >> 1);
189
190
        /* Judge the clip in which side.  */
191
30
        if (_gx_utility_rectangle_point_detect(&rotated_clip, mid_point))
192
        {
193
194
            /* the clip in two sides.  */
195
22
            if (dx >= dy)
196
            {
197
                /* walk out the clipping point.  */
198
171
                for (curx = xstart, cury = ystart, decision = (dx >> 1); curx < mid_point.gx_point_x;
199
161
                     curx++, decision += dy)
200
                {
201
170
                    if (decision >= dx)
202
                    {
203
47
                        decision -= dx;
204
47
                        cury += y_sign;
205
47
                        put += y_increment;
206
                    }
207
208
170
                    if (curx >= rotated_clip.gx_rectangle_left &&
209
95
                        cury >= rotated_clip.gx_rectangle_top &&
210
57
                        cury <= rotated_clip.gx_rectangle_bottom)
211
                    {
212
9
                        break;
213
                    }
214
161
                    put++;
215
                }
216
295
                for (; curx <= mid_point.gx_point_x;
217
285
                     curx++, decision += dy)
218
                {
219
285
                    if (decision >= dx)
220
                    {
221
113
                        decision -= dx;
222
113
                        cury += y_sign;
223
113
                        put += y_increment;
224
                    }
225
285
                    PIXEL_WRITE(put, linecolor);
226
285
                    put++;
227
                }
228
171
                for (nextx = xend, nexty = yend, decision = (dx >> 1); nextx > mid_point.gx_point_x;
229
161
                     nextx--, decision += dy)
230
                {
231
170
                    if (decision >= dx)
232
                    {
233
47
                        decision -= dx;
234
47
                        nexty -= y_sign;
235
47
                        next_put -= y_increment;
236
                    }
237
170
                    if (nextx <= rotated_clip.gx_rectangle_right &&
238
95
                        nexty >= rotated_clip.gx_rectangle_top &&
239
47
                        nexty <= rotated_clip.gx_rectangle_bottom)
240
                    {
241
9
                        break;
242
                    }
243
161
                    next_put--;
244
                }
245
246
289
                for (; nextx > mid_point.gx_point_x;
247
279
                     nextx--, decision += dy)
248
                {
249
279
                    if (decision >= dx)
250
                    {
251
111
                        decision -= dx;
252
111
                        nexty -= y_sign;
253
111
                        next_put -= y_increment;
254
                    }
255
279
                    PIXEL_WRITE(next_put, linecolor);
256
279
                    next_put--;
257
                }
258
            }
259
            else
260
            {
261
381
                for (nextx = xend, nexty = yend, decision = (dy >> 1); nexty > mid_point.gx_point_y;
262
369
                     nexty--, decision += dx)
263
                {
264
380
                    if (decision >= dy)
265
                    {
266
86
                        decision -= dy;
267
86
                        nextx -= x_sign;
268
86
                        next_put -= x_sign;
269
                    }
270
380
                    if (nextx >= rotated_clip.gx_rectangle_left &&
271
176
                        nextx <= rotated_clip.gx_rectangle_right &&
272
128
                        nexty <= rotated_clip.gx_rectangle_bottom)
273
                    {
274
11
                        break;
275
                    }
276
369
                    next_put -= context -> gx_draw_context_pitch;
277
                }
278
279
693
                for (; nexty > mid_point.gx_point_y;
280
681
                     nexty--, decision += dx)
281
                {
282
681
                    if (decision >= dy)
283
                    {
284
196
                        decision -= dy;
285
196
                        nextx -= x_sign;
286
196
                        next_put -= x_sign;
287
                    }
288
681
                    PIXEL_WRITE(next_put, linecolor);
289
681
                    next_put -= context -> gx_draw_context_pitch;
290
                }
291
292
                /* walk out the clipping point.  */
293
381
                for (curx = xstart, cury = ystart, decision = (dy >> 1); cury < mid_point.gx_point_y;
294
369
                     cury++, decision += dx)
295
                {
296
380
                    if (decision >= dy)
297
                    {
298
86
                        decision -= dy;
299
86
                        curx += x_sign;
300
86
                        put += x_sign;
301
                    }
302
303
380
                    if (curx >= rotated_clip.gx_rectangle_left &&
304
332
                        curx <= rotated_clip.gx_rectangle_right &&
305
128
                        cury >= rotated_clip.gx_rectangle_top)
306
                    {
307
11
                        break;
308
                    }
309
369
                    put += context -> gx_draw_context_pitch;
310
                }
311
701
                for (; cury <= mid_point.gx_point_y;
312
689
                     cury++, decision += dx)
313
                {
314
689
                    if (decision >= dy)
315
                    {
316
196
                        decision -= dy;
317
196
                        curx += x_sign;
318
196
                        put += x_sign;
319
                    }
320
689
                    PIXEL_WRITE(put, linecolor);
321
689
                    put += context -> gx_draw_context_pitch;
322
                }
323
            }
324
        }
325
        else
326
        {
327
            /* The clip stay at one side.  */
328
8
            if (dx >= dy)
329
            {
330
4
                half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
331
4
                half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
332
4
                if (y_sign == 1)
333
                {
334
2
                    half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
335
2
                    half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
336
                }
337
                else
338
                {
339
2
                    half_rectangle.gx_rectangle_top = mid_point.gx_point_y;
340
2
                    half_rectangle.gx_rectangle_bottom = (GX_VALUE)ystart;
341
                }
342
343
4
                if (_gx_utility_rectangle_overlap_detect(&rotated_clip, &half_rectangle, &half_over))
344
                {
345
2
                    curx = xstart;
346
2
                    cury = ystart;
347
2
                    steps = mid_point.gx_point_x - curx + 1;
348
2
                    sign = 1;
349
                }
350
                else
351
                {
352
2
                    curx = xend;
353
2
                    cury = yend;
354
2
                    steps = xend - mid_point.gx_point_x;
355
2
                    sign = -1;
356
2
                    y_increment = 0 - y_increment;
357
2
                    y_sign = 0 - y_sign;
358
2
                    put = next_put;
359
                }
360
529
                for (decision = (dx >> 1); steps > 0; curx += sign, decision += dy, steps--)
361
                {
362
525
                    if (decision >= dx)
363
                    {
364
191
                        decision -= dx;
365
191
                        cury += y_sign;
366
191
                        put += y_increment;
367
                    }
368
369
525
                    if (curx >= rotated_clip.gx_rectangle_left &&
370
517
                        curx <= rotated_clip.gx_rectangle_right &&
371
508
                        cury >= rotated_clip.gx_rectangle_top &&
372
371
                        cury <= rotated_clip.gx_rectangle_bottom)
373
                    {
374
234
                        PIXEL_WRITE(put, linecolor);
375
                    }
376
525
                    put += sign;
377
                }
378
            }
379
            else
380
            {
381
4
                half_rectangle.gx_rectangle_top = (GX_VALUE)ystart;
382
4
                half_rectangle.gx_rectangle_bottom = mid_point.gx_point_y;
383
4
                if (x_sign == 1)
384
                {
385
2
                    half_rectangle.gx_rectangle_right = mid_point.gx_point_x;
386
2
                    half_rectangle.gx_rectangle_left = (GX_VALUE)xstart;
387
                }
388
                else
389
                {
390
2
                    half_rectangle.gx_rectangle_right = (GX_VALUE)xstart;
391
2
                    half_rectangle.gx_rectangle_left = mid_point.gx_point_x;
392
                }
393
394
4
                if (_gx_utility_rectangle_overlap_detect(&rotated_clip, &half_rectangle, &half_over))
395
                {
396
2
                    curx = xstart;
397
2
                    cury = ystart;
398
2
                    steps = mid_point.gx_point_y - cury + 1;
399
2
                    y_increment = context -> gx_draw_context_pitch;
400
2
                    sign = 1;
401
                }
402
                else
403
                {
404
2
                    curx = xend;
405
2
                    cury = yend;
406
2
                    steps = yend - mid_point.gx_point_y;
407
2
                    sign = -1;
408
2
                    y_increment = 0 - context -> gx_draw_context_pitch;
409
2
                    x_sign = 0 - x_sign;
410
2
                    put = next_put;
411
                }
412
413
983
                for (decision = (dy >> 1); steps > 0; cury += sign, decision += dx, steps--)
414
                {
415
979
                    if (decision >= dy)
416
                    {
417
248
                        decision -= dy;
418
248
                        curx += x_sign;
419
248
                        put += x_sign;
420
                    }
421
979
                    if (curx >= rotated_clip.gx_rectangle_left &&
422
970
                        curx <= rotated_clip.gx_rectangle_right &&
423
960
                        cury >= rotated_clip.gx_rectangle_top &&
424
856
                        cury <= rotated_clip.gx_rectangle_bottom)
425
                    {
426
752
                        PIXEL_WRITE(put, linecolor);
427
                    }
428
979
                    put += y_increment;
429
                }
430
            }
431
        }
432
    }
433
    else
434
    {
435
        /* here if both line ends lie within clipping rectangle, we can
436
           run a faster inner loop */
437
514
        if (dx >= dy)
438
        {
439
248
            put = (USHORT *)(context -> gx_draw_context_memory) + ystart * context -> gx_draw_context_pitch + xstart;
440
248
            next_put = (USHORT *)(context -> gx_draw_context_memory) + yend * context -> gx_draw_context_pitch + xend;
441
442
248
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
443
22488
                 decision = (dx >> 1); curx <= nextx; curx++, nextx--,
444
22240
                 decision += dy)
445
            {
446
447
22240
                if (decision >= dx)
448
                {
449
9938
                    decision -= dx;
450
9938
                    cury += y_sign;
451
9938
                    nexty -= y_sign;
452
453
9938
                    put += y_increment;
454
9938
                    next_put -= y_increment;
455
                }
456
22240
                PIXEL_WRITE(put, linecolor);
457
22240
                PIXEL_WRITE(next_put, linecolor);
458
459
22240
                put++;
460
22240
                next_put--;
461
            }
462
        }
463
        else
464
        {
465
466
266
            for (curx = xstart, cury = ystart, nextx = xend, nexty = yend,
467
24466
                 decision = (dy >> 1); cury <= nexty; cury++, nexty--,
468
24200
                 decision += dx)
469
            {
470
24200
                if (decision >= dy)
471
                {
472
9910
                    decision -= dy;
473
9910
                    curx += x_sign;
474
9910
                    nextx -= x_sign;
475
476
9910
                    put += x_sign;
477
9910
                    next_put -= x_sign;
478
                }
479
24200
                PIXEL_WRITE(put, linecolor);
480
24200
                PIXEL_WRITE(next_put, linecolor);
481
482
24200
                put += context -> gx_draw_context_pitch;
483
24200
                next_put -= context -> gx_draw_context_pitch;
484
            }
485
        }
486
    }
487
}
488