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 /**   Canvas Management (Canvas)                                          */
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_canvas.h"
30 #include "gx_context.h"
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_canvas_text_draw                                PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function prepares to draw text.                                */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    x_start                               X-coordinate, text left edge  */
49 /*    y_start                               Y-coordinate, text baseline   */
50 /*    string                                String to draw                */
51 /*    length                                Length of string to draw      */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    status                                Completion status             */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _gx_utility_string_length_check       Verify string length          */
60 /*    _gx_canvas_text_draw_ext              Actual text draw function    */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _gx_multi_line_text_view_draw                                       */
65 /*    _gx_single_line_text_input_draw                                     */
66 /*    _gx_widget_text_draw                                                */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
73 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*                                                                        */
76 /**************************************************************************/
77 #if defined(GX_ENABLE_DEPRECATED_STRING_API)
_gx_canvas_text_draw(GX_VALUE x_start,GX_VALUE y_start,GX_CONST GX_CHAR * text,INT length)78 UINT  _gx_canvas_text_draw(GX_VALUE x_start, GX_VALUE y_start, GX_CONST GX_CHAR *text, INT length)
79 {
80 GX_STRING string;
81 UINT      count;
82 UINT      status;
83 
84     string.gx_string_ptr = text;
85 
86     if (length >= 0)
87     {
88         string.gx_string_length = (UINT)length;
89     }
90     else
91     {
92         status = _gx_utility_string_length_check(text, &count, GX_MAX_STRING_LENGTH);
93         if (status != GX_SUCCESS)
94         {
95             return status;
96         }
97         string.gx_string_length = count;
98     }
99     status = _gx_canvas_text_draw_ext(x_start, y_start, &string);
100     return status;
101 }
102 #endif
103 
104 /**************************************************************************/
105 /*                                                                        */
106 /*  FUNCTION                                               RELEASE        */
107 /*                                                                        */
108 /*    _gx_canvas_text_draw_ext                            PORTABLE C      */
109 /*                                                           6.1.3        */
110 /*  AUTHOR                                                                */
111 /*                                                                        */
112 /*    Kenneth Maxwell, Microsoft Corporation                              */
113 /*                                                                        */
114 /*  DESCRIPTION                                                           */
115 /*                                                                        */
116 /*    This function prepares to draw text.                                */
117 /*                                                                        */
118 /*  INPUT                                                                 */
119 /*                                                                        */
120 /*    x_start                               X-coordinate, text left edge  */
121 /*    y_start                               Y-coordinate, text baseline   */
122 /*    string                                String to draw                */
123 /*                                                                        */
124 /*  OUTPUT                                                                */
125 /*                                                                        */
126 /*    status                                Completion status             */
127 /*                                                                        */
128 /*  CALLS                                                                 */
129 /*                                                                        */
130 /*    _gx_utility_rectangle_define          Initialize a rectangle        */
131 /*    _gx_system_string_width_get           Get width of the string in    */
132 /*                                            pixels                      */
133 /*    _gx_utility_rectangle_overlap_detect  Determine if two rectangles   */
134 /*                                            overlap                     */
135 /*    _gx_canvas_glyphs_draw                Draw glyphs on canvas         */
136 /*    [gx_display_driver_horizontal_line_draw]                            */
137 /*                                       The display driver horizontal    */
138 /*                                         line drawing function          */
139 /*                                                                        */
140 /*  CALLED BY                                                             */
141 /*                                                                        */
142 /*    _gx_multi_line_text_view_draw                                       */
143 /*    _gx_single_line_text_input_draw                                     */
144 /*    _gx_widget_text_draw                                                */
145 /*                                                                        */
146 /*  RELEASE HISTORY                                                       */
147 /*                                                                        */
148 /*    DATE              NAME                      DESCRIPTION             */
149 /*                                                                        */
150 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
151 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
152 /*                                            resulting in version 6.1    */
153 /*  12-31-2020     Kenneth Maxwell          Modified comment(s),          */
154 /*                                            replaced font format value  */
155 /*                                            with macro defines,         */
156 /*                                            resulting in version 6.1.3  */
157 /*                                                                        */
158 /**************************************************************************/
_gx_canvas_text_draw_ext(GX_VALUE x_start,GX_VALUE y_start,GX_CONST GX_STRING * string)159 UINT  _gx_canvas_text_draw_ext(GX_VALUE x_start, GX_VALUE y_start, GX_CONST GX_STRING *string)
160 {
161 GX_RECTANGLE bound;
162 GX_RECTANGLE clip;
163 GX_VIEW     *view;
164 GX_VALUE     width;
165 GX_POINT     draw_position;
166 GX_DISPLAY  *display;
167 VOID         (*glyph_draw)(GX_DRAW_CONTEXT *context, GX_RECTANGLE *draw_area,
168                            GX_POINT *map_offset, GX_CONST GX_GLYPH *glyph);
169 UINT         status = GX_FAILURE;
170 
171 /* pickup pointer to current context */
172 GX_DRAW_CONTEXT *context = _gx_system_current_draw_context;
173 
174 /* get pointer to current font */
175 GX_FONT *font = context -> gx_draw_context_brush.gx_brush_font;
176 
177     width = 0;
178 
179     if ((font == GX_NULL) || (font -> gx_font_glyphs.gx_font_normal_glyphs == GX_NULL))
180     {
181         return GX_INVALID_FONT;
182     }
183     display = context -> gx_draw_context_display;
184 
185     _gx_system_string_width_get_ext(font, string, &width);
186 
187     /* calculate bounding rectangle */
188     _gx_utility_rectangle_define(&bound, x_start, y_start,
189                                  (GX_VALUE)(x_start + width - 1),
190                                  (GX_VALUE)(y_start + font -> gx_font_line_height));
191 
192     /* check to see if the text is in the dirty area */
193 
194     if (!_gx_utility_rectangle_overlap_detect(&bound, &context -> gx_draw_context_dirty, &bound))
195     {
196         return(GX_SUCCESS);
197     }
198 
199     /*  loop through viewports, painting text into each that overlaps
200         text bound
201      */
202     view = context -> gx_draw_context_view_head;
203 
204     draw_position.gx_point_x = x_start;
205     draw_position.gx_point_y = y_start;
206 
207     /* use this for underline position, if needed */
208     y_start = (GX_VALUE)(y_start + font -> gx_font_baseline + 1);
209 
210     switch (font -> gx_font_format & GX_FONT_FORMAT_BPP_MASK)
211     {
212     case GX_FONT_FORMAT_1BPP:
213         if (font -> gx_font_format & GX_FONT_FORMAT_COMPRESSED)
214         {
215             glyph_draw = display -> gx_display_driver_1bit_compressed_glyph_draw;
216         }
217         else
218         {
219             glyph_draw = display -> gx_display_driver_1bit_glyph_draw;
220         }
221         break;
222 
223     case GX_FONT_FORMAT_4BPP:
224         if (font -> gx_font_format & GX_FONT_FORMAT_COMPRESSED)
225         {
226             glyph_draw = display -> gx_display_driver_4bit_compressed_glyph_draw;
227         }
228         else
229         {
230             glyph_draw = display -> gx_display_driver_4bit_glyph_draw;
231         }
232         break;
233 
234     case GX_FONT_FORMAT_8BPP:
235         if (font -> gx_font_format & GX_FONT_FORMAT_COMPRESSED)
236         {
237             glyph_draw = display -> gx_display_driver_8bit_compressed_glyph_draw;
238         }
239         else
240         {
241             glyph_draw = display -> gx_display_driver_8bit_glyph_draw;
242         }
243         break;
244 
245     default:
246         glyph_draw = GX_NULL;
247         break;
248     }
249 
250     if (glyph_draw)
251     {
252         while (view)
253         {
254             if (_gx_utility_rectangle_overlap_detect(&view -> gx_view_rectangle, &bound, &clip))
255             {
256                 _gx_canvas_glyphs_draw(context, &draw_position, string, &clip, glyph_draw);
257 
258                 if (context -> gx_draw_context_brush.gx_brush_style & GX_BRUSH_UNDERLINE)
259                 {
260                     /* underline the text.  */
261 
262                     if (clip.gx_rectangle_top <= y_start &&
263                         clip.gx_rectangle_bottom >= y_start)
264                     {
265                         width = context -> gx_draw_context_brush.gx_brush_width;
266                         if (width <= 0)
267                         {
268                             width = 1;
269                         }
270                         if (y_start + width - 1 > clip.gx_rectangle_bottom)
271                         {
272                             width = (GX_VALUE)(clip.gx_rectangle_bottom - y_start + 1);
273                         }
274                         display -> gx_display_driver_horizontal_line_draw(context,
275                                                                           clip.gx_rectangle_left,
276                                                                           clip.gx_rectangle_right,
277                                                                           y_start, width,
278                                                                           context -> gx_draw_context_brush.gx_brush_line_color);
279                     }
280                 }
281             }
282 
283             view = view -> gx_view_next;
284         }
285         status = GX_SUCCESS;
286     }
287 
288     return(status);
289 }
290 
291 /**************************************************************************/
292 /*                                                                        */
293 /*  FUNCTION                                               RELEASE        */
294 /*                                                                        */
295 /*    _gx_canvas_aligned_text_draw                        PORTABLE C      */
296 /*                                                           6.1.11       */
297 /*  AUTHOR                                                                */
298 /*                                                                        */
299 /*    Ting Zhu, Microsoft Corporation                                     */
300 /*                                                                        */
301 /*  DESCRIPTION                                                           */
302 /*                                                                        */
303 /*    This function draws text to canvas with specified alignment style.  */
304 /*                                                                        */
305 /*  INPUT                                                                 */
306 /*                                                                        */
307 /*    string                                String to draw                */
308 /*    rectangle                             Drawing area                  */
309 /*    alignment                             Alignment style               */
310 /*                                                                        */
311 /*  OUTPUT                                                                */
312 /*                                                                        */
313 /*    status                                Completion status             */
314 /*                                                                        */
315 /*  CALLS                                                                 */
316 /*                                                                        */
317 /*    _gx_context_brush_get                 Get context brush             */
318 /*    _gx_system_string_width_get_ext       Get string width              */
319 /*    _gx_canvas_text_draw_ext              Actual text draw function     */
320 /*                                                                        */
321 /*  CALLED BY                                                             */
322 /*                                                                        */
323 /*    Application Code                                                    */
324 /*    GUIX Internal Code                                                  */
325 /*                                                                        */
326 /*  RELEASE HISTORY                                                       */
327 /*                                                                        */
328 /*    DATE              NAME                      DESCRIPTION             */
329 /*                                                                        */
330 /*  04-25-2022     Ting Zhu                 Initial Version 6.1.11        */
331 /*                                                                        */
332 /**************************************************************************/
_gx_canvas_aligned_text_draw(GX_CONST GX_STRING * string,GX_RECTANGLE * rectangle,ULONG alignment)333 UINT  _gx_canvas_aligned_text_draw(GX_CONST GX_STRING *string, GX_RECTANGLE *rectangle, ULONG alignment)
334 {
335 GX_VALUE  text_width;
336 GX_VALUE  text_height;
337 GX_VALUE  x_pos;
338 GX_VALUE  y_pos;
339 GX_BRUSH *brush;
340 GX_VALUE  rect_width;
341 GX_VALUE  rect_height;
342 
343     _gx_context_brush_get(&brush);
344 
345     if (!brush -> gx_brush_font)
346     {
347         return GX_INVALID_FONT;
348     }
349 
350     text_height = brush -> gx_brush_font -> gx_font_line_height;
351 
352     rect_width = (GX_VALUE)(rectangle -> gx_rectangle_right - rectangle -> gx_rectangle_left + 1);
353     rect_height = (GX_VALUE)(rectangle -> gx_rectangle_bottom - rectangle -> gx_rectangle_top + 1);
354 
355     x_pos = rectangle -> gx_rectangle_left;
356     y_pos = rectangle -> gx_rectangle_top;
357     y_pos = (GX_VALUE)(y_pos + (rect_height - text_height) / 2);
358 
359     switch (alignment & GX_STYLE_TEXT_ALIGNMENT_MASK)
360     {
361     case GX_STYLE_TEXT_RIGHT:
362         _gx_system_string_width_get_ext(brush -> gx_brush_font, string, &text_width);
363         x_pos = (GX_VALUE)(x_pos + rect_width - 1);
364         x_pos = (GX_VALUE)(x_pos - text_width);
365         break;
366 
367     case GX_STYLE_TEXT_LEFT:
368         break;
369 
370     default:
371         _gx_system_string_width_get_ext(brush -> gx_brush_font, string, &text_width);
372         x_pos = (GX_VALUE)(x_pos + ((rect_width - text_width) / 2));
373         break;
374     }
375 
376     /* Draw the text.  */
377     return _gx_canvas_text_draw_ext(x_pos, y_pos, string);
378 }
379 
380