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