GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_utility_4444argb_pixelmap_rotate.c Lines: 174 174 100.0 %
Date: 2024-12-05 08:52:37 Branches: 80 80 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
/**   Utility (Utility)                                                   */
18
/**                                                                       */
19
/**************************************************************************/
20
21
#define ALPHAVAL(_c) (GX_UBYTE)(((_c) >> 12) & 0xf)
22
#define REDVAL(_c)   (GX_UBYTE)(((_c) >> 8) & 0xf)
23
#define GREENVAL(_c) (GX_UBYTE)(((_c) >> 4) & 0xf)
24
#define BLUEVAL(_c)  (GX_UBYTE)(((_c)) & 0xf)
25
26
#define ASSEMBLECOLOR(_a, _r, _g, _b)            \
27
    (USHORT)((((_a) & 0xf) << 12)              | \
28
             (((_r) & 0xf) << 8)               | \
29
             (((_g) & 0xf) << 4)               | \
30
             ((_b) & 0xf))
31
32
#define GX_SOURCE_CODE
33
34
35
/* Include necessary system files.  */
36
37
#include "gx_api.h"
38
#include "gx_display.h"
39
#include "gx_context.h"
40
#include "gx_utility.h"
41
#include "gx_system.h"
42
43
/**************************************************************************/
44
/*                                                                        */
45
/*  FUNCTION                                               RELEASE        */
46
/*                                                                        */
47
/*    _gx_utility_4444argb_pixelmap_rotate                PORTABLE C      */
48
/*                                                           6.1          */
49
/*  AUTHOR                                                                */
50
/*                                                                        */
51
/*    Kenneth Maxwell, Microsoft Corporation                              */
52
/*                                                                        */
53
/*  DESCRIPTION                                                           */
54
/*                                                                        */
55
/*    Internal helper funciton that rotate an 4444argb format uncompressed*/
56
/*    pixelmap.                                                           */
57
/*                                                                        */
58
/*  INPUT                                                                 */
59
/*                                                                        */
60
/*    src                                   The pixelmap to be rotated    */
61
/*    angle                                 The angle to be rotated       */
62
/*    destination                           The rotated bitmap to be      */
63
/*                                            returned                    */
64
/*    rot_cx                                X coordinate of rotation      */
65
/*                                            center                      */
66
/*    rot_cy                                Y coordinate of rotation      */
67
/*                                            center                      */
68
/*                                                                        */
69
/*  OUTPUT                                                                */
70
/*                                                                        */
71
/*    status                                Completion status             */
72
/*                                                                        */
73
/*  CALLS                                                                 */
74
/*                                                                        */
75
/*    _gx_system_memory_allocator           Application defined memory    */
76
/*                                            allocation function         */
77
/*    _gx_utility_math_cos                  Calculate cosine of supplied  */
78
/*                                            angle                       */
79
/*    _gx_utility_math_sin                  Calculate sine of supplied    */
80
/*                                            angle                       */
81
/*                                                                        */
82
/*  CALLED BY                                                             */
83
/*                                                                        */
84
/*    GUIX Internal Code                                                  */
85
/*                                                                        */
86
/*  RELEASE HISTORY                                                       */
87
/*                                                                        */
88
/*    DATE              NAME                      DESCRIPTION             */
89
/*                                                                        */
90
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
91
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
92
/*                                            resulting in version 6.1    */
93
/*                                                                        */
94
/**************************************************************************/
95
730
UINT _gx_utility_4444argb_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
96
{
97
USHORT *get;
98
USHORT *put;
99
INT     srcxres;
100
INT     srcyres;
101
INT     cosv;
102
INT     sinv;
103
USHORT  red, green, blue;
104
INT     idxminx, idxmaxx, idxmaxy;
105
INT    *mx;
106
INT    *my;
107
INT     xres;
108
INT     yres;
109
INT     width, height;
110
INT     x, y;
111
INT     xx, yy;
112
USHORT  a, b, c, d;
113
USHORT  alpha[4];
114
INT     xdiff, ydiff;
115
116
730
    mx = _gx_system_scratchpad;
117
730
    my = mx + 4;
118
119
730
    mx[0] = mx[3] = -1;
120
730
    mx[1] = mx[2] = 1;
121
122
730
    my[0] = my[1] = 1;
123
730
    my[2] = my[3] = -1;
124
125
730
    idxminx = (angle / 90) & 0x3;
126
730
    idxmaxx = (idxminx + 2) & 0x3;
127
730
    idxmaxy = (idxminx + 1) & 0x3;
128
129
    /* Calculate the source x and y center. */
130
730
    srcxres = src -> gx_pixelmap_width >> 1;
131
730
    srcyres = src -> gx_pixelmap_height >> 1;
132
133
730
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
134
730
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
135
136
730
    xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
137
730
    yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
138
139
730
    xres = GX_FIXED_VAL_TO_INT(xres);
140
730
    yres = GX_FIXED_VAL_TO_INT(yres);
141
142
    /* Calculate destination width and height. */
143
730
    width = (xres << 1);
144
730
    height = (yres << 1);
145
146
    /* Calculate the new rotation axis. */
147

730
    if (rot_cx && rot_cy)
148
    {
149
722
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
150
722
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
151
152
722
        srcxres = *rot_cx;
153
722
        srcyres = *rot_cy;
154
155
722
        x = GX_FIXED_VAL_TO_INT(x) + xres;
156
722
        y = GX_FIXED_VAL_TO_INT(y) + yres;
157
158
722
        *rot_cx = x;
159
722
        *rot_cy = y;
160
161
722
        xres = *rot_cx;
162
722
        yres = *rot_cy;
163
    }
164
165
730
    destination -> gx_pixelmap_height = (GX_VALUE)height;
166
730
    destination -> gx_pixelmap_width = (GX_VALUE)width;
167
730
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
168
169
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
170
       overflow cannot occur. */
171
730
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
172
730
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
173
174
730
    if (destination -> gx_pixelmap_data == GX_NULL)
175
    {
176
4
        return GX_SYSTEM_MEMORY_ERROR;
177
    }
178
179
726
    put = (USHORT *)destination -> gx_pixelmap_data;
180
181
    /* Loop through the destination's pixels.  */
182
194158
    for (y = 0; y < height; y++)
183
    {
184
52327208
        for (x = 0; x < width; x++)
185
        {
186
52133776
            xx = (x - xres) * cosv + (y - yres) * sinv;
187
52133776
            yy = (y - yres) * cosv - (x - xres) * sinv;
188
189
52133776
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
190
52133776
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
191
192
52133776
            xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
193
52133776
            yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
194
195

52133776
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
196
35977743
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
197
            {
198
199

30162754
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
200
29720272
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
201
                {
202
29562744
                    get = (USHORT *)src -> gx_pixelmap_data;
203
29562744
                    get += yy * src -> gx_pixelmap_width;
204
29562744
                    get += xx;
205
206
29562744
                    a = *get;
207
29562744
                    b = *(get + 1);
208
29562744
                    c = *(get + src -> gx_pixelmap_width);
209
29562744
                    d = *(get + src -> gx_pixelmap_width + 1);
210
29562744
                    alpha[0] = ALPHAVAL(a);
211
29562744
                    alpha[1] = ALPHAVAL(b);
212
29562744
                    alpha[2] = ALPHAVAL(c);
213
29562744
                    alpha[3] = ALPHAVAL(d);
214
                }
215
                else
216
                {
217
600010
                    get = (USHORT *)src -> gx_pixelmap_data;
218
219
600010
                    a = 0;
220
600010
                    b = 0;
221
600010
                    c = 0;
222
600010
                    d = 0;
223
224
600010
                    if (xx == -1)
225
                    {
226
                        /* handle left edge.  */
227
143042
                        if (yy >= 0)
228
                        {
229
142432
                            b = *(get + yy * src -> gx_pixelmap_width);
230
142432
                            alpha[1] = ALPHAVAL(b);
231
                        }
232
233
143042
                        if (yy < src -> gx_pixelmap_height - 1)
234
                        {
235
142402
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
236
142402
                            alpha[3] = ALPHAVAL(d);
237
                        }
238
                    }
239
456968
                    else if (yy == -1)
240
                    {
241
                        /* handle top edge.  */
242
157300
                        c = *(get + xx);
243
157300
                        alpha[2] = ALPHAVAL(c);
244
245
157300
                        if (xx < src -> gx_pixelmap_width - 1)
246
                        {
247
156644
                            d = *(get + xx + 1);
248
156644
                            alpha[3] = ALPHAVAL(d);
249
                        }
250
                    }
251
299668
                    else if (xx == src -> gx_pixelmap_width - 1)
252
                    {
253
                        /* handle right edget. */
254
142140
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
255
142140
                        alpha[0] = ALPHAVAL(a);
256
257
142140
                        if (yy < src -> gx_pixelmap_height - 1)
258
                        {
259
141468
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
260
141468
                            alpha[2] = ALPHAVAL(c);
261
                        }
262
                    }
263
                    else
264
                    {
265
                        /* handle bottom edge. */
266
157528
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
267
157528
                        alpha[0] = ALPHAVAL(a);
268
269
157528
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
270
157528
                        alpha[1] = ALPHAVAL(b);
271
                    }
272
273
600010
                    if (!a)
274
                    {
275
300342
                        alpha[0] = 0;
276
                    }
277
278
600010
                    if (!b)
279
                    {
280
300050
                        alpha[1] = 0;
281
                    }
282
283
600010
                    if (!c)
284
                    {
285
301242
                        alpha[2] = 0;
286
                    }
287
288
600010
                    if (!d)
289
                    {
290
300964
                        alpha[3] = 0;
291
                    }
292
                }
293
294
30162754
                red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
295
30162754
                                REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
296
30162754
                                REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
297
30162754
                                REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
298
299
30162754
                green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
300
30162754
                                  GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
301
30162754
                                  GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
302
30162754
                                  GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
303
304
30162754
                blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
305
30162754
                                 BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
306
30162754
                                 BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
307
30162754
                                 BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
308
309
30162754
                alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) + \
310
30162754
                                     alpha[1] * xdiff * (256 - ydiff) +         \
311
30162754
                                     alpha[2] * ydiff * (256 - xdiff) +         \
312
30162754
                                     alpha[3] * xdiff * ydiff) >> 16);
313
314
30162754
                if (alpha[0])
315
                {
316
24551120
                    red /= alpha[0];
317
24551120
                    green /= alpha[0];
318
24551120
                    blue /= alpha[0];
319
                }
320
30162754
                red = red > 15 ? 15 : red;
321
30162754
                green = green > 15 ? 15 : green;
322
30162754
                blue = blue > 15 ? 15 : blue;
323
30162754
                alpha[0] = alpha[0] > 15 ? 15 : alpha[0];
324
325
30162754
                *put++ = ASSEMBLECOLOR(alpha[0], red, green, blue);
326
            }
327
            else
328
            {
329
21971022
                *put++ = 0;
330
            }
331
        }
332
    }
333
726
    return GX_SUCCESS;
334
}
335
336
/**************************************************************************/
337
/*                                                                        */
338
/*  FUNCTION                                               RELEASE        */
339
/*                                                                        */
340
/*    _gx_utility_4444argb_pixelmap_simple_rotate           PORTABLE C    */
341
/*                                                           6.1          */
342
/*  AUTHOR                                                                */
343
/*                                                                        */
344
/*    Kenneth Maxwell, Microsoft Corporation                              */
345
/*                                                                        */
346
/*  DESCRIPTION                                                           */
347
/*                                                                        */
348
/*    4444argb pixelmap rotation function that handles 90, 180 and 270    */
349
/*    degree case.                                                        */
350
/*                                                                        */
351
/*  INPUT                                                                 */
352
/*                                                                        */
353
/*    src                                   The pixelmap to be rotated    */
354
/*    angle                                 The angle to be rotated       */
355
/*    destination                           The rotated bitmap to be      */
356
/*                                            returned                    */
357
/*    rot_cx                                X coordinate of rotation      */
358
/*                                            center                      */
359
/*    rot_cy                                Y coordinate of rotation      */
360
/*                                            center                      */
361
/*                                                                        */
362
/*  OUTPUT                                                                */
363
/*                                                                        */
364
/*    status                                Completion status             */
365
/*                                                                        */
366
/*  CALLS                                                                 */
367
/*                                                                        */
368
/*    _gx_system_memory_allocator           Application defined memory    */
369
/*                                            allocation function         */
370
/*                                                                        */
371
/*  CALLED BY                                                             */
372
/*                                                                        */
373
/*    GUIX Internal Code                                                  */
374
/*                                                                        */
375
/*  RELEASE HISTORY                                                       */
376
/*                                                                        */
377
/*    DATE              NAME                      DESCRIPTION             */
378
/*                                                                        */
379
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
380
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
381
/*                                            resulting in version 6.1    */
382
/*                                                                        */
383
/**************************************************************************/
384
30
UINT _gx_utility_4444argb_pixelmap_simple_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
385
{
386
USHORT *put;
387
USHORT *get;
388
INT     width;
389
INT     height;
390
INT     x;
391
INT     y;
392
393
30
    width = src -> gx_pixelmap_height;
394
30
    height = src -> gx_pixelmap_width;
395
396
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
397
       overflow cannot occur. */
398
30
    destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(USHORT);
399
30
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
400
401
30
    if (destination -> gx_pixelmap_data == GX_NULL)
402
    {
403
12
        return GX_SYSTEM_MEMORY_ERROR;
404
    }
405
406
18
    if (angle == 90)
407
    {
408
6
        put = (USHORT *)destination -> gx_pixelmap_data;
409
410
1311
        for (y = 0; y < height; y++)
411
        {
412
248220
            for (x = 0; x < width; x++)
413
            {
414
246915
                get = (USHORT *)src -> gx_pixelmap_data;
415
246915
                get += (width - 1 - x) * height;
416
246915
                get += y;
417
418
246915
                *put++ = *get;
419
            }
420
        }
421
422

6
        if (rot_cx && rot_cy)
423
        {
424
2
            x = *rot_cx;
425
2
            y = *rot_cy;
426
427
            /* Get new rotation point. */
428
2
            *rot_cx = (width - 1 - y);
429
2
            *rot_cy = x;
430
        }
431
    }
432
12
    else if (angle == 180)
433
    {
434
6
        GX_SWAP_VALS(width, height);
435
6
        put = (USHORT *)destination -> gx_pixelmap_data;
436
1185
        for (y = 0; y < height; y++)
437
        {
438
248094
            for (x = 0; x < width; x++)
439
            {
440
246915
                get = (USHORT *)src -> gx_pixelmap_data;
441
246915
                get += (height - 1 - y) * width;
442
246915
                get += width - 1 - x;
443
444
246915
                *put++ = *get;
445
            }
446
        }
447
448

6
        if (rot_cx && rot_cy)
449
        {
450
2
            x = *rot_cx;
451
2
            y = *rot_cy;
452
453
            /* Get new rotation point. */
454
2
            *rot_cx = (width - 1 - x);
455
2
            *rot_cy = (height - 1 - y);
456
        }
457
    }
458
    else
459
    {
460
        /* angle  = 270. */
461
6
        put = (USHORT *)destination -> gx_pixelmap_data;
462
463
1311
        for (y = 0; y < height; y++)
464
        {
465
248220
            for (x = 0; x < width; x++)
466
            {
467
246915
                get = (USHORT *)src -> gx_pixelmap_data;
468
246915
                get += x * height;
469
246915
                get += height - 1 - y;
470
471
246915
                *put++ = *get;
472
            }
473
        }
474
475

6
        if (rot_cx && rot_cy)
476
        {
477
2
            x = *rot_cx;
478
2
            y = *rot_cy;
479
480
            /* Get new rotation point. */
481
2
            *rot_cx = y;
482
2
            *rot_cy = (height - 1 - x);
483
        }
484
    }
485
486
18
    destination -> gx_pixelmap_height = (GX_VALUE)height;
487
18
    destination -> gx_pixelmap_width = (GX_VALUE)width;
488
489
18
    return GX_SUCCESS;
490
}
491