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         blend_func(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_16bpp_glyph_1bit_draw            PORTABLE C      */
52 /*                                                           6.3.0        */
53 /*  AUTHOR                                                                */
54 /*                                                                        */
55 /*    Kenneth Maxwell, Microsoft Corporation                              */
56 /*                                                                        */
57 /*  DESCRIPTION                                                           */
58 /*                                                                        */
59 /*    This functions draw monochrome font on 16bpp 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_pixel_blend]       Basic display driver 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 /*  10-31-2023     Ting Zhu                 Modified comment(s),          */
95 /*                                            added partial canvas buffer */
96 /*                                            support,                    */
97 /*                                            resulting in version 6.3.0  */
98 /*                                                                        */
99 /**************************************************************************/
_gx_display_driver_16bpp_glyph_1bit_draw(GX_DRAW_CONTEXT * context,GX_RECTANGLE * draw_area,GX_POINT * map_offset,GX_CONST GX_GLYPH * glyph)100 VOID _gx_display_driver_16bpp_glyph_1bit_draw(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area, GX_POINT *map_offset, GX_CONST GX_GLYPH *glyph)
101 {
102 /* GX_DISPLAY      *display;*/
103 GX_UBYTE *glyph_row;
104 GX_UBYTE *glyph_data;
105 UINT      row;
106 UINT      pixel_per_row;
107 UINT      pixel_in_first_byte;
108 UINT      pixel_in_last_byte = 0;
109 USHORT    text_color;
110 UINT      y_height;
111 GX_UBYTE  alpha;
112 UINT      glyph_width;
113 USHORT   *put;
114 UINT      num_bytes;
115 UINT      num_bits;
116 USHORT   *line_start;
117 GX_UBYTE  mask, init_mask;
118 UINT      i;
119 #if defined (GX_BRUSH_ALPHA_SUPPORT)
120 GX_UBYTE  brush_alpha;
121 INT       xval, yval;
122 VOID    (*blend_func)(GX_DRAW_CONTEXT *, INT, INT, GX_COLOR, GX_UBYTE);
123 
124     brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
125     blend_func = context -> gx_draw_context_display -> gx_display_driver_pixel_blend;
126 
127     if (blend_func == GX_NULL)
128     {
129         /* Pixel blend function is null means alpha isn't supported in this driver.
130         So set alpha value to 0xff to make it draw the original color in case GX_BRUSH_ALPHA_SUPPORT is defined. */
131         brush_alpha = 0xff;
132     }
133     else
134     {
135         if (brush_alpha == 0)
136             return;
137     }
138 #endif
139     text_color =  (USHORT)context -> gx_draw_context_brush.gx_brush_line_color;
140     pixel_per_row = (UINT)(draw_area -> gx_rectangle_right - draw_area -> gx_rectangle_left + 1);
141 
142     /* pickup pointer to current dispaly driver */
143     /*display = context -> gx_draw_context_display;*/
144 
145     /* Find the width of the glyph, in terms of bytes */
146     glyph_width = glyph -> gx_glyph_width;
147     /* Make it byte-aligned. */
148     glyph_width = (glyph_width + 7) >> 3;
149 
150     /* Compute the number of useful bytes from the glyph this routine is going to use.
151        Because of map_offset, the first byte may contain pixel bits we don't need to draw;
152        And the width of the draw_area may produce part of the last byte in the row to be ignored. */
153     num_bytes = (UINT)(((INT)map_offset -> gx_point_x + (INT)pixel_per_row + 7) >> 3);
154     /* Take into account if map_offset specifies the number of bytes to ignore from the beginning of the row. */
155     num_bytes -= ((UINT)(map_offset -> gx_point_x)) >> 3;
156 
157     /* Compute the number of pixels to draw from the first byte of the glyph data. */
158     pixel_in_first_byte = (UINT)(8 - ((map_offset -> gx_point_x) & 0x7));
159     init_mask = (GX_UBYTE)(1 << (pixel_in_first_byte - 1));
160     /* Compute the number of pixels to draw from the last byte, if there are more than one byte in a row. */
161     if (num_bytes != 1)
162     {
163         pixel_in_last_byte = ((UINT)map_offset -> gx_point_x + pixel_per_row) & 0x7;
164         if (pixel_in_last_byte == 0)
165         {
166             pixel_in_last_byte = 8;
167         }
168     }
169     else
170     {
171         if ((map_offset -> gx_point_x + (INT)pixel_per_row) < 8)
172         {
173             pixel_in_first_byte = pixel_per_row;
174         }
175         else
176         {
177             pixel_in_last_byte = 0;
178         }
179     }
180 
181 
182     glyph_row = (GX_UBYTE *)glyph -> gx_glyph_map;
183 
184     if (map_offset -> gx_point_y)
185     {
186         glyph_row = (GX_UBYTE *)(glyph_row + ((INT)glyph_width * (INT)(map_offset -> gx_point_y)));
187     }
188 
189     glyph_row += (map_offset -> gx_point_x >> 3);
190 
191     y_height = (UINT)(draw_area -> gx_rectangle_bottom - draw_area -> gx_rectangle_top + 1);
192 
193     line_start = (USHORT *)context -> gx_draw_context_memory;
194     GX_CALCULATE_PUTROW(line_start, draw_area -> gx_rectangle_left, draw_area -> gx_rectangle_top, context);
195 
196 #if defined(GX_BRUSH_ALPHA_SUPPORT)
197     if (brush_alpha != 0xff)
198     {
199         yval = draw_area -> gx_rectangle_top;
200         for (row = 0; row < y_height; row++)
201         {
202             xval = draw_area -> gx_rectangle_left;
203             glyph_data = glyph_row;
204             mask = init_mask;
205             num_bits = pixel_in_first_byte;
206             for (i = 0; i < num_bytes; i++)
207             {
208                 alpha = *(glyph_data++);
209 
210                 if ((i == (num_bytes - 1)) && (num_bytes > 1))
211                 {
212                     num_bits = pixel_in_last_byte;
213                 }
214                 switch (num_bits)
215                 {
216                 case 8:
217                     BLEND_PIXEL;
218                     /* fallthrough */
219                 case 7:
220                     BLEND_PIXEL;
221                     /* fallthrough */
222                 case 6:
223                     BLEND_PIXEL;
224                     /* fallthrough */
225                 case 5:
226                     BLEND_PIXEL;
227                     /* fallthrough */
228                 case 4:
229                     BLEND_PIXEL;
230                     /* fallthrough */
231                 case 3:
232                     BLEND_PIXEL;
233                     /* fallthrough */
234                 case 2:
235                     BLEND_PIXEL;
236                     /* fallthrough */
237                 default:
238                     if (alpha & mask)
239                     {
240                         blend_func(context, xval, yval, text_color, brush_alpha);
241                     }
242                     xval++;
243                     break;
244                 }
245                 num_bits = 8;
246                 mask = 0x80;
247             }
248 
249             glyph_row += glyph_width;
250             yval++;
251         }
252     }
253     else
254     {
255 #endif
256         for (row = 0; row < y_height; row++)
257         {
258             glyph_data = glyph_row;
259             mask = init_mask;
260             num_bits = pixel_in_first_byte;
261             put = line_start;
262             for (i = 0; i < num_bytes; i++)
263             {
264                 alpha = *(glyph_data++);
265 
266                 if ((i == (num_bytes - 1)) && (num_bytes > 1))
267                 {
268                     num_bits = pixel_in_last_byte;
269                 }
270                 switch (num_bits)
271                 {
272                 case 8:
273                     DRAW_PIXEL;
274                     /* fallthrough */
275                 case 7:
276                     DRAW_PIXEL;
277                     /* fallthrough */
278                 case 6:
279                     DRAW_PIXEL;
280                     /* fallthrough */
281                 case 5:
282                     DRAW_PIXEL;
283                     /* fallthrough */
284                 case 4:
285                     DRAW_PIXEL;
286                     /* fallthrough */
287                 case 3:
288                     DRAW_PIXEL;
289                     /* fallthrough */
290                 case 2:
291                     DRAW_PIXEL;
292                     /* fallthrough */
293                 default:
294                     if (alpha & mask)
295                     {
296                         *put = text_color;
297                     }
298                     put++;
299                     break;
300                 }
301                 num_bits = 8;
302                 mask = 0x80;
303             }
304 
305             glyph_row += glyph_width;
306             line_start += context -> gx_draw_context_pitch;
307         }
308 #if defined (GX_BRUSH_ALPHA_SUPPORT)
309     }
310 #endif
311     return;
312 }
313 
314