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

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

79249128
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
193
50310772
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
194
            {
195

43834332
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
196
43007014
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
197
                {
198
42786298
                    get = (GX_COLOR *)src -> gx_pixelmap_data;
199
42786298
                    get += yy * src -> gx_pixelmap_width;
200
42786298
                    get += xx;
201
202
42786298
                    a = *get;
203
42786298
                    b = *(get + 1);
204
42786298
                    c = *(get + src -> gx_pixelmap_width);
205
42786298
                    d = *(get + src -> gx_pixelmap_width + 1);
206
207
42786298
                    alpha = 0xff;
208
                }
209
                else
210
                {
211
1048034
                    get = (GX_COLOR *)src -> gx_pixelmap_data;
212
213
1048034
                    a = 0;
214
1048034
                    b = 0;
215
1048034
                    c = 0;
216
1048034
                    d = 0;
217
1048034
                    alpha = 0;
218
219
1048034
                    if (xx == -1)
220
                    {
221
                        /* handle left edge.  */
222
303782
                        if (yy >= 0)
223
                        {
224
302424
                            b = *(get + yy * src -> gx_pixelmap_width);
225
                        }
226
227
303782
                        if (yy < src -> gx_pixelmap_height - 1)
228
                        {
229
302350
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
230
                        }
231
                    }
232
744252
                    else if (yy == -1)
233
                    {
234
                        /* handle top edge.  */
235
220644
                        c = *(get + xx);
236
237
220644
                        if (xx < src -> gx_pixelmap_width - 1)
238
                        {
239
219210
                            d = *(get + xx + 1);
240
                        }
241
                    }
242
523608
                    else if (xx == src -> gx_pixelmap_width - 1)
243
                    {
244
                        /* handle right edget. */
245
302892
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
246
247
302892
                        if (yy < src -> gx_pixelmap_height - 1)
248
                        {
249
301458
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
250
                        }
251
                    }
252
                    else
253
                    {
254
                        /* handle bottom edge. */
255
220716
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
256
220716
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
257
                    }
258
259
1048034
                    if (a)
260
                    {
261
523608
                        alpha += (256 - xdiff) * (256 - ydiff);
262
                    }
263
264
1048034
                    if (b)
265
                    {
266
523140
                        alpha += xdiff * (256 - ydiff);
267
                    }
268
269
1048034
                    if (c)
270
                    {
271
522102
                        alpha += ydiff * (256 - xdiff);
272
                    }
273
274
1048034
                    if (d)
275
                    {
276
521560
                        alpha += xdiff * ydiff;
277
                    }
278
279
1048034
                    alpha >>= 8;
280
                }
281
282
43834332
                red = (GX_COLOR)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) + \
283
43834332
                                  REDVAL(b) * xdiff * (256 - ydiff) +         \
284
43834332
                                  REDVAL(c) * ydiff * (256 - xdiff) +         \
285
43834332
                                  REDVAL(d) * xdiff * ydiff) >> 16);
286
287
43834332
                green = (GX_COLOR)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) + \
288
43834332
                                    GREENVAL(b) * xdiff * (256 - ydiff) +         \
289
43834332
                                    GREENVAL(c) * ydiff * (256 - xdiff) +         \
290
43834332
                                    GREENVAL(d) * xdiff * ydiff) >> 16);
291
292
43834332
                blue = (GX_COLOR)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) + \
293
43834332
                                   BLUEVAL(b) * xdiff * (256 - ydiff) +         \
294
43834332
                                   BLUEVAL(c) * ydiff * (256 - xdiff) +         \
295
43834332
                                   BLUEVAL(d) * xdiff * ydiff) >> 16);
296
297

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

3029
    if (rot_cx && rot_cy)
423
    {
424
3025
        x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
425
3025
        y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
426
427
3025
        srcxres = *rot_cx;
428
3025
        srcyres = *rot_cy;
429
430
3025
        x = GX_FIXED_VAL_TO_INT(x) + xres;
431
3025
        y = GX_FIXED_VAL_TO_INT(y) + yres;
432
433
3025
        *rot_cx = x;
434
3025
        *rot_cy = y;
435
436
3025
        xres = *rot_cx;
437
3025
        yres = *rot_cy;
438
    }
439
440
3029
    destination -> gx_pixelmap_height = (GX_VALUE)height;
441
3029
    destination -> gx_pixelmap_width = (GX_VALUE)width;
442
3029
    destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
443
444
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
445
       overflow cannot occur. */
446
3029
    destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_COLOR);
447
3029
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
448
449
3029
    if (destination -> gx_pixelmap_data == GX_NULL)
450
    {
451
2
        return GX_SYSTEM_MEMORY_ERROR;
452
    }
453
454
3027
    put = (GX_COLOR *)destination -> gx_pixelmap_data;
455
456
    /* Loop through the source's pixels.  */
457
578799
    for (y = 0; y < height; y++)
458
    {
459
140564312
        for (x = 0; x < width; x++)
460
        {
461
139988540
            xx = (x - xres) * cosv + (y - yres) * sinv;
462
139988540
            yy = (y - yres) * cosv - (x - xres) * sinv;
463
464
139988540
            xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
465
139988540
            ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
466
467
139988540
            xx = GX_FIXED_VAL_TO_INT(xx);
468
139988540
            yy = GX_FIXED_VAL_TO_INT(yy);
469
470
139988540
            xx += srcxres;
471
139988540
            yy += srcyres;
472
473

139988540
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
474
95901890
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
475
            {
476

80857555
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) && \
477
79473608
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
478
                {
479
79074481
                    get = (GX_COLOR *)src -> gx_pixelmap_data;
480
79074481
                    get += yy * src -> gx_pixelmap_width;
481
79074481
                    get += xx;
482
483
79074481
                    a = *get;
484
79074481
                    b = *(get + 1);
485
79074481
                    c = *(get + src -> gx_pixelmap_width);
486
79074481
                    d = *(get + src -> gx_pixelmap_width + 1);
487
                }
488
                else
489
                {
490
1783074
                    get = (GX_COLOR *)src -> gx_pixelmap_data;
491
492
1783074
                    a = 0;
493
1783074
                    b = a;
494
1783074
                    c = a;
495
1783074
                    d = a;
496
497
1783074
                    if (xx == -1)
498
                    {
499
                        /* handle left edge.  */
500
491850
                        if (yy >= 0)
501
                        {
502
489103
                            b = *(get + yy * src -> gx_pixelmap_width);
503
                        }
504
505
491850
                        if (yy < src -> gx_pixelmap_height - 1)
506
                        {
507
489059
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
508
                        }
509
                    }
510
1291224
                    else if (yy == -1)
511
                    {
512
                        /* handle top edge.  */
513
401706
                        c = *(get + xx);
514
515
401706
                        if (xx < src -> gx_pixelmap_width - 1)
516
                        {
517
399012
                            d = *(get + xx + 1);
518
                        }
519
                    }
520
889518
                    else if (xx == src -> gx_pixelmap_width - 1)
521
                    {
522
                        /* handle right edget. */
523
490391
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
524
525
490391
                        if (yy < src -> gx_pixelmap_height - 1)
526
                        {
527
487585
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
528
                        }
529
                    }
530
                    else
531
                    {
532
                        /* handle bottom edge. */
533
399127
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
534
399127
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
535
                    }
536
                }
537
538
80857555
                red = (ULONG)((REDVAL(a) * (a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
539
80857555
                               REDVAL(b) * (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
540
80857555
                               REDVAL(c) * (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
541
80857555
                               REDVAL(d) * (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
542
543
80857555
                green = (ULONG)((GREENVAL(a) * (a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
544
80857555
                                 GREENVAL(b) * (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
545
80857555
                                 GREENVAL(c) * (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
546
80857555
                                 GREENVAL(d) * (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
547
548
80857555
                blue = (ULONG)((BLUEVAL(a) * (a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
549
80857555
                                BLUEVAL(b) * (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
550
80857555
                                BLUEVAL(c) * (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
551
80857555
                                BLUEVAL(d) * (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
552
553
80857555
                alpha = (INT)(((a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
554
80857555
                               (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
555
80857555
                               (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
556
80857555
                               (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
557
558
80857555
                if (alpha)
559
                {
560
55241753
                    red /= (ULONG)alpha;
561
55241753
                    green /= (ULONG)alpha;
562
55241753
                    blue /= (ULONG)alpha;
563
                }
564
565
80857555
                red = BYTE_RANGE(red);
566
80857555
                green = BYTE_RANGE(green);
567
80857555
                blue = BYTE_RANGE(blue);
568
80857555
                alpha = BYTE_RANGE(alpha);
569
570
80857555
                *put++ = ASSEMBLECOLOR(red, green, blue) + ((ULONG)alpha << 24);
571
            }
572
            else
573
            {
574
59130985
                *put++ = 0;
575
            }
576
        }
577
    }
578
579
3027
    return GX_SUCCESS;
580
}
581
582
/**************************************************************************/
583
/*                                                                        */
584
/*  FUNCTION                                               RELEASE        */
585
/*                                                                        */
586
/*    _gx_utility_32argb_pixelmap_rotate                  PORTABLE C      */
587
/*                                                           6.1          */
588
/*  AUTHOR                                                                */
589
/*                                                                        */
590
/*    Kenneth Maxwell, Microsoft Corporation                              */
591
/*                                                                        */
592
/*  DESCRIPTION                                                           */
593
/*                                                                        */
594
/*    32argb pixelmap rotation function that handles uncompress, with or  */
595
/*    without alpha channel.                                              */
596
/*                                                                        */
597
/*  INPUT                                                                 */
598
/*                                                                        */
599
/*    src                                   The pixelmap to be rotated    */
600
/*    angle                                 The angle to be rotated       */
601
/*    destination                           The rotated bitmap to be      */
602
/*                                            returned                    */
603
/*    rot_cx                                X coordinate of rotation      */
604
/*                                            center                      */
605
/*    rot_cy                                Y coordinate of rotation      */
606
/*                                            center                      */
607
/*                                                                        */
608
/*  OUTPUT                                                                */
609
/*                                                                        */
610
/*    status                                Completion status             */
611
/*                                                                        */
612
/*  CALLS                                                                 */
613
/*                                                                        */
614
/*     _gx_utility_32argb_pixelmap_alpha_rotate                           */
615
/*                                          Rotate an 32bpp pixelmap with */
616
/*                                            alpha channel               */
617
/*     _gx_utility_32argb_pixelmap_raw_rotate                             */
618
/*                                          Rotate an 32bpp pixelmap      */
619
/*                                            without channel             */
620
/*                                                                        */
621
/*  CALLED BY                                                             */
622
/*                                                                        */
623
/*    GUIX Internal Code                                                  */
624
/*                                                                        */
625
/*  RELEASE HISTORY                                                       */
626
/*                                                                        */
627
/*    DATE              NAME                      DESCRIPTION             */
628
/*                                                                        */
629
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
630
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
631
/*                                            resulting in version 6.1    */
632
/*                                                                        */
633
/**************************************************************************/
634
4457
UINT _gx_utility_32argb_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
635
{
636
UINT status;
637
638
4457
    if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
639
    {
640
641
        /* alpha, no compression */
642
3029
        status = _gx_utility_32argb_pixelmap_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
643
    }
644
    else
645
    {
646
        /* no compression or alpha */
647
1428
        status = _gx_utility_32argb_pixelmap_raw_rotate(src, angle, destination, rot_cx, rot_cy);
648
    }
649
650
4457
    return status;
651
}
652
653
/**************************************************************************/
654
/*                                                                        */
655
/*  FUNCTION                                               RELEASE        */
656
/*                                                                        */
657
/*    _gx_utility_32argb_pixelmap_simple_rotate           PORTABLE C      */
658
/*                                                           6.1          */
659
/*  AUTHOR                                                                */
660
/*                                                                        */
661
/*    Kenneth Maxwell, Microsoft Corporation                              */
662
/*                                                                        */
663
/*  DESCRIPTION                                                           */
664
/*                                                                        */
665
/*    32argb pixelmap simple rotation function that hangles 90, 180 and   */
666
/*    270 degreen case of uncompress, with or without alpha channel.      */
667
/*                                                                        */
668
/*  INPUT                                                                 */
669
/*                                                                        */
670
/*    src                                   The pixelmap to be rotated    */
671
/*    angle                                 The angle to be rotated       */
672
/*    destination                           The rotated bitmap to be      */
673
/*                                            returned                    */
674
/*    rot_cx                                X coordinate of rotation      */
675
/*                                            center                      */
676
/*    rot_cy                                Y coordinate of rotation      */
677
/*                                            center                      */
678
/*                                                                        */
679
/*  OUTPUT                                                                */
680
/*                                                                        */
681
/*    status                                Completion status             */
682
/*                                                                        */
683
/*  CALLS                                                                 */
684
/*                                                                        */
685
/*    _gx_system_memory_allocator           Memory Allocation routine     */
686
/*                                                                        */
687
/*  CALLED BY                                                             */
688
/*                                                                        */
689
/*    GUIX Internal Code                                                  */
690
/*                                                                        */
691
/*  RELEASE HISTORY                                                       */
692
/*                                                                        */
693
/*    DATE              NAME                      DESCRIPTION             */
694
/*                                                                        */
695
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
696
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
697
/*                                            resulting in version 6.1    */
698
/*                                                                        */
699
/**************************************************************************/
700
86
UINT _gx_utility_32argb_pixelmap_simple_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
701
{
702
GX_COLOR *put;
703
GX_COLOR *get;
704
INT       width, height;
705
INT       x, y;
706
707
86
    width = src -> gx_pixelmap_height;
708
86
    height = src -> gx_pixelmap_width;
709
710
    /* Safe int math is not required here, calling function limits max width, height to 14 bits so
711
       overflow cannot occur. */
712
86
    destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(GX_COLOR);
713
86
    destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
714
715
86
    if (destination -> gx_pixelmap_data == GX_NULL)
716
    {
717
12
        return GX_SYSTEM_MEMORY_ERROR;
718
    }
719
720
74
    if (angle == 90)
721
    {
722
30
        put = (GX_COLOR *)destination -> gx_pixelmap_data;
723
724
4378
        for (y = 0; y < height; y++)
725
        {
726
818872
            for (x = 0; x < width; x++)
727
            {
728
814524
                get = (GX_COLOR *)src -> gx_pixelmap_data;
729
814524
                get += (width - 1 - x) * height;
730
814524
                get += y;
731
732
814524
                *put++ = *get;
733
            }
734
        }
735
736

30
        if (rot_cx && rot_cy)
737
        {
738
26
            x = *rot_cx;
739
26
            y = *rot_cy;
740
741
            /* Get new rotation point. */
742
26
            *rot_cx = (width - 1 - y);
743
26
            *rot_cy = x;
744
        }
745
    }
746
44
    else if (angle == 180)
747
    {
748
25
        GX_SWAP_VALS(width, height);
749
750
25
        put = (GX_COLOR *)destination -> gx_pixelmap_data;
751
752
3999
        for (y = 0; y < height; y++)
753
        {
754
548786
            for (x = 0; x < width; x++)
755
            {
756
544812
                get = (GX_COLOR *)src -> gx_pixelmap_data;
757
544812
                get += (height - 1 - y) * width;
758
544812
                get += width - 1 - x;
759
760
544812
                *put++ = *get;
761
            }
762
        }
763
764

25
        if (rot_cx && rot_cy)
765
        {
766
21
            x = *rot_cx;
767
21
            y = *rot_cy;
768
769
            /* Get new rotation point. */
770
21
            *rot_cx = (width - 1 - x);
771
21
            *rot_cy = (height - 1 - y);
772
        }
773
    }
774
    else
775
    {
776
        /* angle = 270. */
777
19
        put = (GX_COLOR *)destination -> gx_pixelmap_data;
778
779
2728
        for (y = 0; y < height; y++)
780
        {
781
522213
            for (x = 0; x < width; x++)
782
            {
783
519504
                get = (GX_COLOR *)src -> gx_pixelmap_data;
784
519504
                get += x * height;
785
519504
                get += height - 1 - y;
786
787
519504
                *put++ = *get;
788
            }
789
        }
790
791

19
        if (rot_cx && rot_cy)
792
        {
793
15
            x = *rot_cx;
794
15
            y = *rot_cy;
795
796
            /* Get new rotation point. */
797
15
            *rot_cx = y;
798
15
            *rot_cy = (height - 1 - x);
799
        }
800
    }
801
802
74
    destination -> gx_pixelmap_height = (GX_VALUE)height;
803
74
    destination -> gx_pixelmap_width = (GX_VALUE)width;
804
805
74
    return GX_SUCCESS;
806
}
807