GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_16bpp_simple_line_draw.c Lines: 203 203 100.0 %
Date: 2024-12-05 08:52:37 Branches: 124 124 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_simple_line_draw           PORTABLE C      */
37
/*                                                           6.3.0        */
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
/*                                          Display driver basic simpile  */
62
/*                                            line alpha draw function    */
63
/*    _gx_utility_rectangle_point_detect    Detect whether a pixel is     */
64
/*                                            inside rectangle            */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    GUIX Internal Code                                                  */
69
/*                                                                        */
70
/*  RELEASE HISTORY                                                       */
71
/*                                                                        */
72
/*    DATE              NAME                      DESCRIPTION             */
73
/*                                                                        */
74
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
75
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
76
/*                                            resulting in version 6.1    */
77
/*  10-31-2023     Ting Zhu                 Modified comment(s),          */
78
/*                                            added partial canvas buffer */
79
/*                                            support,                    */
80
/*                                            resulting in version 6.3.0  */
81
/*                                                                        */
82
/**************************************************************************/
83
566
VOID _gx_display_driver_16bpp_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
84
{
85
INT           curx;
86
INT           cury;
87
INT           x_sign;
88
INT           y_sign;
89
INT           decision;
90
INT           nextx;
91
INT           nexty;
92
INT           y_increment;
93
GX_POINT      end_point;
94
GX_POINT      mid_point;
95
GX_RECTANGLE  half_rectangle;
96
GX_RECTANGLE  half_over;
97
INT           sign;
98
INT           steps;
99
100
USHORT       *put;
101
USHORT       *next_put;
102
103
566
GX_BOOL       clipped = GX_TRUE;
104
566
INT           dx = GX_ABS(xend - xstart);
105
566
INT           dy = GX_ABS(yend - ystart);
106
107
566
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
108
566
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
109
110
#if defined GX_BRUSH_ALPHA_SUPPORT
111
GX_UBYTE alpha;
112
113
566
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
114
566
    if (alpha == 0)
115
    {
116
        /* Nothing to drawn. Just return. */
117
362
        return;
118
    }
119
556
    if (alpha != 0xff)
120
    {
121
352
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
122
352
        return;
123
    }
124
#endif
125
126


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