1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Utility (Utility) */
18 /** */
19 /**************************************************************************/
20
21 #define REDVAL(_c) (GX_UBYTE)(((_c) >> 11) & 0x1f)
22 #define GREENVAL(_c) (GX_UBYTE)(((_c) >> 5) & 0x3f)
23 #define BLUEVAL(_c) (GX_UBYTE)(((_c)) & 0x1f)
24
25 #define ASSEMBLECOLOR(_r, _g, _b) \
26 (USHORT)((((_r) & 0x1f) << 11) | \
27 (((_g) & 0x3f) << 5) | \
28 ((_b) & 0x1f))
29
30 #define GX_SOURCE_CODE
31
32
33 /* Include necessary system files. */
34
35 #include "gx_api.h"
36 #include "gx_display.h"
37 #include "gx_context.h"
38 #include "gx_utility.h"
39 #include "gx_system.h"
40
41 /**************************************************************************/
42 /* */
43 /* FUNCTION RELEASE */
44 /* */
45 /* _gx_utility_565rgb_pixelmap_raw_rotate PORTABLE C */
46 /* 6.1 */
47 /* AUTHOR */
48 /* */
49 /* Kenneth Maxwell, Microsoft Corporation */
50 /* */
51 /* DESCRIPTION */
52 /* */
53 /* Internal helper function that rotate an uncompressed pixelmap */
54 /* without alpha. */
55 /* */
56 /* INPUT */
57 /* */
58 /* src The pixelmap to be rotated */
59 /* angle The angle to be rotated */
60 /* destination The rotated bitmap to be */
61 /* returned */
62 /* rot_cx X coordinate of rotation */
63 /* center */
64 /* rot_cy Y coordinate of rotation */
65 /* center */
66 /* */
67 /* OUTPUT */
68 /* */
69 /* status Completion status */
70 /* */
71 /* CALLS */
72 /* */
73 /* _gx_system_memory_allocator Memory Allocation routine */
74 /* _gx_utility_math_cos Compute the cosine value */
75 /* _gx_utility_math_sin Compute the sine value */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* GUIX Internal Code */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
86 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
87 /* resulting in version 6.1 */
88 /* */
89 /**************************************************************************/
_gx_utility_565rgb_pixelmap_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)90 static UINT _gx_utility_565rgb_pixelmap_raw_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
91 {
92 USHORT *put;
93 USHORT *get;
94 GX_UBYTE *putalpha;
95 INT srcxres;
96 INT srcyres;
97 INT cosv;
98 INT sinv;
99 USHORT red, green, blue;
100 INT idxminx, idxmaxx, idxmaxy;
101 INT *mx;
102 INT *my;
103 INT xres;
104 INT yres;
105 INT width, height;
106 INT x, y;
107 INT xx, yy;
108 USHORT a, b, c, d;
109 INT alpha;
110 INT xdiff, ydiff;
111
112 mx = _gx_system_scratchpad;
113 my = mx + 4;
114
115 mx[0] = mx[3] = -1;
116 mx[1] = mx[2] = 1;
117
118 my[0] = my[1] = 1;
119 my[2] = my[3] = -1;
120
121 idxminx = (angle / 90) & 0x3;
122 idxmaxx = (idxminx + 2) & 0x3;
123 idxmaxy = (idxminx + 1) & 0x3;
124
125 /* Calculate the source x and y center. */
126 srcxres = src -> gx_pixelmap_width >> 1;
127 srcyres = src -> gx_pixelmap_height >> 1;
128
129 cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
130 sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
131
132 xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
133 yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
134
135 xres = GX_FIXED_VAL_TO_INT(xres);
136 yres = GX_FIXED_VAL_TO_INT(yres);
137
138 /* Calculate destination width and height. */
139 width = (xres << 1);
140 height = (yres << 1);
141
142 /* Calculate the new rotation axis. */
143 if (rot_cx && rot_cy)
144 {
145 x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
146 y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
147
148 srcxres = (INT)*rot_cx;
149 srcyres = (INT)*rot_cy;
150
151 x = GX_FIXED_VAL_TO_INT(x) + xres;
152 y = GX_FIXED_VAL_TO_INT(y) + yres;
153
154 *rot_cx = x;
155 *rot_cy = y;
156
157 xres = *rot_cx;
158 yres = *rot_cy;
159 }
160
161 destination -> gx_pixelmap_height = (GX_VALUE)height;
162 destination -> gx_pixelmap_width = (GX_VALUE)width;
163 destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
164
165 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
166 overflow cannot occur. */
167 destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
168 destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
169
170 if (destination -> gx_pixelmap_data == GX_NULL)
171 {
172 return GX_SYSTEM_MEMORY_ERROR;
173 }
174
175 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
176 overflow cannot occur. */
177 destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
178 destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
179
180 if (destination -> gx_pixelmap_aux_data == GX_NULL)
181 {
182 _gx_system_memory_free((VOID *)destination -> gx_pixelmap_aux_data);
183
184 return GX_SYSTEM_MEMORY_ERROR;
185 }
186
187 put = (USHORT *)destination -> gx_pixelmap_data;
188 putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
189
190 /* Loop through the destination's pixels. */
191 for (y = 0; y < height; y++)
192 {
193 for (x = 0; x < width; x++)
194 {
195 xx = (x - xres) * cosv + (y - yres) * sinv;
196 yy = (y - yres) * cosv - (x - xres) * sinv;
197
198 xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
199 ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
200
201 xx = GX_FIXED_VAL_TO_INT(xx) + srcxres;
202 yy = GX_FIXED_VAL_TO_INT(yy) + srcyres;
203
204 if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
205 (yy >= -1) && (yy < src -> gx_pixelmap_height))
206 {
207 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
208 (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
209 {
210 get = (USHORT *)src -> gx_pixelmap_data;
211 get += yy * src -> gx_pixelmap_width;
212 get += xx;
213
214 a = *get;
215 b = *(get + 1);
216 c = *(get + src -> gx_pixelmap_width);
217 d = *(get + src -> gx_pixelmap_width + 1);
218
219 alpha = 0xff;
220 }
221 else
222 {
223 get = (USHORT *)src -> gx_pixelmap_data;
224
225 a = 0;
226 b = 0;
227 c = 0;
228 d = 0;
229 alpha = 0;
230
231 if (xx == -1)
232 {
233 /* handle left edge. */
234 if (yy >= 0)
235 {
236 b = *(get + yy * src -> gx_pixelmap_width);
237 alpha += xdiff * (256 - ydiff);
238 }
239
240 if (yy < src -> gx_pixelmap_height - 1)
241 {
242 d = *(get + (yy + 1) * src -> gx_pixelmap_width);
243 alpha += xdiff * ydiff;
244 }
245 }
246 else if (yy == -1)
247 {
248 /* handle top edge. */
249 c = *(get + xx);
250 alpha += ydiff * (256 - xdiff);
251
252 if (xx < src -> gx_pixelmap_width - 1)
253 {
254 d = *(get + xx + 1);
255 alpha += xdiff * ydiff;
256 }
257 }
258 else if (xx == src -> gx_pixelmap_width - 1)
259 {
260 /* handle right edget. */
261 a = *(get + yy * src -> gx_pixelmap_width + xx);
262 alpha += (256 - xdiff) * (256 - ydiff);
263
264 if (yy < src -> gx_pixelmap_height - 1)
265 {
266 c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
267 alpha += ydiff * (256 - xdiff);
268 }
269 }
270 else
271 {
272 /* handle bottom edge. */
273 a = *(get + yy * src -> gx_pixelmap_width + xx);
274 alpha += (256 - xdiff) * (256 - ydiff);
275
276 b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
277 alpha += xdiff * (256 - ydiff);
278 }
279
280 alpha >>= 8;
281 }
282
283 red = (USHORT)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) + \
284 REDVAL(b) * xdiff * (256 - ydiff) + \
285 REDVAL(c) * ydiff * (256 - xdiff) + \
286 REDVAL(d) * xdiff * ydiff) >> 16);
287
288 green = (USHORT)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) + \
289 GREENVAL(b) * xdiff * (256 - ydiff) + \
290 GREENVAL(c) * ydiff * (256 - xdiff) + \
291 GREENVAL(d) * xdiff * ydiff) >> 16);
292
293 blue = (USHORT)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) + \
294 BLUEVAL(b) * xdiff * (256 - ydiff) + \
295 BLUEVAL(c) * ydiff * (256 - xdiff) + \
296 BLUEVAL(d) * xdiff * ydiff) >> 16);
297
298 if (alpha && (alpha < 0xff))
299 {
300 red = (USHORT)((red << 8) / alpha);
301 green = (USHORT)((green << 8) / alpha);
302 blue = (USHORT)((blue << 8) / alpha);
303 }
304
305 red = red > 31 ? 31 : red;
306 green = green > 63 ? 63 : green;
307 blue = blue > 31 ? 31 : blue;
308 alpha = alpha > 255 ? 255 : alpha;
309
310 *put++ = ASSEMBLECOLOR(red, green, blue);
311 *putalpha++ = (GX_UBYTE)alpha;
312 }
313 else
314 {
315 put++;
316 *putalpha++ = 0;
317 }
318 }
319 }
320
321 return GX_SUCCESS;
322 }
323
324 /**************************************************************************/
325 /* */
326 /* FUNCTION RELEASE */
327 /* */
328 /* _gx_utility_565rgb_pixelmap_alpha_rotate PORTABLE C */
329 /* 6.1 */
330 /* AUTHOR */
331 /* */
332 /* Kenneth Maxwell, Microsoft Corporation */
333 /* */
334 /* DESCRIPTION */
335 /* */
336 /* Internal helper function that rotate an uncompressed pixelmap */
337 /* with alpha. */
338 /* */
339 /* INPUT */
340 /* */
341 /* src The pixelmap to be rotated */
342 /* angle The angle to be rotated */
343 /* destination The rotated bitmap to be */
344 /* returned */
345 /* rot_cx X coordinate of rotation */
346 /* center */
347 /* rot_cy Y coordinate of rotation */
348 /* center */
349 /* */
350 /* OUTPUT */
351 /* */
352 /* status Completion status */
353 /* */
354 /* CALLS */
355 /* */
356 /* _gx_system_memory_allocator Memory Allocation routine */
357 /* _gx_utility_math_cos Compute the cosine value */
358 /* _gx_utility_math_sin Compute the sine value */
359 /* */
360 /* CALLED BY */
361 /* */
362 /* GUIX Internal Code */
363 /* */
364 /* RELEASE HISTORY */
365 /* */
366 /* DATE NAME DESCRIPTION */
367 /* */
368 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
369 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
370 /* resulting in version 6.1 */
371 /* */
372 /**************************************************************************/
_gx_utility_565rgb_pixelmap_alpha_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)373 static UINT _gx_utility_565rgb_pixelmap_alpha_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
374 {
375 USHORT *put;
376 USHORT *get;
377 GX_UBYTE *putalpha;
378 GX_UBYTE *getalpha;
379 INT srcxres;
380 INT srcyres;
381 INT cosv;
382 INT sinv;
383 USHORT red, green, blue;
384 INT idxminx, idxmaxx, idxmaxy;
385 INT *mx;
386 INT *my;
387 INT xres;
388 INT yres;
389 INT width, height;
390 INT x, y;
391 INT xx, yy;
392 USHORT a, b, c, d;
393 USHORT alpha[4];
394 INT xdiff, ydiff;
395
396 mx = _gx_system_scratchpad;
397 my = mx + 4;
398
399 mx[0] = mx[3] = -1;
400 mx[1] = mx[2] = 1;
401
402 my[0] = my[1] = 1;
403 my[2] = my[3] = -1;
404
405 idxminx = (angle / 90) & 0x3;
406 idxmaxx = (idxminx + 2) & 0x3;
407 idxmaxy = (idxminx + 1) & 0x3;
408
409 /* Calculate the source x and y center. */
410 srcxres = src -> gx_pixelmap_width >> 1;
411 srcyres = src -> gx_pixelmap_height >> 1;
412
413 cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
414 sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
415
416 xres = mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv;
417 yres = my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv;
418
419 xres = GX_FIXED_VAL_TO_INT(xres);
420 yres = GX_FIXED_VAL_TO_INT(yres);
421
422
423 /* Calculate destination width and height. */
424 width = (xres << 1);
425 height = (yres << 1);
426
427 /* Calculate the new rotation axis. */
428 if (rot_cx && rot_cy)
429 {
430 x = ((*rot_cx) - srcxres) * cosv - ((*rot_cy) - srcyres) * sinv;
431 y = ((*rot_cy) - srcyres) * cosv + ((*rot_cx) - srcxres) * sinv;
432
433 srcxres = *rot_cx;
434 srcyres = *rot_cy;
435
436 x = GX_FIXED_VAL_TO_INT(x) + xres;
437 y = GX_FIXED_VAL_TO_INT(y) + yres;
438
439 *rot_cx = x;
440 *rot_cy = y;
441
442 xres = *rot_cx;
443 yres = *rot_cy;
444 }
445
446 destination -> gx_pixelmap_height = (GX_VALUE)height;
447 destination -> gx_pixelmap_width = (GX_VALUE)width;
448 destination -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
449
450 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
451 overflow cannot occur. */
452 destination -> gx_pixelmap_data_size = (UINT)(height * width) * sizeof(USHORT);
453 destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
454
455 if (destination -> gx_pixelmap_data == GX_NULL)
456 {
457 return GX_SYSTEM_MEMORY_ERROR;
458 }
459
460 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
461 overflow cannot occur. */
462 destination -> gx_pixelmap_aux_data_size = (UINT)(height * width) * sizeof(GX_UBYTE);
463 destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
464
465 if (destination -> gx_pixelmap_aux_data == GX_NULL)
466 {
467 _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
468
469 return GX_SYSTEM_MEMORY_ERROR;
470 }
471
472 put = (USHORT *)destination -> gx_pixelmap_data;
473 putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
474
475 /* Loop through the destination's pixels. */
476 for (y = 0; y < height; y++)
477 {
478 for (x = 0; x < width; x++)
479 {
480 xx = (x - xres) * cosv + (y - yres) * sinv;
481 yy = (y - yres) * cosv - (x - xres) * sinv;
482
483 xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
484 ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
485
486 xx = GX_FIXED_VAL_TO_INT(xx);
487 yy = GX_FIXED_VAL_TO_INT(yy);
488
489 xx += srcxres;
490 yy += srcyres;
491
492 if ((xx >= -1) && (xx < src -> gx_pixelmap_width) &&
493 (yy >= -1) && (yy < src -> gx_pixelmap_height))
494 {
495
496 if ((xx >= 0) && (xx < src -> gx_pixelmap_width - 1) &&
497 (yy >= 0) && (yy < src -> gx_pixelmap_height - 1))
498 {
499 get = (USHORT *)src -> gx_pixelmap_data;
500 get += yy * src -> gx_pixelmap_width;
501 get += xx;
502
503 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
504 getalpha += yy * src -> gx_pixelmap_width;
505 getalpha += xx;
506
507 a = *get;
508 alpha[0] = *getalpha;
509
510 b = *(get + 1);
511 alpha[1] = *(getalpha + 1);
512
513 c = *(get + src -> gx_pixelmap_width);
514 alpha[2] = *(getalpha + src -> gx_pixelmap_width);
515
516 d = *(get + src -> gx_pixelmap_width + 1);
517 alpha[3] = *(getalpha + src -> gx_pixelmap_width + 1);
518 }
519 else
520 {
521 get = (USHORT *)src -> gx_pixelmap_data;
522 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
523
524 a = 0;
525 b = 0;
526 c = 0;
527 d = 0;
528
529 if (xx == -1)
530 {
531 /* handle left edge. */
532 if (yy >= 0)
533 {
534 b = *(get + yy * src -> gx_pixelmap_width);
535 alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width);
536 }
537
538 if (yy < src -> gx_pixelmap_height - 1)
539 {
540 d = *(get + (yy + 1) * src -> gx_pixelmap_width);
541 alpha[3] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width);
542 }
543 }
544 else if (yy == -1)
545 {
546 /* handle top edge. */
547 c = *(get + xx);
548 alpha[2] = *(getalpha + xx);
549
550 if (xx < src -> gx_pixelmap_width - 1)
551 {
552 d = *(get + xx + 1);
553 alpha[3] = *(getalpha + xx + 1);
554 }
555 }
556 else if (xx == src -> gx_pixelmap_width - 1)
557 {
558 /* handle right edget. */
559 a = *(get + yy * src -> gx_pixelmap_width + xx);
560 alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
561
562 if (yy < src -> gx_pixelmap_height - 1)
563 {
564 c = *(get + (yy + 1) * src -> gx_pixelmap_width + xx);
565 alpha[2] = *(getalpha + (yy + 1) * src -> gx_pixelmap_width + xx);
566 }
567 }
568 else
569 {
570 /* handle bottom edge. */
571 a = *(get + yy * src -> gx_pixelmap_width + xx);
572 alpha[0] = *(getalpha + yy * src -> gx_pixelmap_width + xx);
573
574 b = *(get + yy * src -> gx_pixelmap_width + xx + 1);
575 alpha[1] = *(getalpha + yy * src -> gx_pixelmap_width + xx + 1);
576 }
577
578 if (!a)
579 {
580 alpha[0] = 0;
581 }
582
583 if (!b)
584 {
585 alpha[1] = 0;
586 }
587
588 if (!c)
589 {
590 alpha[2] = 0;
591 }
592
593 if (!d)
594 {
595 alpha[3] = 0;
596 }
597 }
598
599 red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
600 REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) + \
601 REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) + \
602 REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
603
604 green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
605 GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) + \
606 GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) + \
607 GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
608
609 blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) + \
610 BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) + \
611 BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) + \
612 BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
613
614 alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) + \
615 alpha[1] * xdiff * (256 - ydiff) + \
616 alpha[2] * ydiff * (256 - xdiff) + \
617 alpha[3] * xdiff * ydiff) >> 16);
618
619 if (alpha[0])
620 {
621 red /= alpha[0];
622 green /= alpha[0];
623 blue /= alpha[0];
624 }
625
626 red = red > 31 ? 31 : red;
627 green = green > 63 ? 63 : green;
628 blue = blue > 31 ? 31 : blue;
629
630 *put++ = ASSEMBLECOLOR(red, green, blue);
631 *putalpha++ = (GX_UBYTE)alpha[0];
632 }
633 else
634 {
635 put++;
636 *putalpha++ = 0;
637 }
638 }
639 }
640
641 return GX_SUCCESS;
642 }
643
644 /**************************************************************************/
645 /* */
646 /* FUNCTION RELEASE */
647 /* */
648 /* _gx_utility_565rgb_pixelmap_simple_raw_rotate PORTABLE C */
649 /* 6.1 */
650 /* AUTHOR */
651 /* */
652 /* Kenneth Maxwell, Microsoft Corporation */
653 /* */
654 /* DESCRIPTION */
655 /* */
656 /* Internal helper function that handles 90, 180 and 270 degree */
657 /* rotation of an uncompressed pixelmap wihout alpha. */
658 /* */
659 /* INPUT */
660 /* */
661 /* src The pixelmap to be rotated */
662 /* angle The angle to be rotated */
663 /* destination The rotated bitmap to be */
664 /* returned */
665 /* rot_cx X coordinate of rotation */
666 /* center */
667 /* rot_cy Y coordinate of rotation */
668 /* center */
669 /* */
670 /* OUTPUT */
671 /* */
672 /* status Completion status */
673 /* */
674 /* CALLS */
675 /* */
676 /* _gx_system_memory_allocator Memory Allocation routine */
677 /* */
678 /* CALLED BY */
679 /* */
680 /* GUIX Internal Code */
681 /* */
682 /* RELEASE HISTORY */
683 /* */
684 /* DATE NAME DESCRIPTION */
685 /* */
686 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
687 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
688 /* resulting in version 6.1 */
689 /* */
690 /**************************************************************************/
_gx_utility_565rgb_pixelmap_simple_raw_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)691 static UINT _gx_utility_565rgb_pixelmap_simple_raw_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
692 {
693 USHORT *put;
694 USHORT *get;
695 INT width, height;
696 INT x, y;
697
698 width = 0;
699 height = 0;
700
701 destination -> gx_pixelmap_aux_data = GX_NULL;
702
703 width = src -> gx_pixelmap_height;
704 height = src -> gx_pixelmap_width;
705
706 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
707 overflow cannot occur. */
708 destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(USHORT);
709 destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
710
711 if (destination -> gx_pixelmap_data == GX_NULL)
712 {
713 return GX_SYSTEM_MEMORY_ERROR;
714 }
715
716 if (angle == 90)
717 {
718 put = (USHORT *)destination -> gx_pixelmap_data;
719
720 for (y = 0; y < height; y++)
721 {
722 for (x = 0; x < width; x++)
723 {
724 get = (USHORT *)src -> gx_pixelmap_data;
725 get += (width - 1 - x) * height;
726 get += y;
727
728 *put++ = *get;
729 }
730 }
731
732 if (rot_cx && rot_cy)
733 {
734 x = *rot_cx;
735 y = *rot_cy;
736
737 *rot_cx = (width - 1 - y);
738 *rot_cy = x;
739 }
740 }
741 else if (angle == 180)
742 {
743 GX_SWAP_VALS(width, height);
744
745 put = (USHORT *)destination -> gx_pixelmap_data;
746
747 for (y = 0; y < height; y++)
748 {
749 for (x = 0; x < width; x++)
750 {
751 get = (USHORT *)src -> gx_pixelmap_data;
752 get += (height - 1 - y) * width;
753 get += width - 1 - x;
754
755 *put++ = *get;
756 }
757 }
758
759 if (rot_cx && rot_cy)
760 {
761 x = *rot_cx;
762 y = *rot_cy;
763
764 *rot_cx = (width - 1 - x);
765 *rot_cy = (height - 1 - y);
766 }
767 }
768 else
769 {
770 /* angle = 270. */
771 put = (USHORT *)destination -> gx_pixelmap_data;
772
773 for (y = 0; y < height; y++)
774 {
775 for (x = 0; x < width; x++)
776 {
777 get = (USHORT *)src -> gx_pixelmap_data;
778 get += x * height;
779 get += height - 1 - y;
780
781 *put++ = *get;
782 }
783 }
784
785 if (rot_cx && rot_cy)
786 {
787 x = *rot_cx;
788 y = *rot_cy;
789
790 *rot_cx = y;
791 *rot_cy = (height - 1 - x);
792 }
793 }
794
795 destination -> gx_pixelmap_height = (GX_VALUE)height;
796 destination -> gx_pixelmap_width = (GX_VALUE)width;
797
798 return GX_SUCCESS;
799 }
800
801 /**************************************************************************/
802 /* */
803 /* FUNCTION RELEASE */
804 /* */
805 /* _gx_utility_565rgb_pixelmap_simple_alpha_rotate PORTABLE C */
806 /* 6.1 */
807 /* AUTHOR */
808 /* */
809 /* Kenneth Maxwell, Microsoft Corporation */
810 /* */
811 /* DESCRIPTION */
812 /* */
813 /* Internal helper function that handles 90, 180 and 270 degree */
814 /* rotation of an uncompressed pixelmap wih alpha. */
815 /* */
816 /* INPUT */
817 /* */
818 /* src The pixelmap to be rotated */
819 /* angle The angle to be rotated */
820 /* destination The rotated bitmap to be */
821 /* returned */
822 /* rot_cx X coordinate of rotation */
823 /* center */
824 /* rot_cy Y coordinate of rotation */
825 /* center */
826 /* */
827 /* OUTPUT */
828 /* */
829 /* None */
830 /* */
831 /* CALLS */
832 /* */
833 /* _gx_system_memory_allocator Memory Allocation routine */
834 /* */
835 /* CALLED BY */
836 /* */
837 /* GUIX Internal Code */
838 /* */
839 /* RELEASE HISTORY */
840 /* */
841 /* DATE NAME DESCRIPTION */
842 /* */
843 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
844 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
845 /* resulting in version 6.1 */
846 /* */
847 /**************************************************************************/
_gx_utility_565rgb_pixelmap_simple_alpha_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)848 static UINT _gx_utility_565rgb_pixelmap_simple_alpha_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
849 {
850 USHORT *put;
851 GX_UBYTE *putalpha;
852 USHORT *get;
853 GX_UBYTE *getalpha;
854 INT width, height;
855 INT x, y;
856
857 width = src -> gx_pixelmap_height;
858 height = src -> gx_pixelmap_width;
859
860 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
861 overflow cannot occur. */
862 destination -> gx_pixelmap_data_size = (UINT)(width * height) * sizeof(USHORT);
863 destination -> gx_pixelmap_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_data_size);
864
865 if (destination -> gx_pixelmap_data == GX_NULL)
866 {
867 return GX_SYSTEM_MEMORY_ERROR;
868 }
869
870 /* Safe int math is not required here, calling function limits max width, height to 14 bits so
871 overflow cannot occur. */
872 destination -> gx_pixelmap_aux_data_size = (UINT)(width * height) * sizeof(GX_UBYTE);
873 destination -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(destination -> gx_pixelmap_aux_data_size);
874
875 if (destination -> gx_pixelmap_aux_data == GX_NULL)
876 {
877 _gx_system_memory_free((VOID *)destination -> gx_pixelmap_data);
878 return GX_SYSTEM_MEMORY_ERROR;
879 }
880
881 if (angle == 90)
882 {
883 put = (USHORT *)destination -> gx_pixelmap_data;
884 putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
885
886 for (y = 0; y < height; y++)
887 {
888 for (x = 0; x < width; x++)
889 {
890 get = (USHORT *)src -> gx_pixelmap_data;
891 get += (width - 1 - x) * height;
892 get += y;
893
894 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
895 getalpha += (width - 1 - x) * height;
896 getalpha += y;
897
898 *put++ = *get;
899 *putalpha++ = *getalpha;
900 }
901 }
902
903 if (rot_cx && rot_cy)
904 {
905 x = *rot_cx;
906 y = *rot_cy;
907
908 /* Get new rotation point. */
909 *rot_cx = (width - 1 - y);
910 *rot_cy = x;
911 }
912 }
913 else if (angle == 180)
914 {
915 GX_SWAP_VALS(width, height);
916
917 put = (USHORT *)destination -> gx_pixelmap_data;
918 putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
919
920 for (y = 0; y < height; y++)
921 {
922 for (x = 0; x < width; x++)
923 {
924 get = (USHORT *)src -> gx_pixelmap_data;
925 get += (height - 1 - y) * width;
926 get += width - 1 - x;
927
928 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
929 getalpha += (height - 1 - y) * width;
930 getalpha += width - 1 - x;
931
932 *put++ = *get;
933 *putalpha++ = *getalpha;
934 }
935 }
936
937 if (rot_cx && rot_cy)
938 {
939 x = *rot_cx;
940 y = *rot_cy;
941
942 /* Get new rotation point. */
943 *rot_cx = (width - 1 - x);
944 *rot_cy = (height - 1 - y);
945 }
946 }
947 else
948 {
949 /* angle = 270. */
950 put = (USHORT *)destination -> gx_pixelmap_data;
951 putalpha = (GX_UBYTE *)destination -> gx_pixelmap_aux_data;
952
953 for (y = 0; y < height; y++)
954 {
955 for (x = 0; x < width; x++)
956 {
957 get = (USHORT *)src -> gx_pixelmap_data;
958 get += x * height;
959 get += height - 1 - y;
960
961 getalpha = (GX_UBYTE *)src -> gx_pixelmap_aux_data;
962 getalpha += x * height;
963 getalpha += height - 1 - y;
964
965 *put++ = *get;
966 *putalpha++ = *getalpha;
967 }
968 }
969
970 if (rot_cx && rot_cy)
971 {
972 x = *rot_cx;
973 y = *rot_cy;
974
975 /* Get new rotation point. */
976 *rot_cx = y;
977 *rot_cy = (height - 1 - x);
978 }
979 }
980
981 destination -> gx_pixelmap_height = (GX_VALUE)height;
982 destination -> gx_pixelmap_width = (GX_VALUE)width;
983
984 return GX_SUCCESS;
985 }
986
987
988 /**************************************************************************/
989 /* */
990 /* FUNCTION RELEASE */
991 /* */
992 /* _gx_utility_565rgb_pixelmap_rotate PORTABLE C */
993 /* 6.1 */
994 /* AUTHOR */
995 /* */
996 /* Kenneth Maxwell, Microsoft Corporation */
997 /* */
998 /* DESCRIPTION */
999 /* */
1000 /* This function rotates 565rgb format uncompressed pixelmap with or */
1001 /* without alpha channel. */
1002 /* */
1003 /* INPUT */
1004 /* */
1005 /* src The pixelmap to be rotated */
1006 /* angle The angle to be rotated */
1007 /* destination The rotated bitmap to be */
1008 /* returned */
1009 /* rot_cx X coordinate of rotation */
1010 /* center */
1011 /* rot_cy Y coordinate of rotation */
1012 /* center */
1013 /* */
1014 /* OUTPUT */
1015 /* */
1016 /* status Completion status */
1017 /* */
1018 /* CALLS */
1019 /* */
1020 /* _gx_utility_565rgb_pixelmap_raw_rotate */
1021 /* Rotate 565rgb format pixelmap */
1022 /* without alpha channel */
1023 /* _gx_utility_565rgb_pixelmap_alpha_rotate */
1024 /* Rotate 565rgb format pixelmap */
1025 /* with alpha channel */
1026 /* */
1027 /* CALLED BY */
1028 /* */
1029 /* GUIX Internal Code */
1030 /* */
1031 /* RELEASE HISTORY */
1032 /* */
1033 /* DATE NAME DESCRIPTION */
1034 /* */
1035 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1036 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1037 /* resulting in version 6.1 */
1038 /* */
1039 /**************************************************************************/
_gx_utility_565rgb_pixelmap_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)1040 UINT _gx_utility_565rgb_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
1041 {
1042 UINT status;
1043
1044 if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
1045 {
1046 /* alpha, no compression */
1047 status = _gx_utility_565rgb_pixelmap_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
1048 }
1049 else
1050 {
1051 /* no compression or alpha */
1052 status = _gx_utility_565rgb_pixelmap_raw_rotate(src, angle, destination, rot_cx, rot_cy);
1053 }
1054
1055 return status;
1056 }
1057
1058
1059 /**************************************************************************/
1060 /* */
1061 /* FUNCTION RELEASE */
1062 /* */
1063 /* _gx_utility_565rgb_pixelmap_simple_rotate PORTABLE C */
1064 /* 6.1 */
1065 /* AUTHOR */
1066 /* */
1067 /* Kenneth Maxwell, Microsoft Corporation */
1068 /* */
1069 /* DESCRIPTION */
1070 /* */
1071 /* This function rotates 565rgb format uncompressed pixelmap with */
1072 /* simple rotation angle 90, 180 or 270 degree. */
1073 /* */
1074 /* INPUT */
1075 /* */
1076 /* src The pixelmap to be rotated */
1077 /* angle The angle to be rotated */
1078 /* destination The rotated bitmap to be */
1079 /* returned */
1080 /* rot_cx X coordinate of rotation */
1081 /* center */
1082 /* rot_cy Y coordinate of rotation */
1083 /* center */
1084 /* */
1085 /* OUTPUT */
1086 /* */
1087 /* status Completion status */
1088 /* */
1089 /* CALLS */
1090 /* */
1091 /* _gx_utility_565rgb_pixelmap_simple_raw_rotate */
1092 /* Rotate 565rgb format pixelmap */
1093 /* without alpha channel */
1094 /* _gx_utility_565rgb_pixelmap_simple_alpha_rotate */
1095 /* Rotate 565rgb format pixelmap */
1096 /* with alpha channel */
1097 /* */
1098 /* CALLED BY */
1099 /* */
1100 /* GUIX Internal Code */
1101 /* */
1102 /* RELEASE HISTORY */
1103 /* */
1104 /* DATE NAME DESCRIPTION */
1105 /* */
1106 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
1107 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
1108 /* resulting in version 6.1 */
1109 /* */
1110 /**************************************************************************/
_gx_utility_565rgb_pixelmap_simple_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)1111 UINT _gx_utility_565rgb_pixelmap_simple_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
1112 {
1113 UINT status;
1114
1115 if (src -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
1116 {
1117 /* alpha, no compression */
1118 status = _gx_utility_565rgb_pixelmap_simple_alpha_rotate(src, angle, destination, rot_cx, rot_cy);
1119 }
1120 else
1121 {
1122 /* no compression or alpha */
1123 status = _gx_utility_565rgb_pixelmap_simple_raw_rotate(src, angle, destination, rot_cx, rot_cy);
1124 }
1125
1126 return status;
1127 }
1128
1129