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_4bpp_glyph_1bit_draw PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Kenneth Maxwell, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function draws monochrome font to the 4bpp canvas, clipped */
44 /* to one viweport. */
45 /* */
46 /* INPUT */
47 /* */
48 /* context Draw context */
49 /* draw_area The region bound by the */
50 /* rectangle where the glyph */
51 /* is drawn */
52 /* map_offset X,Y offset into the glyph map */
53 /* glyph Pointer to the glyph */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* None */
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 /**************************************************************************/
76
77 #define WRITE_PIXEL if (alpha & mask) \
78 { \
79 *put = *put & (GX_UBYTE)(~putmask); \
80 *put = *put | (GX_UBYTE)(text_color & putmask); \
81 } \
82 putmask = putmask >> 4; \
83 if (putmask == 0) \
84 { \
85 putmask = 0xf0; \
86 put++; \
87 }
88
89
_gx_display_driver_4bpp_glyph_1bit_draw(GX_DRAW_CONTEXT * context,GX_RECTANGLE * draw_area,GX_POINT * map_offset,const GX_GLYPH * glyph)90 VOID _gx_display_driver_4bpp_glyph_1bit_draw(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area, GX_POINT *map_offset, const GX_GLYPH *glyph)
91 {
92 GX_UBYTE *glyph_row;
93 GX_UBYTE *glyph_data;
94 UINT row;
95 UINT pixel_per_row;
96 UINT pixel_in_first_byte;
97 UINT pixel_in_last_byte = 0;
98 GX_UBYTE text_color;
99 UINT y_height;
100 GX_UBYTE alpha;
101 UINT glyph_width;
102 GX_UBYTE *put;
103 UINT num_bytes;
104 UINT num_bits;
105 GX_UBYTE *line_start;
106 GX_UBYTE mask, init_mask;
107 UINT i;
108 GX_UBYTE putmask;
109 INT putstride;
110
111 text_color = (GX_UBYTE)context -> gx_draw_context_brush.gx_brush_line_color;
112 text_color |= (GX_UBYTE)(text_color << 4);
113 pixel_per_row = (UINT)draw_area -> gx_rectangle_right - (UINT)draw_area -> gx_rectangle_left + (UINT)1;
114 putstride = (context -> gx_draw_context_pitch + 1) >> 1;
115 /* pickup pointer to current dispaly driver */
116 /*display = context -> gx_draw_context_display;*/
117
118 /* Find the width of the glyph, in terms of bytes */
119 glyph_width = glyph -> gx_glyph_width;
120 /* Make it byte-aligned. */
121 glyph_width = (glyph_width + 7) >> 3;
122
123 /* Compute the number of useful bytes from the glyph this routine is going to use.
124 Because of map_offset, the first byte may contain pixel bits we don't need to draw;
125 And the width of the draw_area may produce part of the last byte in the row to be ignored. */
126 num_bytes = ((UINT)map_offset -> gx_point_x + pixel_per_row + 7) >> 3;
127 /* Take into account if map_offset specifies the number of bytes to ignore from the beginning of the row. */
128 num_bytes -= (UINT)(map_offset -> gx_point_x) >> 3;
129
130 /* Compute the number of pixels to draw from the first byte of the glyph data. */
131 pixel_in_first_byte = (UINT)(8 - ((map_offset -> gx_point_x) & 0x7));
132 init_mask = (GX_UBYTE)(1 << (pixel_in_first_byte - 1));
133 /* Compute the number of pixels to draw from the last byte, if there are more than one byte in a row. */
134 if (num_bytes != 1)
135 {
136 pixel_in_last_byte = (map_offset -> gx_point_x + (INT)pixel_per_row) & 0x7;
137 if (pixel_in_last_byte == 0)
138 {
139 pixel_in_last_byte = 8;
140 }
141 }
142 else
143 {
144 if ((map_offset -> gx_point_x + (INT)pixel_per_row) < 8)
145 {
146 pixel_in_first_byte = pixel_per_row;
147 }
148 else
149 {
150 pixel_in_last_byte = 0;
151 }
152 }
153
154
155 glyph_row = (GX_UBYTE *)glyph -> gx_glyph_map;
156
157 if (map_offset -> gx_point_y)
158 {
159 glyph_row = glyph_row + ((INT)glyph_width * map_offset -> gx_point_y);
160 }
161
162 glyph_row += (map_offset -> gx_point_x >> 3);
163
164 y_height = (UINT)(draw_area -> gx_rectangle_bottom - draw_area -> gx_rectangle_top + 1);
165
166 line_start = (GX_UBYTE *)context -> gx_draw_context_memory;
167 line_start += putstride * (draw_area -> gx_rectangle_top);
168 line_start += draw_area -> gx_rectangle_left >> 1;
169
170
171 for (row = 0; row < y_height; row++)
172 {
173 if (draw_area -> gx_rectangle_left & 0x01)
174 {
175 putmask = 0x0f;
176 }
177 else
178 {
179 putmask = 0xf0;
180 }
181 glyph_data = glyph_row;
182 alpha = *(glyph_data);
183 mask = init_mask;
184 num_bits = pixel_in_first_byte;
185 put = line_start;
186 for (i = 0; i < num_bytes; i++)
187 {
188 if ((i == (num_bytes - 1)) && (num_bytes > 1))
189 {
190 num_bits = pixel_in_last_byte;
191 }
192 switch (num_bits)
193 {
194 case 8:
195 WRITE_PIXEL;
196 mask >>= 1;
197 /* fallthrough */
198 case 7:
199 WRITE_PIXEL;
200 mask >>= 1;
201 /* fallthrough */
202 case 6:
203 WRITE_PIXEL;
204 mask >>= 1;
205 /* fallthrough */
206 case 5:
207 WRITE_PIXEL;
208 mask >>= 1;
209 /* fallthrough */
210 case 4:
211 WRITE_PIXEL;
212 mask >>= 1;
213 /* fallthrough */
214 case 3:
215 WRITE_PIXEL;
216 mask >>= 1;
217 /* fallthrough */
218 case 2:
219 WRITE_PIXEL;
220 mask >>= 1;
221 /* fallthrough */
222 default:
223 WRITE_PIXEL;
224 }
225 glyph_data++;
226 alpha = *(glyph_data);
227 num_bits = 8;
228 mask = 0x80;
229 }
230
231 glyph_row += glyph_width;
232 line_start += putstride;
233 }
234
235 return;
236 }
237
238