GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_display_driver_4444argb_pixelmap_rotate.c Lines: 156 156 100.0 %
Date: 2024-12-05 08:52:37 Branches: 66 66 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
#define ALPHAVAL(_c) (GX_UBYTE)(((_c) >> 12) & 0x0f)
22
#define REDVAL(_c)   (GX_UBYTE)(((_c) >> 8) & 0x0f)
23
#define GREENVAL(_c) (GX_UBYTE)(((_c) >> 4) & 0x0f)
24
#define BLUEVAL(_c)  (GX_UBYTE)(((_c)) & 0x0f)
25
26
#define ASSEMBLECOLOR(_a, _r, _g, _b) \
27
    ((((_a) & 0x0f) << 12) |          \
28
     (((_r) & 0x0f) << 8) |           \
29
     (((_g) & 0x0f) << 4) |           \
30
     (((_b) & 0x0f)))
31
32
#define GX_SOURCE_CODE
33
34
/* Include necessary system files.  */
35
36
#include "gx_api.h"
37
#include "gx_display.h"
38
#include "gx_context.h"
39
#include "gx_utility.h"
40
#include "gx_system.h"
41
42
/**************************************************************************/
43
/*                                                                        */
44
/*  FUNCTION                                               RELEASE        */
45
/*                                                                        */
46
/*    _gx_display_driver_4444argb_pixelmap_general_rotate                 */
47
/*                                                        PORTABLE C      */
48
/*                                                           6.1.10       */
49
/*  AUTHOR                                                                */
50
/*                                                                        */
51
/*    Kenneth Maxwell, Microsoft Corporation                              */
52
/*                                                                        */
53
/*  DESCRIPTION                                                           */
54
/*                                                                        */
55
/*    Internal helper function that rotate an 4444argb format pixelmap    */
56
/*    without compression, without alpha.                                 */
57
/*                                                                        */
58
/*  INPUT                                                                 */
59
/*                                                                        */
60
/*    context                               Drawing context               */
61
/*    xpos                                  x-coord of top-left draw point*/
62
/*    ypos                                  y-coord of top-left draw point*/
63
/*    pixelmap                              Pointer to GX_PIXELMAP struct */
64
/*    angle                                 The angle to rotate           */
65
/*    cx                                    x-coord of rotate center      */
66
/*    cy                                    y-coord of rotate center      */
67
/*                                                                        */
68
/*  OUTPUT                                                                */
69
/*                                                                        */
70
/*    status                                Completion status             */
71
/*                                                                        */
72
/*  CALLS                                                                 */
73
/*                                                                        */
74
/*    _gx_utility_math_cos                  Compute the cosine value      */
75
/*    _gx_utility_math_sin                  Compute the sine value        */
76
/*    [gx_display_driver_pixel_blend]       Display driver basic pixel    */
77
/*                                             blend function             */
78
/*                                                                        */
79
/*  CALLED BY                                                             */
80
/*                                                                        */
81
/*    GUIX Internal Code                                                  */
82
/*                                                                        */
83
/*  RELEASE HISTORY                                                       */
84
/*                                                                        */
85
/*    DATE              NAME                      DESCRIPTION             */
86
/*                                                                        */
87
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
88
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
89
/*                                            resulting in version 6.1    */
90
/*  01-31-2022     Ting Zhu                 Modified comment(s),          */
91
/*                                            corrected logic,            */
92
/*                                            resulting in version 6.1.10 */
93
/*                                                                        */
94
/**************************************************************************/
95
1425
static VOID _gx_display_driver_4444argb_pixelmap_general_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
96
                                                                INT angle, INT cx, INT cy)
97
{
98
USHORT       *get;
99
INT           srcxres;
100
INT           srcyres;
101
INT           cosv;
102
INT           sinv;
103
USHORT        red;
104
USHORT        green;
105
USHORT        blue;
106
INT           idxminx;
107
INT           idxmaxx;
108
INT           idxmaxy;
109
INT          *mx;
110
INT          *my;
111
INT           xres;
112
INT           yres;
113
INT           x;
114
INT           y;
115
INT           xx;
116
INT           yy;
117
USHORT        a;
118
USHORT        b;
119
USHORT        c;
120
USHORT        d;
121
INT           xdiff;
122
INT           ydiff;
123
INT           newxpos;
124
INT           newypos;
125
GX_DISPLAY   *display;
126
GX_RECTANGLE *clip;
127
VOID          (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
128
1425
USHORT        alpha[4] = {0};
129
130
1425
    clip = context -> gx_draw_context_clip;
131
1425
    display = context -> gx_draw_context_display;
132
1425
    blend_func = display -> gx_display_driver_pixel_blend;
133
134
1425
    if (!blend_func)
135
    {
136
1
        return;
137
    }
138
139
1424
    mx = _gx_system_scratchpad;
140
1424
    my = mx + 4;
141
142
1424
    mx[0] = mx[3] = -1;
143
1424
    mx[1] = mx[2] = 1;
144
145
1424
    my[0] = my[1] = 1;
146
1424
    my[2] = my[3] = -1;
147
148
1424
    idxminx = (angle / 90) & 0x3;
149
1424
    idxmaxx = (idxminx + 2) & 0x3;
150
1424
    idxmaxy = (idxminx + 1) & 0x3;
151
152
    /* Calculate the source x and y center. */
153
1424
    srcxres = pixelmap -> gx_pixelmap_width >> 1;
154
1424
    srcyres = pixelmap -> gx_pixelmap_height >> 1;
155
156
1424
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
157
1424
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
158
159
1424
    xres = GX_FIXED_VAL_TO_INT(mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv);
160
1424
    yres = GX_FIXED_VAL_TO_INT(my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv);
161
162
    /* Calculate the new rotation axis. */
163
164
1424
    xres = GX_FIXED_VAL_TO_INT((cx - srcxres) * cosv - (cy - srcyres) * sinv) + xres;
165
1424
    yres = GX_FIXED_VAL_TO_INT((cy - srcyres) * cosv + (cx - srcxres) * sinv) + xres;
166
167
1424
    newxpos = xpos + cx - xres;
168
1424
    newypos = ypos + cy - yres;
169
170
    /* Loop through the destination's pixels.  */
171
318258
    for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
172
    {
173
81087609
        for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
174
        {
175
80770775
            xx = (x - xres) * cosv + (y - yres) * sinv;
176
80770775
            yy = (y - yres) * cosv - (x - xres) * sinv;
177
178
80770775
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
179
80770775
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
180
181
80770775
            xx = GX_FIXED_VAL_TO_INT(xx) + cx;
182
80770775
            yy = GX_FIXED_VAL_TO_INT(yy) + cy;
183
184

80770775
            if ((xx >= -1) && (xx < pixelmap -> gx_pixelmap_width) &&
185
57533958
                (yy >= -1) && (yy < pixelmap -> gx_pixelmap_height))
186
            {
187

47556374
                if ((xx >= 0) && (xx < pixelmap -> gx_pixelmap_width - 1) &&
188
46889878
                    (yy >= 0) && (yy < pixelmap -> gx_pixelmap_height - 1))
189
                {
190
46618699
                    get = (USHORT *)pixelmap -> gx_pixelmap_data;
191
46618699
                    get += yy * pixelmap -> gx_pixelmap_width;
192
46618699
                    get += xx;
193
194
46618699
                    a = *get;
195
46618699
                    b = *(get + 1);
196
46618699
                    c = *(get + pixelmap -> gx_pixelmap_width);
197
46618699
                    d = *(get + pixelmap -> gx_pixelmap_width + 1);
198
46618699
                    alpha[0] = ALPHAVAL(a);
199
46618699
                    alpha[1] = ALPHAVAL(b);
200
46618699
                    alpha[2] = ALPHAVAL(c);
201
46618699
                    alpha[3] = ALPHAVAL(d);
202
                }
203
                else
204
                {
205
937675
                    get = (USHORT *)pixelmap -> gx_pixelmap_data;
206
207
937675
                    a = 0;
208
937675
                    b = 0;
209
937675
                    c = 0;
210
937675
                    d = 0;
211
212
937675
                    if (xx == -1)
213
                    {
214
                        /* handle left edge.  */
215
192402
                        if (yy >= 0)
216
                        {
217
191702
                            b = *(get + yy * pixelmap -> gx_pixelmap_width);
218
191702
                            alpha[1] = ALPHAVAL(b);
219
                        }
220
221
192402
                        if (yy < pixelmap -> gx_pixelmap_height - 1)
222
                        {
223
191509
                            d = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width);
224
191509
                            alpha[3] = ALPHAVAL(d);
225
                        }
226
                    }
227
745273
                    else if (yy == -1)
228
                    {
229
                        /* handle top edge.  */
230
229346
                        c = *(get + xx);
231
229346
                        alpha[2] = ALPHAVAL(c);
232
233
229346
                        if (xx < pixelmap -> gx_pixelmap_width - 1)
234
                        {
235
228292
                            d = *(get + xx + 1);
236
228292
                            alpha[3] = ALPHAVAL(d);
237
                        }
238
                    }
239
515927
                    else if (xx == pixelmap -> gx_pixelmap_width - 1)
240
                    {
241
                        /* handle right edget. */
242
244748
                        a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
243
244748
                        alpha[0] = ALPHAVAL(a);
244
245
244748
                        if (yy < pixelmap -> gx_pixelmap_height - 1)
246
                        {
247
242676
                            c = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width + xx);
248
242676
                            alpha[2] = ALPHAVAL(c);
249
                        }
250
                    }
251
                    else
252
                    {
253
                        /* handle bottom edge. */
254
271179
                        a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
255
271179
                        alpha[0] = ALPHAVAL(a);
256
257
271179
                        b = *(get + yy * pixelmap -> gx_pixelmap_width + xx + 1);
258
271179
                        alpha[1] = ALPHAVAL(b);
259
                    }
260
261
937675
                    if (!a)
262
                    {
263
421748
                        alpha[0] = 0;
264
                    }
265
266
937675
                    if (!b)
267
                    {
268
474794
                        alpha[1] = 0;
269
                    }
270
271
937675
                    if (!c)
272
                    {
273
465653
                        alpha[2] = 0;
274
                    }
275
276
937675
                    if (!d)
277
                    {
278
517874
                        alpha[3] = 0;
279
                    }
280
                }
281
282
47556374
                red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
283
47556374
                                REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
284
47556374
                                REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
285
47556374
                                REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
286
287
47556374
                green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
288
47556374
                                  GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
289
47556374
                                  GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
290
47556374
                                  GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
291
292
47556374
                blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
293
47556374
                                 BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
294
47556374
                                 BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
295
47556374
                                 BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
296
297
47556374
                alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) +
298
47556374
                                     alpha[1] * xdiff * (256 - ydiff) +
299
47556374
                                     alpha[2] * ydiff * (256 - xdiff) +
300
47556374
                                     alpha[3] * xdiff * ydiff) >> 16);
301
302
47556374
                if (alpha[0])
303
                {
304
39320652
                    red /= alpha[0];
305
39320652
                    green /= alpha[0];
306
39320652
                    blue /= alpha[0];
307
                }
308
309
47556374
                red = red > 15 ? 15 : red;
310
47556374
                green = green > 15 ? 15 : green;
311
47556374
                blue = blue > 15 ? 15 : blue;
312
47556374
                alpha[0] = alpha[0] > 15 ? 15 : alpha[0];
313
314
47556374
                blend_func(context, x + newxpos, y + newypos, (GX_COLOR)ASSEMBLECOLOR(alpha[0], red, green, blue), (GX_UBYTE)0xff);
315
            }
316
        }
317
    }
318
}
319
320
/**************************************************************************/
321
/*                                                                        */
322
/*  FUNCTION                                               RELEASE        */
323
/*                                                                        */
324
/*    _gx_display_driver_4444argb_pixelmap_simple_rotate  PORTABLE C      */
325
/*                                                           6.1.7        */
326
/*  AUTHOR                                                                */
327
/*                                                                        */
328
/*    Kenneth Maxwell, Microsoft Corporation                              */
329
/*                                                                        */
330
/*  DESCRIPTION                                                           */
331
/*                                                                        */
332
/*    Internal help function that hangles 90, 180 and 270 degree pixelmap */
333
/*    rotation.                                                           */
334
/*                                                                        */
335
/*  INPUT                                                                 */
336
/*                                                                        */
337
/*    context                               Drawing context               */
338
/*    xpos                                  x-coord of top-left draw point*/
339
/*    ypos                                  y-coord of top-left draw point*/
340
/*    pixelmap                              Pointer to GX_PIXELMAP struct */
341
/*    angle                                 The angle to rotate           */
342
/*    cx                                    x-coord of rotate center      */
343
/*    cy                                    y-coord of rotate center      */
344
/*                                                                        */
345
/*  OUTPUT                                                                */
346
/*                                                                        */
347
/*    status                                Completion status             */
348
/*                                                                        */
349
/*  CALLS                                                                 */
350
/*                                                                        */
351
/*    [gx_display_driver_pixel_blend]       Display driver basic pixel    */
352
/*                                             blend function             */
353
/*                                                                        */
354
/*  CALLED BY                                                             */
355
/*                                                                        */
356
/*    GUIX Internal Code                                                  */
357
/*                                                                        */
358
/*  RELEASE HISTORY                                                       */
359
/*                                                                        */
360
/*    DATE              NAME                      DESCRIPTION             */
361
/*                                                                        */
362
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
363
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
364
/*                                            resulting in version 6.1    */
365
/*  06-02-2021     Kenneth Maxwell          Modified comment(s),          */
366
/*                                            removed unused variable     */
367
/*                                            assignment,                 */
368
/*                                            resulting in version 6.1.7  */
369
/*                                                                        */
370
/**************************************************************************/
371
12
static VOID _gx_display_driver_4444argb_pixelmap_simple_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
372
                                                               INT angle, INT cx, INT cy)
373
{
374
USHORT       *get;
375
INT           width;
376
INT           height;
377
INT           x;
378
INT           y;
379
GX_RECTANGLE *clip;
380
INT           newxpos;
381
INT           newypos;
382
USHORT        color;
383
VOID          (*blend_func)(GX_DRAW_CONTEXT *context, INT x1, INT y1, GX_COLOR color, GX_UBYTE alpha);
384
385
12
    blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
386
12
    clip = context -> gx_draw_context_clip;
387
388
12
    if (angle == 90)
389
    {
390
4
        width = pixelmap -> gx_pixelmap_height;
391
4
        height = pixelmap -> gx_pixelmap_width;
392
393
4
        newxpos = xpos + cx - (width - 1 - cy);
394
4
        newypos = ypos + cy - cx;
395
396
865
        for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
397
        {
398
147567
            for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
399
            {
400
146706
                get = (USHORT *)pixelmap -> gx_pixelmap_data;
401
146706
                get += (width - 1 - x) * height;
402
146706
                get += y;
403
146706
                color = *get;
404
146706
                blend_func(context, x + newxpos, y + newypos, color, 0xff);
405
            }
406
        }
407
    }
408
8
    else if (angle == 180)
409
    {
410
411
4
        width = pixelmap -> gx_pixelmap_width;
412
4
        height = pixelmap -> gx_pixelmap_height;
413
414
4
        newxpos = xpos + cx - (width - 1 - cx);
415
4
        newypos = ypos + cy - (height - 1 - cy);
416
417
541
        for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
418
        {
419
106445
            for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
420
            {
421
105908
                get = (USHORT *)pixelmap -> gx_pixelmap_data;
422
105908
                get += (height - 1 - y) * width;
423
105908
                get += width - 1 - x;
424
105908
                color = *get;
425
105908
                blend_func(context, x + newxpos, y + newypos, color, 0xff);
426
            }
427
        }
428
    }
429
    else
430
    {
431
4
        height = pixelmap -> gx_pixelmap_width;
432
433
4
        newxpos = xpos + cx - cy;
434
4
        newypos = ypos + cx - (height - 1 - cy);
435
436
583
        for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
437
        {
438
106245
            for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
439
            {
440
105666
                get = (USHORT *)pixelmap -> gx_pixelmap_data;
441
105666
                get += x * height;
442
105666
                get += height - 1 - y;
443
105666
                color = *get;
444
105666
                blend_func(context, x + newxpos, y + newypos, color, 0xff);
445
            }
446
        }
447
    }
448
12
}
449
450
/**************************************************************************/
451
/*                                                                        */
452
/*  FUNCTION                                               RELEASE        */
453
/*                                                                        */
454
/*    _gx_display_driver_4444argb_pixelmap_rotate         PORTABLE C      */
455
/*                                                           6.1          */
456
/*  AUTHOR                                                                */
457
/*                                                                        */
458
/*    Kenneth Maxwell, Microsoft Corporation                              */
459
/*                                                                        */
460
/*  DESCRIPTION                                                           */
461
/*                                                                        */
462
/*    This service rotates an 4444argb format pixelmap to canvas memory.  */
463
/*                                                                        */
464
/*  INPUT                                                                 */
465
/*                                                                        */
466
/*    context                               Drawing context               */
467
/*    xpos                                  x-coord of top-left draw point*/
468
/*    ypos                                  y-coord of top-left draw point*/
469
/*    pixelmap                              Pointer to GX_PIXELMAP struct */
470
/*    angle                                 The angle to rotate           */
471
/*    rot_cx                                x-coord of rotating center.   */
472
/*    rot_cy                                y-coord of rotationg center.  */
473
/*                                                                        */
474
/*  OUTPUT                                                                */
475
/*                                                                        */
476
/*    status                                Completion status             */
477
/*                                                                        */
478
/*  CALLS                                                                 */
479
/*                                                                        */
480
/*    _gx_display_driver_4444argb_pixelmap_simple_rotate                  */
481
/*                                          Rotate 4444argb format        */
482
/*                                            pixlemap in simple case     */
483
/*    _gx_display_driver_4444argb_pixelmap_rotate                         */
484
/*                                          Rotate 4444argb format        */
485
/*                                            pixelmap in generate case   */
486
/*                                                                        */
487
/*  CALLED BY                                                             */
488
/*                                                                        */
489
/*    Application Code                                                    */
490
/*    GUIX Internal Code                                                  */
491
/*                                                                        */
492
/*  RELEASE HISTORY                                                       */
493
/*                                                                        */
494
/*    DATE              NAME                      DESCRIPTION             */
495
/*                                                                        */
496
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
497
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
498
/*                                            resulting in version 6.1    */
499
/*                                                                        */
500
/**************************************************************************/
501
1438
VOID _gx_display_driver_4444argb_pixelmap_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
502
                                                 INT angle, INT rot_cx, INT rot_cy)
503
{
504
1438
    switch (pixelmap -> gx_pixelmap_format)
505
    {
506
1437
    case GX_COLOR_FORMAT_4444ARGB:
507
1437
        if (angle % 90 == 0)
508
        {
509
            /* Simple angle rotate: 90 degree, 180 degree and 270 degree.  */
510
12
            _gx_display_driver_4444argb_pixelmap_simple_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
511
        }
512
        else
513
        {
514
1425
            _gx_display_driver_4444argb_pixelmap_general_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
515
        }
516
1437
        break;
517
    }
518
519
1438
    return;
520
}
521