GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_32bpp_rotated_simple_line_draw.c Lines: 216 216 100.0 %
Date: 2024-12-05 08:52:37 Branches: 126 126 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** GUIX Component                                                        */
16
/**                                                                       */
17
/**   Display Management (Display)                                        */
18
/**                                                                       */
19
/**************************************************************************/
20
#define PIXEL_WRITE(loc, val) (*(loc) = (val))
21
22
#define GX_SOURCE_CODE
23
24
/* Include necessary system files.  */
25
26
#include "gx_api.h"
27
#include "gx_utility.h"
28
#include "gx_display.h"
29
30
/**************************************************************************/
31
/*                                                                        */
32
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _gx_display_driver_32bpp_rotated_simple_line_draw   PORTABLE C      */
35
/*                                                           6.1.4        */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Kenneth Maxwell, Microsoft Corporation                              */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    Generic rotated 32bpp color format line draw function.              */
43
/*                                                                        */
44
/*  INPUT                                                                 */
45
/*                                                                        */
46
/*    context                               Drawing context               */
47
/*    xstart                                x-coord of endpoint           */
48
/*    ystart                                y-coord of endpoint           */
49
/*    xend                                  x-coord of endpoint           */
50
/*    yend                                  y-coord of endpoint           */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _gx_display_driver_simple_line_alpha_draw                           */
59
/*                                          Basic display driver line     */
60
/*                                            alpha draw function         */
61
/*                                                                        */
62
/*  CALLED BY                                                             */
63
/*                                                                        */
64
/*    GUIX Internal Code                                                  */
65
/*                                                                        */
66
/*  RELEASE HISTORY                                                       */
67
/*                                                                        */
68
/*    DATE              NAME                      DESCRIPTION             */
69
/*                                                                        */
70
/*  02-02-2021     Kenneth Maxwell          Initial Version 6.1.4         */
71
/*                                                                        */
72
/**************************************************************************/
73
891
VOID _gx_display_driver_32bpp_rotated_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
74
{
75
INT           curx;
76
INT           cury;
77
INT           x_sign;
78
INT           y_sign;
79
INT           decision;
80
INT           nextx;
81
INT           nexty;
82
INT           y_increment;
83
GX_POINT      end_point;
84
GX_POINT      mid_point;
85
GX_RECTANGLE  half_rectangle;
86
GX_RECTANGLE  half_over;
87
INT           sign;
88
INT           steps;
89
ULONG        *put;
90
ULONG        *next_put;
91
891
GX_BOOL       clipped = GX_TRUE;
92
INT           dx;
93
INT           dy;
94
GX_RECTANGLE *clip;
95
GX_RECTANGLE  rotated_clip;
96
891
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
97
98
#if defined GX_BRUSH_ALPHA_SUPPORT
99
GX_UBYTE alpha;
100
101
891
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
102
891
    if (alpha == 0)
103
    {
104
105
        /* Nothing to drawn. Just return. */
106
80
        return;
107
    }
108
851
    if (alpha != 0xff)
109
    {
110
40
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
111
40
        return;
112
    }
113
#endif
114
115
811
    GX_SWAP_VALS(xstart, ystart);
116
811
    GX_SWAP_VALS(xend, yend);
117
811
    clip = context -> gx_draw_context_clip;
118
119
811
    if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
120
    {
121
544
        ystart = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - ystart - 1;
122
544
        yend = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - yend - 1;
123
124
544
        rotated_clip.gx_rectangle_left = clip -> gx_rectangle_top;
125
544
        rotated_clip.gx_rectangle_right = clip -> gx_rectangle_bottom;
126
544
        rotated_clip.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_right - 1);
127
544
        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
811
    dx = GX_ABS(xend - xstart);
141
811
    dy = GX_ABS(yend - ystart);
142
143


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