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