GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_utility_4444argb_pixelmap_rotate.c Lines: 174 174 100.0 %
Date: 2026-03-06 19:21:09 Branches: 80 80 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Utility (Utility)                                                   */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define ALPHAVAL(_c) (GX_UBYTE)(((_c) >> 12) & 0xf)
23
#define REDVAL(_c)   (GX_UBYTE)(((_c) >> 8) & 0xf)
24
#define GREENVAL(_c) (GX_UBYTE)(((_c) >> 4) & 0xf)
25
#define BLUEVAL(_c)  (GX_UBYTE)(((_c)) & 0xf)
26
27
#define ASSEMBLECOLOR(_a, _r, _g, _b)            \
28
    (USHORT)((((_a) & 0xf) << 12)              | \
29
             (((_r) & 0xf) << 8)               | \
30
             (((_g) & 0xf) << 4)               | \
31
             ((_b) & 0xf))
32
33
#define GX_SOURCE_CODE
34
35
36
/* Include necessary system files.  */
37
38
#include "gx_api.h"
39
#include "gx_display.h"
40
#include "gx_context.h"
41
#include "gx_utility.h"
42
#include "gx_system.h"
43
44
/**************************************************************************/
45
/*                                                                        */
46
/*  FUNCTION                                               RELEASE        */
47
/*                                                                        */
48
/*    _gx_utility_4444argb_pixelmap_rotate                PORTABLE C      */
49
/*                                                           6.1          */
50
/*  AUTHOR                                                                */
51
/*                                                                        */
52
/*    Kenneth Maxwell, Microsoft Corporation                              */
53
/*                                                                        */
54
/*  DESCRIPTION                                                           */
55
/*                                                                        */
56
/*    Internal helper funciton that rotate an 4444argb format uncompressed*/
57
/*    pixelmap.                                                           */
58
/*                                                                        */
59
/*  INPUT                                                                 */
60
/*                                                                        */
61
/*    src                                   The pixelmap to be rotated    */
62
/*    angle                                 The angle to be rotated       */
63
/*    destination                           The rotated bitmap to be      */
64
/*                                            returned                    */
65
/*    rot_cx                                X coordinate of rotation      */
66
/*                                            center                      */
67
/*    rot_cy                                Y coordinate of rotation      */
68
/*                                            center                      */
69
/*                                                                        */
70
/*  OUTPUT                                                                */
71
/*                                                                        */
72
/*    status                                Completion status             */
73
/*                                                                        */
74
/*  CALLS                                                                 */
75
/*                                                                        */
76
/*    _gx_system_memory_allocator           Application defined memory    */
77
/*                                            allocation function         */
78
/*    _gx_utility_math_cos                  Calculate cosine of supplied  */
79
/*                                            angle                       */
80
/*    _gx_utility_math_sin                  Calculate sine of supplied    */
81
/*                                            angle                       */
82
/*                                                                        */
83
/*  CALLED BY                                                             */
84
/*                                                                        */
85
/*    GUIX Internal Code                                                  */
86
/*                                                                        */
87
/**************************************************************************/
88
730
UINT _gx_utility_4444argb_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
89
{
90
USHORT *get;
91
USHORT *put;
92
INT     srcxres;
93
INT     srcyres;
94
INT     cosv;
95
INT     sinv;
96
USHORT  red, green, blue;
97
INT     idxminx, idxmaxx, idxmaxy;
98
INT    *mx;
99
INT    *my;
100
INT     xres;
101
INT     yres;
102
INT     width, height;
103
INT     x, y;
104
INT     xx, yy;
105
USHORT  a, b, c, d;
106
USHORT  alpha[4];
107
INT     xdiff, ydiff;
108
109
730
    mx = _gx_system_scratchpad;
110
730
    my = mx + 4;
111
112
730
    mx[0] = mx[3] = -1;
113
730
    mx[1] = mx[2] = 1;
114
115
730
    my[0] = my[1] = 1;
116
730
    my[2] = my[3] = -1;
117
118
730
    idxminx = (angle / 90) & 0x3;
119
730
    idxmaxx = (idxminx + 2) & 0x3;
120
730
    idxmaxy = (idxminx + 1) & 0x3;
121
122
    /* Calculate the source x and y center. */
123
730
    srcxres = src -> gx_pixelmap_width >> 1;
124
730
    srcyres = src -> gx_pixelmap_height >> 1;
125
126
730
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
127
730
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
128
129
730
    xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
130
730
    yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
131
132
730
    xres = GX_FIXED_VAL_TO_INT(xres);
133
730
    yres = GX_FIXED_VAL_TO_INT(yres);
134
135
    /* Calculate destination width and height. */
136
730
    width = (xres << 1);
137
730
    height = (yres << 1);
138
139
    /* Calculate the new rotation axis. */
140

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

52133776
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
189
35977743
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
190
            {
191
192

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

6
        if (rot_cx && rot_cy)
408
        {
409
2
            x = *rot_cx;
410
2
            y = *rot_cy;
411
412
            /* Get new rotation point. */
413
2
            *rot_cx = (width - 1 - y);
414
2
            *rot_cy = x;
415
        }
416
    }
417
12
    else if (angle == 180)
418
    {
419
6
        GX_SWAP_VALS(width, height);
420
6
        put = (USHORT *)destination -> gx_pixelmap_data;
421
1185
        for (y = 0; y < height; y++)
422
        {
423
248094
            for (x = 0; x < width; x++)
424
            {
425
246915
                get = (USHORT *)src -> gx_pixelmap_data;
426
246915
                get += (height - 1 - y) * width;
427
246915
                get += width - 1 - x;
428
429
246915
                *put++ = *get;
430
            }
431
        }
432
433

6
        if (rot_cx && rot_cy)
434
        {
435
2
            x = *rot_cx;
436
2
            y = *rot_cy;
437
438
            /* Get new rotation point. */
439
2
            *rot_cx = (width - 1 - x);
440
2
            *rot_cy = (height - 1 - y);
441
        }
442
    }
443
    else
444
    {
445
        /* angle  = 270. */
446
6
        put = (USHORT *)destination -> gx_pixelmap_data;
447
448
1311
        for (y = 0; y < height; y++)
449
        {
450
248220
            for (x = 0; x < width; x++)
451
            {
452
246915
                get = (USHORT *)src -> gx_pixelmap_data;
453
246915
                get += x * height;
454
246915
                get += height - 1 - y;
455
456
246915
                *put++ = *get;
457
            }
458
        }
459
460

6
        if (rot_cx && rot_cy)
461
        {
462
2
            x = *rot_cx;
463
2
            y = *rot_cy;
464
465
            /* Get new rotation point. */
466
2
            *rot_cx = y;
467
2
            *rot_cy = (height - 1 - x);
468
        }
469
    }
470
471
18
    destination -> gx_pixelmap_height = (GX_VALUE)height;
472
18
    destination -> gx_pixelmap_width = (GX_VALUE)width;
473
474
18
    return GX_SUCCESS;
475
}
476