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_generic_glyph_4bit_draw          PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Kenneth Maxwell, Microsoft Corporation                              */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function draws the specified text using the current context,   */
44 /*    clipped to one viewport                                             */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    context                               Draw context                  */
49 /*    draw_area                             The rectangle where the glyph */
50 /*                                            is drawn to                 */
51 /*    map_offset                            Offset from the glyph map     */
52 /*    glyph                                 The glyph structure           */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    None                                                                */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    [gx_display_driver_pixel_blend]       Call display driver pixel     */
61 /*                                            blend function              */
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 /**************************************************************************/
_gx_display_driver_generic_glyph_4bit_draw(GX_DRAW_CONTEXT * context,GX_RECTANGLE * draw_area,GX_POINT * map_offset,GX_CONST GX_GLYPH * glyph)76 VOID _gx_display_driver_generic_glyph_4bit_draw(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area, GX_POINT *map_offset, GX_CONST GX_GLYPH *glyph)
77 {
78 GX_DISPLAY *display;
79 GX_UBYTE   *glyph_row;
80 GX_UBYTE   *glyph_data;
81 UINT        row;
82 UINT        col;
83 UINT        pixel_width = 0;
84 UINT        leading_pixel;
85 UINT        trailing_pixel;
86 GX_COLOR    text_color;
87 UINT        y_height;
88 GX_UBYTE    alpha;
89 UINT        pitch;
90 UINT        index;
91 VOID        (*blend_func)(GX_DRAW_CONTEXT *context, INT x, INT y, GX_COLOR color, GX_UBYTE alpha);
92 GX_UBYTE    brush_alpha = 0xff;
93 
94 #if defined (GX_BRUSH_ALPHA_SUPPORT)
95 INT         alpha_sum;
96     brush_alpha = context -> gx_draw_context_brush.gx_brush_alpha;
97     if (brush_alpha == 0)
98     {
99         return;
100     }
101 #endif
102 
103     text_color =  context -> gx_draw_context_brush.gx_brush_line_color;
104     pixel_width = (UINT)(draw_area -> gx_rectangle_right - draw_area -> gx_rectangle_left + 1);
105 
106     /* pickup pointer to current dispaly driver */
107     display = context -> gx_draw_context_display;
108 
109     if (display -> gx_display_driver_pixel_blend == GX_NULL)
110     {
111         return;
112     }
113 
114     /* Find the width of the glyph */
115     pitch = glyph -> gx_glyph_width;
116     /* Make it byte-aligned. */
117     pitch = (pitch + 1) >> 1;
118 
119     glyph_row = (GX_UBYTE *)glyph -> gx_glyph_map;
120 
121     if (map_offset -> gx_point_y)
122     {
123         glyph_row = glyph_row + ((INT)pitch * map_offset -> gx_point_y);
124     }
125 
126     glyph_row += (map_offset -> gx_point_x >> 1);
127 
128     y_height = (UINT)(draw_area -> gx_rectangle_bottom - draw_area -> gx_rectangle_top + 1);
129 
130     blend_func = display -> gx_display_driver_pixel_blend;
131 
132     leading_pixel = (map_offset -> gx_point_x & 1);
133 
134     pixel_width -= leading_pixel;
135 
136     trailing_pixel = pixel_width & 1;
137 
138     pixel_width = pixel_width >> 1;
139 
140     if (brush_alpha == 0xff)
141     {
142         for (row = 0; row < y_height; row++)
143         {
144             col = 0;
145             glyph_data = glyph_row;
146 
147             if (leading_pixel)
148             {
149                 alpha = (*glyph_data) & 0x0f;
150                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha << 4));
151 
152                 if (alpha > 0)
153                 {
154                     blend_func(context,
155                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
156                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
157                         text_color, (GX_UBYTE)alpha);
158                 }
159                 col++;
160                 glyph_data++;
161             }
162 
163             for (index = 0; index < pixel_width; index++)
164             {
165                 alpha = (*glyph_data) & 0xf0;
166                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha >> 4));
167 
168                 if (alpha > 0)
169                 {
170                     blend_func(context,
171                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
172                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
173                         text_color, (GX_UBYTE)alpha);
174                 }
175                 col++;
176 
177                 alpha = (*glyph_data) & 0x0f;
178                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha << 4));
179 
180                 if (alpha > 0)
181                 {
182                     blend_func(context,
183                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
184                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
185                         text_color, (GX_UBYTE)alpha);
186                 }
187                 col++;
188                 glyph_data++;
189             }
190 
191             if (trailing_pixel)
192             {
193                 alpha = (*glyph_data) & 0xf0;
194                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha >> 4));
195 
196                 if (alpha > 0)
197                 {
198                     blend_func(context,
199                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
200                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
201                         text_color, (GX_UBYTE)alpha);
202                 }
203             }
204             glyph_row += pitch;
205         }
206     }
207 #if defined (GX_BRUSH_ALPHA_SUPPORT)
208     else
209     {
210         for (row = 0; row < y_height; row++)
211         {
212             col = 0;
213             glyph_data = glyph_row;
214 
215             if (leading_pixel)
216             {
217                 alpha = (*glyph_data) & 0x0f;
218                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha << 4));
219 
220                 alpha_sum = alpha * brush_alpha / 255;
221 
222                 if (alpha_sum > 0)
223                 {
224                     blend_func(context,
225                         draw_area->gx_rectangle_left + (GX_VALUE)col,
226                         draw_area->gx_rectangle_top + (GX_VALUE)row,
227                         text_color, (GX_UBYTE)alpha_sum);
228                 }
229                 col++;
230                 glyph_data++;
231             }
232 
233             for (index = 0; index < pixel_width; index++)
234             {
235                 alpha = (*glyph_data) & 0xf0;
236                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha >> 4));
237                 alpha_sum = alpha * brush_alpha / 255;
238 
239                 if (alpha_sum > 0)
240                 {
241                     blend_func(context,
242                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
243                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
244                         text_color, (GX_UBYTE)alpha_sum);
245                 }
246                 col++;
247 
248                 alpha = (*glyph_data) & 0x0f;
249                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha << 4));
250                 alpha_sum = alpha * brush_alpha / 255;
251 
252                 if (alpha_sum > 0)
253                 {
254                     blend_func(context,
255                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
256                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
257                         text_color, (GX_UBYTE)alpha_sum);
258                 }
259                 col++;
260                 glyph_data++;
261             }
262 
263             if (trailing_pixel)
264             {
265                 alpha = (*glyph_data) & 0xf0;
266                 alpha = (GX_UBYTE)(alpha | (GX_UBYTE)(alpha >> 4));
267                 alpha_sum = alpha * brush_alpha / 255;
268 
269                 if (alpha_sum > 0)
270                 {
271                     blend_func(context,
272                         draw_area -> gx_rectangle_left + (GX_VALUE)col,
273                         draw_area -> gx_rectangle_top + (GX_VALUE)row,
274                         text_color, (GX_UBYTE)alpha_sum);
275                 }
276             }
277             glyph_row += pitch;
278         }
279     }
280 #endif
281 
282 }
283 
284