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