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