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