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