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