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