GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_32bpp_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
#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_rotated_simple_line_draw   PORTABLE C      */
36
/*                                                           6.1.4        */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Kenneth Maxwell, Microsoft Corporation                              */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    Generic rotated 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
891
VOID _gx_display_driver_32bpp_rotated_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
ULONG        *put;
85
ULONG        *next_put;
86
891
GX_BOOL       clipped = GX_TRUE;
87
INT           dx;
88
INT           dy;
89
GX_RECTANGLE *clip;
90
GX_RECTANGLE  rotated_clip;
91
891
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
92
93
#if defined GX_BRUSH_ALPHA_SUPPORT
94
GX_UBYTE alpha;
95
96
891
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
97
891
    if (alpha == 0)
98
    {
99
100
        /* Nothing to drawn. Just return. */
101
80
        return;
102
    }
103
851
    if (alpha != 0xff)
104
    {
105
40
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
106
40
        return;
107
    }
108
#endif
109
110
811
    GX_SWAP_VALS(xstart, ystart);
111
811
    GX_SWAP_VALS(xend, yend);
112
811
    clip = context -> gx_draw_context_clip;
113
114
811
    if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
115
    {
116
544
        ystart = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - ystart - 1;
117
544
        yend = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - yend - 1;
118
119
544
        rotated_clip.gx_rectangle_left = clip -> gx_rectangle_top;
120
544
        rotated_clip.gx_rectangle_right = clip -> gx_rectangle_bottom;
121
544
        rotated_clip.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_right - 1);
122
544
        rotated_clip.gx_rectangle_bottom = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_left - 1);
123
    }
124
    else
125
    {
126
267
        xstart = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xstart - 1;
127
267
        xend = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xend - 1;
128
129
267
        rotated_clip.gx_rectangle_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_bottom - 1);
130
267
        rotated_clip.gx_rectangle_right = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_top - 1);
131
267
        rotated_clip.gx_rectangle_top = clip -> gx_rectangle_left;
132
267
        rotated_clip.gx_rectangle_bottom = clip -> gx_rectangle_right;
133
    }
134
135
811
    dx = GX_ABS(xend - xstart);
136
811
    dy = GX_ABS(yend - ystart);
137
138


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