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