GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_8bpp_rotated_simple_line_draw.c Lines: 212 212 100.0 %
Date: 2024-12-05 08:52:37 Branches: 122 122 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_rotated_simple_line_draw    PORTABLE C      */
37
/*                                                           6.1.4        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Generic 8bpp color format rotated 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
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    GUIX Internal Code                                                  */
68
/*                                                                        */
69
/*  RELEASE HISTORY                                                       */
70
/*                                                                        */
71
/*    DATE              NAME                      DESCRIPTION             */
72
/*                                                                        */
73
/*  02-02-2021     Kenneth Maxwell          Initial Version 6.1.4         */
74
/*                                                                        */
75
/**************************************************************************/
76
544
VOID _gx_display_driver_8bpp_rotated_simple_line_draw(GX_DRAW_CONTEXT *context, INT xstart, INT ystart, INT xend, INT yend)
77
{
78
79
INT           curx;
80
INT           cury;
81
INT           x_sign;
82
INT           y_sign;
83
INT           decision;
84
INT           nextx;
85
INT           nexty;
86
INT           y_increment;
87
GX_POINT      end_point;
88
GX_POINT      mid_point;
89
GX_RECTANGLE  half_rectangle;
90
GX_RECTANGLE  half_over;
91
INT           sign;
92
INT           steps;
93
94
GX_UBYTE     *put;
95
GX_UBYTE     *next_put;
96
97
544
GX_BOOL       clipped = GX_TRUE;
98
INT           dx;
99
INT           dy;
100
101
544
GX_RECTANGLE *clip = context -> gx_draw_context_clip;
102
544
GX_COLOR      linecolor = context -> gx_draw_context_brush.gx_brush_line_color;
103
GX_RECTANGLE  rotated_clip;
104
105
544
    GX_SWAP_VALS(xstart, ystart);
106
544
    GX_SWAP_VALS(xend, yend);
107
544
    clip = context -> gx_draw_context_clip;
108
109
544
    if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
110
    {
111
277
        ystart = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - ystart - 1;
112
277
        yend = context -> gx_draw_context_canvas -> gx_canvas_x_resolution - yend - 1;
113
114
277
        rotated_clip.gx_rectangle_left = clip -> gx_rectangle_top;
115
277
        rotated_clip.gx_rectangle_right = clip -> gx_rectangle_bottom;
116
277
        rotated_clip.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_right - 1);
117
277
        rotated_clip.gx_rectangle_bottom = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - clip -> gx_rectangle_left - 1);
118
    }
119
    else
120
    {
121
267
        xstart = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xstart - 1;
122
267
        xend = context -> gx_draw_context_canvas -> gx_canvas_y_resolution - xend - 1;
123
124
267
        rotated_clip.gx_rectangle_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_bottom - 1);
125
267
        rotated_clip.gx_rectangle_right = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - clip -> gx_rectangle_top - 1);
126
267
        rotated_clip.gx_rectangle_top = clip -> gx_rectangle_left;
127
267
        rotated_clip.gx_rectangle_bottom = clip -> gx_rectangle_right;
128
    }
129
130
544
    dx = GX_ABS(xend - xstart);
131
544
    dy = GX_ABS(yend - ystart);
132
133


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