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 /** Display Management (Display) */
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 ((((_r) & 0x1f) << 11) | \
27 (((_g) & 0x3f) << 5) | \
28 (((_b) & 0x1f)))
29
30 #define GX_SOURCE_CODE
31
32 /* Include necessary system files. */
33
34 #include "gx_api.h"
35 #include "gx_display.h"
36 #include "gx_context.h"
37 #include "gx_utility.h"
38 #include "gx_system.h"
39
40 /**************************************************************************/
41 /* */
42 /* FUNCTION RELEASE */
43 /* */
44 /* _gx_display_driver_565rgb_pixelmap_raw_rotate PORTABLE C */
45 /* 6.1.10 */
46 /* AUTHOR */
47 /* */
48 /* Kenneth Maxwell, Microsoft Corporation */
49 /* */
50 /* DESCRIPTION */
51 /* */
52 /* Internal helper function that rotate an uncompressed pixelmap */
53 /* without alpha. */
54 /* */
55 /* INPUT */
56 /* */
57 /* context Drawing context */
58 /* xpos x-coord of top-left draw point*/
59 /* ypos y-coord of top-left draw point*/
60 /* pixelmap Pointer to GX_PIXELMAP struct */
61 /* angle The angle to rotate */
62 /* cx x-coord of rotate center */
63 /* cy y-coord of rotate center */
64 /* */
65 /* OUTPUT */
66 /* */
67 /* status Completion status */
68 /* */
69 /* CALLS */
70 /* */
71 /* _gx_utility_math_cos Compute the cosine value */
72 /* _gx_utility_math_sin Compute the sine value */
73 /* [gx_display_driver_pixel_blend] Display driver basic pixel */
74 /* blend function */
75 /* */
76 /* CALLED BY */
77 /* */
78 /* GUIX Internal Code */
79 /* */
80 /* RELEASE HISTORY */
81 /* */
82 /* DATE NAME DESCRIPTION */
83 /* */
84 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
85 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
86 /* resulting in version 6.1 */
87 /* 01-31-2022 Ting Zhu Modified comment(s), */
88 /* corrected logic, */
89 /* resulting in version 6.1.10 */
90 /* */
91 /**************************************************************************/
_gx_display_driver_565rgb_pixelmap_raw_rotate(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap,INT angle,INT cx,INT cy)92 static VOID _gx_display_driver_565rgb_pixelmap_raw_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
93 INT angle, INT cx, INT cy)
94 {
95 USHORT *get;
96 INT srcxres;
97 INT srcyres;
98 INT cosv;
99 INT sinv;
100 INT alpha;
101 USHORT red;
102 USHORT green;
103 USHORT blue;
104 INT idxminx;
105 INT idxmaxx;
106 INT idxmaxy;
107 INT *mx;
108 INT *my;
109 INT xres;
110 INT yres;
111 INT x;
112 INT y;
113 INT xx;
114 INT yy;
115 USHORT a;
116 USHORT b;
117 USHORT c;
118 USHORT d;
119 INT xdiff;
120 INT ydiff;
121 INT newxpos;
122 INT newypos;
123 GX_DISPLAY *display;
124 GX_RECTANGLE *clip;
125 VOID (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
126
127 clip = context -> gx_draw_context_clip;
128 display = context -> gx_draw_context_display;
129 blend_func = display -> gx_display_driver_pixel_blend;
130
131 if (!blend_func)
132 {
133 return;
134 }
135
136 mx = _gx_system_scratchpad;
137 my = mx + 4;
138
139 mx[0] = mx[3] = -1;
140 mx[1] = mx[2] = 1;
141
142 my[0] = my[1] = 1;
143 my[2] = my[3] = -1;
144
145 idxminx = (angle / 90) & 0x3;
146 idxmaxx = (idxminx + 2) & 0x3;
147 idxmaxy = (idxminx + 1) & 0x3;
148
149 /* Calculate the source x and y center. */
150 srcxres = pixelmap -> gx_pixelmap_width >> 1;
151 srcyres = pixelmap -> gx_pixelmap_height >> 1;
152
153 cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
154 sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
155
156 xres = GX_FIXED_VAL_TO_INT(mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv);
157 yres = GX_FIXED_VAL_TO_INT(my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv);
158
159 /* Calculate the new rotation axis. */
160
161 xres = GX_FIXED_VAL_TO_INT((cx - srcxres) * cosv - (cy - srcyres) * sinv) + xres;
162 yres = GX_FIXED_VAL_TO_INT((cy - srcyres) * cosv + (cx - srcxres) * sinv) + yres;
163
164 newxpos = xpos + cx - xres;
165 newypos = ypos + cy - yres;
166
167 /* Loop through the destination's pixels. */
168 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
169 {
170 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
171 {
172 xx = (x - xres) * cosv + (y - yres) * sinv;
173 yy = (y - yres) * cosv - (x - xres) * sinv;
174
175 xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
176 ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
177
178 xx = GX_FIXED_VAL_TO_INT(xx) + cx;
179 yy = GX_FIXED_VAL_TO_INT(yy) + cy;
180
181 if ((xx >= -1) && (xx < pixelmap -> gx_pixelmap_width) &&
182 (yy >= -1) && (yy < pixelmap -> gx_pixelmap_height))
183 {
184 if ((xx >= 0) && (xx < pixelmap -> gx_pixelmap_width - 1) &&
185 (yy >= 0) && (yy < pixelmap -> gx_pixelmap_height - 1))
186 {
187 get = (USHORT *)pixelmap -> gx_pixelmap_data;
188 get += yy * pixelmap -> gx_pixelmap_width;
189 get += xx;
190
191 a = *get;
192 b = *(get + 1);
193 c = *(get + pixelmap -> gx_pixelmap_width);
194 d = *(get + pixelmap -> gx_pixelmap_width + 1);
195
196 alpha = 0xff;
197 }
198 else
199 {
200 get = (USHORT *)pixelmap -> gx_pixelmap_data;
201
202 a = 0;
203 b = 0;
204 c = 0;
205 d = 0;
206 alpha = 0;
207
208 if (xx == -1)
209 {
210 /* handle left edge. */
211 if (yy >= 0)
212 {
213 b = *(get + yy * pixelmap -> gx_pixelmap_width);
214 alpha += xdiff * (256 - ydiff);
215 }
216
217 if (yy < pixelmap -> gx_pixelmap_height - 1)
218 {
219 d = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width);
220 alpha += xdiff * ydiff;
221 }
222 }
223 else if (yy == -1)
224 {
225 /* handle top edge. */
226 c = *(get + xx);
227 alpha += ydiff * (256 - xdiff);
228
229 if (xx < pixelmap -> gx_pixelmap_width - 1)
230 {
231 d = *(get + xx + 1);
232 alpha += xdiff * ydiff;
233 }
234 }
235 else if (xx == pixelmap -> gx_pixelmap_width - 1)
236 {
237 /* handle right edge. */
238 a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
239 alpha += (256 - xdiff) * (256 - ydiff);
240
241 if (yy < pixelmap -> gx_pixelmap_height - 1)
242 {
243 c = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width + xx);
244 alpha += ydiff * (256 - xdiff);
245 }
246 }
247 else
248 {
249 /* handle bottom edge. */
250 a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
251 alpha += (256 - xdiff) * (256 - ydiff);
252
253 b = *(get + yy * pixelmap -> gx_pixelmap_width + xx + 1);
254 alpha += xdiff * (256 - ydiff);
255 }
256
257 alpha >>= 8;
258 }
259
260 red = (USHORT)((REDVAL(a) * (256 - xdiff) * (256 - ydiff) +
261 REDVAL(b) * xdiff * (256 - ydiff) +
262 REDVAL(c) * ydiff * (256 - xdiff) +
263 REDVAL(d) * xdiff * ydiff) >> 16);
264
265 green = (USHORT)((GREENVAL(a) * (256 - xdiff) * (256 - ydiff) +
266 GREENVAL(b) * xdiff * (256 - ydiff) +
267 GREENVAL(c) * ydiff * (256 - xdiff) +
268 GREENVAL(d) * xdiff * ydiff) >> 16);
269
270 blue = (USHORT)((BLUEVAL(a) * (256 - xdiff) * (256 - ydiff) +
271 BLUEVAL(b) * xdiff * (256 - ydiff) +
272 BLUEVAL(c) * ydiff * (256 - xdiff) +
273 BLUEVAL(d) * xdiff * ydiff) >> 16);
274
275 if ((alpha > 0) && (alpha < 0xff))
276 {
277 red = (USHORT)((red << 8) / alpha);
278 green = (USHORT)((green << 8) / alpha);
279 blue = (USHORT)((blue << 8) / alpha);
280 }
281
282 red = red > 31 ? 31 : red;
283 green = green > 63 ? 63 : green;
284 blue = blue > 31 ? 31 : blue;
285 alpha = alpha > 255 ? 255 : alpha;
286
287 blend_func(context, x + newxpos, y + newypos, (GX_COLOR)ASSEMBLECOLOR(red, green, blue), (GX_UBYTE)alpha);
288 }
289 }
290 }
291 }
292
293 /**************************************************************************/
294 /* */
295 /* FUNCTION RELEASE */
296 /* */
297 /* _gx_display_driver_565rgb_pixelmap_alpha_rotate PORTABLE C */
298 /* 6.1.10 */
299 /* AUTHOR */
300 /* */
301 /* Kenneth Maxwell, Microsoft Corporation */
302 /* */
303 /* DESCRIPTION */
304 /* */
305 /* Internal helper function that rotate an uncompressed pixelmap */
306 /* with alpha. */
307 /* */
308 /* INPUT */
309 /* */
310 /* context Drawing context */
311 /* xpos x-coord of top-left draw point*/
312 /* ypos y-coord of top-left draw point*/
313 /* pixelmap Pointer to GX_PIXELMAP struct */
314 /* angle The angle to rotate */
315 /* cx x-coord of rotate center */
316 /* cy y-coord of rotate center */
317 /* */
318 /* OUTPUT */
319 /* */
320 /* status Completion status */
321 /* */
322 /* CALLS */
323 /* */
324 /* _gx_utility_math_cos Compute the cosine value */
325 /* _gx_utility_math_sin Compute the sine value */
326 /* [gx_display_driver_pixel_blend] Display driver basic pixel */
327 /* blend function */
328 /* */
329 /* CALLED BY */
330 /* */
331 /* GUIX Internal Code */
332 /* */
333 /* RELEASE HISTORY */
334 /* */
335 /* DATE NAME DESCRIPTION */
336 /* */
337 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
338 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
339 /* resulting in version 6.1 */
340 /* 01-31-2022 Ting Zhu Modified comment(s), */
341 /* corrected logic, */
342 /* resulting in version 6.1.10 */
343 /* */
344 /**************************************************************************/
_gx_display_driver_565rgb_pixelmap_alpha_rotate(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap,INT angle,INT cx,INT cy)345 static VOID _gx_display_driver_565rgb_pixelmap_alpha_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
346 INT angle, INT cx, INT cy)
347 {
348 USHORT *get;
349 GX_UBYTE *getalpha;
350 INT srcxres;
351 INT srcyres;
352 INT cosv;
353 INT sinv;
354 USHORT red;
355 USHORT green;
356 USHORT blue;
357 INT idxminx;
358 INT idxmaxx;
359 INT idxmaxy;
360 INT *mx;
361 INT *my;
362 INT xres;
363 INT yres;
364 INT x;
365 INT y;
366 INT xx;
367 INT yy;
368 USHORT a;
369 USHORT b;
370 USHORT c;
371 USHORT d;
372 USHORT alpha[4];
373 GX_FIXED_VAL xdiff;
374 GX_FIXED_VAL ydiff;
375 INT newxpos;
376 INT newypos;
377 GX_DISPLAY *display;
378 GX_RECTANGLE *clip;
379 VOID (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
380
381 clip = context -> gx_draw_context_clip;
382 display = context -> gx_draw_context_display;
383 blend_func = display -> gx_display_driver_pixel_blend;
384
385 if (!blend_func)
386 {
387 return;
388 }
389
390 mx = _gx_system_scratchpad;
391 my = mx + 4;
392
393 mx[0] = mx[3] = -1;
394 mx[1] = mx[2] = 1;
395
396 my[0] = my[1] = 1;
397 my[2] = my[3] = -1;
398
399 idxminx = (angle / 90) & 0x3;
400 idxmaxx = (idxminx + 2) & 0x3;
401 idxmaxy = (idxminx + 1) & 0x3;
402
403 /* Calculate the source x and y center. */
404 srcxres = pixelmap -> gx_pixelmap_width >> 1;
405 srcyres = pixelmap -> gx_pixelmap_height >> 1;
406
407 cosv = _gx_utility_math_cos(GX_FIXED_VAL_MAKE(angle));
408 sinv = _gx_utility_math_sin(GX_FIXED_VAL_MAKE(angle));
409
410 xres = GX_FIXED_VAL_TO_INT(mx[idxmaxx] * (srcxres + 2) * cosv - my[idxmaxx] * (srcyres + 2) * sinv);
411 yres = GX_FIXED_VAL_TO_INT(my[idxmaxy] * (srcyres + 2) * cosv + mx[idxmaxy] * (srcxres + 2) * sinv);
412
413 xres = GX_FIXED_VAL_TO_INT((cx - srcxres) * cosv - (cy - srcyres) * sinv) + xres;
414 yres = GX_FIXED_VAL_TO_INT((cy - srcyres) * cosv + (cx - srcxres) * sinv) + yres;
415
416 newxpos = xpos + cx - xres;
417 newypos = ypos + cy - yres;
418
419 /* Loop through the source's pixels. */
420 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
421 {
422 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
423 {
424 xx = (x - xres) * cosv + (y - yres) * sinv;
425 yy = (y - yres) * cosv - (x - xres) * sinv;
426
427 xdiff = GX_FIXED_VAL_TO_INT(xx << 8) & 0xff;
428 ydiff = GX_FIXED_VAL_TO_INT(yy << 8) & 0xff;
429
430 xx = GX_FIXED_VAL_TO_INT(xx) + cx;
431 yy = GX_FIXED_VAL_TO_INT(yy) + cy;
432
433 if ((xx >= -1) && (xx < pixelmap -> gx_pixelmap_width) &&
434 (yy >= -1) && (yy < pixelmap -> gx_pixelmap_height))
435 {
436 if ((xx >= 0) && (xx < pixelmap -> gx_pixelmap_width - 1) && \
437 (yy >= 0) && (yy < pixelmap -> gx_pixelmap_height - 1))
438 {
439 get = (USHORT *)pixelmap -> gx_pixelmap_data;
440 get += yy * pixelmap -> gx_pixelmap_width;
441 get += xx;
442
443 getalpha = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
444 getalpha += yy * pixelmap -> gx_pixelmap_width;
445 getalpha += xx;
446
447 a = *get;
448 alpha[0] = *getalpha;
449
450 b = *(get + 1);
451 alpha[1] = *(getalpha + 1);
452
453 c = *(get + pixelmap -> gx_pixelmap_width);
454 alpha[2] = *(getalpha + pixelmap -> gx_pixelmap_width);
455
456 d = *(get + pixelmap -> gx_pixelmap_width + 1);
457 alpha[3] = *(getalpha + pixelmap -> gx_pixelmap_width + 1);
458 }
459 else
460 {
461 get = (USHORT *)pixelmap -> gx_pixelmap_data;
462 getalpha = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
463
464 a = 0;
465 b = 0;
466 c = 0;
467 d = 0;
468
469 if (xx == -1)
470 {
471 /* handle left edge. */
472 if (yy >= 0)
473 {
474 b = *(get + yy * pixelmap -> gx_pixelmap_width);
475 alpha[1] = *(getalpha + yy * pixelmap -> gx_pixelmap_width);
476 }
477
478 if (yy < pixelmap -> gx_pixelmap_height - 1)
479 {
480 d = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width);
481 alpha[3] = *(getalpha + (yy + 1) * pixelmap -> gx_pixelmap_width);
482 }
483 }
484 else if (yy == -1)
485 {
486 /* handle top edge. */
487 c = *(get + xx);
488 alpha[2] = *(getalpha + xx);
489
490 if (xx < pixelmap -> gx_pixelmap_width - 1)
491 {
492 d = *(get + xx + 1);
493 alpha[3] = *(getalpha + xx + 1);
494 }
495 }
496 else if (xx == pixelmap -> gx_pixelmap_width - 1)
497 {
498 /* handle right edget. */
499 a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
500 alpha[0] = *(getalpha + yy * pixelmap -> gx_pixelmap_width + xx);
501
502 if (yy < pixelmap -> gx_pixelmap_height - 1)
503 {
504 c = *(get + (yy + 1) * pixelmap -> gx_pixelmap_width + xx);
505 alpha[2] = *(getalpha + (yy + 1) * pixelmap -> gx_pixelmap_width + xx);
506 }
507 }
508 else
509 {
510 /* handle bottom edge. */
511 a = *(get + yy * pixelmap -> gx_pixelmap_width + xx);
512 alpha[0] = *(getalpha + yy * pixelmap -> gx_pixelmap_width + xx);
513
514 b = *(get + yy * pixelmap -> gx_pixelmap_width + xx + 1);
515 alpha[1] = *(getalpha + yy * pixelmap -> gx_pixelmap_width + xx + 1);
516 }
517
518 if (!a)
519 {
520 alpha[0] = 0;
521 }
522
523 if (!b)
524 {
525 alpha[1] = 0;
526 }
527
528 if (!c)
529 {
530 alpha[2] = 0;
531 }
532
533 if (!d)
534 {
535 alpha[3] = 0;
536 }
537 }
538
539 red = (USHORT)((REDVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
540 REDVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
541 REDVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
542 REDVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
543
544 green = (USHORT)((GREENVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
545 GREENVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
546 GREENVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
547 GREENVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
548
549 blue = (USHORT)((BLUEVAL(a) * alpha[0] * (256 - xdiff) * (256 - ydiff) +
550 BLUEVAL(b) * alpha[1] * xdiff * (256 - ydiff) +
551 BLUEVAL(c) * alpha[2] * ydiff * (256 - xdiff) +
552 BLUEVAL(d) * alpha[3] * xdiff * ydiff) >> 16);
553
554 alpha[0] = (USHORT)((alpha[0] * (256 - xdiff) * (256 - ydiff) +
555 alpha[1] * xdiff * (256 - ydiff) +
556 alpha[2] * ydiff * (256 - xdiff) +
557 alpha[3] * xdiff * ydiff) >> 16);
558
559 if (alpha[0])
560 {
561 red /= alpha[0];
562 green /= alpha[0];
563 blue /= alpha[0];
564 }
565
566 red = red > 31 ? 31 : red;
567 green = green > 63 ? 63 : green;
568 blue = blue > 31 ? 31 : blue;
569 alpha[0] = alpha[0] > 255 ? 255 : alpha[0];
570
571 blend_func(context, x + newxpos, y + newypos, (GX_COLOR)ASSEMBLECOLOR(red, green, blue), (GX_UBYTE)alpha[0]);
572 }
573 }
574 }
575 }
576
577 /**************************************************************************/
578 /* */
579 /* FUNCTION RELEASE */
580 /* */
581 /* _gx_display_driver_16bpp_pixelmap_simple_rotate PORTABLE C */
582 /* 6.3.0 */
583 /* AUTHOR */
584 /* */
585 /* Kenneth Maxwell, Microsoft Corporation */
586 /* */
587 /* DESCRIPTION */
588 /* */
589 /* Internal help function that hangles 90, 180 and 270 degree pixelmap */
590 /* rotation. */
591 /* */
592 /* INPUT */
593 /* */
594 /* context Drawing context */
595 /* xpos x-coord of top-left draw point*/
596 /* ypos y-coord of top-left draw point*/
597 /* pixelmap Pointer to GX_PIXELMAP struct */
598 /* angle The angle to rotate */
599 /* cx x-coord of rotate center */
600 /* cy y-coord of rotate center */
601 /* */
602 /* OUTPUT */
603 /* */
604 /* status Completion status */
605 /* */
606 /* CALLS */
607 /* */
608 /* None */
609 /* */
610 /* CALLED BY */
611 /* */
612 /* GUIX Internal Code */
613 /* */
614 /* RELEASE HISTORY */
615 /* */
616 /* DATE NAME DESCRIPTION */
617 /* */
618 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
619 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
620 /* resulting in version 6.1 */
621 /* 06-02-2021 Kenneth Maxwell Modified comment(s), */
622 /* remove unused assignment, */
623 /* resulting in version 6.1.7 */
624 /* 10-31-2023 Ting Zhu Modified comment(s), */
625 /* added partial canvas buffer */
626 /* support, */
627 /* resulting in version 6.3.0 */
628 /* */
629 /**************************************************************************/
_gx_display_driver_16bpp_pixelmap_simple_rotate(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap,INT angle,INT cx,INT cy)630 VOID _gx_display_driver_16bpp_pixelmap_simple_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
631 INT angle, INT cx, INT cy)
632 {
633 USHORT *putrow;
634 USHORT *put;
635 USHORT *get;
636 INT width;
637 INT height;
638 INT x;
639 INT y;
640 GX_RECTANGLE *clip;
641 INT newxpos;
642 INT newypos;
643
644 clip = context -> gx_draw_context_clip;
645
646 putrow = (USHORT *)context -> gx_draw_context_memory;
647
648 GX_CALCULATE_PUTROW(putrow, clip -> gx_rectangle_left, clip -> gx_rectangle_top, context);
649
650 if (angle == 90)
651 {
652 width = pixelmap -> gx_pixelmap_height;
653 height = pixelmap -> gx_pixelmap_width;
654
655 newxpos = xpos + cx - (width - 1 - cy);
656 newypos = ypos + cy - cx;
657
658 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
659 {
660 put = putrow;
661
662 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
663 {
664 get = (USHORT *)pixelmap -> gx_pixelmap_data;
665 get += (width - 1 - x) * height;
666 get += y;
667
668 *put++ = *get;
669 }
670
671 putrow += context -> gx_draw_context_pitch;
672 }
673 }
674 else if (angle == 180)
675 {
676
677 width = pixelmap -> gx_pixelmap_width;
678 height = pixelmap -> gx_pixelmap_height;
679
680 newxpos = xpos + cx - (width - 1 - cx);
681 newypos = ypos + cy - (height - 1 - cy);
682
683 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
684 {
685 put = putrow;
686 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
687 {
688 get = (USHORT *)pixelmap -> gx_pixelmap_data;
689 get += (height - 1 - y) * width;
690 get += width - 1 - x;
691
692 *put++ = *get;
693 }
694
695 putrow += context -> gx_draw_context_pitch;
696 }
697 }
698 else
699 {
700 height = pixelmap -> gx_pixelmap_width;
701
702 newxpos = xpos + cx - cy;
703 newypos = ypos + cx - (height - 1 - cy);
704
705 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
706 {
707 put = putrow;
708
709 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
710 {
711 get = (USHORT *)pixelmap -> gx_pixelmap_data;
712 get += x * height;
713 get += height - 1 - y;
714
715 *put++ = *get;
716 }
717
718 putrow += context -> gx_draw_context_pitch;
719 }
720 }
721 }
722
723 /**************************************************************************/
724 /* */
725 /* FUNCTION RELEASE */
726 /* */
727 /* _gx_display_driver_16bpp_pixelmap_simple_alpha_rotate */
728 /* PORTABLE C */
729 /* 6.1.7 */
730 /* AUTHOR */
731 /* */
732 /* Kenneth Maxwell, Microsoft Corporation */
733 /* */
734 /* DESCRIPTION */
735 /* */
736 /* Internal help function that hangles 90, 180 and 270 degree pixelmap */
737 /* rotation with alpha channel. */
738 /* */
739 /* INPUT */
740 /* */
741 /* context Drawing context */
742 /* xpos x-coord of top-left draw point*/
743 /* ypos y-coord of top-left draw point*/
744 /* pixelmap Pointer to GX_PIXELMAP struct */
745 /* angle The angle to rotate */
746 /* cx x-coord of rotate center */
747 /* cy y-coord of rotate center */
748 /* */
749 /* OUTPUT */
750 /* */
751 /* status Completion status */
752 /* */
753 /* CALLS */
754 /* */
755 /* [gx_display_driver_pixel_blend] Display driver basic pixel */
756 /* blend function */
757 /* */
758 /* CALLED BY */
759 /* */
760 /* GUIX Internal Code */
761 /* */
762 /* RELEASE HISTORY */
763 /* */
764 /* DATE NAME DESCRIPTION */
765 /* */
766 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
767 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
768 /* resulting in version 6.1 */
769 /* 06-02-2021 Kenneth Maxwell Modified comment(s), */
770 /* remove unused assignment, */
771 /* resulting in version 6.1.7 */
772 /* */
773 /**************************************************************************/
_gx_display_driver_16bpp_pixelmap_simple_alpha_rotate(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap,INT angle,INT cx,INT cy)774 VOID _gx_display_driver_16bpp_pixelmap_simple_alpha_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
775 INT angle, INT cx, INT cy)
776 {
777 USHORT *get;
778 GX_UBYTE *getalpha;
779 INT width;
780 INT height;
781 INT x;
782 INT y;
783 GX_RECTANGLE *clip;
784 INT newxpos;
785 INT newypos;
786 VOID (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
787
788 clip = context -> gx_draw_context_clip;
789 blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
790
791 if (GX_NULL == blend_func)
792 {
793 return;
794 }
795
796 if (angle == 90)
797 {
798 width = pixelmap -> gx_pixelmap_height;
799 height = pixelmap -> gx_pixelmap_width;
800
801 newxpos = xpos + cx - (width - 1 - cy);
802 newypos = ypos + cy - cx;
803
804 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
805 {
806 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
807 {
808 get = (USHORT *)pixelmap -> gx_pixelmap_data;
809 getalpha = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
810 get += (width - 1 - x) * height;
811 get += y;
812 getalpha += (width - 1 - x) * height;
813 getalpha += y;
814 blend_func(context, x + newxpos, y + newypos, *get, *getalpha);
815 }
816 }
817 }
818 else if (angle == 180)
819 {
820
821 width = pixelmap -> gx_pixelmap_width;
822 height = pixelmap -> gx_pixelmap_height;
823
824 newxpos = xpos + cx - (width - 1 - cx);
825 newypos = ypos + cy - (height - 1 - cy);
826
827
828 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
829 {
830 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
831 {
832 get = (USHORT *)pixelmap -> gx_pixelmap_data;
833 getalpha = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
834 get += (height - 1 - y) * width;
835 get += width - 1 - x;
836 getalpha += (height - 1 - y) * width;
837 getalpha += width - 1 - x;
838
839 blend_func(context, x + newxpos, y + newypos, *get, *getalpha);
840 }
841 }
842 }
843 else
844 {
845 height = pixelmap -> gx_pixelmap_width;
846
847 newxpos = xpos + cx - cy;
848 newypos = ypos + cx - (height - 1 - cy);
849
850 for (y = clip -> gx_rectangle_top - newypos; y <= clip -> gx_rectangle_bottom - newypos; y++)
851 {
852 for (x = clip -> gx_rectangle_left - newxpos; x <= clip -> gx_rectangle_right - newxpos; x++)
853 {
854 get = (USHORT *)pixelmap -> gx_pixelmap_data;
855 getalpha = (GX_UBYTE *)pixelmap -> gx_pixelmap_aux_data;
856 get += x * height;
857 get += height - 1 - y;
858 getalpha += x * height;
859 getalpha += height - 1 - y;
860
861 blend_func(context, x + newxpos, y + newypos, *get, *getalpha);
862 }
863 }
864 }
865 }
866
867 /**************************************************************************/
868 /* */
869 /* FUNCTION RELEASE */
870 /* */
871 /* _gx_display_driver_16bpp_pixelmap_rotate PORTABLE C */
872 /* 6.1 */
873 /* AUTHOR */
874 /* */
875 /* Kenneth Maxwell, Microsoft Corporation */
876 /* */
877 /* DESCRIPTION */
878 /* */
879 /* This service rotate a pixelmap directly to canvas memory. */
880 /* */
881 /* INPUT */
882 /* */
883 /* context Drawing context */
884 /* xpos x-coord of top-left draw point*/
885 /* ypos y-coord of top-left draw point*/
886 /* pixelmap Pointer to GX_PIXELMAP struct */
887 /* angle The angle to rotate */
888 /* rot_cx x-coord of rotating center. */
889 /* rot_cy y-coord of rotationg center. */
890 /* */
891 /* OUTPUT */
892 /* */
893 /* status Completion status */
894 /* */
895 /* CALLS */
896 /* */
897 /* _gx_display_driver_16bpp_pixelmap_simple_alpha_rotate */
898 /* Real rotate functin */
899 /* _gx_display_driver_16bpp_pixelmap_simple_rotate */
900 /* Real rotate functin */
901 /* _gx_display_driver_565rgb_pixelmap_alpha_rotate */
902 /* Real rotate functin */
903 /* _gx_display_driver_565rgb_pixelmap_raw_rotate */
904 /* Real rotate functin */
905 /* */
906 /* CALLED BY */
907 /* */
908 /* Application Code */
909 /* GUIX Internal Code */
910 /* */
911 /* RELEASE HISTORY */
912 /* */
913 /* DATE NAME DESCRIPTION */
914 /* */
915 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
916 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
917 /* added 565bgr format support,*/
918 /* resulting in version 6.1 */
919 /* */
920 /**************************************************************************/
_gx_display_driver_16bpp_pixelmap_rotate(GX_DRAW_CONTEXT * context,INT xpos,INT ypos,GX_PIXELMAP * pixelmap,INT angle,INT rot_cx,INT rot_cy)921 VOID _gx_display_driver_16bpp_pixelmap_rotate(GX_DRAW_CONTEXT *context, INT xpos, INT ypos, GX_PIXELMAP *pixelmap,
922 INT angle, INT rot_cx, INT rot_cy)
923 {
924 switch (pixelmap -> gx_pixelmap_format)
925 {
926 case GX_COLOR_FORMAT_565RGB:
927 case GX_COLOR_FORMAT_565BGR:
928 if (angle % 90 == 0)
929 {
930 /* Simple angle rotate: 90 degree, 180 degree and 270 degree. */
931 if (pixelmap -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
932 {
933 _gx_display_driver_16bpp_pixelmap_simple_alpha_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
934 }
935 else
936 {
937 _gx_display_driver_16bpp_pixelmap_simple_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
938 }
939 break;
940 }
941 else
942 {
943 /* General rotation case. */
944 if (pixelmap -> gx_pixelmap_flags & GX_PIXELMAP_ALPHA)
945 {
946 /* alpha, no compression */
947 _gx_display_driver_565rgb_pixelmap_alpha_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
948 }
949 else
950 {
951
952 /* no compression or alpha */
953 _gx_display_driver_565rgb_pixelmap_raw_rotate(context, xpos, ypos, pixelmap, angle, rot_cx, rot_cy);
954 }
955 break;
956 }
957 }
958 return;
959 }
960
961