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 #define DRAW_PIXEL if (alpha & mask) \
32     {                                \
33         *put = text_color;           \
34     }                                \
35     put++;                           \
36     mask = mask >> 1;
37 
38 #if defined (GX_BRUSH_ALPHA_SUPPORT)
39 #define BLEND_PIXEL if (alpha & mask)                                                        \
40     {                                                                                        \
41         _gx_display_driver_24xrgb_pixel_blend(context, xval, yval, text_color, brush_alpha); \
42     }                                                                                        \
43     xval++;                                                                                  \
44     mask = mask >> 1;
45 #endif
46 
47 /**************************************************************************/
48 /*                                                                        */
49 /*  FUNCTION                                               RELEASE        */
50 /*                                                                        */
51 /*    _gx_display_driver_32bpp_glyph_1bit_draw            PORTABLE C      */
52 /*                                                           6.1.11       */
53 /*  AUTHOR                                                                */
54 /*                                                                        */
55 /*    Kenneth Maxwell, Microsoft Corporation                              */
56 /*                                                                        */
57 /*  DESCRIPTION                                                           */
58 /*                                                                        */
59 /*    This functions draw monochrome font on 32bpp canvas, clipped to     */
60 /*    one viewport.                                                       */
61 /*                                                                        */
62 /*  INPUT                                                                 */
63 /*                                                                        */
64 /*    context                               Draw context                  */
65 /*    draw_area                             The region bound by the       */
66 /*                                            rectangle where the glyph   */
67 /*                                            is drawn                    */
68 /*    map_offset                            X,Y offset into the glyph map */
69 /*    glyph                                 Pointer to the glyph          */
70 /*                                                                        */
71 /*  OUTPUT                                                                */
72 /*                                                                        */
73 /*    None                                                                */
74 /*                                                                        */
75 /*  CALLS                                                                 */
76 /*                                                                        */
77 /*    _gx_display_driver_24xrgb_pixel_blend Display driver basic pixel    */
78 /*                                            blend function              */
79 /*                                                                        */
80 /*  CALLED BY                                                             */
81 /*                                                                        */
82 /*    GUIX internal code                                                  */
83 /*                                                                        */
84 /*  RELEASE HISTORY                                                       */
85 /*                                                                        */
86 /*    DATE              NAME                      DESCRIPTION             */
87 /*                                                                        */
88 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
89 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
90 /*                                            resulting in version 6.1    */
91 /*  04-25-2022     Ting Zhu                 Modified comment(s),          */
92 /*                                            fixed access violation bug, */
93 /*                                            resulting in version 6.1.11 */
94 /*                                                                        */
95 /**************************************************************************/
_gx_display_driver_32bpp_glyph_1bit_draw(GX_DRAW_CONTEXT * context,GX_RECTANGLE * draw_area,GX_POINT * map_offset,GX_CONST GX_GLYPH * glyph)96 VOID _gx_display_driver_32bpp_glyph_1bit_draw(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area, GX_POINT *map_offset, GX_CONST GX_GLYPH *glyph)
97 {
98 GX_UBYTE *glyph_row;
99 GX_UBYTE *glyph_data;
100 UINT      row;
101 UINT      pixel_per_row;
102 UINT      pixel_in_first_byte;
103 UINT      pixel_in_last_byte = 0;
104 GX_COLOR  text_color;
105 UINT      y_height;
106 GX_UBYTE  alpha;
107 UINT      glyph_width;
108 UINT     *put;
109 UINT      num_bytes;
110 UINT      num_bits;
111 UINT     *line_start;
112 GX_UBYTE  mask, init_mask;
113 UINT      i;
114 
115 #if defined (GX_BRUSH_ALPHA_SUPPORT)
116 GX_UBYTE  brush_alpha;
117 INT       xval, yval;
118 
119     brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
120     if (brush_alpha == 0)
121     {
122         return;
123     }
124 #endif
125 
126     text_color = context -> gx_draw_context_brush.gx_brush_line_color;
127     pixel_per_row = (UINT)(draw_area -> gx_rectangle_right - draw_area -> gx_rectangle_left + 1);
128 
129     /* pickup pointer to current dispaly driver */
130     /*display = context -> gx_draw_context_display;*/
131 
132     /* Find the width of the glyph, in terms of bytes */
133     glyph_width = glyph -> gx_glyph_width;
134     /* Make it byte-aligned. */
135     glyph_width = (glyph_width + 7) >> 3;
136 
137     /* Compute the number of useful bytes from the glyph this routine is going to use.
138        Because of map_offset, the first byte may contain pixel bits we don't need to draw;
139        And the width of the draw_area may produce part of the last byte in the row to be ignored. */
140     num_bytes = (UINT)(((UINT)(map_offset -> gx_point_x) + pixel_per_row + 7) >> 3);
141     /* Take into account if map_offset specifies the number of bytes to ignore from the beginning of the row. */
142     num_bytes = num_bytes - (((UINT)(map_offset -> gx_point_x)) >> 3);
143 
144     /* Compute the number of pixels to draw from the first byte of the glyph data. */
145     pixel_in_first_byte = 8 - (UINT)((map_offset -> gx_point_x) & 0x7);
146     init_mask = (GX_UBYTE)(1 << (pixel_in_first_byte - 1));
147     /* Compute the number of pixels to draw from the last byte, if there are more than one byte in a row. */
148     if (num_bytes != 1)
149     {
150         pixel_in_last_byte = (((UINT)(map_offset -> gx_point_x) + pixel_per_row) & 0x7);
151         if (pixel_in_last_byte == 0)
152         {
153             pixel_in_last_byte = 8;
154         }
155     }
156     else
157     {
158         if (((UINT)(map_offset -> gx_point_x) + pixel_per_row) < 8)
159         {
160             pixel_in_first_byte = pixel_per_row;
161         }
162         else
163         {
164             pixel_in_last_byte = 0;
165         }
166     }
167 
168     glyph_row = (GX_UBYTE *)glyph -> gx_glyph_map;
169 
170     if (map_offset -> gx_point_y)
171     {
172         glyph_row = glyph_row + ((INT)glyph_width * (INT)(map_offset -> gx_point_y));
173     }
174 
175     glyph_row += (map_offset -> gx_point_x >> 3);
176 
177     y_height = (UINT)(draw_area -> gx_rectangle_bottom - draw_area -> gx_rectangle_top + 1);
178 
179 #if defined (GX_BRUSH_ALPHA_SUPPORT)
180     if (brush_alpha != 0xff)
181     {
182         yval = draw_area -> gx_rectangle_top;
183         for (row = 0; row < y_height; row++)
184         {
185             xval = draw_area -> gx_rectangle_left;
186             glyph_data = glyph_row;
187             mask = init_mask;
188             num_bits = pixel_in_first_byte;
189             for (i = 0; i < num_bytes; i++)
190             {
191                 alpha = *(glyph_data++);
192 
193                 if ((i == (num_bytes - 1)) && (num_bytes > 1))
194                 {
195                     num_bits = pixel_in_last_byte;
196                 }
197                 switch (num_bits)
198                 {
199                 case 8:
200                     BLEND_PIXEL;
201                     /* fallthrough */
202                 case 7:
203                     BLEND_PIXEL;
204                     /* fallthrough */
205                 case 6:
206                     BLEND_PIXEL;
207                     /* fallthrough */
208                 case 5:
209                     BLEND_PIXEL;
210                     /* fallthrough */
211                 case 4:
212                     BLEND_PIXEL;
213                     /* fallthrough */
214                 case 3:
215                     BLEND_PIXEL;
216                     /* fallthrough */
217                 case 2:
218                     BLEND_PIXEL;
219                     /* fallthrough */
220                 default:
221                     if (alpha & mask)
222                     {
223                         _gx_display_driver_24xrgb_pixel_blend(context, xval, yval, text_color, brush_alpha);
224                     }
225                     xval++;
226                     break;
227                 }
228                 num_bits = 8;
229                 mask = 0x80;
230             }
231 
232             glyph_row += glyph_width;
233             yval++;
234         }
235     }
236     else
237     {
238 #endif
239         line_start = (UINT *)context -> gx_draw_context_memory;
240         line_start += context -> gx_draw_context_pitch * (draw_area -> gx_rectangle_top);
241         line_start += draw_area -> gx_rectangle_left;
242 
243         for (row = 0; row < y_height; row++)
244         {
245             glyph_data = glyph_row;
246             mask = init_mask;
247             num_bits = pixel_in_first_byte;
248             put = line_start;
249             for (i = 0; i < num_bytes; i++)
250             {
251                 alpha = *(glyph_data++);
252 
253                 if ((i == (num_bytes - 1)) && (num_bytes > 1))
254                 {
255                     num_bits = pixel_in_last_byte;
256                 }
257                 switch (num_bits)
258                 {
259                 case 8:
260                     DRAW_PIXEL;
261                     /* fallthrough */
262                 case 7:
263                     DRAW_PIXEL;
264                     /* fallthrough */
265                 case 6:
266                     DRAW_PIXEL;
267                     /* fallthrough */
268                 case 5:
269                     DRAW_PIXEL;
270                     /* fallthrough */
271                 case 4:
272                     DRAW_PIXEL;
273                     /* fallthrough */
274                 case 3:
275                     DRAW_PIXEL;
276                     /* fallthrough */
277                 case 2:
278                     DRAW_PIXEL;
279                     /* fallthrough */
280                 default:
281                     if (alpha & mask)
282                     {
283                         *put = text_color;
284                     }
285                     put++;
286                     break;
287                 }
288                 num_bits = 8;
289                 mask = 0x80;
290             }
291 
292             glyph_row += glyph_width;
293             line_start += context -> gx_draw_context_pitch;
294         }
295 #if defined (GX_BRUSH_ALPHA_SUPPORT)
296     }
297 #endif
298     return;
299 }
300 
301