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