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