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

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

64208536
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
205
41285400
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
206
            {
207

35476776
                if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
208
34815902
                    (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
209
                {
210
34628706
                    get = (USHORT *)src -> gx_pixelmap_data;
211
34628706
                    get += yy * src -> gx_pixelmap_width;
212
34628706
                    get += xx;
213
214
34628706
                    a = *get;
215
34628706
                    b = *(get + 1);
216
34628706
                    c = *(get + src -> gx_pixelmap_width);
217
34628706
                    d = *(get + src -> gx_pixelmap_width + 1);
218
219
34628706
                    alpha = 0xff;
220
                }
221
                else
222
                {
223
848070
                    get = (USHORT *)src -> gx_pixelmap_data;
224
225
848070
                    a = 0;
226
848070
                    b = 0;
227
848070
                    c = 0;
228
848070
                    d = 0;
229
848070
                    alpha = 0;
230
231
848070
                    if (xx == -1)
232
                    {
233
                        /* handle left edge.  */
234
237450
                        if (yy >= 0)
235
                        {
236
236380
                            b = *(get + yy * src -> gx_pixelmap_width);
237
236380
                            alpha += xdiff * (256 - ydiff);
238
                        }
239
240
237450
                        if (yy < src -> gx_pixelmap_height - 1)
241
                        {
242
236290
                            d = *(get + (yy + 1) * src -> gx_pixelmap_width);
243
236290
                            alpha += xdiff * ydiff;
244
                        }
245
                    }
246
610620
                    else if (yy == -1)
247
                    {
248
                        /* handle top edge.  */
249
187296
                        c = *(get + xx);
250
187296
                        alpha += ydiff * (256 - xdiff);
251
252
187296
                        if (xx < src -> gx_pixelmap_width - 1)
253
                        {
254
186134
                            d = *(get + xx + 1);
255
186134
                            alpha += xdiff * ydiff;
256
                        }
257
                    }
258
423324
                    else if (xx == src -> gx_pixelmap_width - 1)
259
                    {
260
                        /* handle right edget. */
261
236128
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
262
236128
                        alpha += (256 - xdiff) * (256 - ydiff);
263
264
236128
                        if (yy < src -> gx_pixelmap_height - 1)
265
                        {
266
234962
                            c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
267
234962
                            alpha += ydiff * (256 - xdiff);
268
                        }
269
                    }
270
                    else
271
                    {
272
                        /* handle bottom edge. */
273
187196
                        a = *(get + yy * src -> gx_pixelmap_width + xx);
274
187196
                        alpha += (256 - xdiff) * (256 - ydiff);
275
276
187196
                        b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
277
187196
                        alpha += xdiff * (256 - ydiff);
278
                    }
279
280
848070
                    alpha >>= 8;
281
                }
282
283
35476776
                red = (USHORT)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) + \
284
35476776
                                REDVAL(b) * xdiff * (256 - ydiff) +         \
285
35476776
                                REDVAL(c) * ydiff * (256 - xdiff) +         \
286
35476776
                                REDVAL(d) * xdiff * ydiff) >> 16);
287
288
35476776
                green = (USHORT)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) + \
289
35476776
                                  GREENVAL(b) * xdiff * (256 - ydiff) +         \
290
35476776
                                  GREENVAL(c) * ydiff * (256 - xdiff) +         \
291
35476776
                                  GREENVAL(d) * xdiff * ydiff) >> 16);
292
293
35476776
                blue = (USHORT)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) + \
294
35476776
                                 BLUEVAL(b) * xdiff * (256 - ydiff) +         \
295
35476776
                                 BLUEVAL(c) * ydiff * (256 - xdiff) +         \
296
35476776
                                 BLUEVAL(d) * xdiff * ydiff) >> 16);
297
298

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

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

102727304
            if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
493
72643059
                (yy >= -1) && (yy < src -> gx_pixelmap_height))
494
            {
495
496

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

7
        if (rot_cx && rot_cy)
733
        {
734
5
            x = *rot_cx;
735
5
            y = *rot_cy;
736
737
5
            *rot_cx = (width - 1 - y);
738
5
            *rot_cy = x;
739
        }
740
    }
741
14
    else if (angle == 180)
742
    {
743
7
        GX_SWAP_VALS(width, height);
744
745
7
        put = (USHORT *)destination -> gx_pixelmap_data;
746
747
1117
        for (y = 0; y < height; y++)
748
        {
749
212790
            for (x = 0; x < width; x++)
750
            {
751
211680
                get = (USHORT *)src -> gx_pixelmap_data;
752
211680
                get += (height - 1 - y) * width;
753
211680
                get += width - 1 - x;
754
755
211680
                *put++ = *get;
756
            }
757
        }
758
759

7
        if (rot_cx && rot_cy)
760
        {
761
5
            x = *rot_cx;
762
5
            y = *rot_cy;
763
764
5
            *rot_cx = (width - 1 - x);
765
5
            *rot_cy = (height - 1 - y);
766
        }
767
    }
768
    else
769
    {
770
        /* angle = 270. */
771
7
        put = (USHORT *)destination -> gx_pixelmap_data;
772
773
1459
        for (y = 0; y < height; y++)
774
        {
775
213132
            for (x = 0; x < width; x++)
776
            {
777
211680
                get = (USHORT *)src -> gx_pixelmap_data;
778
211680
                get += x * height;
779
211680
                get += height - 1 - y;
780
781
211680
                *put++ = *get;
782
            }
783
        }
784
785

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

17
        if (rot_cx && rot_cy)
904
        {
905
11
            x = *rot_cx;
906
11
            y = *rot_cy;
907
908
            /* Get new rotation point. */
909
11
            *rot_cx = (width - 1 - y);
910
11
            *rot_cy = x;
911
        }
912
    }
913
28
    else if (angle == 180)
914
    {
915
14
        GX_SWAP_VALS(width, height);
916
917
14
        put = (USHORT *)destination -> gx_pixelmap_data;
918
14
        putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
919
920
2636
        for (y = 0; y < height; y++)
921
        {
922
506839
            for (x = 0; x < width; x++)
923
            {
924
504217
                get = (USHORT *)src -> gx_pixelmap_data;
925
504217
                get += (height - 1 - y) * width;
926
504217
                get += width - 1 - x;
927
928
504217
                getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
929
504217
                getalpha += (height - 1 - y) * width;
930
504217
                getalpha += width - 1 - x;
931
932
504217
                *put++ = *get;
933
504217
                *putalpha++ = *getalpha;
934
            }
935
        }
936
937

14
        if (rot_cx && rot_cy)
938
        {
939
8
            x = *rot_cx;
940
8
            y = *rot_cy;
941
942
            /* Get new rotation point. */
943
8
            *rot_cx = (width - 1 - x);
944
8
            *rot_cy = (height - 1 - y);
945
        }
946
    }
947
    else
948
    {
949
        /* angle = 270. */
950
14
        put = (USHORT *)destination -> gx_pixelmap_data;
951
14
        putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
952
953
2498
        for (y = 0; y < height; y++)
954
        {
955
506701
            for (x = 0; x < width; x++)
956
            {
957
504217
                get = (USHORT *)src -> gx_pixelmap_data;
958
504217
                get += x * height;
959
504217
                get += height - 1 - y;
960
961
504217
                getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
962
504217
                getalpha += x * height;
963
504217
                getalpha += height - 1 - y;
964
965
504217
                *put++ = *get;
966
504217
                *putalpha++ = *getalpha;
967
            }
968
        }
969
970

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