GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_8bpp_simple_line_draw.c Lines: 203 203 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) = ((GX_UBYTE)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_8bpp_simple_line_draw            PORTABLE C      */
37
/*                                                           6.1          */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Generic 8bpp 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_ABS                                Compute the absolute value    */
61
/*    GX_SWAP_VALUE                         Swap two values               */
62
/*    [PIXEL_WRITE]                         Driver level pixel write      */
63
/*                                            routine                     */
64
/*    _gx_display_driver_simple_line_alpha_draw                           */
65
/*                                          Basic display driver simple   */
66
/*                                            alpha line draw function    */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    GUIX Internal Code                                                  */
71
/*                                                                        */
72
/*  RELEASE HISTORY                                                       */
73
/*                                                                        */
74
/*    DATE              NAME                      DESCRIPTION             */
75
/*                                                                        */
76
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
77
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
78
/*                                            resulting in version 6.1    */
79
/*                                                                        */
80
/**************************************************************************/
81
721
VOID _gx_display_driver_8bpp_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
82
{
83
84
INT           curx;
85
INT           cury;
86
INT           x_sign;
87
INT           y_sign;
88
INT           decision;
89
INT           nextx;
90
INT           nexty;
91
INT           y_increment;
92
GX_POINT      end_point;
93
GX_POINT      mid_point;
94
GX_RECTANGLE  half_rectangle;
95
GX_RECTANGLE  half_over;
96
INT           sign;
97
INT           steps;
98
99
GX_UBYTE     *put;
100
GX_UBYTE     *next_put;
101
102
721
GX_BOOL       clipped = GX_TRUE;
103
721
INT           dx = GX_ABS(xend - xstart);
104
721
INT           dy = GX_ABS(yend - ystart);
105
106
721
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
107
721
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
108
#if defined GX_BRUSH_ALPHA_SUPPORT
109
GX_UBYTE      alpha;
110
111
721
    alpha = context -> gx_draw_context_brush.gx_brush_alpha;
112
721
    if (alpha == 0)
113
    {
114
        /* Nothing to drawn. Just return. */
115
51
        return;
116
    }
117
709
    if (alpha != 0xff)
118
    {
119
39
        if (context -> gx_draw_context_display -> gx_display_color_format != GX_COLOR_FORMAT_8BIT_PACKED_PIXEL)
120
        {
121
            /* Alpha blend is not supported for palette driver. */
122
12
            return;
123
        }
124
125
27
        _gx_display_driver_simple_line_alpha_draw(context, xstart, ystart, xend, yend, alpha);
126
27
        return;
127
    }
128
#endif
129
130


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