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