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 GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_display.h"
28 #include "gx_context.h"
29 #include "gx_utility.h"
30 #include "gx_system.h"
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_utility_4bpp_pixelmap_rotate                    PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    4bpp pixelmap rotation function that handles uncompress, with or    */
45 /*    without alpha channel.                                              */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    src                                   The pixelmap to be rotated    */
50 /*    angle                                 The angle to be rotated       */
51 /*    destination                           The rotated bitmap to be      */
52 /*                                            returned                    */
53 /*    rot_cx                                X coordinate of rotation      */
54 /*                                            center                      */
55 /*    rot_cy                                Y coordinate of rotation      */
56 /*                                            center                      */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    None                                                                */
61 /*                                                                        */
62 /*  CALLS                                                                 */
63 /*                                                                        */
64 /*    _gx_system_memory_allocator           Memory Allocation routine     */
65 /*    _gx_utility_math_cos                  Compute the cosine value      */
66 /*    _gx_utility_math_sin                  Compute the sine value        */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    Application Code                                                    */
71 /*                                                                        */
72 /*  RELEASE HISTORY                                                       */
73 /*                                                                        */
74 /*    DATE              NAME                      DESCRIPTION             */
75 /*                                                                        */
76 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
77 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
78 /*                                            resulting in version 6.1    */
79 /*                                                                        */
80 /**************************************************************************/
_gx_utility_4bpp_pixelmap_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)81 UINT _gx_utility_4bpp_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
82 {
83 GX_UBYTE *putrow;
84 GX_UBYTE *put;
85 GX_UBYTE *get;
86 INT       srcxres;
87 INT       srcyres;
88 INT       cosv;
89 INT       sinv;
90 INT       idxminx, idxmaxx, idxmaxy;
91 INT       mx[] = {-1, 1, 1, -1};
92 INT       my[] = {1, 1, -1, -1};
93 INT       xres;
94 INT       yres;
95 INT       width, height;
96 INT       x, y;
97 INT       xx, yy;
98 INT       putstride;
99 INT       getstride;
100 INT       putauxstride;
101 INT       getauxstride;
102 GX_UBYTE  putmask;
103 GX_UBYTE  pixel;
104 GX_UBYTE *putaux;
105 GX_UBYTE *putauxrow;
106 GX_UBYTE  putauxmask;
107 GX_UBYTE  transmask;
108 GX_UBYTE *getaux;
109 GX_BOOL   draw = GX_TRUE;
110 
111     idxminx = (angle / 90) & 0x3;
112     idxmaxx = (idxminx + 2) & 0x3;
113     idxmaxy = (idxminx + 1) & 0x3;
114 
115     /* Calculate the source x and y center. */
116     srcxres = src -> gx_pixelmap_width >> 1;
117     srcyres = src -> gx_pixelmap_height >> 1;
118 
119     cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
120     sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
121 
122     xres = GX_FIXED_VAL_TO_INT((mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv));
123     yres = GX_FIXED_VAL_TO_INT((my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv));
124 
125     /* Calculate destination width and height. */
126     width = (xres << 1);
127     height = (yres << 1);
128 
129     if (rot_cx && rot_cy)
130     {
131         /* Calculate the new rotation axis. */
132         x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
133         y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
134 
135         x = GX_FIXED_VAL_TO_INT(x) + xres;
136         y = GX_FIXED_VAL_TO_INT(y) + yres;
137 
138         srcxres = *rot_cx;
139         srcyres = *rot_cy;
140 
141         *rot_cx = x;
142         *rot_cy = y;
143 
144         xres = *rot_cx;
145         yres = *rot_cy;
146     }
147 
148     /* Set width and height of destination pixelmap.  */
149     destination -> gx_pixelmap_width = (GX_VALUE)width;
150     destination -> gx_pixelmap_height = (GX_VALUE)height;
151     destination -> gx_pixelmap_flags |= GX_PIXELMAP_TRANSPARENT;
152     putstride = (width + 1) >> 1;
153     putauxstride = (width + 7) >> 3;
154     getstride = (src -> gx_pixelmap_width + 1) >> 1;
155     getauxstride = 0;
156 
157     if (src -> gx_pixelmap_flags & GX_PIXELMAP_TRANSPARENT)
158     {
159         getauxstride = (src -> gx_pixelmap_width + 7) >> 3;
160     }
161 
162     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
163        overflow cannot occur. */
164     destination -> gx_pixelmap_data_size = (UINT)(putstride * height) * sizeof(GX_UBYTE);
165 
166     /* Allocate memory for destination pixelmap to load pixel information.  */
167     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
168 
169     if (destination -> gx_pixelmap_data == GX_NULL)
170     {
171         return GX_SYSTEM_MEMORY_ERROR;
172     }
173 
174     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
175        overflow cannot occur. */
176     destination -> gx_pixelmap_aux_data_size = (UINT)(putauxstride * height) * sizeof(GX_UBYTE);
177 
178     /* Allocate memory for destination pixelmap to load pixel information.  */
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         return GX_SYSTEM_MEMORY_ERROR;
185     }
186 
187     putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
188     putauxrow = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
189 
190     /* For every pixel in destination bitmap, find its position in source bitmap,
191        and set the pixel with the value in source bitmap.  */
192     for (y = 0; y < height; y++)
193     {
194         put = putrow;
195         putaux = putauxrow;
196         putmask = 0xf0;
197         putauxmask = 0x80;
198 
199         for (x = 0; x < width; x++)
200         {
201             xx = GX_FIXED_VAL_TO_INT((x - xres) * cosv + (y - yres) * sinv);
202             yy = GX_FIXED_VAL_TO_INT((y - yres) * cosv - (x - xres) * sinv);
203 
204             xx += srcxres;
205             yy += srcyres;
206 
207             if (getauxstride)
208             {
209                 getaux = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
210                 getaux += yy * getauxstride;
211                 getaux += xx >> 3;
212                 transmask = (GX_UBYTE)(0x80 >> (xx & 0x07));
213 
214                 if (transmask & (*getaux))
215                 {
216                     draw = GX_FALSE;
217                 }
218                 else
219                 {
220                     draw = GX_TRUE;
221                 }
222             }
223 
224             /* Set bits first. */
225             *put &= (GX_UBYTE)(~putmask);
226             if (draw && (xx >= 0) && (xx < src -> gx_pixelmap_width) &&
227                 (yy >= 0) && (yy < src -> gx_pixelmap_height))
228             {
229                 get = (GX_UBYTE *)src -> gx_pixelmap_data;
230                 get += yy * getstride;
231                 get += xx >> 1;
232 
233                 if (xx & 1)
234                 {
235                     pixel = *get & 0x0f;
236                 }
237                 else
238                 {
239                     pixel = (*get & 0xf0) >> 4;
240                 }
241                 pixel |= (GX_UBYTE)(pixel << 4);
242                 /* set pixel */
243                 *put |= pixel & putmask;
244                 /* Set transparent info. */
245                 *putaux &= (GX_UBYTE)(~putauxmask);
246             }
247             else
248             {
249                 *putaux |= putauxmask;
250             }
251 
252             putauxmask >>= 1;
253             if (putauxmask == 0)
254             {
255                 putaux++;
256                 putauxmask = 0x80;
257             }
258 
259             putmask >>= 4;
260             if (putmask == 0)
261             {
262                 put++;
263                 putmask = 0xf0;
264             }
265         }
266         putrow += putstride;
267         putauxrow += putauxstride;
268     }
269 
270     return GX_SUCCESS;
271 }
272 /**************************************************************************/
273 /*                                                                        */
274 /*  FUNCTION                                               RELEASE        */
275 /*                                                                        */
276 /*    _gx_utility_4bpp_pixelmap_simple_raw_rotate         PORTABLE C      */
277 /*                                                           6.1          */
278 /*  AUTHOR                                                                */
279 /*                                                                        */
280 /*    Kenneth Maxwell, Microsoft Corporation                              */
281 /*                                                                        */
282 /*  DESCRIPTION                                                           */
283 /*                                                                        */
284 /*    Internal helper function that handles 90, 180 and 270 degree        */
285 /*      rotation of an uncompressed pixelmap with or wihout alpha.        */
286 /*                                                                        */
287 /*  INPUT                                                                 */
288 /*                                                                        */
289 /*    src                                   The pixelmap to be rotated    */
290 /*    angle                                 The angle to be rotated       */
291 /*    destination                           The rotated bitmap to be      */
292 /*                                            returned                    */
293 /*    rot_cx                                X coordinate of rotation      */
294 /*                                            center                      */
295 /*    rot_cy                                Y coordinate of rotation      */
296 /*                                            center                      */
297 /*                                                                        */
298 /*  OUTPUT                                                                */
299 /*                                                                        */
300 /*    None                                                                */
301 /*                                                                        */
302 /*  CALLS                                                                 */
303 /*                                                                        */
304 /*    _gx_system_memory_allocator           Memory Allocation routine     */
305 /*                                                                        */
306 /*  CALLED BY                                                             */
307 /*                                                                        */
308 /*   _gx_utility_4bpp_pixelmap_simple_rotate                              */
309 /*                                                                        */
310 /*  RELEASE HISTORY                                                       */
311 /*                                                                        */
312 /*    DATE              NAME                      DESCRIPTION             */
313 /*                                                                        */
314 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
315 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
316 /*                                            resulting in version 6.1    */
317 /*                                                                        */
318 /**************************************************************************/
_gx_utility_4bpp_pixelmap_simple_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)319 static UINT _gx_utility_4bpp_pixelmap_simple_raw_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
320 {
321 GX_UBYTE *put;
322 GX_UBYTE *putrow;
323 GX_UBYTE *get;
324 INT       width, height;
325 INT       x, y;
326 INT       putstride;
327 GX_UBYTE  putmask;
328 GX_UBYTE  pixel;
329 INT       getstride;
330 
331     getstride = (src -> gx_pixelmap_width + 1) >> 1;
332 
333     width = src -> gx_pixelmap_height;
334     height = src -> gx_pixelmap_width;
335 
336     if (angle == 180)
337     {
338         GX_SWAP_VALS(width, height);
339     }
340 
341     putstride = (width + 1) >> 1;
342 
343     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
344        overflow cannot occur. */
345     destination -> gx_pixelmap_data_size = (UINT)(putstride * height) * sizeof(GX_UBYTE);
346     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
347 
348     if (destination -> gx_pixelmap_data == GX_NULL)
349     {
350         return GX_SYSTEM_MEMORY_ERROR;
351     }
352 
353     if (angle == 90)
354     {
355         putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
356 
357         for (y = 0; y < height; y++)
358         {
359             put = putrow;
360             putmask = 0xf0;
361             for (x = 0; x < width; x++)
362             {
363                 get = (GX_UBYTE *)src -> gx_pixelmap_data;
364                 get += (width - 1 - x) * getstride;
365                 get += y >> 1;
366 
367                 if (y & 1)
368                 {
369                     pixel = *get & 0x0f;
370                 }
371                 else
372                 {
373                     pixel = (*get & 0xf0) >> 4;
374                 }
375                 pixel |= (GX_UBYTE)(pixel << 4);
376                 *put &= (GX_UBYTE)(~putmask);
377                 *put |= pixel & putmask;
378 
379                 putmask >>= 4;
380                 if (putmask == 0)
381                 {
382                     put++;
383                     putmask = 0xf0;
384                 }
385             }
386             putrow += putstride;
387         }
388 
389         if (rot_cx && rot_cy)
390         {
391             x = *rot_cx;
392             y = *rot_cy;
393 
394             *rot_cx = (width - 1 - y);
395             *rot_cy = x;
396         }
397     }
398     else if (angle == 180)
399     {
400         putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
401 
402         for (y = 0; y < height; y++)
403         {
404             put = putrow;
405             putmask = 0xf0;
406             for (x = 0; x < width; x++)
407             {
408                 get = (GX_UBYTE *)src -> gx_pixelmap_data;
409                 get += (height - 1 - y) * getstride;
410                 get += (width - 1 - x) >> 1;
411 
412                 if ((width - 1 - x) & 1)
413                 {
414                     pixel = *get & 0x0f;
415                 }
416                 else
417                 {
418                     pixel = (*get & 0xf0) >> 4;
419                 }
420                 pixel |= (GX_UBYTE)(pixel << 4);
421                 *put &= (GX_UBYTE)(~putmask);
422                 *put |= pixel & putmask;
423 
424                 putmask >>= 4;
425                 if (putmask == 0)
426                 {
427                     put++;
428                     putmask = 0xf0;
429                 }
430             }
431             putrow += putstride;
432         }
433 
434         if (rot_cx && rot_cy)
435         {
436             x = *rot_cx;
437             y = *rot_cy;
438 
439             *rot_cx = (width - 1 - x);
440             *rot_cy = (height - 1 - y);
441         }
442     }
443     else
444     {
445         /* angle = 270. */
446         putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
447 
448         for (y = 0; y < height; y++)
449         {
450             put = putrow;
451             putmask = 0xf0;
452 
453             for (x = 0; x < width; x++)
454             {
455                 get = (GX_UBYTE *)src -> gx_pixelmap_data;
456                 get += x * getstride;
457                 get += (height - 1 - y) >> 1;
458 
459                 if ((height - 1 - y) & 1)
460                 {
461                     pixel = *get & 0x0f;
462                 }
463                 else
464                 {
465                     pixel = (*get & 0xf0) >> 4;
466                 }
467                 pixel |= (GX_UBYTE)(pixel << 4);
468                 *put &= (GX_UBYTE)(~putmask);
469                 *put |= pixel & putmask;
470 
471                 putmask >>= 4;
472                 if (putmask == 0)
473                 {
474                     put++;
475                     putmask = 0xf0;
476                 }
477             }
478             putrow += putstride;
479         }
480 
481         if (rot_cx && rot_cy)
482         {
483             x = *rot_cx;
484             y = *rot_cy;
485 
486             *rot_cx = y;
487             *rot_cy = (height - 1 - x);
488         }
489     }
490 
491     destination -> gx_pixelmap_height = (GX_VALUE)height;
492     destination -> gx_pixelmap_width  = (GX_VALUE)width;
493 
494     return GX_SUCCESS;
495 }
496 
497 /**************************************************************************/
498 /*                                                                        */
499 /*  FUNCTION                                               RELEASE        */
500 /*                                                                        */
501 /*    _gx_utility_4bpp_pixelmap_simple_transparent_rotate PORTABLE C      */
502 /*                                                           6.1          */
503 /*  AUTHOR                                                                */
504 /*                                                                        */
505 /*    Kenneth Maxwell, Microsoft Corporation                              */
506 /*                                                                        */
507 /*  DESCRIPTION                                                           */
508 /*                                                                        */
509 /*    Internal helper function that handles 90, 180 and 270 degree        */
510 /*      rotation of an uncompressed pixelmap with or wihout alpha.        */
511 /*                                                                        */
512 /*  INPUT                                                                 */
513 /*                                                                        */
514 /*    src                                   The pixelmap to be rotated    */
515 /*    angle                                 The angle to be rotated       */
516 /*    destination                           The rotated bitmap to be      */
517 /*                                            returned                    */
518 /*    rot_cx                                X coordinate of rotation      */
519 /*                                            center                      */
520 /*    rot_cy                                Y coordinate of rotation      */
521 /*                                            center                      */
522 /*                                                                        */
523 /*  OUTPUT                                                                */
524 /*                                                                        */
525 /*    None                                                                */
526 /*                                                                        */
527 /*  CALLS                                                                 */
528 /*                                                                        */
529 /*    _gx_system_memory_allocator           Memory Allocation routine     */
530 /*                                                                        */
531 /*  CALLED BY                                                             */
532 /*                                                                        */
533 /*   _gx_utility_4bpp_pixelmap_simple_rotate                              */
534 /*                                                                        */
535 /*  RELEASE HISTORY                                                       */
536 /*                                                                        */
537 /*    DATE              NAME                      DESCRIPTION             */
538 /*                                                                        */
539 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
540 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
541 /*                                            resulting in version 6.1    */
542 /*                                                                        */
543 /**************************************************************************/
_gx_utility_4bpp_pixelmap_simple_transparent_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)544 static UINT _gx_utility_4bpp_pixelmap_simple_transparent_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
545 {
546 GX_UBYTE *put;
547 GX_UBYTE *putrow;
548 GX_UBYTE *putaux;
549 GX_UBYTE *putauxrow;
550 GX_UBYTE *get;
551 INT       width, height;
552 INT       x, y;
553 INT       putstride;
554 INT       putauxstride;
555 GX_UBYTE  putmask;
556 GX_UBYTE  pixel;
557 GX_UBYTE  transmask;
558 GX_UBYTE  putauxmask;
559 GX_UBYTE *getaux;
560 INT       getstride;
561 INT       getauxstride;
562 
563     getstride = (src -> gx_pixelmap_width + 1) >> 1;
564     getauxstride = (src -> gx_pixelmap_width + 7) >> 3;
565 
566     width = src -> gx_pixelmap_height;
567     height = src -> gx_pixelmap_width;
568 
569     if (angle == 180)
570     {
571         GX_SWAP_VALS(width, height);
572     }
573 
574     putstride = (width + 1) >> 1;
575     putauxstride = (width + 7) >> 3;
576 
577     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
578        overflow cannot occur. */
579     destination -> gx_pixelmap_data_size = (UINT)(putstride * height) * sizeof(GX_UBYTE);
580     destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
581 
582     if (destination -> gx_pixelmap_data == GX_NULL)
583     {
584         return GX_SYSTEM_MEMORY_ERROR;
585     }
586 
587     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
588        overflow cannot occur. */
589     destination -> gx_pixelmap_aux_data_size = (UINT)(putauxstride * height) * sizeof(GX_UBYTE);
590     destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
591 
592     if (destination -> gx_pixelmap_aux_data == GX_NULL)
593     {
594         _gx_system_memory_free((void *)destination -> gx_pixelmap_data);
595         return GX_SYSTEM_MEMORY_ERROR;
596     }
597 
598     if (angle == 90)
599     {
600         putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
601         putauxrow = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
602 
603         for (y = 0; y < height; y++)
604         {
605             put = putrow;
606             putaux = putauxrow;
607             putmask = 0xf0;
608             putauxmask = 0x80;
609             for (x = 0; x < width; x++)
610             {
611                 /* set bits first. */
612                 *put &= (GX_UBYTE)(~putmask);
613                 getaux = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
614                 getaux += (width - 1 - x) * getauxstride;
615                 getaux += y >> 3;
616 
617                 transmask = (GX_UBYTE)(0x80 >> (y & 0x07));
618                 if (transmask & (*getaux))
619                 {
620                     /* transparent pixel, set destination true */
621                     *putaux |= putauxmask;
622                 }
623                 else
624                 {
625                     /* not transparent, set destination bit to 0. */
626                     *putaux &= (GX_UBYTE)(~putauxmask);
627 
628                     get = (GX_UBYTE *)src -> gx_pixelmap_data;
629                     get += (width - 1 - x) * getstride;
630                     get += y >> 1;
631 
632                     if (y & 1)
633                     {
634                         pixel = *get & 0x0f;
635                     }
636                     else
637                     {
638                         pixel = (*get & 0xf0) >> 4;
639                     }
640                     pixel |= (GX_UBYTE)(pixel << 4);
641 
642                     /* set data. */
643                     *put |= pixel & putmask;
644                 }
645 
646                 putmask >>= 4;
647                 if (putmask == 0)
648                 {
649                     put++;
650                     putmask = 0xf0;
651                 }
652                 putauxmask >>= 1;
653                 if (putauxmask == 0)
654                 {
655                     putaux++;
656                     putauxmask = 0x80;
657                 }
658             }
659             putrow += putstride;
660             putauxrow += putauxstride;
661         }
662 
663         if (rot_cx && rot_cy)
664         {
665             x = *rot_cx;
666             y = *rot_cy;
667 
668             *rot_cx = (width - 1 - y);
669             *rot_cy = x;
670         }
671     }
672     else if (angle == 180)
673     {
674         putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
675         putauxrow = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
676 
677         for (y = 0; y < height; y++)
678         {
679             put = putrow;
680             putaux = putauxrow;
681             putmask = 0xf0;
682             putauxmask = 0x80;
683             for (x = 0; x < width; x++)
684             {
685                 /* set bits first. */
686                 *put &= (GX_UBYTE)(~putmask);
687                 getaux = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
688                 getaux += (height - 1 - y) * getauxstride;
689                 getaux += (width - 1 - x) >> 3;
690 
691                 transmask = (GX_UBYTE)(0x80 >> ((width - 1 - x) & 0x07));
692                 if (transmask & (*getaux))
693                 {
694                     /* transparent pixel, set destination true */
695                     *putaux |= putauxmask;
696                 }
697                 else
698                 {
699                     /* not transparent, set destination bit to 0. */
700                     *putaux &= (GX_UBYTE)(~putauxmask);
701 
702                     get = (GX_UBYTE *)src -> gx_pixelmap_data;
703                     get += (height - 1 - y) * getstride;
704                     get += (width - 1 - x) >> 1;
705 
706                     if ((width - 1 - x) & 1)
707                     {
708                         pixel = *get & 0x0f;
709                     }
710                     else
711                     {
712                         pixel = (*get & 0xf0) >> 4;
713                     }
714                     pixel |= (GX_UBYTE)(pixel << 4);
715                     *put |= pixel & putmask;
716                 }
717                 putmask >>= 4;
718                 if (putmask == 0)
719                 {
720                     put++;
721                     putmask = 0xf0;
722                 }
723                 putauxmask >>= 1;
724                 if (putauxmask == 0)
725                 {
726                     putaux++;
727                     putauxmask = 0x80;
728                 }
729             }
730             putrow += putstride;
731             putauxrow += putauxstride;
732         }
733         if (rot_cx && rot_cy)
734         {
735             x = *rot_cx;
736             y = *rot_cy;
737 
738             *rot_cx = (width - 1 - x);
739             *rot_cy = (height - 1 - y);
740         }
741     }
742     else
743     {
744         /* angle = 270. */
745         putrow = (GX_UBYTE *)destination -> gx_pixelmap_data;
746         putauxrow = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
747 
748         for (y = 0; y < height; y++)
749         {
750             put = putrow;
751             putaux = putauxrow;
752             putmask = 0xf0;
753             putauxmask = 0x80;
754 
755             for (x = 0; x < width; x++)
756             {
757                 /* set bits first. */
758                 *put &= (GX_UBYTE)(~putmask);
759                 getaux = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
760                 getaux += x * getauxstride;
761                 getaux += (height - 1 - y) >> 3;
762 
763                 transmask = (GX_UBYTE)(0x80 >> ((height - 1 - y) & 0x07));
764                 if (transmask & (*getaux))
765                 {
766                     /* transparent pixel, set destination true */
767                     *putaux |= putauxmask;
768                 }
769                 else
770                 {
771                     /* not transparent, set destination bit to 0. */
772                     *putaux &= (GX_UBYTE)(~putauxmask);
773 
774                     get = (GX_UBYTE *)src -> gx_pixelmap_data;
775                     get += x * getstride;
776                     get += (height - 1 - y) >> 1;
777 
778                     if ((height - 1 - y) & 1)
779                     {
780                         pixel = *get & 0x0f;
781                     }
782                     else
783                     {
784                         pixel = (*get & 0xf0) >> 4;
785                     }
786                     pixel |= (GX_UBYTE)(pixel << 4);
787                     *put |= pixel & putmask;
788                 }
789                 putmask >>= 4;
790                 if (putmask == 0)
791                 {
792                     put++;
793                     putmask = 0xf0;
794                 }
795                 putauxmask >>= 1;
796                 if (putauxmask == 0)
797                 {
798                     putaux++;
799                     putauxmask = 0x80;
800                 }
801             }
802             putrow += putstride;
803             putauxrow += putauxstride;
804         }
805 
806         if (rot_cx && rot_cy)
807         {
808             x = *rot_cx;
809             y = *rot_cy;
810 
811             *rot_cx = y;
812             *rot_cy = (height - 1 - x);
813         }
814     }
815 
816     destination -> gx_pixelmap_height = (GX_VALUE)height;
817     destination -> gx_pixelmap_width = (GX_VALUE)width;
818 
819     return GX_SUCCESS;
820 }
821 /**************************************************************************/
822 /*                                                                        */
823 /*  FUNCTION                                               RELEASE        */
824 /*                                                                        */
825 /*    _gx_utility_4bpp_pixelmap_simple_rotate             PORTABLE C      */
826 /*                                                           6.1          */
827 /*  AUTHOR                                                                */
828 /*                                                                        */
829 /*    Kenneth Maxwell, Microsoft Corporation                              */
830 /*                                                                        */
831 /*  DESCRIPTION                                                           */
832 /*                                                                        */
833 /*    Internal helper function that handles 90, 180 and 270 degree        */
834 /*      rotation of an uncompressed pixelmap with or wihout alpha.        */
835 /*                                                                        */
836 /*  INPUT                                                                 */
837 /*                                                                        */
838 /*    src                                   The pixelmap to be rotated    */
839 /*    angle                                 The angle to be rotated       */
840 /*    destination                           The rotated bitmap to be      */
841 /*                                            returned                    */
842 /*    rot_cx                                X coordinate of rotation      */
843 /*                                            center                      */
844 /*    rot_cy                                Y coordinate of rotation      */
845 /*                                            center                      */
846 /*                                                                        */
847 /*  OUTPUT                                                                */
848 /*                                                                        */
849 /*    None                                                                */
850 /*                                                                        */
851 /*  CALLS                                                                 */
852 /*                                                                        */
853 /*    _gx_utility_4bpp_pixelmap_simple_transparent_rotate                 */
854 /*                                          Real pixelmap rotate function */
855 /*    _gx_utility_4bpp_pixelmap_simple_raw_rotate                         */
856 /*                                          Real pixelmap rotate function */
857 /*                                                                        */
858 /*  CALLED BY                                                             */
859 /*                                                                        */
860 /*    GUIX Internal Code                                                  */
861 /*                                                                        */
862 /*  RELEASE HISTORY                                                       */
863 /*                                                                        */
864 /*    DATE              NAME                      DESCRIPTION             */
865 /*                                                                        */
866 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
867 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
868 /*                                            resulting in version 6.1    */
869 /*                                                                        */
870 /**************************************************************************/
_gx_utility_4bpp_pixelmap_simple_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)871 UINT _gx_utility_4bpp_pixelmap_simple_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
872 {
873 UINT status;
874 
875     if (src -> gx_pixelmap_flags & GX_PIXELMAP_TRANSPARENT)
876     {
877         /* with transparent, no compression */
878         status = _gx_utility_4bpp_pixelmap_simple_transparent_rotate(src, angle, destination, rot_cx, rot_cy);
879     }
880     else
881     {
882         /* no compression or transparent */
883         status = _gx_utility_4bpp_pixelmap_simple_raw_rotate(src, angle, destination, rot_cx, rot_cy);
884     }
885 
886     return status;
887 }
888 
889