GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_utility_8bpp_pixelmap_rotate.c Lines: 189 189 100.0 %
Date: 2026-03-06 19:21:09 Branches: 90 90 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 GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_display.h"
29
#include "gx_context.h"
30
#include "gx_utility.h"
31
#include "gx_system.h"
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_utility_8bpp_pixelmap_rotate                    PORTABLE C      */
38
/*                                                           6.1          */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function rotates an 8bpp format uncompressed pixelmap with or  */
46
/*    without alpha channel.                                              */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    src                                   The pixelmap to be rotated    */
51
/*    angle                                 The angle to be rotated       */
52
/*    destination                           The rotated bitmap to be      */
53
/*                                            returned                    */
54
/*    rot_cx                                X coordinate of rotation      */
55
/*                                            center                      */
56
/*    rot_cy                                Y coordinate of rotation      */
57
/*                                            center                      */
58
/*                                                                        */
59
/*  OUTPUT                                                                */
60
/*                                                                        */
61
/*    Completion Status                                                   */
62
/*                                                                        */
63
/*  CALLS                                                                 */
64
/*                                                                        */
65
/*    _gx_system_memory_allocator           Memory Allocation routine     */
66
/*    _gx_utility_math_cos                  Compute the cosine value      */
67
/*    _gx_utility_math_sin                  Compute the sine value        */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    GUIX Internal Code                                                  */
72
/*                                                                        */
73
/**************************************************************************/
74
2144
UINT _gx_utility_8bpp_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
75
{
76
GX_UBYTE *putrow;
77
GX_UBYTE *put;
78
GX_UBYTE *get;
79
INT       srcxres;
80
INT       srcyres;
81
INT       cosv;
82
INT       sinv;
83
INT       idxminx, idxmaxx, idxmaxy;
84
2144
INT       mx[] = {-1, 1, 1, -1};
85
2144
INT       my[] = {1, 1, -1, -1};
86
INT       xres;
87
INT       yres;
88
INT       width, height;
89
INT       x, y;
90
INT       xx, yy;
91
92
    /* Set transparent color.  */
93
2144
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_TRANSPARENT)
94
    {
95
1072
        destination -> gx_pixelmap_transparent_color = src -> gx_pixelmap_transparent_color;
96
    }
97
    else
98
    {
99
1072
        destination -> gx_pixelmap_transparent_color = 0xff;
100
    }
101
102
2144
    idxminx = (angle / 90) & 0x3;
103
2144
    idxmaxx = (idxminx + 2) & 0x3;
104
2144
    idxmaxy = (idxminx + 1) & 0x3;
105
106
    /* Calculate the source x and y center. */
107
2144
    srcxres = src -> gx_pixelmap_width >> 1;
108
2144
    srcyres = src -> gx_pixelmap_height >> 1;
109
110
2144
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
111
2144
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
112
113
2144
    xres = GX_FIXED_VAL_TO_INT((mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv));
114
2144
    yres = GX_FIXED_VAL_TO_INT((my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv));
115
116
    /* Calculate destination width and height. */
117
2144
    width = (xres << 1);
118
2144
    height = (yres << 1);
119
120

2144
    if (rot_cx && rot_cy)
121
    {
122
        /* Calculate the new rotation axis. */
123
2136
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
124
2136
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
125
126
2136
        x = GX_FIXED_VAL_TO_INT(x) + xres;
127
2136
        y = GX_FIXED_VAL_TO_INT(y) + yres;
128
129
2136
        srcxres = *rot_cx;
130
2136
        srcyres = *rot_cy;
131
132
2136
        *rot_cx = x;
133
2136
        *rot_cy = y;
134
135
2136
        xres = *rot_cx;
136
2136
        yres = *rot_cy;
137
    }
138
139
    /* Set width and height of destination pixelmap.  */
140
2144
    destination -> gx_pixelmap_width = (GX_VALUE)width;
141
2144
    destination -> gx_pixelmap_height = (GX_VALUE)height;
142
2144
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
143
144
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
145
       overflow cannot occur. */
146
2144
    destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
147
148
    /* Allocate memory for destination pixelmap to load pixel information.  */
149
2144
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
150
151
2144
    if (destination -> gx_pixelmap_data == GX_NULL)
152
    {
153
4
        return GX_SYSTEM_MEMORY_ERROR;
154
    }
155
156
2140
    putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
157
158
    /* For every pixel in destination bitmap, find its position in source bitmap,
159
       and set the pixel with the value in source bitmap.  */
160
573512
    for (y = 0; y < height; y++)
161
    {
162
571372
        put = putrow;
163
164
154754084
        for (x = 0; x < width; x++)
165
        {
166
154182712
            xx = (x - xres) * cosv + (y - yres) * sinv;
167
154182712
            yy = (y - yres) * cosv - (x - xres) * sinv;
168
169
154182712
            xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
170
154182712
            yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
171
172

154182712
            if ((xx >= 0) && (xx < src -> gx_pixelmap_width) &&
173
104459799
                (yy >= 0) && (yy < src -> gx_pixelmap_height))
174
            {
175
88447904
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
176
88447904
                get += yy * src -> gx_pixelmap_width;
177
88447904
                get += xx;
178
179
88447904
                *put++ = *get;
180
            }
181
            else
182
            {
183
65734808
                *put++ = (GX_UBYTE)destination -> gx_pixelmap_transparent_color;
184
            }
185
        }
186
571372
        putrow += destination -> gx_pixelmap_width;
187
    }
188
189
2140
    return GX_SUCCESS;
190
}
191
192
/**************************************************************************/
193
/*                                                                        */
194
/*  FUNCTION                                               RELEASE        */
195
/*                                                                        */
196
/*    _gx_utility_8bpp_pixelmap_simple_rotate             PORTABLE C      */
197
/*                                                           6.1          */
198
/*  AUTHOR                                                                */
199
/*                                                                        */
200
/*    Kenneth Maxwell, Microsoft Corporation                              */
201
/*                                                                        */
202
/*  DESCRIPTION                                                           */
203
/*                                                                        */
204
/*    This function rotates an 8bpp format uncompressed pixelmap with     */
205
/*    special rotation angle 90, 180 or 270 degree.                       */
206
/*                                                                        */
207
/*  INPUT                                                                 */
208
/*                                                                        */
209
/*    src                                   The pixelmap to be rotated    */
210
/*    angle                                 The angle to be rotated       */
211
/*    destination                           The rotated bitmap to be      */
212
/*                                            returned                    */
213
/*    rot_cx                                X coordinate of rotation      */
214
/*                                            center                      */
215
/*    rot_cy                                Y coordinate of rotation      */
216
/*                                            center                      */
217
/*                                                                        */
218
/*  OUTPUT                                                                */
219
/*                                                                        */
220
/*    Completion Status                                                   */
221
/*                                                                        */
222
/*  CALLS                                                                 */
223
/*                                                                        */
224
/*    _gx_system_memory_allocator           Memory Allocation routine     */
225
/*                                                                        */
226
/*  CALLED BY                                                             */
227
/*                                                                        */
228
/*    GUIX Internal Code                                                  */
229
/*                                                                        */
230
/**************************************************************************/
231
81
UINT _gx_utility_8bpp_pixelmap_simple_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
232
{
233
GX_UBYTE *put;
234
GX_UBYTE *get;
235
INT       width, height;
236
INT       x, y;
237
238
81
    destination -> gx_pixelmap_transparent_color = src -> gx_pixelmap_transparent_color;
239
240
81
    width = src -> gx_pixelmap_height;
241
81
    height = src -> gx_pixelmap_width;
242
243
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
244
       overflow cannot occur. */
245
81
    destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
246
81
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
247
248
81
    if (destination -> gx_pixelmap_data == GX_NULL)
249
    {
250
24
        return GX_SYSTEM_MEMORY_ERROR;
251
    }
252
253
57
    if (angle == 90)
254
    {
255
25
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
256
257
4419
        for (y = 0; y < height; y++)
258
        {
259
779569
            for (x = 0; x < width; x++)
260
            {
261
775175
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
262
775175
                get += (width - 1 - x) * height;
263
775175
                get += y;
264
265
775175
                *put++ = *get;
266
            }
267
        }
268
269

25
        if (rot_cx && rot_cy)
270
        {
271
19
            x = *rot_cx;
272
19
            y = *rot_cy;
273
274
19
            *rot_cx = (width - 1 - y);
275
19
            *rot_cy = x;
276
        }
277
    }
278
32
    else if (angle == 180)
279
    {
280
16
        GX_SWAP_VALS(width, height);
281
282
16
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
283
284
2704
        for (y = 0; y < height; y++)
285
        {
286
536483
            for (x = 0; x < width; x++)
287
            {
288
533795
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
289
533795
                get += (height - 1 - y) * width;
290
533795
                get += width - 1 - x;
291
292
533795
                *put++ = *get;
293
            }
294
        }
295
296

16
        if (rot_cx && rot_cy)
297
        {
298
10
            x = *rot_cx;
299
10
            y = *rot_cy;
300
301
10
            *rot_cx = (width - 1 - x);
302
10
            *rot_cy = (height - 1 - y);
303
        }
304
    }
305
    else
306
    {
307
        /* angle = 270. */
308
16
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
309
310
3069
        for (y = 0; y < height; y++)
311
        {
312
536848
            for (x = 0; x < width; x++)
313
            {
314
533795
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
315
533795
                get += x * height;
316
533795
                get += height - 1 - y;
317
318
533795
                *put++ = *get;
319
            }
320
        }
321
322

16
        if (rot_cx && rot_cy)
323
        {
324
10
            x = *rot_cx;
325
10
            y = *rot_cy;
326
327
10
            *rot_cx = y;
328
10
            *rot_cy = (height - 1 - x);
329
        }
330
    }
331
332
57
    destination -> gx_pixelmap_height = (GX_VALUE)height;
333
57
    destination -> gx_pixelmap_width  = (GX_VALUE)width;
334
335
57
    return GX_SUCCESS;
336
}
337
338
/**************************************************************************/
339
/*                                                                        */
340
/*  FUNCTION                                               RELEASE        */
341
/*                                                                        */
342
/*    _gx_utility_8bit_alphamap_rotate                    PORTABLE C      */
343
/*                                                           6.1          */
344
/*  AUTHOR                                                                */
345
/*                                                                        */
346
/*    Kenneth Maxwell, Microsoft Corporation                              */
347
/*                                                                        */
348
/*  DESCRIPTION                                                           */
349
/*                                                                        */
350
/*    This function rotates an 8bit alphamap.                             */
351
/*                                                                        */
352
/*  INPUT                                                                 */
353
/*                                                                        */
354
/*    src                                   The pixelmap to be rotated    */
355
/*    angle                                 The angle to be rotated       */
356
/*    destination                           The rotated bitmap to be      */
357
/*                                            returned                    */
358
/*    rot_cx                                X coordinate of rotation      */
359
/*                                            center                      */
360
/*    rot_cy                                Y coordinate of rotation      */
361
/*                                            center                      */
362
/*                                                                        */
363
/*  OUTPUT                                                                */
364
/*                                                                        */
365
/*    Completion Status                                                   */
366
/*                                                                        */
367
/*  CALLS                                                                 */
368
/*                                                                        */
369
/*    _gx_system_memory_allocator           Memory Allocation routine     */
370
/*    _gx_utility_math_cos                  Compute the cosine value      */
371
/*    _gx_utility_math_sin                  Compute the sine value        */
372
/*                                                                        */
373
/*  CALLED BY                                                             */
374
/*                                                                        */
375
/*    GUIX Internal Code                                                  */
376
/*                                                                        */
377
/**************************************************************************/
378
1445
UINT _gx_utility_8bit_alphamap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
379
{
380
GX_UBYTE          *put;
381
GX_CONST GX_UBYTE *get;
382
INT                srcxres;
383
INT                srcyres;
384
INT                cosv;
385
INT                sinv;
386
INT                alpha;
387
INT                idxminx;
388
INT                idxmaxx;
389
INT                idxmaxy;
390
INT               *mx;
391
INT               *my;
392
INT                xres;
393
INT                yres;
394
INT                width;
395
INT                height;
396
INT                x;
397
INT                y;
398
INT                xx;
399
INT                yy;
400
GX_UBYTE           a;
401
GX_UBYTE           b;
402
GX_UBYTE           c;
403
GX_UBYTE           d;
404
INT                xdiff;
405
INT                ydiff;
406
407
1445
    mx = _gx_system_scratchpad;
408
1445
    my = mx + 4;
409
410
1445
    mx[0] = mx[3] = -1;
411
1445
    mx[1] = mx[2] = 1;
412
413
1445
    my[0] = my[1] = 1;
414
1445
    my[2] = my[3] = -1;
415
416
1445
    idxminx = (angle / 90) & 0x3;
417
1445
    idxmaxx = (idxminx + 2) & 0x3;
418
1445
    idxmaxy = (idxminx + 1) & 0x3;
419
420
    /* Calculate the source x and y center. */
421
1445
    srcxres = src -> gx_pixelmap_width >> 1;
422
1445
    srcyres = src -> gx_pixelmap_height >> 1;
423
424
1445
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
425
1445
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
426
427
1445
    xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
428
1445
    yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
429
430
1445
    xres = GX_FIXED_VAL_TO_INT(xres);
431
1445
    yres = GX_FIXED_VAL_TO_INT(yres);
432
433
    /* Calculate destination width and height. */
434
1445
    width = (xres << 1);
435
1445
    height = (yres << 1);
436
437
    /* Calculate the new rotation axis. */
438

1445
    if (rot_cx && rot_cy)
439
    {
440
1437
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
441
1437
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
442
443
1437
        srcxres = *rot_cx;
444
1437
        srcyres = *rot_cy;
445
446
1437
        x = GX_FIXED_VAL_TO_INT(x) + xres;
447
1437
        y = GX_FIXED_VAL_TO_INT(y) + yres;
448
449
1437
        *rot_cx = x;
450
1437
        *rot_cy = y;
451
452
1437
        xres = *rot_cx;
453
1437
        yres = *rot_cy;
454
    }
455
456
1445
    destination -> gx_pixelmap_height = (GX_VALUE)height;
457
1445
    destination -> gx_pixelmap_width = (GX_VALUE)width;
458
1445
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
459
1445
    destination -> gx_pixelmap_transparent_color = 0;
460
1445
    destination -> gx_pixelmap_format = GX_COLOR_FORMAT_8BIT_ALPHAMAP;
461
462
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
463
       overflow cannot occur. */
464
1445
    destination -> gx_pixelmap_data_size = (UINT)(height * width);
465
1445
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
466
467
1445
    if (destination -> gx_pixelmap_data == GX_NULL)
468
    {
469
5
        return GX_SYSTEM_MEMORY_ERROR;
470
    }
471
472
1440
    put = (GX_UBYTE *)destination -> gx_pixelmap_data;
473
474
    /* Loop through the source's pixels.  */
475
161416
    for (y = 0; y < height; y++)
476
    {
477
19780352
        for (x = 0; x < width; x++)
478
        {
479
19620376
            xx = (x - xres) * cosv + (y - yres) * sinv;
480
19620376
            yy = (y - yres) * cosv - (x - xres) * sinv;
481
482
19620376
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
483
19620376
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
484
485
19620376
            xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
486
19620376
            yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
487
488

19620376
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
489
13004517
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
490
            {
491

6897134
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) && \
492
6613503
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
493
                {
494
6407316
                    get = src -> gx_pixelmap_data;
495
6407316
                    get += yy * src -> gx_pixelmap_width;
496
6407316
                    get += xx;
497
498
6407316
                    a = *get;
499
6407316
                    b = *(get + 1);
500
6407316
                    c = *(get + src -> gx_pixelmap_width);
501
6407316
                    d = *(get + src -> gx_pixelmap_width + 1);
502
                }
503
                else
504
                {
505
489818
                    get = src -> gx_pixelmap_data;
506
507
489818
                    a = 0;
508
489818
                    b = a;
509
489818
                    c = a;
510
489818
                    d = a;
511
512
489818
                    if (xx == -1)
513
                    {
514
                        /* handle left edge.  */
515
39607
                        if (yy >= 0)
516
                        {
517
38167
                            b = *(get + yy * src -> gx_pixelmap_width);
518
                        }
519
520
39607
                        if (yy < src -> gx_pixelmap_height - 1)
521
                        {
522
38091
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
523
                        }
524
                    }
525
450211
                    else if (yy == -1)
526
                    {
527
                        /* handle top edge.  */
528
205765
                        c = *(get + xx);
529
530
205765
                        if (xx < src -> gx_pixelmap_width - 1)
531
                        {
532
204400
                            d = *(get + xx + 1);
533
                        }
534
                    }
535
244446
                    else if (xx == src -> gx_pixelmap_width - 1)
536
                    {
537
                        /* handle right edget. */
538
38259
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
539
540
38259
                        if (yy < src -> gx_pixelmap_height - 1)
541
                        {
542
36823
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
543
                        }
544
                    }
545
                    else
546
                    {
547
                        /* handle bottom edge. */
548
206187
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
549
206187
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
550
                    }
551
                }
552
553
6897134
                alpha = (INT)((a * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
554
6897134
                               b * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
555
6897134
                               c * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
556
6897134
                               d * (ULONG)xdiff * (ULONG)ydiff) >> 16);
557
558
6897134
                *put++ = (GX_UBYTE)alpha;
559
            }
560
            else
561
            {
562
12723242
                *put++ = 0;
563
            }
564
        }
565
    }
566
567
1440
    return GX_SUCCESS;
568
}
569