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 #define DRAW_PIXEL if (alpha & mask) \
32 { \
33 *put = text_color; \
34 } \
35 put++; \
36 mask = mask >> 1;
37
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_8bpp_rotated_glyph_1bit_draw PORTABLE C */
53 /* 6.1.4 */
54 /* AUTHOR */
55 /* */
56 /* Kenneth Maxwell, Microsoft Corporation */
57 /* */
58 /* DESCRIPTION */
59 /* */
60 /* This function draws monochrome font to the 8bpp canvas, clipped */
61 /* to one viweport. */
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 /* 02-02-2021 Kenneth Maxwell Initial Version 6.1.4 */
90 /* */
91 /**************************************************************************/
_gx_display_driver_8bpp_rotated_glyph_1bit_draw(GX_DRAW_CONTEXT * context,GX_RECTANGLE * draw_area,GX_POINT * map_offset,GX_CONST GX_GLYPH * glyph)92 VOID _gx_display_driver_8bpp_rotated_glyph_1bit_draw(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area, GX_POINT *map_offset, GX_CONST GX_GLYPH *glyph)
93 {
94 GX_UBYTE *glyph_row;
95 GX_UBYTE *glyph_data;
96 UINT row;
97 UINT pixel_per_row;
98 UINT pixel_in_first_byte;
99 UINT pixel_in_last_byte = 0;
100 GX_UBYTE text_color;
101 UINT y_height;
102 GX_UBYTE alpha;
103 UINT glyph_width;
104 GX_UBYTE *put;
105 UINT num_bytes;
106 UINT num_bits;
107 GX_UBYTE *line_start;
108 GX_UBYTE mask, init_mask;
109 UINT i;
110 GX_VALUE rotated_map_offset_x;
111 GX_VALUE rotated_map_offset_y;
112 GX_VALUE rotated_draw_left;
113 GX_VALUE rotated_draw_top;
114
115 text_color = (GX_UBYTE)context -> gx_draw_context_brush.gx_brush_line_color;
116 pixel_per_row = (UINT)draw_area -> gx_rectangle_bottom - (UINT)draw_area -> gx_rectangle_top + (UINT)1;
117 y_height = (UINT)(draw_area -> gx_rectangle_right - draw_area -> gx_rectangle_left + 1);
118
119 /* Find the width of the glyph, in terms of bytes */
120 glyph_width = glyph -> gx_glyph_height;
121
122 /* Make it byte-aligned. */
123 glyph_width = (glyph_width + 7) >> 3;
124
125 if (context -> gx_draw_context_display -> gx_display_rotation_angle == GX_SCREEN_ROTATION_CW)
126 {
127 rotated_draw_left = draw_area -> gx_rectangle_top;
128 rotated_draw_top = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_x_resolution - draw_area -> gx_rectangle_right - 1);
129
130 rotated_map_offset_x = map_offset -> gx_point_y;
131 rotated_map_offset_y = (GX_VALUE)(glyph -> gx_glyph_width - map_offset -> gx_point_x - (GX_VALUE)y_height);
132 }
133 else
134 {
135 rotated_draw_left = (GX_VALUE)(context -> gx_draw_context_canvas -> gx_canvas_display_offset_y - draw_area -> gx_rectangle_bottom - 1);
136 rotated_draw_top = draw_area -> gx_rectangle_left;
137
138 rotated_map_offset_x = (GX_VALUE)(glyph -> gx_glyph_height - map_offset -> gx_point_y - (GX_VALUE)pixel_per_row);
139 rotated_map_offset_y = map_offset -> gx_point_x;
140 }
141
142 /* Compute the number of useful bytes from the glyph this routine is going to use.
143 Because of map_offset, the first byte may contain pixel bits we don't need to draw;
144 And the width of the draw_area may produce part of the last byte in the row to be ignored. */
145 num_bytes = ((UINT)rotated_map_offset_x + pixel_per_row + 7) >> 3;
146
147 /* Take into account if map_offset specifies the number of bytes to ignore from the beginning of the row. */
148 num_bytes -= (UINT)(rotated_map_offset_x) >> 3;
149
150 /* Compute the number of pixels to draw from the first byte of the glyph data. */
151 pixel_in_first_byte = (UINT)(8 - (rotated_map_offset_x & 0x7));
152 init_mask = (GX_UBYTE)(1 << (pixel_in_first_byte - 1));
153
154 /* Compute the number of pixels to draw from the last byte, if there are more than one byte in a row. */
155 if (num_bytes != 1)
156 {
157 pixel_in_last_byte = (rotated_map_offset_x + (INT)pixel_per_row) & 0x7;
158 if (pixel_in_last_byte == 0)
159 {
160 pixel_in_last_byte = 8;
161 }
162 }
163 else
164 {
165 pixel_in_first_byte = pixel_per_row;
166 }
167
168
169 glyph_row = (GX_UBYTE *)glyph -> gx_glyph_map;
170
171 if (rotated_map_offset_y)
172 {
173 glyph_row = glyph_row + ((INT)glyph_width * rotated_map_offset_y);
174 }
175
176 glyph_row += (rotated_map_offset_x >> 3);
177
178 line_start = (GX_UBYTE *)context -> gx_draw_context_memory;
179 line_start += context -> gx_draw_context_pitch * rotated_draw_top;
180 line_start += rotated_draw_left;
181
182 for (row = 0; row < y_height; row++)
183 {
184 glyph_data = glyph_row;
185 alpha = *(glyph_data);
186 mask = init_mask;
187 num_bits = pixel_in_first_byte;
188 put = line_start;
189
190 for (i = 0; i < num_bytes; i++)
191 {
192 if ((i == (num_bytes - 1)) && (num_bytes > 1))
193 {
194 num_bits = pixel_in_last_byte;
195 }
196 switch (num_bits)
197 {
198 case 8:
199 DRAW_PIXEL;
200 /* fallthrough */
201 case 7:
202 DRAW_PIXEL;
203 /* fallthrough */
204 case 6:
205 DRAW_PIXEL;
206 /* fallthrough */
207 case 5:
208 DRAW_PIXEL;
209 /* fallthrough */
210 case 4:
211 DRAW_PIXEL;
212 /* fallthrough */
213 case 3:
214 DRAW_PIXEL;
215 /* fallthrough */
216 case 2:
217 DRAW_PIXEL;
218 /* fallthrough */
219
220 default:
221 if (alpha & mask)
222 {
223 *put = text_color;
224 }
225 put++;
226 break;
227 }
228 glyph_data++;
229 alpha = *(glyph_data);
230 num_bits = 8;
231 mask = 0x80;
232 }
233
234 glyph_row += glyph_width;
235 line_start += context -> gx_draw_context_pitch;
236 }
237
238 return;
239 }
240
241