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

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

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

25
        if (rot_cx && rot_cy)
285
        {
286
19
            x = *rot_cx;
287
19
            y = *rot_cy;
288
289
19
            *rot_cx = (width - 1 - y);
290
19
            *rot_cy = x;
291
        }
292
    }
293
32
    else if (angle == 180)
294
    {
295
16
        GX_SWAP_VALS(width, height);
296
297
16
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
298
299
2704
        for (y = 0; y < height; y++)
300
        {
301
536483
            for (x = 0; x < width; x++)
302
            {
303
533795
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
304
533795
                get += (height - 1 - y) * width;
305
533795
                get += width - 1 - x;
306
307
533795
                *put++ = *get;
308
            }
309
        }
310
311

16
        if (rot_cx && rot_cy)
312
        {
313
10
            x = *rot_cx;
314
10
            y = *rot_cy;
315
316
10
            *rot_cx = (width - 1 - x);
317
10
            *rot_cy = (height - 1 - y);
318
        }
319
    }
320
    else
321
    {
322
        /* angle = 270. */
323
16
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
324
325
3069
        for (y = 0; y < height; y++)
326
        {
327
536848
            for (x = 0; x < width; x++)
328
            {
329
533795
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
330
533795
                get += x * height;
331
533795
                get += height - 1 - y;
332
333
533795
                *put++ = *get;
334
            }
335
        }
336
337

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

1445
    if (rot_cx && rot_cy)
462
    {
463
1437
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
464
1437
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
465
466
1437
        srcxres = *rot_cx;
467
1437
        srcyres = *rot_cy;
468
469
1437
        x = GX_FIXED_VAL_TO_INT(x) + xres;
470
1437
        y = GX_FIXED_VAL_TO_INT(y) + yres;
471
472
1437
        *rot_cx = x;
473
1437
        *rot_cy = y;
474
475
1437
        xres = *rot_cx;
476
1437
        yres = *rot_cy;
477
    }
478
479
1445
    destination -> gx_pixelmap_height = (GX_VALUE)height;
480
1445
    destination -> gx_pixelmap_width = (GX_VALUE)width;
481
1445
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
482
1445
    destination -> gx_pixelmap_transparent_color = 0;
483
1445
    destination -> gx_pixelmap_format = GX_COLOR_FORMAT_8BIT_ALPHAMAP;
484
485
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
486
       overflow cannot occur. */
487
1445
    destination -> gx_pixelmap_data_size = (UINT)(height * width);
488
1445
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
489
490
1445
    if (destination -> gx_pixelmap_data == GX_NULL)
491
    {
492
5
        return GX_SYSTEM_MEMORY_ERROR;
493
    }
494
495
1440
    put = (GX_UBYTE *)destination -> gx_pixelmap_data;
496
497
    /* Loop through the source's pixels.  */
498
161416
    for (y = 0; y < height; y++)
499
    {
500
19780352
        for (x = 0; x < width; x++)
501
        {
502
19620376
            xx = (x - xres) * cosv + (y - yres) * sinv;
503
19620376
            yy = (y - yres) * cosv - (x - xres) * sinv;
504
505
19620376
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
506
19620376
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
507
508
19620376
            xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
509
19620376
            yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
510
511

19620376
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
512
13004517
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
513
            {
514

6897134
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) && \
515
6613503
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
516
                {
517
6407316
                    get = src -> gx_pixelmap_data;
518
6407316
                    get += yy * src -> gx_pixelmap_width;
519
6407316
                    get += xx;
520
521
6407316
                    a = *get;
522
6407316
                    b = *(get + 1);
523
6407316
                    c = *(get + src -> gx_pixelmap_width);
524
6407316
                    d = *(get + src -> gx_pixelmap_width + 1);
525
                }
526
                else
527
                {
528
489818
                    get = src -> gx_pixelmap_data;
529
530
489818
                    a = 0;
531
489818
                    b = a;
532
489818
                    c = a;
533
489818
                    d = a;
534
535
489818
                    if (xx == -1)
536
                    {
537
                        /* handle left edge.  */
538
39607
                        if (yy >= 0)
539
                        {
540
38167
                            b = *(get + yy * src -> gx_pixelmap_width);
541
                        }
542
543
39607
                        if (yy < src -> gx_pixelmap_height - 1)
544
                        {
545
38091
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
546
                        }
547
                    }
548
450211
                    else if (yy == -1)
549
                    {
550
                        /* handle top edge.  */
551
205765
                        c = *(get + xx);
552
553
205765
                        if (xx < src -> gx_pixelmap_width - 1)
554
                        {
555
204400
                            d = *(get + xx + 1);
556
                        }
557
                    }
558
244446
                    else if (xx == src -> gx_pixelmap_width - 1)
559
                    {
560
                        /* handle right edget. */
561
38259
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
562
563
38259
                        if (yy < src -> gx_pixelmap_height - 1)
564
                        {
565
36823
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
566
                        }
567
                    }
568
                    else
569
                    {
570
                        /* handle bottom edge. */
571
206187
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
572
206187
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
573
                    }
574
                }
575
576
6897134
                alpha = (INT)((a * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
577
6897134
                               b * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
578
6897134
                               c * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
579
6897134
                               d * (ULONG)xdiff * (ULONG)ydiff) >> 16);
580
581
6897134
                *put++ = (GX_UBYTE)alpha;
582
            }
583
            else
584
            {
585
12723242
                *put++ = 0;
586
            }
587
        }
588
    }
589
590
1440
    return GX_SUCCESS;
591
}
592