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