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

362
    if (rot_cx && rot_cy)
142
    {
143
356
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
144
356
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
145
146
356
        srcxres = *rot_cx;
147
356
        srcyres = *rot_cy;
148
149
356
        x = GX_FIXED_VAL_TO_INT(x) + xres;
150
356
        y = GX_FIXED_VAL_TO_INT(y) + yres;
151
152
356
        *rot_cx = x;
153
356
        *rot_cy = y;
154
155
356
        xres = *rot_cx;
156
356
        yres = *rot_cy;
157
    }
158
159
362
    destination -> gx_pixelmap_height = (GX_VALUE)height;
160
362
    destination -> gx_pixelmap_width = (GX_VALUE)width;
161
362
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
162
163
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
164
       overflow cannot occur. */
165
362
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
166
362
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
167
168
362
    if (destination -> gx_pixelmap_data == GX_NULL)
169
    {
170
3
        return GX_SYSTEM_MEMORY_ERROR;
171
    }
172
173
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
174
       overflow cannot occur. */
175
359
    destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
176
359
    destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
177
178
359
    if (destination -> gx_pixelmap_aux_data == GX_NULL)
179
    {
180
1
        _gx_system_memory_free((VOID *)destination -> gx_pixelmap_aux_data);
181
182
1
        return GX_SYSTEM_MEMORY_ERROR;
183
    }
184
185
358
    put = (GX_UBYTE *)destination -> gx_pixelmap_data;
186
358
    putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
187
188
    /* Loop through the destination's pixels.  */
189
85218
    for (y = 0; y < height; y++)
190
    {
191
19993316
        for (x = 0; x < width; x++)
192
        {
193
19908456
            xx = (x - xres) * cosv + (y - yres) * sinv;
194
19908456
            yy = (y - yres) * cosv - (x - xres) * sinv;
195
196
19908456
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
197
19908456
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
198
199
19908456
            xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
200
19908456
            yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
201
202

19908456
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
203
14512884
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
204
            {
205

11004532
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
206
10827830
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
207
                {
208
10741590
                    get = (GX_UBYTE *)src -> gx_pixelmap_data;
209
10741590
                    get += yy * src -> gx_pixelmap_width;
210
10741590
                    get += xx;
211
212
10741590
                    a = *get;
213
10741590
                    b = *(get + 1);
214
10741590
                    c = *(get + src -> gx_pixelmap_width);
215
10741590
                    d = *(get + src -> gx_pixelmap_width + 1);
216
217
10741590
                    alpha = 0xff;
218
                }
219
                else
220
                {
221
262942
                    get = (GX_UBYTE *)src -> gx_pixelmap_data;
222
223
262942
                    a = 0;
224
262942
                    b = 0;
225
262942
                    c = 0;
226
262942
                    d = 0;
227
262942
                    alpha = 0;
228
229
262942
                    if (xx == -1)
230
                    {
231
                        /* handle left edge.  */
232
45698
                        if (yy >= 0)
233
                        {
234
45388
                            b = *(get + yy * src -> gx_pixelmap_width);
235
45388
                            alpha += xdiff * (256 - ydiff);
236
                        }
237
238
45698
                        if (yy < src -> gx_pixelmap_height - 1)
239
                        {
240
45354
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
241
45354
                            alpha += xdiff * ydiff;
242
                        }
243
                    }
244
217244
                    else if (yy == -1)
245
                    {
246
                        /* handle top edge.  */
247
85892
                        c = *(get + xx);
248
85892
                        alpha += ydiff * (256 - xdiff);
249
250
85892
                        if (xx < src -> gx_pixelmap_width - 1)
251
                        {
252
85534
                            d = *(get + xx + 1);
253
85534
                            alpha += xdiff * ydiff;
254
                        }
255
                    }
256
131352
                    else if (xx == src -> gx_pixelmap_width - 1)
257
                    {
258
                        /* handle right edget. */
259
45112
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
260
45112
                        alpha += (256 - xdiff) * (256 - ydiff);
261
262
45112
                        if (yy < src -> gx_pixelmap_height - 1)
263
                        {
264
44746
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
265
44746
                            alpha += ydiff * (256 - xdiff);
266
                        }
267
                    }
268
                    else
269
                    {
270
                        /* handle bottom edge. */
271
86240
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
272
86240
                        alpha += (256 - xdiff) * (256 - ydiff);
273
274
86240
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
275
86240
                        alpha += xdiff * (256 - ydiff);
276
                    }
277
278
262942
                    alpha >>= 8;
279
                }
280
281
11004532
                red = (USHORT)((REDVAL_332(a) * (256 - xdiff) * (256 - ydiff) + \
282
11004532
                                REDVAL_332(b) * xdiff * (256 - ydiff) +         \
283
11004532
                                REDVAL_332(c) * ydiff * (256 - xdiff) +         \
284
11004532
                                REDVAL_332(d) * xdiff * ydiff) >> 16);
285
286
11004532
                green = (USHORT)((GREENVAL_332(a) * (256 - xdiff) * (256 - ydiff) + \
287
11004532
                                  GREENVAL_332(b) * xdiff * (256 - ydiff) +         \
288
11004532
                                  GREENVAL_332(c) * ydiff * (256 - xdiff) +         \
289
11004532
                                  GREENVAL_332(d) * xdiff * ydiff) >> 16);
290
291
11004532
                blue = (USHORT)((BLUEVAL_332(a) * (256 - xdiff) * (256 - ydiff) + \
292
11004532
                                 BLUEVAL_332(b) * xdiff * (256 - ydiff) +         \
293
11004532
                                 BLUEVAL_332(c) * ydiff * (256 - xdiff) +         \
294
11004532
                                 BLUEVAL_332(d) * xdiff * ydiff) >> 16);
295
296

11004532
                if (alpha && (alpha < 0xff))
297
                {
298
260730
                    red = (USHORT)((red << 8) / alpha);
299
260730
                    green = (USHORT)((green << 8) / alpha);
300
260730
                    blue = (USHORT)((blue << 8) / alpha);
301
                }
302
303
11004532
                red = red > 7 ? 7 : red;
304
11004532
                green = green > 7 ? 7 : green;
305
11004532
                blue = blue > 3 ? 3 : blue;
306
11004532
                alpha = alpha > 255 ? 255 : alpha;
307
308
11004532
                *put++ = (GX_UBYTE)ASSEMBLECOLOR_332(red, green, blue);
309
11004532
                *putalpha++ = (GX_UBYTE)alpha;
310
            }
311
            else
312
            {
313
8903924
                put++;
314
8903924
                *putalpha++ = 0;
315
            }
316
        }
317
    }
318
319
358
    return GX_SUCCESS;
320
}
321
322
/**************************************************************************/
323
/*                                                                        */
324
/*  FUNCTION                                               RELEASE        */
325
/*                                                                        */
326
/*    _gx_utility_332rgb_pixelmap_alpha_rotate            PORTABLE C      */
327
/*                                                           6.1          */
328
/*  AUTHOR                                                                */
329
/*                                                                        */
330
/*    Kenneth Maxwell, Microsoft Corporation                              */
331
/*                                                                        */
332
/*  DESCRIPTION                                                           */
333
/*                                                                        */
334
/*    Internal helper function that rotate an uncompressed pixelmap       */
335
/*    with alpha.                                                         */
336
/*                                                                        */
337
/*  INPUT                                                                 */
338
/*                                                                        */
339
/*    src                                   The pixelmap to be rotated    */
340
/*    angle                                 The angle to be rotated       */
341
/*    destination                           The rotated bitmap to be      */
342
/*                                            returned                    */
343
/*    rot_cx                                X coordinate of rotation      */
344
/*                                            center                      */
345
/*    rot_cy                                Y coordinate of rotation      */
346
/*                                            center                      */
347
/*                                                                        */
348
/*  OUTPUT                                                                */
349
/*                                                                        */
350
/*    status                                Completion status             */
351
/*                                                                        */
352
/*  CALLS                                                                 */
353
/*                                                                        */
354
/*    _gx_system_memory_allocator           Memory Allocation routine     */
355
/*    _gx_utility_math_cos                  Compute the cosine value      */
356
/*    _gx_utility_math_sin                  Compute the sine value        */
357
/*                                                                        */
358
/*  CALLED BY                                                             */
359
/*                                                                        */
360
/*    _gx_utility_332rgb_pixelmap_rotate                                  */
361
/*                                                                        */
362
/*  RELEASE HISTORY                                                       */
363
/*                                                                        */
364
/*    DATE              NAME                      DESCRIPTION             */
365
/*                                                                        */
366
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
367
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
368
/*                                            resulting in version 6.1    */
369
/*                                                                        */
370
/**************************************************************************/
371
368
static UINT _gx_utility_332rgb_pixelmap_alpha_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
372
{
373
GX_UBYTE *put;
374
GX_UBYTE *get;
375
GX_UBYTE *putalpha;
376
GX_UBYTE *getalpha;
377
INT       srcxres;
378
INT       srcyres;
379
INT       cosv;
380
INT       sinv;
381
USHORT    red, green, blue;
382
INT       idxminx, idxmaxx, idxmaxy;
383
INT      *mx;
384
INT      *my;
385
INT       xres;
386
INT       yres;
387
INT       width, height;
388
INT       x, y;
389
INT       xx, yy;
390
USHORT    a, b, c, d;
391
USHORT    alpha[4];
392
INT       xdiff, ydiff;
393
394
368
    mx = _gx_system_scratchpad;
395
368
    my = mx + 4;
396
397
368
    mx[0] = mx[3] = -1;
398
368
    mx[1] = mx[2] = 1;
399
400
368
    my[0] = my[1] = 1;
401
368
    my[2] = my[3] = -1;
402
403
368
    idxminx = (angle / 90) & 0x3;
404
368
    idxmaxx = (idxminx + 2) & 0x3;
405
368
    idxmaxy = (idxminx + 1) & 0x3;
406
407
    /* Calculate the source x and y center. */
408
368
    srcxres = src -> gx_pixelmap_width >> 1;
409
368
    srcyres = src -> gx_pixelmap_height >> 1;
410
411
368
    cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
412
368
    sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
413
414
368
    xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
415
368
    yres = my[idxmaxy] * (srcyres + 2)  * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
416
417
368
    xres = GX_FIXED_VAL_TO_INT(xres);
418
368
    yres = GX_FIXED_VAL_TO_INT(yres);
419
420
    /* Calculate destination width and height. */
421
368
    width = (xres << 1);
422
368
    height = (yres << 1);
423
424
    /* Calculate the new rotation axis. */
425

368
    if (rot_cx && rot_cy)
426
    {
427
356
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
428
356
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
429
430
356
        srcxres = *rot_cx;
431
356
        srcyres = *rot_cy;
432
433
356
        x = GX_FIXED_VAL_TO_INT(x) + xres;
434
356
        y = GX_FIXED_VAL_TO_INT(y) + yres;
435
436
356
        *rot_cx = x;
437
356
        *rot_cy = y;
438
439
356
        xres = *rot_cx;
440
356
        yres = *rot_cy;
441
    }
442
443
368
    destination -> gx_pixelmap_height = (GX_VALUE)height;
444
368
    destination -> gx_pixelmap_width = (GX_VALUE)width;
445
368
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
446
447
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
448
       overflow cannot occur. */
449
368
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
450
368
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
451
452
368
    if (destination -> gx_pixelmap_data == GX_NULL)
453
    {
454
6
        return GX_SYSTEM_MEMORY_ERROR;
455
    }
456
457
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
458
       overflow cannot occur. */
459
362
    destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
460
362
    destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
461
462
362
    if (destination -> gx_pixelmap_aux_data == GX_NULL)
463
    {
464
2
        _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
465
466
2
        return GX_SYSTEM_MEMORY_ERROR;
467
    }
468
469
360
    put = (GX_UBYTE *)destination -> gx_pixelmap_data;
470
360
    putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
471
472
    /* Loop through the destination's pixels.  */
473
107156
    for (y = 0; y < height; y++)
474
    {
475
31916532
        for (x = 0; x < width; x++)
476
        {
477
31809736
            xx = (x - xres) * cosv + (y - yres) * sinv;
478
31809736
            yy = (y - yres) * cosv - (x - xres) * sinv;
479
480
31809736
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
481
31809736
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
482
483
31809736
            xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
484
31809736
            yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
485
486

31809736
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
487
21188595
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
488
            {
489
490

18939990
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
491
18678066
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
492
                {
493
18608210
                    get = (GX_UBYTE *)src -> gx_pixelmap_data;
494
18608210
                    get += yy * src -> gx_pixelmap_width;
495
18608210
                    get += xx;
496
497
18608210
                    getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
498
18608210
                    getalpha += yy * src -> gx_pixelmap_width;
499
18608210
                    getalpha += xx;
500
501
18608210
                    a = *get;
502
18608210
                    alpha[0] = *getalpha;
503
504
18608210
                    b = *(get + 1);
505
18608210
                    alpha[1] = *(getalpha + 1);
506
507
18608210
                    c = *(get + src -> gx_pixelmap_width);
508
18608210
                    alpha[2] = *(getalpha + src -> gx_pixelmap_width);
509
510
18608210
                    d = *(get + src -> gx_pixelmap_width + 1);
511
18608210
                    alpha[3] = *(getalpha + src -> gx_pixelmap_width + 1);
512
                }
513
                else
514
                {
515
331780
                    get = (GX_UBYTE *)src -> gx_pixelmap_data;
516
331780
                    getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
517
518
331780
                    a = 0;
519
331780
                    b = 0;
520
331780
                    c = 0;
521
331780
                    d = 0;
522
523
331780
                    if (xx == -1)
524
                    {
525
                        /* handle left edge.  */
526
96144
                        if (yy >= 0)
527
                        {
528
95852
                            b = *(get + yy * src -> gx_pixelmap_width);
529
95852
                            alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width);
530
                        }
531
532
96144
                        if (yy < src -> gx_pixelmap_height - 1)
533
                        {
534
95856
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
535
95856
                            alpha[3] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width);
536
                        }
537
                    }
538
235636
                    else if (yy == -1)
539
                    {
540
                        /* handle top edge.  */
541
69960
                        c = *(get + xx);
542
69960
                        alpha[2] = *(getalpha + xx);
543
544
69960
                        if (xx < src -> gx_pixelmap_width - 1)
545
                        {
546
69670
                            d = *(get + xx + 1);
547
69670
                            alpha[3] = *(getalpha + xx + 1);
548
                        }
549
                    }
550
165676
                    else if (xx == src -> gx_pixelmap_width - 1)
551
                    {
552
                        /* handle right edget. */
553
95820
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
554
95820
                        alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
555
556
95820
                        if (yy < src -> gx_pixelmap_height - 1)
557
                        {
558
95530
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
559
95530
                            alpha[2] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width + xx);
560
                        }
561
                    }
562
                    else
563
                    {
564
                        /* handle bottom edge. */
565
69856
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
566
69856
                        alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
567
568
69856
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
569
69856
                        alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width + xx + 1);
570
                    }
571
572
331780
                    if (!a)
573
                    {
574
166104
                        alpha[0] = 0;
575
                    }
576
577
331780
                    if (!b)
578
                    {
579
166072
                        alpha[1] = 0;
580
                    }
581
582
331780
                    if (!c)
583
                    {
584
166290
                        alpha[2] = 0;
585
                    }
586
587
331780
                    if (!d)
588
                    {
589
166254
                        alpha[3] = 0;
590
                    }
591
                }
592
593
18939990
                red = (USHORT)((REDVAL_332(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
594
18939990
                                REDVAL_332(b) * alpha[1] * xdiff * (256 - ydiff) +         \
595
18939990
                                REDVAL_332(c) * alpha[2] * ydiff * (256 - xdiff) +         \
596
18939990
                                REDVAL_332(d) * alpha[3] * xdiff * ydiff) >> 16);
597
598
18939990
                green = (USHORT)((GREENVAL_332(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
599
18939990
                                  GREENVAL_332(b) * alpha[1] * xdiff * (256 - ydiff) +         \
600
18939990
                                  GREENVAL_332(c) * alpha[2] * ydiff * (256 - xdiff) +         \
601
18939990
                                  GREENVAL_332(d) * alpha[3] * xdiff * ydiff) >> 16);
602
603
18939990
                blue = (USHORT)((BLUEVAL_332(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
604
18939990
                                 BLUEVAL_332(b) * alpha[1] * xdiff * (256 - ydiff) +         \
605
18939990
                                 BLUEVAL_332(c) * alpha[2] * ydiff * (256 - xdiff) +         \
606
18939990
                                 BLUEVAL_332(d) * alpha[3] * xdiff * ydiff) >> 16);
607
608
18939990
                alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) + \
609
18939990
                                     alpha[1] * xdiff * (256 - ydiff) +         \
610
18939990
                                     alpha[2] * ydiff * (256 - xdiff) +         \
611
18939990
                                     alpha[3] * xdiff * ydiff) >> 16);
612
613
18939990
                if (alpha[0])
614
                {
615
13446314
                    red /= alpha[0];
616
13446314
                    green /= alpha[0];
617
13446314
                    blue /= alpha[0];
618
                }
619
620
18939990
                red = red > 7 ? 7 : red;
621
18939990
                green = green > 7 ? 7 : green;
622
18939990
                blue = blue > 3 ? 3 : blue;
623
18939990
                alpha[0] = alpha[0] > 255 ? 255 : alpha[0];
624
625
18939990
                *put++ = (GX_UBYTE)ASSEMBLECOLOR_332(red, green, blue);
626
18939990
                *putalpha++ = (GX_UBYTE)alpha[0];
627
            }
628
            else
629
            {
630
12869746
                put++;
631
12869746
                *putalpha++ = 0;
632
            }
633
        }
634
    }
635
636
360
    return GX_SUCCESS;
637
}
638
639
640
/**************************************************************************/
641
/*                                                                        */
642
/*  FUNCTION                                               RELEASE        */
643
/*                                                                        */
644
/*    _gx_utility_332rgb_pixelmap_simple_raw_rotate       PORTABLE C      */
645
/*                                                           6.1          */
646
/*  AUTHOR                                                                */
647
/*                                                                        */
648
/*    Kenneth Maxwell, Microsoft Corporation                              */
649
/*                                                                        */
650
/*  DESCRIPTION                                                           */
651
/*                                                                        */
652
/*    Internal helper function that handles 90, 180 and 270 degree        */
653
/*    rotation of an uncompressed pixelmap wihout alpha.                  */
654
/*                                                                        */
655
/*  INPUT                                                                 */
656
/*                                                                        */
657
/*    src                                   The pixelmap to be rotated    */
658
/*    angle                                 The angle to be rotated       */
659
/*    destination                           The rotated bitmap to be      */
660
/*                                            returned                    */
661
/*    rot_cx                                X coordinate of rotation      */
662
/*                                            center                      */
663
/*    rot_cy                                Y coordinate of rotation      */
664
/*                                            center                      */
665
/*                                                                        */
666
/*  OUTPUT                                                                */
667
/*                                                                        */
668
/*    status                                Completion status             */
669
/*                                                                        */
670
/*  CALLS                                                                 */
671
/*                                                                        */
672
/*    _gx_system_memory_allocator           Memory Allocation routine     */
673
/*                                                                        */
674
/*  CALLED BY                                                             */
675
/*                                                                        */
676
/*    _gx_utility_332rgb_pixelmap_simple_rotate                           */
677
/*                                                                        */
678
/*  RELEASE HISTORY                                                       */
679
/*                                                                        */
680
/*    DATE              NAME                      DESCRIPTION             */
681
/*                                                                        */
682
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
683
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
684
/*                                            resulting in version 6.1    */
685
/*                                                                        */
686
/**************************************************************************/
687
21
static UINT _gx_utility_332rgb_pixelmap_simple_raw_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
688
{
689
GX_UBYTE *put;
690
GX_UBYTE *get;
691
INT       width;
692
INT       height;
693
INT       x, y;
694
695
21
    destination -> gx_pixelmap_aux_data = GX_NULL;
696
697
21
    width = src -> gx_pixelmap_width;
698
21
    height = src -> gx_pixelmap_height;
699
700
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
701
       overflow cannot occur. */
702
21
    destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
703
21
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
704
705
21
    if (destination -> gx_pixelmap_data == GX_NULL)
706
    {
707
12
        return GX_SYSTEM_MEMORY_ERROR;
708
    }
709
710
9
    if (angle == 90)
711
    {
712
3
        GX_SWAP_VALS(width, height);
713
714
3
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
715
716
723
        for (y = 0; y < height; y++)
717
        {
718
91440
            for (x = 0; x < width; x++)
719
            {
720
90720
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
721
90720
                get += (width - 1 - x) * height;
722
90720
                get += y;
723
724
90720
                *put++ = *get;
725
            }
726
        }
727
728

3
        if (rot_cx && rot_cy)
729
        {
730
1
            x = *rot_cx;
731
1
            y = *rot_cy;
732
733
1
            *rot_cx = (width - 1 - y);
734
1
            *rot_cy = x;
735
        }
736
    }
737
6
    else if (angle == 180)
738
    {
739
3
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
740
741
381
        for (y = 0; y < height; y++)
742
        {
743
91098
            for (x = 0; x < width; x++)
744
            {
745
90720
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
746
90720
                get += (height - 1 - y) * width;
747
90720
                get += width - 1 - x;
748
749
90720
                *put++ = *get;
750
            }
751
        }
752
753

3
        if (rot_cx && rot_cy)
754
        {
755
1
            x = *rot_cx;
756
1
            y = *rot_cy;
757
758
1
            *rot_cx = (width - 1 - x);
759
1
            *rot_cy = (height - 1 - y);
760
        }
761
    }
762
    else
763
    {
764
        /* angle = 270. */
765
3
        GX_SWAP_VALS(width, height);
766
767
3
        put = (GX_UBYTE *)destination -> gx_pixelmap_data;
768
769
723
        for (y = 0; y < height; y++)
770
        {
771
91440
            for (x = 0; x < width; x++)
772
            {
773
90720
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
774
90720
                get += x * height;
775
90720
                get += height - 1 - y;
776
777
90720
                *put++ = *get;
778
            }
779
        }
780
781

3
        if (rot_cx && rot_cy)
782
        {
783
1
            x = *rot_cx;
784
1
            y = *rot_cy;
785
786
1
            *rot_cx = y;
787
1
            *rot_cy = (height - 1 - x);
788
        }
789
    }
790
791
9
    destination -> gx_pixelmap_height = (GX_VALUE)height;
792
9
    destination -> gx_pixelmap_width = (GX_VALUE)width;
793
794
9
    return GX_SUCCESS;
795
}
796
797
798
/**************************************************************************/
799
/*                                                                        */
800
/*  FUNCTION                                               RELEASE        */
801
/*                                                                        */
802
/*    _gx_utility_332rgb_pixelmap_simple_alpha_rotate     PORTABLE C      */
803
/*                                                           6.1          */
804
/*  AUTHOR                                                                */
805
/*                                                                        */
806
/*    Kenneth Maxwell, Microsoft Corporation                              */
807
/*                                                                        */
808
/*  DESCRIPTION                                                           */
809
/*                                                                        */
810
/*    Internal helper function that handles 90, 180 and 270 degree        */
811
/*    rotation of an uncompressed pixelmap wih alpha.                     */
812
/*                                                                        */
813
/*  INPUT                                                                 */
814
/*                                                                        */
815
/*    src                                   The pixelmap to be rotated    */
816
/*    angle                                 The angle to be rotated       */
817
/*    destination                           The rotated bitmap to be      */
818
/*                                            returned                    */
819
/*    rot_cx                                X coordinate of rotation      */
820
/*                                            center                      */
821
/*    rot_cy                                Y coordinate of rotation      */
822
/*                                            center                      */
823
/*                                                                        */
824
/*  OUTPUT                                                                */
825
/*                                                                        */
826
/*    None                                                                */
827
/*                                                                        */
828
/*  CALLS                                                                 */
829
/*                                                                        */
830
/*    _gx_system_memory_allocator           Memory Allocation routine     */
831
/*                                                                        */
832
/*  CALLED BY                                                             */
833
/*                                                                        */
834
/*    _gx_utility_332rgb_pixelmap_simple_rotate                           */
835
/*                                                                        */
836
/*  RELEASE HISTORY                                                       */
837
/*                                                                        */
838
/*    DATE              NAME                      DESCRIPTION             */
839
/*                                                                        */
840
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
841
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
842
/*                                            resulting in version 6.1    */
843
/*                                                                        */
844
/**************************************************************************/
845
39
static UINT _gx_utility_332rgb_pixelmap_simple_alpha_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
846
{
847
GX_UBYTE *put;
848
GX_UBYTE *putalpha;
849
GX_UBYTE *get;
850
GX_UBYTE *getalpha;
851
INT       width;
852
INT       height;
853
INT       x, y;
854
855
39
    width = src -> gx_pixelmap_width;
856
39
    height = src -> gx_pixelmap_height;
857
858
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
859
       overflow cannot occur. */
860
39
    destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
861
39
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
862
863
39
    if (destination -> gx_pixelmap_data == GX_NULL)
864
    {
865
12
        return GX_SYSTEM_MEMORY_ERROR;
866
    }
867
868
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
869
       overflow cannot occur. */
870
27
    destination -> gx_pixelmap_aux_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
871
27
    destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
872
873
27
    if (destination -> gx_pixelmap_aux_data == GX_NULL)
874
    {
875
6
        _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
876
6
        return GX_SYSTEM_MEMORY_ERROR;
877
    }
878
879
21
    put = (GX_UBYTE *)destination -> gx_pixelmap_data;
880
21
    putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
881
882
21
    if (angle == 90)
883
    {
884
7
        GX_SWAP_VALS(width, height);
885
886
1312
        for (y = 0; y < height; y++)
887
        {
888
264780
            for (x = 0; x < width; x++)
889
            {
890
263475
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
891
263475
                get += (width - 1 - x) * height;
892
263475
                get += y;
893
894
263475
                getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
895
263475
                getalpha += (width - 1 - x) * height;
896
263475
                getalpha += y;
897
898
263475
                *put++ = *get;
899
263475
                *putalpha++ = *getalpha;
900
            }
901
        }
902
903

7
        if (rot_cx && rot_cy)
904
        {
905
1
            x = *rot_cx;
906
1
            y = *rot_cy;
907
908
            /* Get new rotation point. */
909
1
            *rot_cx = width - 1 - y;
910
1
            *rot_cy = x;
911
        }
912
    }
913
14
    else if (angle == 180)
914
    {
915
1404
        for (y = 0; y < height; y++)
916
        {
917
264872
            for (x = 0; x < width; x++)
918
            {
919
263475
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
920
263475
                get += (height - 1 - y) * width;
921
263475
                get += width - 1 - x;
922
923
263475
                getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
924
263475
                getalpha += (height - 1 - y) * width;
925
263475
                getalpha += width - 1 - x;
926
927
263475
                *put++ = *get;
928
263475
                *putalpha++ = *getalpha;
929
            }
930
        }
931
932

7
        if (rot_cx && rot_cy)
933
        {
934
1
            x = *rot_cx;
935
1
            y = *rot_cy;
936
937
            /* Get new rotation point. */
938
1
            *rot_cx = width - 1 - x;
939
1
            *rot_cy = height - 1 - y;
940
        }
941
    }
942
    else
943
    {
944
        /* angle = 270. */
945
7
        GX_SWAP_VALS(width, height);
946
947
1312
        for (y = 0; y < height; y++)
948
        {
949
264780
            for (x = 0; x < width; x++)
950
            {
951
263475
                get = (GX_UBYTE *)src -> gx_pixelmap_data;
952
263475
                get += x * height;
953
263475
                get += height - 1 - y;
954
955
263475
                getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
956
263475
                getalpha += x * height;
957
263475
                getalpha += height - 1 - y;
958
959
263475
                *put++ = *get;
960
263475
                *putalpha++ = *getalpha;
961
            }
962
        }
963
964

7
        if (rot_cx && rot_cy)
965
        {
966
1
            x = *rot_cx;
967
1
            y = *rot_cy;
968
969
            /* Get new rotation point. */
970
1
            *rot_cx = y;
971
1
            *rot_cy = height - 1 - x;
972
        }
973
    }
974
975
21
    destination -> gx_pixelmap_height = (GX_VALUE)height;
976
21
    destination -> gx_pixelmap_width = (GX_VALUE)width;
977
978
21
    return GX_SUCCESS;
979
}
980
981
/**************************************************************************/
982
/*                                                                        */
983
/*  FUNCTION                                               RELEASE        */
984
/*                                                                        */
985
/*    _gx_utility_332rgb_pixelmap_simple_rotate           PORTABLE C      */
986
/*                                                           6.1          */
987
/*  AUTHOR                                                                */
988
/*                                                                        */
989
/*    Kenneth Maxwell, Microsoft Corporation                              */
990
/*                                                                        */
991
/*  DESCRIPTION                                                           */
992
/*                                                                        */
993
/*    332rgb pixelmap rotation function that handles 90, 180 and 270      */
994
/*    degree case.                                                        */
995
/*                                                                        */
996
/*  INPUT                                                                 */
997
/*                                                                        */
998
/*    src                                   The pixelmap to be rotated    */
999
/*    angle                                 The angle to be rotated       */
1000
/*    destination                           The rotated bitmap to be      */
1001
/*                                            returned                    */
1002
/*    rot_cx                                X coordinate of rotation      */
1003
/*                                            center                      */
1004
/*    rot_cy                                Y coordinate of rotation      */
1005
/*                                            center                      */
1006
/*                                                                        */
1007
/*  OUTPUT                                                                */
1008
/*                                                                        */
1009
/*    status                                Completion status             */
1010
/*                                                                        */
1011
/*  CALLS                                                                 */
1012
/*                                                                        */
1013
/*     _gx_utility_332rgb_pixelmap_simple_raw_rotate                      */
1014
/*                                          Rotate an 332rgb format       */
1015
/*                                            pixelmap without alpha      */
1016
/*     _gx_utility_332rgb_pixelmap_simple_alpha_rotate                    */
1017
/*                                          Rotate an 332rgb format       */
1018
/*                                            pixelmap with alpha         */
1019
/*                                                                        */
1020
/*  CALLED BY                                                             */
1021
/*                                                                        */
1022
/*    GUIX Internal Code                                                  */
1023
/*                                                                        */
1024
/*  RELEASE HISTORY                                                       */
1025
/*                                                                        */
1026
/*    DATE              NAME                      DESCRIPTION             */
1027
/*                                                                        */
1028
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1029
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1030
/*                                            resulting in version 6.1    */
1031
/*                                                                        */
1032
/**************************************************************************/
1033
60
UINT _gx_utility_332rgb_pixelmap_simple_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
1034
{
1035
UINT status;
1036
1037
60
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
1038
    {
1039
        /* alpha, no compression */
1040
39
        status = _gx_utility_332rgb_pixelmap_simple_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
1041
    }
1042
    else
1043
    {
1044
1045
        /* no compression or alpha */
1046
21
        status = _gx_utility_332rgb_pixelmap_simple_raw_rotate(src, angle, destination, rot_cx, rot_cy);
1047
    }
1048
1049
60
    return status;
1050
}
1051
1052
/**************************************************************************/
1053
/*                                                                        */
1054
/*  FUNCTION                                               RELEASE        */
1055
/*                                                                        */
1056
/*    _gx_utility_332rgb_pixelmap_rotate                  PORTABLE C      */
1057
/*                                                           6.1          */
1058
/*  AUTHOR                                                                */
1059
/*                                                                        */
1060
/*    Kenneth Maxwell, Microsoft Corporation                              */
1061
/*                                                                        */
1062
/*  DESCRIPTION                                                           */
1063
/*                                                                        */
1064
/*    332rgb pixelmap rotation function that handles uncompress, with or  */
1065
/*    alpha channel.                                                      */
1066
/*                                                                        */
1067
/*  INPUT                                                                 */
1068
/*                                                                        */
1069
/*    src                                   The pixelmap to be rotated    */
1070
/*    angle                                 The angle to be rotated       */
1071
/*    destination                           The rotated bitmap to be      */
1072
/*                                            returned                    */
1073
/*    rot_cx                                X coordinate of rotation      */
1074
/*                                            center                      */
1075
/*    rot_cy                                Y coordinate of rotation      */
1076
/*                                            center                      */
1077
/*                                                                        */
1078
/*  OUTPUT                                                                */
1079
/*                                                                        */
1080
/*    status                                Completion status             */
1081
/*                                                                        */
1082
/*  CALLS                                                                 */
1083
/*                                                                        */
1084
/*     _gx_utility_332rgb_pixelmap_raw_rotate                             */
1085
/*                                          Rotate an 332rgb format       */
1086
/*                                            pixelmap without alpha      */
1087
/*     _gx_utility_332rgb_pixelmap_alpha_rotate                           */
1088
/*                                          Rotate an 332rgb format       */
1089
/*                                            pixelmap with alpha         */
1090
/*                                                                        */
1091
/*  CALLED BY                                                             */
1092
/*                                                                        */
1093
/*    GUIX Internal Code                                                  */
1094
/*                                                                        */
1095
/*  RELEASE HISTORY                                                       */
1096
/*                                                                        */
1097
/*    DATE              NAME                      DESCRIPTION             */
1098
/*                                                                        */
1099
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1100
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1101
/*                                            resulting in version 6.1    */
1102
/*                                                                        */
1103
/**************************************************************************/
1104
730
UINT _gx_utility_332rgb_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
1105
{
1106
730
UINT status = 0;
1107
1108
730
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
1109
    {
1110
        /* alpha, no compression */
1111
368
        status = _gx_utility_332rgb_pixelmap_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
1112
    }
1113
    else
1114
    {
1115
        /* no compression or alpha */
1116
362
        status = _gx_utility_332rgb_pixelmap_raw_rotate(src, angle, destination, rot_cx, rot_cy);
1117
    }
1118
1119
730
    return status;
1120
}
1121