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 /**   Utility (Utility)                                                   */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _gx_utility_pixelmap_rotation                       PORTABLE C      */
35 /*                                                           6.1.3        */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    Kenneth Maxwell, Microsoft Corporation                              */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    This service rotate a pixelmap.                                     */
43 /*                                                                        */
44 /*  INPUT                                                                 */
45 /*                                                                        */
46 /*    src                                   The pixelmap to rotate        */
47 /*    angle                                 The angle to rotate           */
48 /*    destination                           Destination buffer for        */
49 /*                                            rotated pixelmap.           */
50 /*    rot_cx                                X coordinate of rotation      */
51 /*                                            center                      */
52 /*    rot_cy                                Y coordinate of rotation      */
53 /*                                            center                      */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    status                                Completion status             */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    _gx_utility_32argb_pixelmap_rotate    Rotate 32bpp pixelmap         */
62 /*    _gx_utility_565rgb_pixelmap_rotate    Rotate 565rgb pixelmap        */
63 /*    _gx_utility_4444argb_pixelmap_rotate  Rotate 4444argb pixelmap      */
64 /*    _gx_utility_8bpp_pixelmap_rotate      Rotate 8bit palette pixelmap  */
65 /*    _gx_utility_332rgb_pixelmap_rotate    Rotate 332rgb pixelmap        */
66 /*    _gx_utility_8bit_alphamap_rotate      Rotate 8bit alphamap          */
67 /*    _gx_utility_4bpp_pixelmap_rotate      Rotate 4bpp pixelmap          */
68 /*    _gx_utility_1bpp_pixelmap_rotate      Rotate 1bpp pixelmap          */
69 /*                                                                        */
70 /*  CALLED BY                                                             */
71 /*                                                                        */
72 /*    Application Code                                                    */
73 /*    GUIX Internal Code                                                  */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
80 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
81 /*                                            added 565bgr format support,*/
82 /*                                            resulting in version 6.1    */
83 /*  12-31-2020     Kenneth Maxwell          Modified comment(s), added    */
84 /*                                            display rotation support,   */
85 /*                                            resulting in version 6.1.3  */
86 /*                                                                        */
87 /**************************************************************************/
_gx_utility_pixelmap_rotate(GX_PIXELMAP * src,INT angle,GX_PIXELMAP * destination,INT * rot_cx,INT * rot_cy)88 UINT _gx_utility_pixelmap_rotate(GX_PIXELMAP *src, INT angle, GX_PIXELMAP *destination, INT *rot_cx, INT *rot_cy)
89 {
90 UINT        status = GX_SUCCESS;
91 GX_PIXELMAP rotated_src;
92 
93     /* Limit pixelmap width to 14bits. */
94     if (src -> gx_pixelmap_width > GX_MAX_PIXELMAP_RESOLUTION)
95     {
96         return GX_INVALID_WIDTH;
97     }
98 
99     /* Limit pixelmap height to 14bits. */
100     if (src -> gx_pixelmap_height > GX_MAX_PIXELMAP_RESOLUTION)
101     {
102         return GX_INVALID_HEIGHT;
103     }
104 
105     if ((src -> gx_pixelmap_flags & GX_PIXELMAP_ROTATED_90) ||
106         (src -> gx_pixelmap_flags & GX_PIXELMAP_ROTATED_270))
107     {
108         rotated_src = (*src);
109         GX_SWAP_VALS(rotated_src.gx_pixelmap_width, rotated_src.gx_pixelmap_height);
110         src = &rotated_src;
111 
112         if (rot_cx && rot_cy)
113         {
114             GX_SWAP_VALS(*rot_cx, *rot_cy);
115 
116             if (src -> gx_pixelmap_flags & GX_PIXELMAP_ROTATED_90)
117             {
118                 *rot_cy = src -> gx_pixelmap_height - 1 - (*rot_cy);
119             }
120             else
121             {
122                 *rot_cx = src -> gx_pixelmap_width - 1 - (*rot_cx);
123             }
124         }
125     }
126 
127     angle = angle % 360;
128 
129     if (angle == 0)
130     {
131         return GX_INVALID_VALUE;
132     }
133     else if (angle < 0)
134     {
135         angle += 360;
136     }
137 
138     if ((_gx_system_memory_allocator == GX_NULL) || (_gx_system_memory_free == GX_NULL))
139     {
140         return GX_SYSTEM_MEMORY_ERROR;
141     }
142 
143     if (src -> gx_pixelmap_flags & GX_PIXELMAP_COMPRESSED)
144     {
145         return GX_INVALID_FORMAT;
146     }
147 
148     if ((angle % 90) == 0)
149     {
150         _gx_utility_pixelmap_simple_rotate(src, angle, destination, rot_cx, rot_cy);
151     }
152     else
153     {
154         memset(destination, 0, sizeof(GX_PIXELMAP));
155         destination -> gx_pixelmap_format = src -> gx_pixelmap_format;
156         destination -> gx_pixelmap_version_major = src -> gx_pixelmap_version_major;
157         destination -> gx_pixelmap_version_minor = src -> gx_pixelmap_version_major;
158         destination -> gx_pixelmap_flags = src -> gx_pixelmap_flags;
159 
160         switch (src -> gx_pixelmap_format)
161         {
162         case GX_COLOR_FORMAT_32ARGB:
163         case GX_COLOR_FORMAT_24XRGB:
164             /* Call 32argb pixelmap rotate. */
165             status = _gx_utility_32argb_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
166             break;
167 
168         case GX_COLOR_FORMAT_565RGB:
169         case GX_COLOR_FORMAT_565BGR:
170             /* Call 565rgb pixelmap rotate.  */
171             status = _gx_utility_565rgb_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
172             break;
173 
174         case GX_COLOR_FORMAT_1555XRGB:
175             status = _gx_utility_1555xrgb_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
176             break;
177 
178         case GX_COLOR_FORMAT_4444ARGB:
179             status = _gx_utility_4444argb_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
180             break;
181 
182         case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
183             status = _gx_utility_332rgb_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
184             break;
185 
186         case GX_COLOR_FORMAT_8BIT_PALETTE:
187             /* Call 8bpp pixelmap rotate.  */
188             status = _gx_utility_8bpp_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
189             break;
190 
191         case GX_COLOR_FORMAT_8BIT_ALPHAMAP:
192             /* Call 8bit alphamap rotate.  */
193             status = _gx_utility_8bit_alphamap_rotate(src, angle, destination, rot_cx, rot_cy);
194             break;
195 
196         case GX_COLOR_FORMAT_4BIT_GRAY:
197             status = _gx_utility_4bpp_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
198             break;
199 
200         case GX_COLOR_FORMAT_MONOCHROME:
201             status = _gx_utility_1bpp_pixelmap_rotate(src, angle, destination, rot_cx, rot_cy);
202             break;
203 
204         default:
205             return GX_INVALID_FORMAT;
206         }
207     }
208 
209     if ((src -> gx_pixelmap_flags & GX_PIXELMAP_ROTATED_90) ||
210         (src -> gx_pixelmap_flags & GX_PIXELMAP_ROTATED_270))
211     {
212         GX_SWAP_VALS(destination -> gx_pixelmap_width, destination -> gx_pixelmap_height);
213 
214         if (rot_cx && rot_cy)
215         {
216             GX_SWAP_VALS(*rot_cx, *rot_cy);
217 
218             if (src -> gx_pixelmap_flags & GX_PIXELMAP_ROTATED_90)
219             {
220                 *rot_cx = destination -> gx_pixelmap_width - 1 - (*rot_cx);
221             }
222             else
223             {
224                 *rot_cy = destination -> gx_pixelmap_height - 1 - (*rot_cy);
225             }
226         }
227     }
228 
229     return status;
230 }
231 
232