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 GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_display.h"
28 #include "gx_system.h"
29 #include "gx_utility.h"
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _gx_display_driver_16bpp_rotated_block_move PORTABLE C */
36 /* 6.1.3 */
37 /* AUTHOR */
38 /* */
39 /* Kenneth Maxwell, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* Generic 16bpp color format display driver rotated block moving */
44 /* function. */
45 /* */
46 /* INPUT */
47 /* */
48 /* context Draw context */
49 /* block The rectangle to be moved */
50 /* xshift Amount to move on X-axis */
51 /* yshift Amount to move on Y-axis */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* None */
56 /* */
57 /* CALLS */
58 /* */
59 /* memmove Move a block of data */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* GUIX Internal Code */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 12-31-2020 Kenneth Maxwell Initial Version 6.1.3 */
70 /* */
71 /**************************************************************************/
_gx_display_driver_16bpp_rotated_block_move(GX_DRAW_CONTEXT * context,GX_RECTANGLE * block,INT xshift,INT yshift)72 VOID _gx_display_driver_16bpp_rotated_block_move(GX_DRAW_CONTEXT *context,
73 GX_RECTANGLE *block, INT xshift, INT yshift)
74 {
75 USHORT *pGet;
76 USHORT *pPut;
77 INT width;
78 INT width_in_bytes;
79 INT y;
80 INT height;
81 GX_RECTANGLE rotated_block;
82
83 GX_SWAP_VALS(xshift, yshift);
84
85 if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
86 {
87 rotated_block.gx_rectangle_left = block -> gx_rectangle_top;
88 rotated_block.gx_rectangle_right = block -> gx_rectangle_bottom;
89 rotated_block.gx_rectangle_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - block -> gx_rectangle_right - 1);
90 rotated_block.gx_rectangle_bottom = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - block -> gx_rectangle_left - 1);
91
92 yshift = -yshift;
93 }
94 else
95 {
96 rotated_block.gx_rectangle_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - block -> gx_rectangle_bottom - 1);
97 rotated_block.gx_rectangle_right = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_y_resolution - block -> gx_rectangle_top - 1);
98 rotated_block.gx_rectangle_top = block -> gx_rectangle_left;
99 rotated_block.gx_rectangle_bottom = block -> gx_rectangle_right;
100
101 xshift = -xshift;
102 }
103
104 if (xshift)
105 {
106 if (xshift > 0)
107 {
108
109 /* Have to copy from left to right. */
110 pPut = (USHORT *)context -> gx_draw_context_memory;
111 pPut += rotated_block.gx_rectangle_top * context -> gx_draw_context_pitch;
112 pPut += rotated_block.gx_rectangle_left + xshift;
113
114 pGet = (USHORT *)context -> gx_draw_context_memory;
115 pGet += rotated_block.gx_rectangle_top * context -> gx_draw_context_pitch;
116 pGet += rotated_block.gx_rectangle_left;
117
118 width = rotated_block.gx_rectangle_right - rotated_block.gx_rectangle_left + 1 - xshift;
119 width_in_bytes = width * (int)sizeof(USHORT);
120
121 if (width_in_bytes <= 0)
122 {
123 return;
124 }
125
126 for (y = rotated_block.gx_rectangle_top; y <= rotated_block.gx_rectangle_bottom; y++)
127 {
128 memmove(pPut, pGet, (size_t)width_in_bytes);
129
130 pPut += context -> gx_draw_context_pitch;
131 pGet += context -> gx_draw_context_pitch;
132 }
133 }
134 else
135 {
136
137 /* Have to copy from right to left. */
138 pPut = (USHORT *)context -> gx_draw_context_memory;
139 pPut += rotated_block.gx_rectangle_top * context -> gx_draw_context_pitch;
140 pPut += rotated_block.gx_rectangle_left;
141
142 pGet = (USHORT *)context -> gx_draw_context_memory;
143 pGet += rotated_block.gx_rectangle_top * context -> gx_draw_context_pitch;
144 pGet += rotated_block.gx_rectangle_left - xshift;
145
146 width = rotated_block.gx_rectangle_right - rotated_block.gx_rectangle_left + 1 + xshift;
147 width_in_bytes = width * (int)sizeof(USHORT);
148
149 if (width_in_bytes <= 0)
150 {
151 return;
152 }
153
154 for (y = rotated_block.gx_rectangle_top; y <= rotated_block.gx_rectangle_bottom; y++)
155 {
156 memmove(pPut, pGet, (size_t)width_in_bytes);
157
158 pPut += context -> gx_draw_context_pitch;
159 pGet += context -> gx_draw_context_pitch;
160 }
161 }
162 }
163 else
164 {
165 width = rotated_block.gx_rectangle_right - rotated_block.gx_rectangle_left + 1;
166 width_in_bytes = width * (int)sizeof(USHORT);
167
168 if (yshift > 0)
169 {
170
171 /* Have to copy from top to bottom. */
172 pPut = (USHORT *)context -> gx_draw_context_memory;
173 pPut += rotated_block.gx_rectangle_bottom * context -> gx_draw_context_pitch;
174 pPut += rotated_block.gx_rectangle_left;
175
176 pGet = (USHORT *)context -> gx_draw_context_memory;
177 pGet += (rotated_block.gx_rectangle_bottom - yshift) * context -> gx_draw_context_pitch;
178 pGet += rotated_block.gx_rectangle_left;
179
180 height = rotated_block.gx_rectangle_bottom - rotated_block.gx_rectangle_top + 1 - yshift;
181
182 for (y = 0; y < height; y++)
183 {
184 memmove(pPut, pGet, (size_t)width_in_bytes);
185
186 pPut -= context -> gx_draw_context_pitch;
187 pGet -= context -> gx_draw_context_pitch;
188 }
189 }
190 else
191 {
192
193 /* Have to copy from bottom to top. */
194 pPut = (USHORT *)context -> gx_draw_context_memory;
195 pPut += rotated_block.gx_rectangle_top * context -> gx_draw_context_pitch;
196 pPut += rotated_block.gx_rectangle_left;
197
198 pGet = (USHORT *)context -> gx_draw_context_memory;
199 pGet += (rotated_block.gx_rectangle_top - yshift) * context -> gx_draw_context_pitch;
200 pGet += rotated_block.gx_rectangle_left;
201
202 height = rotated_block.gx_rectangle_bottom - rotated_block.gx_rectangle_top + 1 + yshift;
203
204 for (y = 0; y < height; y++)
205 {
206 memmove(pPut, pGet, (size_t)width_in_bytes);
207
208 pPut += context -> gx_draw_context_pitch;
209 pGet += context -> gx_draw_context_pitch;
210 }
211 }
212 }
213 }
214
215