GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_8bpp_rotated_simple_line_draw.c Lines: 212 212 100.0 %
Date: 2026-03-06 19:21:09 Branches: 122 122 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_rotated_simple_line_draw    PORTABLE C      */
38
/*                                                           6.1.4        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    Generic 8bpp color format rotated 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
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    GUIX Internal Code                                                  */
69
/*                                                                        */
70
/**************************************************************************/
71
544
VOID _gx_display_driver_8bpp_rotated_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
72
{
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
GX_UBYTE     *put;
90
GX_UBYTE     *next_put;
91
92
544
GX_BOOL       clipped = GX_TRUE;
93
INT           dx;
94
INT           dy;
95
96
544
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
97
544
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
98
GX_RECTANGLE  rotated_clip;
99
100
544
    GX_SWAP_VALS(xstart, ystart);
101
544
    GX_SWAP_VALS(xend, yend);
102
544
    clip = context -> gx_draw_context_clip;
103
104
544
    if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
105
    {
106
277
        ystart = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - ystart - 1;
107
277
        yend = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - yend - 1;
108
109
277
        rotated_clip.gx_rectangle_left = clip -> gx_rectangle_top;
110
277
        rotated_clip.gx_rectangle_right = clip -> gx_rectangle_bottom;
111
277
        rotated_clip.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_right - 1);
112
277
        rotated_clip.gx_rectangle_bottom = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_left - 1);
113
    }
114
    else
115
    {
116
267
        xstart = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xstart - 1;
117
267
        xend = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xend - 1;
118
119
267
        rotated_clip.gx_rectangle_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_bottom - 1);
120
267
        rotated_clip.gx_rectangle_right = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_top - 1);
121
267
        rotated_clip.gx_rectangle_top = clip -> gx_rectangle_left;
122
267
        rotated_clip.gx_rectangle_bottom = clip -> gx_rectangle_right;
123
    }
124
125
544
    dx = GX_ABS(xend - xstart);
126
544
    dy = GX_ABS(yend - ystart);
127
128


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