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 /**   Text Input Management (Single Line Text Input)                      */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 /* Include necessary system files.  */
22 #define GX_SOURCE_CODE
23 
24 #include "gx_api.h"
25 #include "gx_utility.h"
26 
27 #define BI_RGB       0L
28 #define BI_BITFIELDS 3L
29 
30 #define DATA_OFFSET  54
31 typedef struct bitmap_file_header_struct
32 {
33     USHORT filetype;
34     UINT   filesize;
35     UINT   reserved;
36     UINT   offset;
37 } bitmap_file_header;
38 
39 typedef struct bmp_info_struct
40 {
41     UINT   bi_Size;
42     INT    bi_Width;
43     INT    bi_Height;
44     USHORT bi_Planes;
45     USHORT bi_BitCount;
46     UINT   bi_Compression;
47     UINT   bi_SizeImage;
48     UINT   bi_XPelsPerMeter;
49     UINT   bi_YPelsPerMeter;
50     UINT   bi_ClrUsed;
51     UINT   bi_ClrImportant;
52 } bmp_info;
53 
54 
55 /**************************************************************************/
56 /*                                                                        */
57 /*  FUNCTION                                               RELEASE        */
58 /*                                                                        */
59 /*    _gx_utility_write_bitmap_header                     PORTABLE C      */
60 /*                                                           6.1          */
61 /*  AUTHOR                                                                */
62 /*                                                                        */
63 /*    Kenneth Maxwell, Microsoft Corporation                              */
64 /*                                                                        */
65 /*  DESCRIPTION                                                           */
66 /*                                                                        */
67 /*    This function create bitmap header and write it to bmp file.        */
68 /*                                                                        */
69 /*  INPUT                                                                 */
70 /*                                                                        */
71 /*    canvas                                Canvas control block          */
72 /*    rectangle                             Rectangle specification       */
73 /*    write_data                            Write data callback function  */
74 /*                                                                        */
75 /*  OUTPUT                                                                */
76 /*                                                                        */
77 /*    status                                Completion status             */
78 /*                                                                        */
79 /*  CALLS                                                                 */
80 /*                                                                        */
81 /*    None                                                                */
82 /*                                                                        */
83 /*  CALLED BY                                                             */
84 /*                                                                        */
85 /*    _gx_utility_canvas_to_bmp                                           */
86 /*                                                                        */
87 /*  RELEASE HISTORY                                                       */
88 /*                                                                        */
89 /*    DATE              NAME                      DESCRIPTION             */
90 /*                                                                        */
91 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
92 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
93 /*                                            resulting in version 6.1    */
94 /*                                                                        */
95 /**************************************************************************/
_gx_utility_write_bitmap_header(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))96 static UINT _gx_utility_write_bitmap_header(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
97 {
98 bitmap_file_header bmp_fheader;
99 bmp_info           b_info;
100 GX_COLOR           color;
101 GX_COLOR          *palette;
102 INT                count;
103 INT                r;
104 INT                g;
105 INT                b;
106 INT                red;
107 INT                green;
108 INT                blue;
109 
110     memset(&bmp_fheader, 0, sizeof(bitmap_file_header));
111     memset(&b_info, 0, sizeof(bmp_info));
112     bmp_fheader.filetype = 0x4d42; /* "MB" */
113     bmp_fheader.reserved = 0;
114 
115     /* calculate data offset */
116     bmp_fheader.offset = DATA_OFFSET;
117 
118     /* set common datas for bmp info. */
119     b_info.bi_Width = rect -> gx_rectangle_right - rect -> gx_rectangle_left + 1;
120     b_info.bi_Height = rect -> gx_rectangle_bottom - rect -> gx_rectangle_top + 1;
121     b_info.bi_Size = sizeof(bmp_info);
122     b_info.bi_Planes = 1;
123     b_info.bi_Compression = BI_RGB;
124     b_info.bi_XPelsPerMeter = 0;
125     b_info.bi_YPelsPerMeter = 0;
126     b_info.bi_ClrUsed = 0;
127     b_info.bi_ClrImportant = 0;
128 
129     switch (canvas -> gx_canvas_display -> gx_display_color_format)
130     {
131     case GX_COLOR_FORMAT_32ARGB:
132     case GX_COLOR_FORMAT_24XRGB:
133         b_info.bi_BitCount = 32;
134         b_info.bi_SizeImage = (UINT)((b_info.bi_Width << 2) * b_info.bi_Height);
135         break;
136 
137     case GX_COLOR_FORMAT_1555XRGB:
138     case GX_COLOR_FORMAT_4444ARGB:
139     case GX_COLOR_FORMAT_565RGB:
140         b_info.bi_BitCount = 16;
141         b_info.bi_SizeImage = (UINT)((((UINT)(b_info.bi_Width + 1) & 0xfffffffe) << 1) * (UINT)b_info.bi_Height);
142         b_info.bi_ClrUsed = 3;
143         b_info.bi_ClrImportant = 3;
144         b_info.bi_Compression = BI_BITFIELDS;
145         /* Three color entries in palette */
146         bmp_fheader.offset += 3 * sizeof(GX_COLOR);
147         break;
148 
149     case GX_COLOR_FORMAT_8BIT_PALETTE:
150         if ((canvas -> gx_canvas_display -> gx_display_palette == GX_NULL) ||
151             (canvas -> gx_canvas_display -> gx_display_palette_size == 0))
152         {
153             return GX_FAILURE;
154         }
155         b_info.bi_BitCount = 8;
156         b_info.bi_SizeImage = (UINT)(((UINT)(b_info.bi_Width + 3) & 0xfffffffc) * (UINT)b_info.bi_Height);
157         b_info.bi_ClrUsed = canvas -> gx_canvas_display -> gx_display_palette_size;
158         b_info.bi_ClrImportant = canvas -> gx_canvas_display -> gx_display_palette_size;
159         bmp_fheader.offset += canvas -> gx_canvas_display -> gx_display_palette_size * sizeof(GX_COLOR);
160         break;
161 
162     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
163         b_info.bi_BitCount = 8;
164         b_info.bi_SizeImage = (UINT)(((UINT)(b_info.bi_Width + 3) & 0xfffffffc) * (UINT)b_info.bi_Height);
165         /* Palette for 332rgb is default to 256. */
166         b_info.bi_ClrImportant = 256;
167         b_info.bi_ClrUsed = 256;
168         bmp_fheader.offset += 256 * sizeof(GX_COLOR);
169         break;
170 
171     case GX_COLOR_FORMAT_4BIT_GRAY:
172         b_info.bi_BitCount = 4;
173         b_info.bi_SizeImage = (UINT)((((UINT)(b_info.bi_Width + 7) & 0xfffffff8) >> 1) * (UINT)b_info.bi_Height);
174         b_info.bi_ClrUsed = 16;
175         b_info.bi_ClrImportant = 16;
176         bmp_fheader.offset += 16 * sizeof(GX_COLOR);
177         break;
178 
179     case GX_COLOR_FORMAT_MONOCHROME:
180         b_info.bi_BitCount = 1;
181         b_info.bi_SizeImage = (UINT)((((UINT)(b_info.bi_Width + 63) & 0xffffffc0) >> 3) * (UINT)b_info.bi_Height);
182         b_info.bi_ClrUsed = 2;
183         b_info.bi_ClrImportant = 2;
184         bmp_fheader.offset += 2 * sizeof(GX_COLOR);
185         break;
186 
187     default:
188         break;
189     }
190 
191     /* total file size */
192     bmp_fheader.filesize = bmp_fheader.offset + b_info.bi_SizeImage;
193 
194     /* write bmp file header */
195     write_data((GX_UBYTE *)&bmp_fheader.filetype, sizeof(USHORT));
196     write_data((GX_UBYTE *)&bmp_fheader.filesize, sizeof(UINT));
197     write_data((GX_UBYTE *)&bmp_fheader.reserved, sizeof(UINT));
198     write_data((GX_UBYTE *)&bmp_fheader.offset, sizeof(UINT));
199 
200     /* height value is negtive means we can write image data from top to bottom. */
201     b_info.bi_Height = -b_info.bi_Height;
202     /* write bmp info */
203     write_data((GX_UBYTE *)&b_info, sizeof(bmp_info));
204 
205     /* I don't want to add a matrix with 256 to store the palette.
206        so let's write the palette by colors.*/
207     switch (canvas -> gx_canvas_display -> gx_display_color_format)
208     {
209     case GX_COLOR_FORMAT_565RGB:
210         color = 0x0000f800;
211         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
212         color = 0x000007e0;
213         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
214         color = 0x0000001f;
215         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
216         break;
217 
218     case GX_COLOR_FORMAT_1555XRGB:
219         color = 0x00007c00;
220         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
221         color = 0x000003e0;
222         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
223         color = 0x0000001f;
224         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
225         break;
226 
227     case GX_COLOR_FORMAT_4444ARGB:
228         color = 0x00000f00;
229         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
230         color = 0x000000f0;
231         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
232         color = 0x0000000f;
233         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
234         break;
235 
236     case GX_COLOR_FORMAT_8BIT_PALETTE:
237         palette = canvas -> gx_canvas_display -> gx_display_palette;
238         count = (INT)(canvas -> gx_canvas_display -> gx_display_palette_size);
239         while (count)
240         {
241             write_data((GX_UBYTE *)palette, sizeof(GX_COLOR));
242             palette++;
243             count--;
244         }
245         break;
246 
247     case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
248         for (r = 0; r < 8; r++)
249         {
250             red = r << 21;
251             if (red & 0x200000)
252             {
253                 red |= 0x1f0000;
254             }
255             for (g = 0; g < 8; g++)
256             {
257                 green = g << 13;
258                 if (green & 0x2000)
259                 {
260                     green |= 0x1f00;
261                 }
262                 for (b = 0; b < 4; b++)
263                 {
264                     blue = b << 6;
265                     if (blue & 0x40)
266                     {
267                         blue |= 0x3f;
268                     }
269                     color = (GX_COLOR)(red | green | blue);
270                     write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
271                 }
272             }
273         }
274         break;
275 
276     case GX_COLOR_FORMAT_4BIT_GRAY:
277         for (r = 0; r <= 0xff; r += 0x11)
278         {
279             color = (GX_COLOR)((GX_COLOR)((r << 16) | (r << 8) | r) | 0xff000000);
280             write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
281         }
282         break;
283 
284     case GX_COLOR_FORMAT_MONOCHROME:
285         color = 0xff000000;
286         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
287         color = 0xffffffff;
288         write_data((GX_UBYTE *)&color, sizeof(GX_COLOR));
289         break;
290 
291     default:
292         break;
293     }
294 
295     return GX_SUCCESS;
296 }
297 
298 /**************************************************************************/
299 /*                                                                        */
300 /*  FUNCTION                                               RELEASE        */
301 /*                                                                        */
302 /*    _gx_utility_write_bitmap_data_32bpp                 PORTABLE C      */
303 /*                                                           6.1          */
304 /*  AUTHOR                                                                */
305 /*                                                                        */
306 /*    Kenneth Maxwell, Microsoft Corporation                              */
307 /*                                                                        */
308 /*  DESCRIPTION                                                           */
309 /*                                                                        */
310 /*    This function read canvas memory data and write it to bmp file.     */
311 /*                                                                        */
312 /*  INPUT                                                                 */
313 /*                                                                        */
314 /*    canvas                                Canvas control block          */
315 /*    rectangle                             Rectangle specification       */
316 /*    write_data                            Write data callback function  */
317 /*                                                                        */
318 /*  OUTPUT                                                                */
319 /*                                                                        */
320 /*    None                                                                */
321 /*                                                                        */
322 /*  CALLS                                                                 */
323 /*                                                                        */
324 /*    None                                                                */
325 /*                                                                        */
326 /*  CALLED BY                                                             */
327 /*                                                                        */
328 /*    _gx_utility_canvas_to_bmp                                           */
329 /*                                                                        */
330 /*  RELEASE HISTORY                                                       */
331 /*                                                                        */
332 /*    DATE              NAME                      DESCRIPTION             */
333 /*                                                                        */
334 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
335 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
336 /*                                            resulting in version 6.1    */
337 /*                                                                        */
338 /**************************************************************************/
_gx_utility_write_bitmap_data_32bpp(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))339 static void _gx_utility_write_bitmap_data_32bpp(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
340 {
341 GX_COLOR *get;
342 GX_COLOR *get_row;
343 INT       x;
344 INT       y;
345 
346     get_row = (GX_COLOR *)(canvas -> gx_canvas_memory);
347     get_row += canvas -> gx_canvas_x_resolution * rect -> gx_rectangle_top;
348     get_row += rect -> gx_rectangle_left;
349 
350     for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
351     {
352         get = get_row;
353         for (x = rect -> gx_rectangle_left; x <= rect -> gx_rectangle_right; x++)
354         {
355             write_data((GX_UBYTE *)get, sizeof(GX_COLOR));
356             get++;
357         }
358         get_row += canvas -> gx_canvas_x_resolution;
359     }
360 }
361 
362 /**************************************************************************/
363 /*                                                                        */
364 /*  FUNCTION                                               RELEASE        */
365 /*                                                                        */
366 /*    _gx_utility_write_bitmap_data_16bpp                 PORTABLE C      */
367 /*                                                           6.1          */
368 /*  AUTHOR                                                                */
369 /*                                                                        */
370 /*    Kenneth Maxwell, Microsoft Corporation                              */
371 /*                                                                        */
372 /*  DESCRIPTION                                                           */
373 /*                                                                        */
374 /*    This function read canvas memory data and write it to bmp file.     */
375 /*                                                                        */
376 /*  INPUT                                                                 */
377 /*                                                                        */
378 /*    canvas                                Canvas control block          */
379 /*    rectangle                             Rectangle specification       */
380 /*    write_data                            Write data callback function  */
381 /*                                                                        */
382 /*  OUTPUT                                                                */
383 /*                                                                        */
384 /*    None                                                                */
385 /*                                                                        */
386 /*  CALLS                                                                 */
387 /*                                                                        */
388 /*    None                                                                */
389 /*                                                                        */
390 /*  CALLED BY                                                             */
391 /*                                                                        */
392 /*    _gx_utility_canvas_to_bmp                                           */
393 /*                                                                        */
394 /*  RELEASE HISTORY                                                       */
395 /*                                                                        */
396 /*    DATE              NAME                      DESCRIPTION             */
397 /*                                                                        */
398 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
399 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
400 /*                                            resulting in version 6.1    */
401 /*                                                                        */
402 /**************************************************************************/
_gx_utility_write_bitmap_data_16bpp(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))403 static void _gx_utility_write_bitmap_data_16bpp(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
404 {
405 USHORT *get;
406 USHORT *get_row;
407 INT     x;
408 INT     y;
409 INT     width;
410 
411     get_row = (USHORT *)(canvas -> gx_canvas_memory);
412     get_row += canvas -> gx_canvas_x_resolution * rect -> gx_rectangle_top;
413     get_row += rect -> gx_rectangle_left;
414     width = rect -> gx_rectangle_right - rect -> gx_rectangle_left + 1;
415 
416     for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
417     {
418         get = get_row;
419         for (x = 0; x < width; x++)
420         {
421             write_data((GX_UBYTE *)get, sizeof(USHORT));
422             get++;
423         }
424         if (width & 1)
425         {
426             /* Fix data to 4 bytes aligned. */
427             write_data((GX_UBYTE *)get, sizeof(USHORT));
428         }
429         get_row += canvas -> gx_canvas_x_resolution;
430     }
431 }
432 
433 /**************************************************************************/
434 /*                                                                        */
435 /*  FUNCTION                                               RELEASE        */
436 /*                                                                        */
437 /*    _gx_utility_write_bitmap_data_8bpp                  PORTABLE C      */
438 /*                                                           6.1          */
439 /*  AUTHOR                                                                */
440 /*                                                                        */
441 /*    Kenneth Maxwell, Microsoft Corporation                              */
442 /*                                                                        */
443 /*  DESCRIPTION                                                           */
444 /*                                                                        */
445 /*    This function read canvas memory data and write it to bmp file.     */
446 /*                                                                        */
447 /*  INPUT                                                                 */
448 /*                                                                        */
449 /*    canvas                                Canvas control block          */
450 /*    rectangle                             Rectangle specification       */
451 /*    write_data                            Write data callback function  */
452 /*                                                                        */
453 /*  OUTPUT                                                                */
454 /*                                                                        */
455 /*    None                                                                */
456 /*                                                                        */
457 /*  CALLS                                                                 */
458 /*                                                                        */
459 /*    None                                                                */
460 /*                                                                        */
461 /*  CALLED BY                                                             */
462 /*                                                                        */
463 /*    _gx_utility_canvas_to_bmp                                           */
464 /*                                                                        */
465 /*  RELEASE HISTORY                                                       */
466 /*                                                                        */
467 /*    DATE              NAME                      DESCRIPTION             */
468 /*                                                                        */
469 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
470 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
471 /*                                            resulting in version 6.1    */
472 /*                                                                        */
473 /**************************************************************************/
_gx_utility_write_bitmap_data_8bpp(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))474 static void _gx_utility_write_bitmap_data_8bpp(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
475 {
476 GX_UBYTE *get;
477 GX_UBYTE *get_row;
478 INT       x;
479 INT       y;
480 INT       width;
481 INT       fixed_count;
482 
483     get_row = (GX_UBYTE *)(canvas -> gx_canvas_memory);
484     get_row += canvas -> gx_canvas_x_resolution * rect -> gx_rectangle_top;
485     get_row += rect -> gx_rectangle_left;
486     width = rect -> gx_rectangle_right - rect -> gx_rectangle_left + 1;
487     fixed_count = width & 3;
488     if (fixed_count)
489     {
490         fixed_count = 4 - fixed_count;
491     }
492 
493     for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
494     {
495         get = get_row;
496         for (x = 0; x < width; x++)
497         {
498             write_data((GX_UBYTE *)get, sizeof(GX_UBYTE));
499             get++;
500         }
501 
502         /* Fix data to 4 bytes aligned. */
503         for (x = 0; x < fixed_count; x++)
504         {
505             write_data((GX_UBYTE *)get, sizeof(GX_UBYTE));
506         }
507         get_row += canvas -> gx_canvas_x_resolution;
508     }
509 }
510 
511 /**************************************************************************/
512 /*                                                                        */
513 /*  FUNCTION                                               RELEASE        */
514 /*                                                                        */
515 /*    _gx_utility_write_bitmap_data_4bpp                  PORTABLE C      */
516 /*                                                           6.1          */
517 /*  AUTHOR                                                                */
518 /*                                                                        */
519 /*    Kenneth Maxwell, Microsoft Corporation                              */
520 /*                                                                        */
521 /*  DESCRIPTION                                                           */
522 /*                                                                        */
523 /*    This function read canvas memory data and write it to bmp file.     */
524 /*                                                                        */
525 /*  INPUT                                                                 */
526 /*                                                                        */
527 /*    canvas                                Canvas control block          */
528 /*    rectangle                             Rectangle specification       */
529 /*    write_data                            Write data callback function  */
530 /*                                                                        */
531 /*  OUTPUT                                                                */
532 /*                                                                        */
533 /*    None                                                                */
534 /*                                                                        */
535 /*  CALLS                                                                 */
536 /*                                                                        */
537 /*    None                                                                */
538 /*                                                                        */
539 /*  CALLED BY                                                             */
540 /*                                                                        */
541 /*    _gx_utility_canvas_to_bmp                                           */
542 /*                                                                        */
543 /*  RELEASE HISTORY                                                       */
544 /*                                                                        */
545 /*    DATE              NAME                      DESCRIPTION             */
546 /*                                                                        */
547 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
548 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
549 /*                                            resulting in version 6.1    */
550 /*                                                                        */
551 /**************************************************************************/
_gx_utility_write_bitmap_data_4bpp(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))552 static void _gx_utility_write_bitmap_data_4bpp(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
553 {
554 GX_UBYTE *get;
555 GX_UBYTE *get_row;
556 GX_UBYTE  color = 0;
557 INT       x;
558 INT       y;
559 INT       fixed_count;
560 INT       row_count;
561 
562     get_row = (GX_UBYTE *)(canvas -> gx_canvas_memory);
563     get_row += ((canvas -> gx_canvas_x_resolution + 1) >> 1) * rect -> gx_rectangle_top;
564     get_row += rect -> gx_rectangle_left >> 1;
565     row_count = rect -> gx_rectangle_right - rect -> gx_rectangle_left + 1;
566     row_count = (row_count + 1) >> 1;
567     fixed_count = row_count & 3;
568     if (fixed_count)
569     {
570         fixed_count = 4 - fixed_count;
571     }
572 
573     if (rect -> gx_rectangle_left & 1)
574     {
575         /* If start pixel is not at the first bit of byte. We need to make it aligned. */
576         for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
577         {
578             get = get_row;
579             for (x = 0; x < row_count; x++)
580             {
581                 color = (GX_UBYTE)((*get & 0x0f) << 4);
582                 get++;
583                 color |= (*get & 0xf0) >> 4;
584 
585                 write_data((GX_UBYTE *)&color, sizeof(GX_UBYTE));
586             }
587 
588             /* Fix data to 4 bytes aligned. */
589             for (x = 0; x < fixed_count; x++)
590             {
591                 write_data((GX_UBYTE *)&color, sizeof(GX_UBYTE));
592             }
593 
594             get_row += (canvas -> gx_canvas_x_resolution + 1) >> 1;
595         }
596     }
597     else
598     {
599         for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
600         {
601             get = get_row;
602             for (x = 0; x < row_count; x++)
603             {
604                 write_data((GX_UBYTE *)get, sizeof(GX_UBYTE));
605                 get++;
606             }
607 
608             /* Fix data to 4 bytes aligned. */
609             for (x = 0; x < fixed_count; x++)
610             {
611                 write_data((GX_UBYTE *)&color, sizeof(GX_UBYTE));
612             }
613             get_row += (canvas -> gx_canvas_x_resolution + 1) >> 1;
614         }
615     }
616 }
617 
618 /**************************************************************************/
619 /*                                                                        */
620 /*  FUNCTION                                               RELEASE        */
621 /*                                                                        */
622 /*    _gx_utility_write_bitmap_data_monochrome            PORTABLE C      */
623 /*                                                           6.1          */
624 /*  AUTHOR                                                                */
625 /*                                                                        */
626 /*    Kenneth Maxwell, Microsoft Corporation                              */
627 /*                                                                        */
628 /*  DESCRIPTION                                                           */
629 /*                                                                        */
630 /*    This function read canvas memory data and write it to bmp file.     */
631 /*                                                                        */
632 /*  INPUT                                                                 */
633 /*                                                                        */
634 /*    canvas                                Canvas control block          */
635 /*    rectangle                             Rectangle specification       */
636 /*    write_data                            Write data callback function  */
637 /*                                                                        */
638 /*  OUTPUT                                                                */
639 /*                                                                        */
640 /*    None                                                                */
641 /*                                                                        */
642 /*  CALLS                                                                 */
643 /*                                                                        */
644 /*    None                                                                */
645 /*                                                                        */
646 /*  CALLED BY                                                             */
647 /*                                                                        */
648 /*    _gx_utility_canvas_to_bmp                                           */
649 /*                                                                        */
650 /*  RELEASE HISTORY                                                       */
651 /*                                                                        */
652 /*    DATE              NAME                      DESCRIPTION             */
653 /*                                                                        */
654 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
655 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
656 /*                                            resulting in version 6.1    */
657 /*                                                                        */
658 /**************************************************************************/
_gx_utility_write_bitmap_data_monochrome(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))659 static void _gx_utility_write_bitmap_data_monochrome(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
660 {
661 GX_UBYTE *get;
662 GX_UBYTE *get_row;
663 INT       x;
664 INT       y;
665 INT       row_count;
666 INT       fixed_count;
667 INT       bits_in_first_byte;
668 GX_UBYTE  color = 0;
669 
670     get_row = (GX_UBYTE *)(canvas -> gx_canvas_memory);
671     get_row += ((canvas -> gx_canvas_x_resolution + 7) >> 3) * rect -> gx_rectangle_top;
672     get_row += rect -> gx_rectangle_left >> 3;
673     row_count = rect -> gx_rectangle_right - rect -> gx_rectangle_left + 1;
674     row_count = (row_count + 7) >> 3;
675     bits_in_first_byte = rect -> gx_rectangle_left & 7;
676     fixed_count = row_count & 3;
677     if (fixed_count)
678     {
679         fixed_count = 4 - fixed_count;
680     }
681 
682     if (bits_in_first_byte)
683     {
684         bits_in_first_byte = 8 - (rect -> gx_rectangle_left & 7);
685 
686         /* If start pixel is not at the first bit of byte. We need to make it aligned. */
687         for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
688         {
689             get = get_row;
690             for (x = 0; x < row_count; x++)
691             {
692                 color = (GX_UBYTE)((*get) << (8 - bits_in_first_byte));
693                 get++;
694                 color = (GX_UBYTE)(color | ((*get) >> bits_in_first_byte));
695 
696                 write_data((GX_UBYTE *)&color, sizeof(GX_UBYTE));
697             }
698 
699             /* Fix data to 4 bytes aligned. */
700             for (x = 0; x < fixed_count; x++)
701             {
702                 write_data((GX_UBYTE *)&color, sizeof(GX_UBYTE));
703             }
704 
705             get_row += (canvas -> gx_canvas_x_resolution + 7) >> 3;
706         }
707     }
708     else
709     {
710         for (y = rect -> gx_rectangle_top; y <= rect -> gx_rectangle_bottom; y++)
711         {
712             get = get_row;
713             for (x = 0; x < row_count; x++)
714             {
715                 write_data((GX_UBYTE *)get, sizeof(GX_UBYTE));
716                 get++;
717             }
718 
719             /* Fix data to 4 bytes aligned. */
720             for (x = 0; x < fixed_count; x++)
721             {
722                 write_data((GX_UBYTE *)&color, sizeof(GX_UBYTE));
723             }
724 
725             get_row += (canvas -> gx_canvas_x_resolution + 7) >> 3;
726         }
727     }
728 }
729 
730 /**************************************************************************/
731 /*                                                                        */
732 /*  FUNCTION                                               RELEASE        */
733 /*                                                                        */
734 /*    _gx_utility_canvas_to_bmp                           PORTABLE C      */
735 /*                                                           6.1          */
736 /*  AUTHOR                                                                */
737 /*                                                                        */
738 /*    Kenneth Maxwell, Microsoft Corporation                              */
739 /*                                                                        */
740 /*  DESCRIPTION                                                           */
741 /*                                                                        */
742 /*    Covert canvas memory data to bmp file.                              */
743 /*                                                                        */
744 /*  INPUT                                                                 */
745 /*                                                                        */
746 /*    canvas                                Canvas control block          */
747 /*    rectangle                             Rectangle specification       */
748 /*    write_data                            Write data callback function  */
749 /*                                                                        */
750 /*  OUTPUT                                                                */
751 /*                                                                        */
752 /*    status                                Completion status             */
753 /*                                                                        */
754 /*  CALLS                                                                 */
755 /*                                                                        */
756 /*    _gx_utility_rectangle_define          Define a rectangle            */
757 /*    _gx_utility_rectangle_inside_detect   Detect rect inside of another */
758 /*    _gx_utility_write_bitmap_header       Create bmp file header        */
759 /*    _gx_utility_write_bitmap_data_monochrome                            */
760 /*    _gx_utility_write_bitmap_data_4bpp                                  */
761 /*    _gx_utility_write_bitmap_data_8bpp                                  */
762 /*    _gx_utility_write_bitmap_data_16bpp                                 */
763 /*    _gx_utility_write_bitmap_data_32bpp   Above functions read canvas   */
764 /*                                            memory and write data to    */
765 /*                                            file.                       */
766 /*                                                                        */
767 /*  CALLED BY                                                             */
768 /*                                                                        */
769 /*    _gxe_utility_canvas_to_bmp            Error checking function       */
770 /*                                                                        */
771 /*  RELEASE HISTORY                                                       */
772 /*                                                                        */
773 /*    DATE              NAME                      DESCRIPTION             */
774 /*                                                                        */
775 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
776 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
777 /*                                            resulting in version 6.1    */
778 /*                                                                        */
779 /**************************************************************************/
_gx_utility_canvas_to_bmp(GX_CANVAS * canvas,GX_RECTANGLE * rect,UINT (* write_data)(GX_UBYTE * byte_data,UINT data_count))780 UINT _gx_utility_canvas_to_bmp(GX_CANVAS *canvas, GX_RECTANGLE *rect, UINT (*write_data)(GX_UBYTE *byte_data, UINT data_count))
781 {
782 UINT         status;
783 UINT         pixelmap_format;
784 GX_RECTANGLE canvas_size;
785 
786     _gx_utility_rectangle_define(&canvas_size, 0, 0, (GX_VALUE)(canvas -> gx_canvas_x_resolution - 1), (GX_VALUE)(canvas -> gx_canvas_y_resolution - 1));
787 
788     if (!_gx_utility_rectangle_inside_detect(&canvas_size, rect))
789     {
790         return GX_INVALID_SIZE;
791     }
792 
793     /* write bmp file header. */
794     status = _gx_utility_write_bitmap_header(canvas, rect, write_data);
795 
796     if (status == GX_SUCCESS)
797     {
798         /* write bmp image data*/
799         pixelmap_format = canvas -> gx_canvas_display -> gx_display_color_format;
800 
801         switch (pixelmap_format)
802         {
803         case GX_COLOR_FORMAT_MONOCHROME:
804             _gx_utility_write_bitmap_data_monochrome(canvas, rect, write_data);
805             break;
806 
807 
808         case GX_COLOR_FORMAT_4BIT_GRAY:
809             _gx_utility_write_bitmap_data_4bpp(canvas, rect, write_data);
810             break;
811 
812         case GX_COLOR_FORMAT_8BIT_PACKED_PIXEL:
813         case GX_COLOR_FORMAT_8BIT_PALETTE:
814             _gx_utility_write_bitmap_data_8bpp(canvas, rect, write_data);
815             break;
816 
817         case GX_COLOR_FORMAT_1555XRGB:
818         case GX_COLOR_FORMAT_4444ARGB:
819         case GX_COLOR_FORMAT_565RGB:
820             _gx_utility_write_bitmap_data_16bpp(canvas, rect, write_data);
821             break;
822 
823         case GX_COLOR_FORMAT_24XRGB:
824         case GX_COLOR_FORMAT_32ARGB:
825             _gx_utility_write_bitmap_data_32bpp(canvas, rect, write_data);
826             break;
827 
828         case GX_COLOR_FORMAT_2BIT_GRAY: /* Not support now. */
829         default:
830             return GX_NOT_SUPPORTED;
831         }
832     }
833 
834     return status;
835 }
836 
837