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