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