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 /**************************************************************************/
_gx_utility_32argb_pixelmap_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)92 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     mx = _gx_system_scratchpad;
114     my = mx + 4;
115 
116     mx[0] = mx[3] = -1;
117     mx[1] = mx[2] = 1;
118 
119     my[0] = my[1] = 1;
120     my[2] = my[3] = -1;
121 
122     idxminx = (angle / 90) & 0x3;
123     idxmaxx = (idxminx + 2) & 0x3;
124     idxmaxy = (idxminx + 1) & 0x3;
125 
126     /* Calculate the source x and y center. */
127     srcxres = src -> gx_pixelmap_width >> 1;
128     srcyres = src -> gx_pixelmap_height >> 1;
129 
130     cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
131     sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
132 
133     xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
134     yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
135 
136     xres = GX_FIXED_VAL_TO_INT(xres);
137     yres = GX_FIXED_VAL_TO_INT(yres);
138 
139     /* Calculate destination width and height. */
140     width = (xres << 1);
141     height = (yres << 1);
142 
143     /* Calculate the new rotation axis. */
144     if (rot_cx && rot_cy)
145     {
146         x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
147         y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
148 
149         srcxres = *rot_cx;
150         srcyres = *rot_cy;
151 
152         x = GX_FIXED_VAL_TO_INT(x) + xres;
153         y = GX_FIXED_VAL_TO_INT(y) + yres;
154 
155         *rot_cx = x;
156         *rot_cy = y;
157 
158         xres = *rot_cx;
159         yres = *rot_cy;
160     }
161 
162     destination -> gx_pixelmap_height = (GX_VALUE)height;
163     destination -> gx_pixelmap_width = (GX_VALUE)width;
164     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     destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_COLOR);
169     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
170 
171     if (destination -> gx_pixelmap_data == GX_NULL)
172     {
173         return GX_SYSTEM_MEMORY_ERROR;
174     }
175 
176     put = (GX_COLOR *)destination -> gx_pixelmap_data;
177 
178     /* Loop through the destination's pixels.  */
179     for (y = 0; y < height; y++)
180     {
181         for (x = 0; x < width; x++)
182         {
183             xx = (x - xres) * cosv + (y - yres) * sinv;
184             yy = (y - yres) * cosv - (x - xres) * sinv;
185 
186             xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
187             ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
188 
189             xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
190             yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
191 
192             if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
193                 (yy >= -1) && (yy < src -> gx_pixelmap_height))
194             {
195                 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
196                     (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
197                 {
198                     get = (GX_COLOR *)src -> gx_pixelmap_data;
199                     get += yy * src -> gx_pixelmap_width;
200                     get += xx;
201 
202                     a = *get;
203                     b = *(get + 1);
204                     c = *(get + src -> gx_pixelmap_width);
205                     d = *(get + src -> gx_pixelmap_width + 1);
206 
207                     alpha = 0xff;
208                 }
209                 else
210                 {
211                     get = (GX_COLOR *)src -> gx_pixelmap_data;
212 
213                     a = 0;
214                     b = 0;
215                     c = 0;
216                     d = 0;
217                     alpha = 0;
218 
219                     if (xx == -1)
220                     {
221                         /* handle left edge.  */
222                         if (yy >= 0)
223                         {
224                             b = *(get + yy * src -> gx_pixelmap_width);
225                         }
226 
227                         if (yy < src -> gx_pixelmap_height - 1)
228                         {
229                             d = *(get + (yy + 1) * src -> gx_pixelmap_width);
230                         }
231                     }
232                     else if (yy == -1)
233                     {
234                         /* handle top edge.  */
235                         c = *(get + xx);
236 
237                         if (xx < src -> gx_pixelmap_width - 1)
238                         {
239                             d = *(get + xx + 1);
240                         }
241                     }
242                     else if (xx == src -> gx_pixelmap_width - 1)
243                     {
244                         /* handle right edget. */
245                         a = *(get + yy * src -> gx_pixelmap_width + xx);
246 
247                         if (yy < src -> gx_pixelmap_height - 1)
248                         {
249                             c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
250                         }
251                     }
252                     else
253                     {
254                         /* handle bottom edge. */
255                         a = *(get + yy * src -> gx_pixelmap_width + xx);
256                         b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
257                     }
258 
259                     if (a)
260                     {
261                         alpha += (256 - xdiff) * (256 - ydiff);
262                     }
263 
264                     if (b)
265                     {
266                         alpha += xdiff * (256 - ydiff);
267                     }
268 
269                     if (c)
270                     {
271                         alpha += ydiff * (256 - xdiff);
272                     }
273 
274                     if (d)
275                     {
276                         alpha += xdiff * ydiff;
277                     }
278 
279                     alpha >>= 8;
280                 }
281 
282                 red = (GX_COLOR)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) + \
283                                   REDVAL(b) * xdiff * (256 - ydiff) +         \
284                                   REDVAL(c) * ydiff * (256 - xdiff) +         \
285                                   REDVAL(d) * xdiff * ydiff) >> 16);
286 
287                 green = (GX_COLOR)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) + \
288                                     GREENVAL(b) * xdiff * (256 - ydiff) +         \
289                                     GREENVAL(c) * ydiff * (256 - xdiff) +         \
290                                     GREENVAL(d) * xdiff * ydiff) >> 16);
291 
292                 blue = (GX_COLOR)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) + \
293                                    BLUEVAL(b) * xdiff * (256 - ydiff) +         \
294                                    BLUEVAL(c) * ydiff * (256 - xdiff) +         \
295                                    BLUEVAL(d) * xdiff * ydiff) >> 16);
296 
297                 if ((alpha > 0) && (alpha < 0xff))
298                 {
299                     red = (red << 8) / (ULONG)alpha;
300                     green = (green << 8) / (ULONG)alpha;
301                     blue = (blue << 8) / (ULONG)alpha;
302                 }
303 
304                 red = BYTE_RANGE(red);
305                 green = BYTE_RANGE(green);
306                 blue = BYTE_RANGE(blue);
307                 alpha = BYTE_RANGE(alpha);
308 
309                 *put++ = ASSEMBLECOLOR(red, green, blue) + (ULONG)(alpha << 24);
310             }
311             else
312             {
313                 *put++ = 0;
314             }
315         }
316     }
317 
318     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 /**************************************************************************/
_gx_utility_32argb_pixelmap_alpha_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)370 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     mx = _gx_system_scratchpad;
392     my = mx + 4;
393 
394     mx[0] = mx[3] = -1;
395     mx[1] = mx[2] = 1;
396 
397     my[0] = my[1] = 1;
398     my[2] = my[3] = -1;
399 
400     idxminx = (angle / 90) & 0x3;
401     idxmaxx = (idxminx + 2) & 0x3;
402     idxmaxy = (idxminx + 1) & 0x3;
403 
404     /* Calculate the source x and y center. */
405     srcxres = src -> gx_pixelmap_width >> 1;
406     srcyres = src -> gx_pixelmap_height >> 1;
407 
408     cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
409     sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
410 
411     xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
412     yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
413 
414     xres = GX_FIXED_VAL_TO_INT(xres);
415     yres = GX_FIXED_VAL_TO_INT(yres);
416 
417     /* Calculate destination width and height. */
418     width = (xres << 1);
419     height = (yres << 1);
420 
421     /* Calculate the new rotation axis. */
422     if (rot_cx && rot_cy)
423     {
424         x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
425         y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
426 
427         srcxres = *rot_cx;
428         srcyres = *rot_cy;
429 
430         x = GX_FIXED_VAL_TO_INT(x) + xres;
431         y = GX_FIXED_VAL_TO_INT(y) + yres;
432 
433         *rot_cx = x;
434         *rot_cy = y;
435 
436         xres = *rot_cx;
437         yres = *rot_cy;
438     }
439 
440     destination -> gx_pixelmap_height = (GX_VALUE)height;
441     destination -> gx_pixelmap_width = (GX_VALUE)width;
442     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     destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(GX_COLOR);
447     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
448 
449     if (destination -> gx_pixelmap_data == GX_NULL)
450     {
451         return GX_SYSTEM_MEMORY_ERROR;
452     }
453 
454     put = (GX_COLOR *)destination -> gx_pixelmap_data;
455 
456     /* Loop through the source's pixels.  */
457     for (y = 0; y < height; y++)
458     {
459         for (x = 0; x < width; x++)
460         {
461             xx = (x - xres) * cosv + (y - yres) * sinv;
462             yy = (y - yres) * cosv - (x - xres) * sinv;
463 
464             xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
465             ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
466 
467             xx = GX_FIXED_VAL_TO_INT(xx);
468             yy = GX_FIXED_VAL_TO_INT(yy);
469 
470             xx += srcxres;
471             yy += srcyres;
472 
473             if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
474                 (yy >= -1) && (yy < src -> gx_pixelmap_height))
475             {
476                 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) && \
477                     (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
478                 {
479                     get = (GX_COLOR *)src -> gx_pixelmap_data;
480                     get += yy * src -> gx_pixelmap_width;
481                     get += xx;
482 
483                     a = *get;
484                     b = *(get + 1);
485                     c = *(get + src -> gx_pixelmap_width);
486                     d = *(get + src -> gx_pixelmap_width + 1);
487                 }
488                 else
489                 {
490                     get = (GX_COLOR *)src -> gx_pixelmap_data;
491 
492                     a = 0;
493                     b = a;
494                     c = a;
495                     d = a;
496 
497                     if (xx == -1)
498                     {
499                         /* handle left edge.  */
500                         if (yy >= 0)
501                         {
502                             b = *(get + yy * src -> gx_pixelmap_width);
503                         }
504 
505                         if (yy < src -> gx_pixelmap_height - 1)
506                         {
507                             d = *(get + (yy + 1) * src -> gx_pixelmap_width);
508                         }
509                     }
510                     else if (yy == -1)
511                     {
512                         /* handle top edge.  */
513                         c = *(get + xx);
514 
515                         if (xx < src -> gx_pixelmap_width - 1)
516                         {
517                             d = *(get + xx + 1);
518                         }
519                     }
520                     else if (xx == src -> gx_pixelmap_width - 1)
521                     {
522                         /* handle right edget. */
523                         a = *(get + yy * src -> gx_pixelmap_width + xx);
524 
525                         if (yy < src -> gx_pixelmap_height - 1)
526                         {
527                             c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
528                         }
529                     }
530                     else
531                     {
532                         /* handle bottom edge. */
533                         a = *(get + yy * src -> gx_pixelmap_width + xx);
534                         b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
535                     }
536                 }
537 
538                 red = (ULONG)((REDVAL(a) * (a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
539                                REDVAL(b) * (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
540                                REDVAL(c) * (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
541                                REDVAL(d) * (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
542 
543                 green = (ULONG)((GREENVAL(a) * (a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
544                                  GREENVAL(b) * (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
545                                  GREENVAL(c) * (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
546                                  GREENVAL(d) * (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
547 
548                 blue = (ULONG)((BLUEVAL(a) * (a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
549                                 BLUEVAL(b) * (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
550                                 BLUEVAL(c) * (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
551                                 BLUEVAL(d) * (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
552 
553                 alpha = (INT)(((a >> 24) * (256 - (ULONG)xdiff) * (256 - (ULONG)ydiff) + \
554                                (b >> 24) * (ULONG)xdiff * (256 - (ULONG)ydiff) +         \
555                                (c >> 24) * (ULONG)ydiff * (256 - (ULONG)xdiff) +         \
556                                (d >> 24) * (ULONG)xdiff * (ULONG)ydiff) >> 16);
557 
558                 if (alpha)
559                 {
560                     red /= (ULONG)alpha;
561                     green /= (ULONG)alpha;
562                     blue /= (ULONG)alpha;
563                 }
564 
565                 red = BYTE_RANGE(red);
566                 green = BYTE_RANGE(green);
567                 blue = BYTE_RANGE(blue);
568                 alpha = BYTE_RANGE(alpha);
569 
570                 *put++ = ASSEMBLECOLOR(red, green, blue) + ((ULONG)alpha << 24);
571             }
572             else
573             {
574                 *put++ = 0;
575             }
576         }
577     }
578 
579     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 /**************************************************************************/
_gx_utility_32argb_pixelmap_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)634 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     if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
639     {
640 
641         /* alpha, no compression */
642         status = _gx_utility_32argb_pixelmap_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
643     }
644     else
645     {
646         /* no compression or alpha */
647         status = _gx_utility_32argb_pixelmap_raw_rotate(src, angle, destination, rot_cx, rot_cy);
648     }
649 
650     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 /**************************************************************************/
_gx_utility_32argb_pixelmap_simple_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)700 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     width = src -> gx_pixelmap_height;
708     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     destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(GX_COLOR);
713     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
714 
715     if (destination -> gx_pixelmap_data == GX_NULL)
716     {
717         return GX_SYSTEM_MEMORY_ERROR;
718     }
719 
720     if (angle == 90)
721     {
722         put = (GX_COLOR *)destination -> gx_pixelmap_data;
723 
724         for (y = 0; y < height; y++)
725         {
726             for (x = 0; x < width; x++)
727             {
728                 get = (GX_COLOR *)src -> gx_pixelmap_data;
729                 get += (width - 1 - x) * height;
730                 get += y;
731 
732                 *put++ = *get;
733             }
734         }
735 
736         if (rot_cx && rot_cy)
737         {
738             x = *rot_cx;
739             y = *rot_cy;
740 
741             /* Get new rotation point. */
742             *rot_cx = (width - 1 - y);
743             *rot_cy = x;
744         }
745     }
746     else if (angle == 180)
747     {
748         GX_SWAP_VALS(width, height);
749 
750         put = (GX_COLOR *)destination -> gx_pixelmap_data;
751 
752         for (y = 0; y < height; y++)
753         {
754             for (x = 0; x < width; x++)
755             {
756                 get = (GX_COLOR *)src -> gx_pixelmap_data;
757                 get += (height - 1 - y) * width;
758                 get += width - 1 - x;
759 
760                 *put++ = *get;
761             }
762         }
763 
764         if (rot_cx && rot_cy)
765         {
766             x = *rot_cx;
767             y = *rot_cy;
768 
769             /* Get new rotation point. */
770             *rot_cx = (width - 1 - x);
771             *rot_cy = (height - 1 - y);
772         }
773     }
774     else
775     {
776         /* angle = 270. */
777         put = (GX_COLOR *)destination -> gx_pixelmap_data;
778 
779         for (y = 0; y < height; y++)
780         {
781             for (x = 0; x < width; x++)
782             {
783                 get = (GX_COLOR *)src -> gx_pixelmap_data;
784                 get += x * height;
785                 get += height - 1 - y;
786 
787                 *put++ = *get;
788             }
789         }
790 
791         if (rot_cx && rot_cy)
792         {
793             x = *rot_cx;
794             y = *rot_cy;
795 
796             /* Get new rotation point. */
797             *rot_cx = y;
798             *rot_cy = (height - 1 - x);
799         }
800     }
801 
802     destination -> gx_pixelmap_height = (GX_VALUE)height;
803     destination -> gx_pixelmap_width = (GX_VALUE)width;
804 
805     return GX_SUCCESS;
806 }
807 
808