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_system.h"
28 #include "gx_utility.h"
29 #include "gx_display.h"
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _gx_display_driver_4bpp_glyph_1bit_draw             PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Kenneth Maxwell, Microsoft Corporation                              */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function draws monochrome font to the 4bpp canvas, clipped     */
44 /*    to one viweport.                                                    */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    context                               Draw context                  */
49 /*    draw_area                             The region bound by the       */
50 /*                                            rectangle where the glyph   */
51 /*                                            is drawn                    */
52 /*    map_offset                            X,Y offset into the glyph map */
53 /*    glyph                                 Pointer to the glyph          */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    None                                                                */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    None                                                                */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    GUIX internal code                                                  */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
72 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
76 
77 #define WRITE_PIXEL if (alpha & mask)                      \
78     {                                                      \
79         *put = *put & (GX_UBYTE)(~putmask);                \
80         *put = *put | (GX_UBYTE)(text_color & putmask);    \
81     }                                                      \
82     putmask = putmask >> 4;                                \
83     if (putmask == 0)                                      \
84     {                                                      \
85         putmask = 0xf0;                                    \
86         put++;                                             \
87     }
88 
89 
_gx_display_driver_4bpp_glyph_1bit_draw(GX_DRAW_CONTEXT * context,GX_RECTANGLE * draw_area,GX_POINT * map_offset,const GX_GLYPH * glyph)90 VOID _gx_display_driver_4bpp_glyph_1bit_draw(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area, GX_POINT *map_offset, const GX_GLYPH *glyph)
91 {
92 GX_UBYTE *glyph_row;
93 GX_UBYTE *glyph_data;
94 UINT      row;
95 UINT      pixel_per_row;
96 UINT      pixel_in_first_byte;
97 UINT      pixel_in_last_byte = 0;
98 GX_UBYTE  text_color;
99 UINT      y_height;
100 GX_UBYTE  alpha;
101 UINT      glyph_width;
102 GX_UBYTE *put;
103 UINT      num_bytes;
104 UINT      num_bits;
105 GX_UBYTE *line_start;
106 GX_UBYTE  mask, init_mask;
107 UINT      i;
108 GX_UBYTE  putmask;
109 INT       putstride;
110 
111     text_color =  (GX_UBYTE)context -> gx_draw_context_brush.gx_brush_line_color;
112     text_color |= (GX_UBYTE)(text_color << 4);
113     pixel_per_row = (UINT)draw_area -> gx_rectangle_right - (UINT)draw_area -> gx_rectangle_left + (UINT)1;
114     putstride = (context -> gx_draw_context_pitch + 1) >> 1;
115     /* pickup pointer to current dispaly driver */
116     /*display = context -> gx_draw_context_display;*/
117 
118     /* Find the width of the glyph, in terms of bytes */
119     glyph_width = glyph -> gx_glyph_width;
120     /* Make it byte-aligned. */
121     glyph_width = (glyph_width + 7) >> 3;
122 
123     /* Compute the number of useful bytes from the glyph this routine is going to use.
124        Because of map_offset, the first byte may contain pixel bits we don't need to draw;
125        And the width of the draw_area may produce part of the last byte in the row to be ignored. */
126     num_bytes = ((UINT)map_offset -> gx_point_x + pixel_per_row + 7) >> 3;
127     /* Take into account if map_offset specifies the number of bytes to ignore from the beginning of the row. */
128     num_bytes -= (UINT)(map_offset -> gx_point_x) >> 3;
129 
130     /* Compute the number of pixels to draw from the first byte of the glyph data. */
131     pixel_in_first_byte = (UINT)(8 - ((map_offset -> gx_point_x) & 0x7));
132     init_mask = (GX_UBYTE)(1 << (pixel_in_first_byte - 1));
133     /* Compute the number of pixels to draw from the last byte, if there are more than one byte in a row. */
134     if (num_bytes != 1)
135     {
136         pixel_in_last_byte = (map_offset -> gx_point_x + (INT)pixel_per_row) & 0x7;
137         if (pixel_in_last_byte == 0)
138         {
139             pixel_in_last_byte = 8;
140         }
141     }
142     else
143     {
144         if ((map_offset -> gx_point_x + (INT)pixel_per_row) < 8)
145         {
146             pixel_in_first_byte = pixel_per_row;
147         }
148         else
149         {
150             pixel_in_last_byte = 0;
151         }
152     }
153 
154 
155     glyph_row = (GX_UBYTE *)glyph -> gx_glyph_map;
156 
157     if (map_offset -> gx_point_y)
158     {
159         glyph_row = glyph_row + ((INT)glyph_width * map_offset -> gx_point_y);
160     }
161 
162     glyph_row += (map_offset -> gx_point_x >> 3);
163 
164     y_height = (UINT)(draw_area -> gx_rectangle_bottom - draw_area -> gx_rectangle_top + 1);
165 
166     line_start = (GX_UBYTE *)context -> gx_draw_context_memory;
167     line_start += putstride * (draw_area -> gx_rectangle_top);
168     line_start += draw_area -> gx_rectangle_left >> 1;
169 
170 
171     for (row = 0; row < y_height; row++)
172     {
173         if (draw_area -> gx_rectangle_left & 0x01)
174         {
175             putmask = 0x0f;
176         }
177         else
178         {
179             putmask = 0xf0;
180         }
181         glyph_data = glyph_row;
182         alpha = *(glyph_data);
183         mask = init_mask;
184         num_bits = pixel_in_first_byte;
185         put = line_start;
186         for (i = 0; i < num_bytes; i++)
187         {
188             if ((i == (num_bytes - 1)) && (num_bytes > 1))
189             {
190                 num_bits = pixel_in_last_byte;
191             }
192             switch (num_bits)
193             {
194             case 8:
195                 WRITE_PIXEL;
196                 mask >>= 1;
197                 /* fallthrough */
198             case 7:
199                 WRITE_PIXEL;
200                 mask >>= 1;
201                 /* fallthrough */
202             case 6:
203                 WRITE_PIXEL;
204                 mask >>= 1;
205                 /* fallthrough */
206             case 5:
207                 WRITE_PIXEL;
208                 mask >>= 1;
209                 /* fallthrough */
210             case 4:
211                 WRITE_PIXEL;
212                 mask >>= 1;
213                 /* fallthrough */
214             case 3:
215                 WRITE_PIXEL;
216                 mask >>= 1;
217                 /* fallthrough */
218             case 2:
219                 WRITE_PIXEL;
220                 mask >>= 1;
221                 /* fallthrough */
222             default:
223                 WRITE_PIXEL;
224             }
225             glyph_data++;
226             alpha = *(glyph_data);
227             num_bits = 8;
228             mask = 0x80;
229         }
230 
231         glyph_row +=  glyph_width;
232         line_start += putstride;
233     }
234 
235     return;
236 }
237 
238