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 /**************************************************************************/
_gx_utility_565rgb_pixelmap_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)90 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     mx = _gx_system_scratchpad;
113     my = mx + 4;
114 
115     mx[0] = mx[3] = -1;
116     mx[1] = mx[2] = 1;
117 
118     my[0] = my[1] = 1;
119     my[2] = my[3] = -1;
120 
121     idxminx = (angle / 90) & 0x3;
122     idxmaxx = (idxminx + 2) & 0x3;
123     idxmaxy = (idxminx + 1) & 0x3;
124 
125     /* Calculate the source x and y center. */
126     srcxres = src -> gx_pixelmap_width >> 1;
127     srcyres = src -> gx_pixelmap_height >> 1;
128 
129     cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
130     sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
131 
132     xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
133     yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
134 
135     xres = GX_FIXED_VAL_TO_INT(xres);
136     yres = GX_FIXED_VAL_TO_INT(yres);
137 
138     /* Calculate destination width and height. */
139     width = (xres << 1);
140     height = (yres << 1);
141 
142     /* Calculate the new rotation axis. */
143     if (rot_cx && rot_cy)
144     {
145         x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
146         y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
147 
148         srcxres = (INT)*rot_cx;
149         srcyres = (INT)*rot_cy;
150 
151         x = GX_FIXED_VAL_TO_INT(x) + xres;
152         y = GX_FIXED_VAL_TO_INT(y) + yres;
153 
154         *rot_cx = x;
155         *rot_cy = y;
156 
157         xres = *rot_cx;
158         yres = *rot_cy;
159     }
160 
161     destination -> gx_pixelmap_height = (GX_VALUE)height;
162     destination -> gx_pixelmap_width  = (GX_VALUE)width;
163     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     destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
168     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
169 
170     if (destination -> gx_pixelmap_data == GX_NULL)
171     {
172         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     destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
178     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
179 
180     if (destination -> gx_pixelmap_aux_data == GX_NULL)
181     {
182         _gx_system_memory_free((VOID *)destination -> gx_pixelmap_aux_data);
183 
184         return GX_SYSTEM_MEMORY_ERROR;
185     }
186 
187     put = (USHORT *)destination -> gx_pixelmap_data;
188     putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
189 
190     /* Loop through the destination's pixels.  */
191     for (y = 0; y < height; y++)
192     {
193         for (x = 0; x < width; x++)
194         {
195             xx = (x - xres) * cosv + (y - yres) * sinv;
196             yy = (y - yres) * cosv - (x - xres) * sinv;
197 
198             xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
199             ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
200 
201             xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
202             yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
203 
204             if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
205                 (yy >= -1) && (yy < src -> gx_pixelmap_height))
206             {
207                 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
208                     (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
209                 {
210                     get = (USHORT *)src -> gx_pixelmap_data;
211                     get += yy * src -> gx_pixelmap_width;
212                     get += xx;
213 
214                     a = *get;
215                     b = *(get + 1);
216                     c = *(get + src -> gx_pixelmap_width);
217                     d = *(get + src -> gx_pixelmap_width + 1);
218 
219                     alpha = 0xff;
220                 }
221                 else
222                 {
223                     get = (USHORT *)src -> gx_pixelmap_data;
224 
225                     a = 0;
226                     b = 0;
227                     c = 0;
228                     d = 0;
229                     alpha = 0;
230 
231                     if (xx == -1)
232                     {
233                         /* handle left edge.  */
234                         if (yy >= 0)
235                         {
236                             b = *(get + yy * src -> gx_pixelmap_width);
237                             alpha += xdiff * (256 - ydiff);
238                         }
239 
240                         if (yy < src -> gx_pixelmap_height - 1)
241                         {
242                             d = *(get + (yy + 1) * src -> gx_pixelmap_width);
243                             alpha += xdiff * ydiff;
244                         }
245                     }
246                     else if (yy == -1)
247                     {
248                         /* handle top edge.  */
249                         c = *(get + xx);
250                         alpha += ydiff * (256 - xdiff);
251 
252                         if (xx < src -> gx_pixelmap_width - 1)
253                         {
254                             d = *(get + xx + 1);
255                             alpha += xdiff * ydiff;
256                         }
257                     }
258                     else if (xx == src -> gx_pixelmap_width - 1)
259                     {
260                         /* handle right edget. */
261                         a = *(get + yy * src -> gx_pixelmap_width + xx);
262                         alpha += (256 - xdiff) * (256 - ydiff);
263 
264                         if (yy < src -> gx_pixelmap_height - 1)
265                         {
266                             c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
267                             alpha += ydiff * (256 - xdiff);
268                         }
269                     }
270                     else
271                     {
272                         /* handle bottom edge. */
273                         a = *(get + yy * src -> gx_pixelmap_width + xx);
274                         alpha += (256 - xdiff) * (256 - ydiff);
275 
276                         b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
277                         alpha += xdiff * (256 - ydiff);
278                     }
279 
280                     alpha >>= 8;
281                 }
282 
283                 red = (USHORT)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) + \
284                                 REDVAL(b) * xdiff * (256 - ydiff) +         \
285                                 REDVAL(c) * ydiff * (256 - xdiff) +         \
286                                 REDVAL(d) * xdiff * ydiff) >> 16);
287 
288                 green = (USHORT)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) + \
289                                   GREENVAL(b) * xdiff * (256 - ydiff) +         \
290                                   GREENVAL(c) * ydiff * (256 - xdiff) +         \
291                                   GREENVAL(d) * xdiff * ydiff) >> 16);
292 
293                 blue = (USHORT)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) + \
294                                  BLUEVAL(b) * xdiff * (256 - ydiff) +         \
295                                  BLUEVAL(c) * ydiff * (256 - xdiff) +         \
296                                  BLUEVAL(d) * xdiff * ydiff) >> 16);
297 
298                 if (alpha && (alpha < 0xff))
299                 {
300                     red   = (USHORT)((red << 8) / alpha);
301                     green = (USHORT)((green << 8) / alpha);
302                     blue  = (USHORT)((blue << 8) / alpha);
303                 }
304 
305                 red = red > 31 ? 31 : red;
306                 green = green > 63 ? 63 : green;
307                 blue = blue > 31 ? 31 : blue;
308                 alpha = alpha > 255 ? 255 : alpha;
309 
310                 *put++ = ASSEMBLECOLOR(red, green, blue);
311                 *putalpha++ = (GX_UBYTE)alpha;
312             }
313             else
314             {
315                 put++;
316                 *putalpha++ = 0;
317             }
318         }
319     }
320 
321     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 /**************************************************************************/
_gx_utility_565rgb_pixelmap_alpha_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)373 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     mx = _gx_system_scratchpad;
397     my = mx + 4;
398 
399     mx[0] = mx[3] = -1;
400     mx[1] = mx[2] = 1;
401 
402     my[0] = my[1] = 1;
403     my[2] = my[3] = -1;
404 
405     idxminx = (angle / 90) & 0x3;
406     idxmaxx = (idxminx + 2) & 0x3;
407     idxmaxy = (idxminx + 1) & 0x3;
408 
409     /* Calculate the source x and y center. */
410     srcxres = src -> gx_pixelmap_width >> 1;
411     srcyres = src -> gx_pixelmap_height >> 1;
412 
413     cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
414     sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
415 
416     xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
417     yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
418 
419     xres = GX_FIXED_VAL_TO_INT(xres);
420     yres = GX_FIXED_VAL_TO_INT(yres);
421 
422 
423     /* Calculate destination width and height. */
424     width = (xres << 1);
425     height = (yres << 1);
426 
427     /* Calculate the new rotation axis. */
428     if (rot_cx && rot_cy)
429     {
430         x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
431         y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
432 
433         srcxres = *rot_cx;
434         srcyres = *rot_cy;
435 
436         x = GX_FIXED_VAL_TO_INT(x) + xres;
437         y = GX_FIXED_VAL_TO_INT(y) + yres;
438 
439         *rot_cx = x;
440         *rot_cy = y;
441 
442         xres = *rot_cx;
443         yres = *rot_cy;
444     }
445 
446     destination -> gx_pixelmap_height = (GX_VALUE)height;
447     destination -> gx_pixelmap_width = (GX_VALUE)width;
448     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     destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
453     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
454 
455     if (destination -> gx_pixelmap_data == GX_NULL)
456     {
457         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     destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
463     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
464 
465     if (destination -> gx_pixelmap_aux_data == GX_NULL)
466     {
467         _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
468 
469         return GX_SYSTEM_MEMORY_ERROR;
470     }
471 
472     put = (USHORT *)destination -> gx_pixelmap_data;
473     putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
474 
475     /* Loop through the destination's pixels.  */
476     for (y = 0; y < height; y++)
477     {
478         for (x = 0; x < width; x++)
479         {
480             xx = (x - xres) * cosv + (y - yres) * sinv;
481             yy = (y - yres) * cosv - (x - xres) * sinv;
482 
483             xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
484             ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
485 
486             xx = GX_FIXED_VAL_TO_INT(xx);
487             yy = GX_FIXED_VAL_TO_INT(yy);
488 
489             xx += srcxres;
490             yy += srcyres;
491 
492             if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
493                 (yy >= -1) && (yy < src -> gx_pixelmap_height))
494             {
495 
496                 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
497                     (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
498                 {
499                     get = (USHORT *)src -> gx_pixelmap_data;
500                     get += yy * src -> gx_pixelmap_width;
501                     get += xx;
502 
503                     getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
504                     getalpha += yy * src -> gx_pixelmap_width;
505                     getalpha += xx;
506 
507                     a = *get;
508                     alpha[0] = *getalpha;
509 
510                     b = *(get + 1);
511                     alpha[1] = *(getalpha + 1);
512 
513                     c = *(get + src -> gx_pixelmap_width);
514                     alpha[2] = *(getalpha + src -> gx_pixelmap_width);
515 
516                     d = *(get + src -> gx_pixelmap_width + 1);
517                     alpha[3] = *(getalpha + src -> gx_pixelmap_width + 1);
518                 }
519                 else
520                 {
521                     get = (USHORT *)src -> gx_pixelmap_data;
522                     getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
523 
524                     a = 0;
525                     b = 0;
526                     c = 0;
527                     d = 0;
528 
529                     if (xx == -1)
530                     {
531                         /* handle left edge.  */
532                         if (yy >= 0)
533                         {
534                             b = *(get + yy * src -> gx_pixelmap_width);
535                             alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width);
536                         }
537 
538                         if (yy < src -> gx_pixelmap_height - 1)
539                         {
540                             d = *(get + (yy + 1) * src -> gx_pixelmap_width);
541                             alpha[3] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width);
542                         }
543                     }
544                     else if (yy == -1)
545                     {
546                         /* handle top edge.  */
547                         c = *(get + xx);
548                         alpha[2] = *(getalpha + xx);
549 
550                         if (xx < src -> gx_pixelmap_width - 1)
551                         {
552                             d = *(get + xx + 1);
553                             alpha[3] = *(getalpha + xx + 1);
554                         }
555                     }
556                     else if (xx == src -> gx_pixelmap_width - 1)
557                     {
558                         /* handle right edget. */
559                         a = *(get + yy * src -> gx_pixelmap_width + xx);
560                         alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
561 
562                         if (yy < src -> gx_pixelmap_height - 1)
563                         {
564                             c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
565                             alpha[2] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width + xx);
566                         }
567                     }
568                     else
569                     {
570                         /* handle bottom edge. */
571                         a = *(get + yy * src -> gx_pixelmap_width + xx);
572                         alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
573 
574                         b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
575                         alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width + xx + 1);
576                     }
577 
578                     if (!a)
579                     {
580                         alpha[0] = 0;
581                     }
582 
583                     if (!b)
584                     {
585                         alpha[1] = 0;
586                     }
587 
588                     if (!c)
589                     {
590                         alpha[2] = 0;
591                     }
592 
593                     if (!d)
594                     {
595                         alpha[3] = 0;
596                     }
597                 }
598 
599                 red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
600                                 REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
601                                 REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
602                                 REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
603 
604                 green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
605                                   GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
606                                   GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
607                                   GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
608 
609                 blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
610                                  BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
611                                  BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
612                                  BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
613 
614                 alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) + \
615                                      alpha[1] * xdiff * (256 - ydiff) +         \
616                                      alpha[2] * ydiff * (256 - xdiff) +         \
617                                      alpha[3] * xdiff * ydiff) >> 16);
618 
619                 if (alpha[0])
620                 {
621                     red /= alpha[0];
622                     green /=  alpha[0];
623                     blue /= alpha[0];
624                 }
625 
626                 red = red > 31 ? 31 : red;
627                 green = green > 63 ? 63 : green;
628                 blue = blue > 31 ? 31 : blue;
629 
630                 *put++ = ASSEMBLECOLOR(red, green, blue);
631                 *putalpha++ = (GX_UBYTE)alpha[0];
632             }
633             else
634             {
635                 put++;
636                 *putalpha++ = 0;
637             }
638         }
639     }
640 
641     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 /**************************************************************************/
_gx_utility_565rgb_pixelmap_simple_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)691 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     width = 0;
699     height = 0;
700 
701     destination -> gx_pixelmap_aux_data = GX_NULL;
702 
703     width = src -> gx_pixelmap_height;
704     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     destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(USHORT);
709     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
710 
711     if (destination -> gx_pixelmap_data == GX_NULL)
712     {
713         return GX_SYSTEM_MEMORY_ERROR;
714     }
715 
716     if (angle == 90)
717     {
718         put = (USHORT *)destination -> gx_pixelmap_data;
719 
720         for (y = 0; y < height; y++)
721         {
722             for (x = 0; x < width; x++)
723             {
724                 get = (USHORT *)src -> gx_pixelmap_data;
725                 get += (width - 1 - x) * height;
726                 get += y;
727 
728                 *put++ = *get;
729             }
730         }
731 
732         if (rot_cx && rot_cy)
733         {
734             x = *rot_cx;
735             y = *rot_cy;
736 
737             *rot_cx = (width - 1 - y);
738             *rot_cy = x;
739         }
740     }
741     else if (angle == 180)
742     {
743         GX_SWAP_VALS(width, height);
744 
745         put = (USHORT *)destination -> gx_pixelmap_data;
746 
747         for (y = 0; y < height; y++)
748         {
749             for (x = 0; x < width; x++)
750             {
751                 get = (USHORT *)src -> gx_pixelmap_data;
752                 get += (height - 1 - y) * width;
753                 get += width - 1 - x;
754 
755                 *put++ = *get;
756             }
757         }
758 
759         if (rot_cx && rot_cy)
760         {
761             x = *rot_cx;
762             y = *rot_cy;
763 
764             *rot_cx = (width - 1 - x);
765             *rot_cy = (height - 1 - y);
766         }
767     }
768     else
769     {
770         /* angle = 270. */
771         put = (USHORT *)destination -> gx_pixelmap_data;
772 
773         for (y = 0; y < height; y++)
774         {
775             for (x = 0; x < width; x++)
776             {
777                 get = (USHORT *)src -> gx_pixelmap_data;
778                 get += x * height;
779                 get += height - 1 - y;
780 
781                 *put++ = *get;
782             }
783         }
784 
785         if (rot_cx && rot_cy)
786         {
787             x = *rot_cx;
788             y = *rot_cy;
789 
790             *rot_cx = y;
791             *rot_cy = (height - 1 - x);
792         }
793     }
794 
795     destination -> gx_pixelmap_height = (GX_VALUE)height;
796     destination -> gx_pixelmap_width = (GX_VALUE)width;
797 
798     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 /**************************************************************************/
_gx_utility_565rgb_pixelmap_simple_alpha_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)848 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     width = src -> gx_pixelmap_height;
858     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     destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(USHORT);
863     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
864 
865     if (destination -> gx_pixelmap_data == GX_NULL)
866     {
867         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     destination -> gx_pixelmap_aux_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
873     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
874 
875     if (destination -> gx_pixelmap_aux_data == GX_NULL)
876     {
877         _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
878         return GX_SYSTEM_MEMORY_ERROR;
879     }
880 
881     if (angle == 90)
882     {
883         put = (USHORT *)destination -> gx_pixelmap_data;
884         putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
885 
886         for (y = 0; y < height; y++)
887         {
888             for (x = 0; x < width; x++)
889             {
890                 get = (USHORT *)src -> gx_pixelmap_data;
891                 get += (width - 1 - x) * height;
892                 get += y;
893 
894                 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
895                 getalpha += (width - 1 - x) * height;
896                 getalpha += y;
897 
898                 *put++ = *get;
899                 *putalpha++ = *getalpha;
900             }
901         }
902 
903         if (rot_cx && rot_cy)
904         {
905             x = *rot_cx;
906             y = *rot_cy;
907 
908             /* Get new rotation point. */
909             *rot_cx = (width - 1 - y);
910             *rot_cy = x;
911         }
912     }
913     else if (angle == 180)
914     {
915         GX_SWAP_VALS(width, height);
916 
917         put = (USHORT *)destination -> gx_pixelmap_data;
918         putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
919 
920         for (y = 0; y < height; y++)
921         {
922             for (x = 0; x < width; x++)
923             {
924                 get = (USHORT *)src -> gx_pixelmap_data;
925                 get += (height - 1 - y) * width;
926                 get += width - 1 - x;
927 
928                 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
929                 getalpha += (height - 1 - y) * width;
930                 getalpha += width - 1 - x;
931 
932                 *put++ = *get;
933                 *putalpha++ = *getalpha;
934             }
935         }
936 
937         if (rot_cx && rot_cy)
938         {
939             x = *rot_cx;
940             y = *rot_cy;
941 
942             /* Get new rotation point. */
943             *rot_cx = (width - 1 - x);
944             *rot_cy = (height - 1 - y);
945         }
946     }
947     else
948     {
949         /* angle = 270. */
950         put = (USHORT *)destination -> gx_pixelmap_data;
951         putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
952 
953         for (y = 0; y < height; y++)
954         {
955             for (x = 0; x < width; x++)
956             {
957                 get = (USHORT *)src -> gx_pixelmap_data;
958                 get += x * height;
959                 get += height - 1 - y;
960 
961                 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
962                 getalpha += x * height;
963                 getalpha += height - 1 - y;
964 
965                 *put++ = *get;
966                 *putalpha++ = *getalpha;
967             }
968         }
969 
970         if (rot_cx && rot_cy)
971         {
972             x = *rot_cx;
973             y = *rot_cy;
974 
975             /* Get new rotation point. */
976             *rot_cx = y;
977             *rot_cy = (height - 1 - x);
978         }
979     }
980 
981     destination -> gx_pixelmap_height = (GX_VALUE)height;
982     destination -> gx_pixelmap_width = (GX_VALUE)width;
983 
984     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 /**************************************************************************/
_gx_utility_565rgb_pixelmap_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)1040 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     if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
1045     {
1046         /* alpha, no compression */
1047         status = _gx_utility_565rgb_pixelmap_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
1048     }
1049     else
1050     {
1051         /* no compression or alpha */
1052         status = _gx_utility_565rgb_pixelmap_raw_rotate(src, angle, destination, rot_cx, rot_cy);
1053     }
1054 
1055     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 /**************************************************************************/
_gx_utility_565rgb_pixelmap_simple_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)1111 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     if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
1116     {
1117         /* alpha, no compression */
1118         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         status = _gx_utility_565rgb_pixelmap_simple_raw_rotate(src, angle, destination, rot_cx, rot_cy);
1124     }
1125 
1126     return status;
1127 }
1128 
1129