GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_16bpp_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
21
22
#define PIXEL_WRITE(loc, val) (*(loc) = ((USHORT)val))
23
24
#define GX_SOURCE_CODE
25
26
/* Include necessary system files.  */
27
28
#include "gx_api.h"
29
#include "gx_utility.h"
30
#include "gx_display.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_display_driver_16bpp_rotated_simple_line_draw   PORTABLE C      */
37
/*                                                           6.1.3        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Generic 16bpp color format line draw function.                      */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    context                               Drawing context               */
49
/*    xstart                                x-coord of endpoint           */
50
/*    ystart                                y-coord of endpoint           */
51
/*    xend                                  x-coord of endpoint           */
52
/*    yend                                  y-coord of endpoint           */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    None                                                                */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _gx_display_driver_simple_line_alpha_draw                           */
61
/*                                          Generic line draw with alpha  */
62
/*    _gx_display_driver_16bpp_simple_line_draw                           */
63
/*                                          Generic 16bpp line draw       */
64
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    GUIX Internal Code                                                  */
68
/*                                                                        */
69
/*  RELEASE HISTORY                                                       */
70
/*                                                                        */
71
/*    DATE              NAME                      DESCRIPTION             */
72
/*                                                                        */
73
/*  12-31-2020     Kenneth Maxwell          Initial Version 6.1.3         */
74
/*                                                                        */
75
/**************************************************************************/
76
604
VOID _gx_display_driver_16bpp_rotated_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
77
{
78
INT           curx;
79
INT           cury;
80
INT           x_sign;
81
INT           y_sign;
82
INT           decision;
83
INT           nextx;
84
INT           nexty;
85
INT           y_increment;
86
GX_POINT      end_point;
87
GX_POINT      mid_point;
88
GX_RECTANGLE  half_rectangle;
89
GX_RECTANGLE  half_over;
90
INT           sign;
91
INT           steps;
92
93
USHORT       *put;
94
USHORT       *next_put;
95
96
604
GX_BOOL       clipped = GX_TRUE;
97
INT           dx;
98
INT           dy;
99
100
GX_RECTANGLE *clip;
101
GX_RECTANGLE  rotated_clip;
102
GX_COLOR      linecolor;
103
104
#if defined GX_BRUSH_ALPHA_SUPPORT
105
GX_UBYTE alpha;
106
107
604
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
108
604
    if (alpha == 0)
109
    {
110
        /* Nothing to drawn. Just return. */
111
60
        return;
112
    }
113
574
    if (alpha != 0xff)
114
    {
115
30
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
116
30
        return;
117
    }
118
#endif
119
120
544
    GX_SWAP_VALS(xstart, ystart);
121
544
    GX_SWAP_VALS(xend, yend);
122
544
    clip = context -> gx_draw_context_clip;
123
124
544
    if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
125
    {
126
277
        ystart = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - ystart - 1;
127
277
        yend = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - yend - 1;
128
129
277
        rotated_clip.gx_rectangle_left = clip -> gx_rectangle_top;
130
277
        rotated_clip.gx_rectangle_right = clip -> gx_rectangle_bottom;
131
277
        rotated_clip.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_right - 1);
132
277
        rotated_clip.gx_rectangle_bottom = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_left - 1);
133
    }
134
    else
135
    {
136
267
        xstart = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xstart - 1;
137
267
        xend = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xend - 1;
138
139
267
        rotated_clip.gx_rectangle_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_bottom - 1);
140
267
        rotated_clip.gx_rectangle_right = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_top - 1);
141
267
        rotated_clip.gx_rectangle_top = clip -> gx_rectangle_left;
142
267
        rotated_clip.gx_rectangle_bottom = clip -> gx_rectangle_right;
143
    }
144
145
544
    dx = GX_ABS(xend - xstart);
146
544
    dy = GX_ABS(yend - ystart);
147
148
149
544
    linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
150
151


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