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) >> 10) & 0x1f)
22 #define GREENVAL(_c) (GX_UBYTE)(((_c) >> 5) & 0x1f)
23 #define BLUEVAL(_c)  (GX_UBYTE)(((_c)) & 0x1f)
24 
25 #define ASSEMBLECOLOR(_r, _g, _b)    \
26     (USHORT)((((_r) & 0x1f) << 10) | \
27              (((_g) & 0x1f) << 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_1555xrgb_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 1555xrgb format pixelmap    */
54 /*    without compression, 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_1555xrgb_pixelmap_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)90 static UINT _gx_utility_1555xrgb_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 
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 = (INT)*rot_cx;
150         srcyres = (INT)*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(USHORT);
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     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
177        overflow cannot occur. */
178     destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
179     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
180 
181     if (destination -> gx_pixelmap_aux_data == GX_NULL)
182     {
183         _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
184 
185         return GX_SYSTEM_MEMORY_ERROR;
186     }
187 
188     put = (USHORT *)destination -> gx_pixelmap_data;
189     putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
190 
191     /* Loop through the destination's pixels.  */
192     for (y = 0; y < height; y++)
193     {
194         for (x = 0; x < width; x++)
195         {
196             xx = (x - xres) * cosv + (y - yres) * sinv;
197             yy = (y - yres) * cosv - (x - xres) * sinv;
198 
199             xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
200             ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
201 
202             xx = GX_FIXED_VAL_TO_INT(xx);
203             yy = GX_FIXED_VAL_TO_INT(yy);
204 
205             xx += srcxres;
206             yy += srcyres;
207 
208             if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
209                 (yy >= -1) && (yy < src -> gx_pixelmap_height))
210             {
211                 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
212                     (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
213                 {
214                     get = (USHORT *)src -> gx_pixelmap_data;
215                     get += yy * src -> gx_pixelmap_width;
216                     get += xx;
217 
218                     a = *get;
219                     b = *(get + 1);
220                     c = *(get + src -> gx_pixelmap_width);
221                     d = *(get + src -> gx_pixelmap_width + 1);
222 
223                     alpha = 0xff;
224                 }
225                 else
226                 {
227                     get = (USHORT *)src -> gx_pixelmap_data;
228 
229                     a = 0;
230                     b = 0;
231                     c = 0;
232                     d = 0;
233                     alpha = 0;
234 
235                     if (xx == -1)
236                     {
237                         /* handle left edge.  */
238                         if (yy >= 0)
239                         {
240                             b = *(get + yy * src -> gx_pixelmap_width);
241                             alpha += xdiff * (256 - ydiff);
242                         }
243 
244                         if (yy < src -> gx_pixelmap_height - 1)
245                         {
246                             d = *(get + (yy + 1) * src -> gx_pixelmap_width);
247                             alpha += xdiff * ydiff;
248                         }
249                     }
250                     else if (yy == -1)
251                     {
252                         /* handle top edge.  */
253                         c = *(get + xx);
254                         alpha += ydiff * (256 - xdiff);
255 
256                         if (xx < src -> gx_pixelmap_width - 1)
257                         {
258                             d = *(get + xx + 1);
259                             alpha += xdiff * ydiff;
260                         }
261                     }
262                     else if (xx == src -> gx_pixelmap_width - 1)
263                     {
264                         /* handle right edget. */
265                         a = *(get + yy * src -> gx_pixelmap_width + xx);
266                         alpha += (256 - xdiff) * (256 - ydiff);
267 
268                         if (yy < src -> gx_pixelmap_height - 1)
269                         {
270                             c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
271                             alpha += ydiff * (256 - xdiff);
272                         }
273                     }
274                     else
275                     {
276                         /* handle bottom edge. */
277                         a = *(get + yy * src -> gx_pixelmap_width + xx);
278                         alpha += (256 - xdiff) * (256 - ydiff);
279 
280                         b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
281                         alpha += xdiff * (256 - ydiff);
282                     }
283 
284                     alpha >>= 8;
285                 }
286 
287                 red = (USHORT)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) + \
288                                 REDVAL(b) * xdiff * (256 - ydiff) +         \
289                                 REDVAL(c) * ydiff * (256 - xdiff) +         \
290                                 REDVAL(d) * xdiff * ydiff) >> 16);
291 
292                 green = (USHORT)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) + \
293                                   GREENVAL(b) * xdiff * (256 - ydiff) +         \
294                                   GREENVAL(c) * ydiff * (256 - xdiff) +         \
295                                   GREENVAL(d) * xdiff * ydiff) >> 16);
296 
297                 blue = (USHORT)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) + \
298                                  BLUEVAL(b) * xdiff * (256 - ydiff) +         \
299                                  BLUEVAL(c) * ydiff * (256 - xdiff) +         \
300                                  BLUEVAL(d) * xdiff * ydiff) >> 16);
301 
302                 if (alpha && (alpha < 0xff))
303                 {
304                     red = (USHORT)((red << 8) / alpha);
305                     green = (USHORT)((green << 8) / alpha);
306                     blue = (USHORT)((blue << 8) / alpha);
307                 }
308 
309                 red = red > 31 ? 31 : red;
310                 green = green > 63 ? 63 : green;
311                 blue = blue > 31 ? 31 : blue;
312                 alpha = alpha > 255 ? 255 : alpha;
313 
314                 *put++ = ASSEMBLECOLOR(red, green, blue);
315                 *putalpha++ = (GX_UBYTE)alpha;
316             }
317             else
318             {
319                 put++;
320                 *putalpha++ = 0;
321             }
322         }
323     }
324 
325     return GX_SUCCESS;
326 }
327 
328 /**************************************************************************/
329 /*                                                                        */
330 /*  FUNCTION                                               RELEASE        */
331 /*                                                                        */
332 /*    _gx_utility_1555xrgb_pixelmap_alpha_rotate          PORTABLE C      */
333 /*                                                           6.1          */
334 /*  AUTHOR                                                                */
335 /*                                                                        */
336 /*    Kenneth Maxwell, Microsoft Corporation                              */
337 /*                                                                        */
338 /*  DESCRIPTION                                                           */
339 /*                                                                        */
340 /*    Internal helper function that rotate an 1555xrgb format pixelmap    */
341 /*    without compression, with alpha.                                    */
342 /*                                                                        */
343 /*  INPUT                                                                 */
344 /*                                                                        */
345 /*    src                                   The pixelmap to be rotated    */
346 /*    angle                                 The angle to be rotated       */
347 /*    destination                           The rotated bitmap to be      */
348 /*                                            returned                    */
349 /*    rot_cx                                X coordinate of rotation      */
350 /*                                            center                      */
351 /*    rot_cy                                Y coordinate of rotation      */
352 /*                                            center                      */
353 /*                                                                        */
354 /*  OUTPUT                                                                */
355 /*                                                                        */
356 /*    status                                Completion status             */
357 /*                                                                        */
358 /*  CALLS                                                                 */
359 /*                                                                        */
360 /*    _gx_system_memory_allocator           Memory Allocation routine     */
361 /*    _gx_utility_math_cos                  Compute the cosine value      */
362 /*    _gx_utility_math_sin                  Compute the sine value        */
363 /*                                                                        */
364 /*  CALLED BY                                                             */
365 /*                                                                        */
366 /*    GUIX Internal Code                                                  */
367 /*                                                                        */
368 /*  RELEASE HISTORY                                                       */
369 /*                                                                        */
370 /*    DATE              NAME                      DESCRIPTION             */
371 /*                                                                        */
372 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
373 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
374 /*                                            resulting in version 6.1    */
375 /*                                                                        */
376 /**************************************************************************/
_gx_utility_1555xrgb_pixelmap_alpha_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)377 static UINT _gx_utility_1555xrgb_pixelmap_alpha_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
378 {
379 USHORT   *put;
380 USHORT   *get;
381 GX_UBYTE *putalpha;
382 GX_UBYTE *getalpha;
383 INT       srcxres;
384 INT       srcyres;
385 INT       cosv;
386 INT       sinv;
387 USHORT    red, green, blue;
388 INT       idxminx, idxmaxx, idxmaxy;
389 INT      *mx;
390 INT      *my;
391 INT       xres;
392 INT       yres;
393 INT       width, height;
394 INT       x, y;
395 INT       xx, yy;
396 USHORT    a, b, c, d;
397 USHORT    alpha[4];
398 INT       xdiff, ydiff;
399 
400     idxminx = (angle / 90) & 0x3;
401     idxmaxx = (idxminx + 2) & 0x3;
402     idxmaxy = (idxminx + 1) & 0x3;
403 
404     mx = _gx_system_scratchpad;
405     my = mx + 4;
406 
407     mx[0] = mx[3] = -1;
408     mx[1] = mx[2] = 1;
409 
410     my[0] = my[1] = 1;
411     my[2] = my[3] = -1;
412 
413     /* Calculate the source x and y center. */
414     srcxres = src -> gx_pixelmap_width >> 1;
415     srcyres = src -> gx_pixelmap_height >> 1;
416 
417     cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
418     sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
419 
420     xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
421     yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
422 
423     xres = GX_FIXED_VAL_TO_INT(xres);
424     yres = GX_FIXED_VAL_TO_INT(yres);
425 
426     /* Calculate destination width and height. */
427     width = (xres << 1);
428     height = (yres << 1);
429 
430     /* Calculate the new rotation axis. */
431     if (rot_cx && rot_cy)
432     {
433         x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
434         y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
435 
436         srcxres = *rot_cx;
437         srcyres = *rot_cy;
438 
439         x = GX_FIXED_VAL_TO_INT(x) + xres;
440         y = GX_FIXED_VAL_TO_INT(y) + yres;
441 
442         *rot_cx = x;
443         *rot_cy = y;
444 
445         xres = *rot_cx;
446         yres = *rot_cy;
447     }
448 
449     destination -> gx_pixelmap_height = (GX_VALUE)height;
450     destination -> gx_pixelmap_width = (GX_VALUE)width;
451     destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
452 
453     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
454        overflow cannot occur. */
455     destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
456     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
457 
458     if (destination -> gx_pixelmap_data == GX_NULL)
459     {
460         return GX_SYSTEM_MEMORY_ERROR;
461     }
462 
463     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
464        overflow cannot occur. */
465     destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
466     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
467 
468     if (destination -> gx_pixelmap_aux_data == GX_NULL)
469     {
470         _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
471 
472         return GX_SYSTEM_MEMORY_ERROR;
473     }
474 
475     put = (USHORT *)destination -> gx_pixelmap_data;
476     putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
477 
478     /* Loop through the destination's pixels.  */
479     for (y = 0; y < height; y++)
480     {
481         for (x = 0; x < width; x++)
482         {
483             xx = (x - xres) * cosv + (y - yres) * sinv;
484             yy = (y - yres) * cosv - (x - xres) * sinv;
485 
486             xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
487             ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
488 
489             xx = GX_FIXED_VAL_TO_INT(xx);
490             yy = GX_FIXED_VAL_TO_INT(yy);
491 
492             xx += srcxres;
493             yy += srcyres;
494 
495             if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
496                 (yy >= -1) && (yy < src -> gx_pixelmap_height))
497             {
498 
499                 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
500                     (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
501                 {
502                     get = (USHORT *)src -> gx_pixelmap_data;
503                     get += yy * src -> gx_pixelmap_width;
504                     get += xx;
505 
506                     getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
507                     getalpha += yy * src -> gx_pixelmap_width;
508                     getalpha += xx;
509 
510                     a = *get;
511                     alpha[0] = *getalpha;
512 
513                     b = *(get + 1);
514                     alpha[1] = *(getalpha + 1);
515 
516                     c = *(get + src -> gx_pixelmap_width);
517                     alpha[2] = *(getalpha + src -> gx_pixelmap_width);
518 
519                     d = *(get + src -> gx_pixelmap_width + 1);
520                     alpha[3] = *(getalpha + src -> gx_pixelmap_width + 1);
521                 }
522                 else
523                 {
524                     get = (USHORT *)src -> gx_pixelmap_data;
525                     getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
526 
527                     a = 0;
528                     b = 0;
529                     c = 0;
530                     d = 0;
531 
532                     if (xx == -1)
533                     {
534                         /* handle left edge.  */
535                         if (yy >= 0)
536                         {
537                             b = *(get + yy * src -> gx_pixelmap_width);
538                             alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width);
539                         }
540 
541                         if (yy < src -> gx_pixelmap_height - 1)
542                         {
543                             d = *(get + (yy + 1) * src -> gx_pixelmap_width);
544                             alpha[3] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width);
545                         }
546                     }
547                     else if (yy == -1)
548                     {
549                         /* handle top edge.  */
550                         c = *(get + xx);
551                         alpha[2] = *(getalpha + xx);
552 
553                         if (xx < src -> gx_pixelmap_width - 1)
554                         {
555                             d = *(get + xx + 1);
556                             alpha[3] = *(getalpha + xx + 1);
557                         }
558                     }
559                     else if (xx == src -> gx_pixelmap_width - 1)
560                     {
561                         /* handle right edget. */
562                         a = *(get + yy * src -> gx_pixelmap_width + xx);
563                         alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
564 
565                         if (yy < src -> gx_pixelmap_height - 1)
566                         {
567                             c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
568                             alpha[2] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width + xx);
569                         }
570                     }
571                     else
572                     {
573                         /* handle bottom edge. */
574                         a = *(get + yy * src -> gx_pixelmap_width + xx);
575                         alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
576 
577                         b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
578                         alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width + xx + 1);
579                     }
580 
581                     if (!a)
582                     {
583                         alpha[0] = 0;
584                     }
585 
586                     if (!b)
587                     {
588                         alpha[1] = 0;
589                     }
590 
591                     if (!c)
592                     {
593                         alpha[2] = 0;
594                     }
595 
596                     if (!d)
597                     {
598                         alpha[3] = 0;
599                     }
600                 }
601 
602                 red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
603                                 REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
604                                 REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
605                                 REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
606 
607                 green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
608                                   GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
609                                   GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
610                                   GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
611 
612                 blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
613                                  BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) +         \
614                                  BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) +         \
615                                  BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
616 
617                 alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) + \
618                                      alpha[1] * xdiff * (256 - ydiff) +         \
619                                      alpha[2] * ydiff * (256 - xdiff) +         \
620                                      alpha[3] * xdiff * ydiff) >> 16);
621 
622                 if (alpha[0])
623                 {
624                     red /= alpha[0];
625                     green /= alpha[0];
626                     blue /= alpha[0];
627                 }
628 
629                 red = red > 31 ? 31 : red;
630                 green = green > 63 ? 63 : green;
631                 blue = blue > 31 ? 31 : blue;
632 
633                 *put++ = ASSEMBLECOLOR(red, green, blue);
634                 *putalpha++ = (GX_UBYTE)alpha[0];
635             }
636             else
637             {
638                 put++;
639                 *putalpha++ = 0;
640             }
641         }
642     }
643 
644     return GX_SUCCESS;
645 }
646 
647 /**************************************************************************/
648 /*                                                                        */
649 /*  FUNCTION                                               RELEASE        */
650 /*                                                                        */
651 /*    _gx_utility_1555xrgb_pixelmap_rotate                PORTABLE C      */
652 /*                                                           6.1          */
653 /*  AUTHOR                                                                */
654 /*                                                                        */
655 /*    Kenneth Maxwell, Microsoft Corporation                              */
656 /*                                                                        */
657 /*  DESCRIPTION                                                           */
658 /*                                                                        */
659 /*    This function rotates an 1555xrgb format uncompressed pixelmap with */
660 /*    or without alpha channel.                                           */
661 /*                                                                        */
662 /*  INPUT                                                                 */
663 /*                                                                        */
664 /*    src                                   The pixelmap to be rotated    */
665 /*    angle                                 The angle to be rotated       */
666 /*    destination                           The rotated bitmap to be      */
667 /*                                            returned                    */
668 /*    rot_cx                                X coordinate of rotation      */
669 /*                                            center                      */
670 /*    rot_cy                                Y coordinate of rotation      */
671 /*                                            center                      */
672 /*                                                                        */
673 /*  OUTPUT                                                                */
674 /*                                                                        */
675 /*    status                                Completion status             */
676 /*                                                                        */
677 /*  CALLS                                                                 */
678 /*                                                                        */
679 /*     _gx_utility_1555xrgb_pixelmap_raw_rotate                           */
680 /*                                          Rotate 1555xrgb format        */
681 /*                                            pixlemap without alpha      */
682 /*     _gx_utility_1555xrgb_pixelmap_alpha_rotate                         */
683 /*                                          Rotate 1555xrgb format        */
684 /*                                            pixelmap with alpha         */
685 /*                                                                        */
686 /*  CALLED BY                                                             */
687 /*                                                                        */
688 /*    GUIX Internal Code                                                  */
689 /*                                                                        */
690 /*  RELEASE HISTORY                                                       */
691 /*                                                                        */
692 /*    DATE              NAME                      DESCRIPTION             */
693 /*                                                                        */
694 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
695 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
696 /*                                            resulting in version 6.1    */
697 /*                                                                        */
698 /**************************************************************************/
_gx_utility_1555xrgb_pixelmap_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)699 UINT _gx_utility_1555xrgb_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
700 {
701 UINT status;
702 
703     if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
704     {
705         /* alpha, no compression */
706         status = _gx_utility_1555xrgb_pixelmap_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
707     }
708     else
709     {
710         /* no compression or alpha */
711         status = _gx_utility_1555xrgb_pixelmap_raw_rotate(src, angle, destination, rot_cx, rot_cy);
712     }
713 
714     return status;
715 }
716 
717