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_1bpp_block_move                  PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Kenneth Maxwell, Microsoft Corporation                              */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    1-bit color palette display driver block moving function.           */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    context                               Draw context                  */
48 /*    block                                 The rectangle to be moved     */
49 /*    xshift                                Amount to move on X-axis      */
50 /*    yshift                                Amount to move on Y-axis      */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    None                                                                */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    memmove                               Move a block of data          */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    GUIX Internal Code                                                  */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
69 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
70 /*                                            resulting in version 6.1    */
71 /*                                                                        */
72 /**************************************************************************/
_gx_display_driver_1bpp_block_move(GX_DRAW_CONTEXT * context,GX_RECTANGLE * block,INT xshift,INT yshift)73 VOID _gx_display_driver_1bpp_block_move(GX_DRAW_CONTEXT *context,
74                                         GX_RECTANGLE *block, INT xshift, INT yshift)
75 {
76 GX_UBYTE *putrow;
77 GX_UBYTE *getrow;
78 GX_UBYTE *pGet;
79 GX_UBYTE *pPut;
80 INT       width;
81 INT       column;
82 INT       y;
83 INT       height;
84 INT       stride;
85 GX_UBYTE  putmask;
86 GX_UBYTE  getmask;
87 INT       move_width;
88 
89     putrow = (GX_UBYTE *)context -> gx_draw_context_memory;
90 
91     stride = (context -> gx_draw_context_pitch + 7) >> 3;
92 
93     if (xshift)
94     {
95         if (xshift > 0)
96         {
97             /* Copy from left to right.  */
98             width = block -> gx_rectangle_right - block -> gx_rectangle_left + 1;
99             width -= xshift;
100 
101             putrow += block -> gx_rectangle_top * stride;
102             getrow = putrow;
103 
104             putrow += block -> gx_rectangle_right >> 3;
105             getrow += (block -> gx_rectangle_left + width - 1) >> 3;
106 
107             for (y = block -> gx_rectangle_top; y <= block -> gx_rectangle_bottom; y++)
108             {
109                 pPut = putrow;
110                 pGet = getrow;
111 
112                 putmask = (GX_UBYTE)(0x80 >> (block -> gx_rectangle_right & 0x07));
113                 getmask = (GX_UBYTE)(0x80 >> ((block -> gx_rectangle_left + width - 1) & 0x07));
114 
115                 for (column = 0; column < width; column++)
116                 {
117                     if ((*pGet) & getmask)
118                     {
119                         *pPut |= putmask;
120                     }
121                     else
122                     {
123                         *pPut = (GX_UBYTE)((*pPut) & (~putmask));
124                     }
125 
126                     if (getmask == 0x80)
127                     {
128                         getmask = 0x01;
129                         pGet--;
130                     }
131                     else
132                     {
133                         getmask = (GX_UBYTE)(getmask << 1);
134                     }
135 
136                     if (putmask == 0x80)
137                     {
138                         putmask = 0x01;
139                         pPut--;
140                     }
141                     else
142                     {
143                         putmask = (GX_UBYTE)(putmask << 1);
144                     }
145                 }
146 
147                 putrow += stride;
148                 getrow += stride;
149             }
150         }
151         else
152         {
153             /* Copy from right to left.  */
154             width = block -> gx_rectangle_right - block -> gx_rectangle_left + 1;
155             width += xshift;
156 
157             putrow += block -> gx_rectangle_top * stride;
158             getrow = putrow;
159 
160             putrow += block -> gx_rectangle_left >> 3;
161             getrow += (block -> gx_rectangle_left - xshift) >> 3;
162 
163             for (y = block -> gx_rectangle_top; y <= block -> gx_rectangle_bottom; y++)
164             {
165                 pPut = putrow;
166                 pGet = getrow;
167 
168                 putmask = (GX_UBYTE)(0x80 >> (block -> gx_rectangle_left & 0x07));
169                 getmask = (GX_UBYTE)(0x80 >> ((block -> gx_rectangle_left - xshift) & 0x07));
170 
171                 for (column = 0; column < width; column++)
172                 {
173                     if ((*pGet) & getmask)
174                     {
175                         *pPut |= putmask;
176                     }
177                     else
178                     {
179                         *pPut &= (GX_UBYTE)(~putmask);
180                     }
181 
182                     getmask >>= 1;
183                     putmask >>= 1;
184 
185                     if (!getmask)
186                     {
187                         getmask = 0x80;
188                         pGet++;
189                     }
190                     if (!putmask)
191                     {
192                         putmask = 0x80;
193                         pPut++;
194                     }
195                 }
196 
197                 putrow += stride;
198                 getrow += stride;
199             }
200         }
201     }
202     else
203     {
204         width = block -> gx_rectangle_right - block -> gx_rectangle_left + 1;
205 
206         if (yshift > 0)
207         {
208             /* Copy from top to bottom.  */
209             putrow += (block -> gx_rectangle_bottom * stride);
210             putrow += (block -> gx_rectangle_left >> 3);
211 
212             getrow = putrow;
213             getrow -= yshift * stride;
214 
215             height = block -> gx_rectangle_bottom - block -> gx_rectangle_top + 1;
216             height -= yshift;
217 
218             for (y = 0; y < height; y++)
219             {
220                 pPut = putrow;
221                 pGet = getrow;
222 
223                 putmask = (GX_UBYTE)(0x80 >> (block -> gx_rectangle_left & 0x07));
224 
225                 column = 0;
226                 while (column < width)
227                 {
228                     if ((putmask == 0x80) && (width - column >= 8))
229                     {
230                         move_width = (width - column) >> 3;
231                         memmove(pPut, pGet, (size_t)move_width);
232                         pPut += move_width;
233                         pGet += move_width;
234                         column += (move_width << 3);
235                     }
236                     else
237                     {
238                         if ((*pGet) & putmask)
239                         {
240                             *pPut |= putmask;
241                         }
242                         else
243                         {
244                             *pPut &= (GX_UBYTE)(~putmask);
245                         }
246 
247                         putmask >>= 1;
248 
249                         if (!putmask)
250                         {
251                             putmask = 0x80;
252                             pPut++;
253                             pGet++;
254                         }
255 
256                         column++;
257                     }
258                 }
259 
260                 putrow -= stride;
261                 getrow -= stride;
262             }
263         }
264         else
265         {
266             /* Copy from bottom to top.  */
267             putrow += (block -> gx_rectangle_top * stride);
268             putrow += (block -> gx_rectangle_left >> 3);
269 
270             getrow = putrow;
271             getrow -= yshift * stride;
272 
273             height = block -> gx_rectangle_bottom - block -> gx_rectangle_top + 1;
274             height += yshift;
275 
276             for (y = 0; y < height; y++)
277             {
278                 pPut = putrow;
279                 pGet = getrow;
280 
281                 putmask = (GX_UBYTE)(0x80 >> (block -> gx_rectangle_left & 0x07));
282 
283                 column = 0;
284 
285                 while (column < width)
286                 {
287                     if ((putmask == 0x80) && (width - column >= 8))
288                     {
289                         move_width = (width - column) >> 3;
290                         memmove(pPut, pGet, (size_t)move_width);
291                         pPut += move_width;
292                         pGet += move_width;
293                         column += (move_width << 3);
294                     }
295                     else
296                     {
297                         if ((*pGet) & putmask)
298                         {
299                             *pPut |= putmask;
300                         }
301                         else
302                         {
303                             *pPut &= (GX_UBYTE)(~putmask);
304                         }
305 
306                         putmask >>= 1;
307 
308                         if (!putmask)
309                         {
310                             putmask = 0x80;
311                             pPut++;
312                             pGet++;
313                         }
314 
315                         column++;
316                     }
317                 }
318 
319                 putrow += stride;
320                 getrow += stride;
321             }
322         }
323     }
324 }
325 
326