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 /**   System Management (System)                                          */
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 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _gx_system_string_width_compressed_font_get         PORTABLE C      */
35 /*                                                           6.1          */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    Kenneth Maxwell, Microsoft Corporation                              */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    This service gets the width (in pixels) of the supplied string,     */
43 /*    for a given compressed font.                                        */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    font                                  Pointer to font of strings    */
48 /*    string                                Pointer to string             */
49 /*    string_length                         Raw length of string, in bytes*/
50 /*    return_width                          Destination for width of      */
51 /*                                            string                      */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    status                                Completion status             */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _gx_utility_utf8_string_character_get                               */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    Application Code                                                    */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
70 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
71 /*                                            resulting in version 6.1    */
72 /*                                                                        */
73 /**************************************************************************/
_gx_system_string_width_compressed_font_get(GX_CONST GX_FONT * font,GX_STRING * string,GX_VALUE * return_width)74 static UINT  _gx_system_string_width_compressed_font_get(GX_CONST GX_FONT *font,
75                                                          GX_STRING *string,
76                                                          GX_VALUE *return_width)
77 {
78 INT                           width = 0;
79 GX_CHAR_CODE                  char_val;
80 GX_CONST GX_COMPRESSED_GLYPH *glyph;
81 GX_CONST GX_FONT             *font_link;
82 GX_STRING                     string_copy = *string;
83 
84 #ifdef GX_UTF8_SUPPORT
85 UINT ret;
86 #endif /* GX_UTF8_SUPPORT */
87 
88     /* Process complete string.  */
89     while (string_copy.gx_string_length > 0)
90     {
91 #ifdef GX_UTF8_SUPPORT
92         ret = _gx_utility_utf8_string_character_get(&string_copy, &char_val, GX_NULL);
93 
94         if ((ret != GX_SUCCESS) || (char_val == 0))
95 #else
96         char_val = (GX_CHAR_CODE)(*string_copy.gx_string_ptr);
97         string_copy.gx_string_ptr++;
98         string_copy.gx_string_length--;
99 
100         if (char_val == 0)
101 #endif /* GX_UTF8_SUPPORT */
102         {
103             break;
104         }
105 
106         font_link = font;
107         while (font_link)
108         {
109             if (char_val >= font_link -> gx_font_first_glyph &&
110                 char_val <= font_link -> gx_font_last_glyph)
111             {
112                 break;
113             }
114             font_link = font_link -> gx_font_next_page;
115         }
116         if (font_link)
117         {
118             char_val = (GX_CHAR_CODE)(char_val - font_link -> gx_font_first_glyph);
119             glyph = &font_link -> gx_font_glyphs.gx_font_compressed_glyphs[char_val];
120 
121             width += glyph -> gx_glyph_advance;
122         }
123     }
124 
125     /* Setup return width.  */
126     *return_width =  (GX_VALUE)width;
127 
128     /* Return successful completion.  */
129     return(GX_SUCCESS);
130 }
131 
132 /**************************************************************************/
133 /*                                                                        */
134 /*  FUNCTION                                               RELEASE        */
135 /*                                                                        */
136 /*    _gx_system_string_width_kerning_font_get            PORTABLE C      */
137 /*                                                           6.1          */
138 /*  AUTHOR                                                                */
139 /*                                                                        */
140 /*    Kenneth Maxwell, Microsoft Corporation                              */
141 /*                                                                        */
142 /*  DESCRIPTION                                                           */
143 /*                                                                        */
144 /*    This service gets the width (in pixels) of the supplied string,     */
145 /*    for a given compressed font.                                        */
146 /*                                                                        */
147 /*  INPUT                                                                 */
148 /*                                                                        */
149 /*    font                                  Pointer to font of strings    */
150 /*    string                                Pointer to string             */
151 /*    string_length                         Raw length of string, in bytes*/
152 /*    return_width                          Destination for width of      */
153 /*                                            string                      */
154 /*                                                                        */
155 /*  OUTPUT                                                                */
156 /*                                                                        */
157 /*    status                                Completion status             */
158 /*                                                                        */
159 /*  CALLS                                                                 */
160 /*                                                                        */
161 /*    _gx_utility_utf8_string_character_get                               */
162 /*                                                                        */
163 /*  CALLED BY                                                             */
164 /*                                                                        */
165 /*    Application Code                                                    */
166 /*                                                                        */
167 /*  RELEASE HISTORY                                                       */
168 /*                                                                        */
169 /*    DATE              NAME                      DESCRIPTION             */
170 /*                                                                        */
171 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
172 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
173 /*                                            resulting in version 6.1    */
174 /*                                                                        */
175 /**************************************************************************/
176 #if defined(GX_FONT_KERNING_SUPPORT)
_gx_system_string_width_kerning_font_get(GX_CONST GX_FONT * font,GX_CONST GX_STRING * string,GX_VALUE * return_width)177 static UINT  _gx_system_string_width_kerning_font_get(GX_CONST GX_FONT *font,
178                                                       GX_CONST GX_STRING *string,
179                                                       GX_VALUE *return_width)
180 {
181 INT                        width = 0;
182 GX_CHAR_CODE               char_val;
183 GX_CONST GX_KERNING_GLYPH *glyph;
184 GX_CONST GX_FONT          *font_link;
185 GX_STRING                  string_copy;
186 
187 /* Used for kerning glyph. */
188 GX_CHAR_CODE       pre_char_val = 0;
189 GX_CHAR            kerning_offset = 0;
190 GX_CONST GX_UBYTE *kerning_table;
191 INT                kerning_counts;
192 INT                index;
193 GX_UBYTE          *left_glyph_ptr;
194 
195 #ifdef GX_UTF8_SUPPORT
196 UINT ret;
197 #endif /* GX_UTF8_SUPPORT */
198 
199     string_copy = *string;
200 
201     /* Process complete string.  */
202     while (string_copy.gx_string_length > 0)
203     {
204 #ifdef GX_UTF8_SUPPORT
205         ret = _gx_utility_utf8_string_character_get(&string_copy, &char_val, GX_NULL);
206         if ((ret != GX_SUCCESS) || (char_val == 0))
207 #else
208         char_val = (GX_CHAR_CODE)(*string_copy.gx_string_ptr++);
209         string_copy.gx_string_length--;
210         if (char_val == 0)
211 #endif /* GX_UTF8_SUPPORT */
212         {
213             break;
214         }
215 
216         font_link = font;
217         while (font_link)
218         {
219             if (char_val >= font_link -> gx_font_first_glyph &&
220                 char_val <= font_link -> gx_font_last_glyph)
221             {
222                 break;
223             }
224             font_link = font_link -> gx_font_next_page;
225         }
226         if (font_link)
227         {
228             char_val = (GX_CHAR_CODE)(char_val - font_link -> gx_font_first_glyph);
229 
230             glyph = &font_link -> gx_font_glyphs.gx_font_kerning_glyphs[char_val];
231             kerning_table = glyph -> gx_kerning_table;
232 
233             if (kerning_table && (pre_char_val != 0))
234             {
235                 /* Search the kerning table for the kerning value. */
236                 kerning_counts = *kerning_table;
237                 left_glyph_ptr = (GX_UBYTE *)(kerning_table + 1);
238 
239                 for (index = 0; index < kerning_counts; index++)
240                 {
241                     if ((*left_glyph_ptr) == (pre_char_val + font_link -> gx_font_first_glyph))
242                     {
243                         kerning_offset = (GX_CHAR)(*(left_glyph_ptr + 1));
244                         break;
245                     }
246                     left_glyph_ptr += 2;
247                 }
248             }
249 
250             width += glyph -> gx_glyph_advance;
251             width += kerning_offset;
252         }
253         /* Store previous character value. */
254         pre_char_val = char_val;
255         kerning_offset = 0;
256     }
257 
258     /* Setup return width.  */
259     *return_width =  (GX_VALUE)width;
260 
261     /* Return successful completion.  */
262     return(GX_SUCCESS);
263 }
264 #endif
265 
266 /**************************************************************************/
267 /*                                                                        */
268 /*  FUNCTION                                               RELEASE        */
269 /*                                                                        */
270 /*    _gx_system_string_width_get                         PORTABLE C      */
271 /*                                                           6.1          */
272 /*  AUTHOR                                                                */
273 /*                                                                        */
274 /*    Kenneth Maxwell, Microsoft Corporation                              */
275 /*                                                                        */
276 /*  DESCRIPTION                                                           */
277 /*                                                                        */
278 /*    This service gets the width (in pixels) of the supplied string,     */
279 /*    for a given font.                                                   */
280 /*                                                                        */
281 /*  INPUT                                                                 */
282 /*                                                                        */
283 /*    font                                  Pointer to font of strings    */
284 /*    string                                Pointer to string             */
285 /*    string_length                         Raw length of string, in bytes*/
286 /*    return_width                          Destination for width of      */
287 /*                                            string                      */
288 /*                                                                        */
289 /*  OUTPUT                                                                */
290 /*                                                                        */
291 /*    status                                Completion status             */
292 /*                                                                        */
293 /*  CALLS                                                                 */
294 /*                                                                        */
295 /*    _gx_utility_utf8_string_character_get                               */
296 /*                                                                        */
297 /*  CALLED BY                                                             */
298 /*                                                                        */
299 /*    Application Code                                                    */
300 /*                                                                        */
301 /*  RELEASE HISTORY                                                       */
302 /*                                                                        */
303 /*    DATE              NAME                      DESCRIPTION             */
304 /*                                                                        */
305 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
306 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
307 /*                                            resulting in version 6.1    */
308 /*                                                                        */
309 /**************************************************************************/
310 #if defined(GX_ENABLE_DEPRECATED_STRING_API)
_gx_system_string_width_get(GX_CONST GX_FONT * font,GX_CONST GX_CHAR * text,INT string_length,GX_VALUE * return_width)311 UINT  _gx_system_string_width_get(GX_CONST GX_FONT *font, GX_CONST GX_CHAR *text, INT string_length, GX_VALUE *return_width)
312 {
313 UINT      status = GX_SUCCESS;
314 UINT      length = 0;
315 GX_STRING string;
316 
317     string.gx_string_ptr = text;
318     if (string_length >= 0)
319     {
320         string.gx_string_length = (UINT)string_length;
321     }
322     else
323     {
324         status = _gx_utility_string_length_check(text, &length, GX_MAX_STRING_LENGTH);
325         if (status == GX_SUCCESS)
326         {
327             string.gx_string_length = length;
328         }
329     }
330     if (status == GX_SUCCESS)
331     {
332         status = _gx_system_string_width_get_ext(font, &string, return_width);
333     }
334     return status;
335 }
336 #endif
337 
338 /**************************************************************************/
339 /*                                                                        */
340 /*  FUNCTION                                               RELEASE        */
341 /*                                                                        */
342 /*    _gx_system_string_width_get_ext                     PORTABLE C      */
343 /*                                                           6.1          */
344 /*  AUTHOR                                                                */
345 /*                                                                        */
346 /*    Kenneth Maxwell, Microsoft Corporation                              */
347 /*                                                                        */
348 /*  DESCRIPTION                                                           */
349 /*                                                                        */
350 /*    This service gets the width (in pixels) of the supplied string,     */
351 /*    for a given font.                                                   */
352 /*                                                                        */
353 /*  INPUT                                                                 */
354 /*                                                                        */
355 /*    font                                  Pointer to font of strings    */
356 /*    string                                Pointer to string             */
357 /*    string_length                         Raw length of string, in bytes*/
358 /*    return_width                          Destination for width of      */
359 /*                                            string                      */
360 /*                                                                        */
361 /*  OUTPUT                                                                */
362 /*                                                                        */
363 /*    status                                Completion status             */
364 /*                                                                        */
365 /*  CALLS                                                                 */
366 /*                                                                        */
367 /*    _gx_utility_utf8_string_character_get                               */
368 /*                                                                        */
369 /*  CALLED BY                                                             */
370 /*                                                                        */
371 /*    Application Code                                                    */
372 /*                                                                        */
373 /*  RELEASE HISTORY                                                       */
374 /*                                                                        */
375 /*    DATE              NAME                      DESCRIPTION             */
376 /*                                                                        */
377 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
378 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
379 /*                                            resulting in version 6.1    */
380 /*                                                                        */
381 /**************************************************************************/
_gx_system_string_width_get_ext(GX_CONST GX_FONT * font,GX_CONST GX_STRING * string,GX_VALUE * return_width)382 UINT  _gx_system_string_width_get_ext(GX_CONST GX_FONT *font, GX_CONST GX_STRING *string, GX_VALUE *return_width)
383 {
384 
385 INT                width = 0;
386 GX_CHAR_CODE       char_val;
387 GX_CONST GX_GLYPH *glyph;
388 GX_CONST GX_FONT  *font_link;
389 GX_STRING          string_copy = *string;
390 
391 #ifdef GX_UTF8_SUPPORT
392 UINT ret;
393 #endif /* GX_UTF8_SUPPORT */
394 
395     /* Check for NULL pointers.  */
396     if (!font || !string_copy.gx_string_ptr)
397     {
398         /* Yes, one of the input pointers are NULL.  */
399         return(GX_PTR_ERROR);
400     }
401 
402     if (font -> gx_font_format & GX_FONT_FORMAT_COMPRESSED)
403     {
404         return _gx_system_string_width_compressed_font_get(font, &string_copy, return_width);
405     }
406 #if defined(GX_FONT_KERNING_SUPPORT)
407     else
408     {
409         if (font -> gx_font_format & GX_FONT_FORMAT_KERNING)
410         {
411             return _gx_system_string_width_kerning_font_get(font, &string_copy, return_width);
412         }
413     }
414 #endif
415 
416     /* Process complete string.  */
417     while (string_copy.gx_string_length > 0)
418     {
419         /* Pickup first character of the string.  */
420 #ifdef GX_UTF8_SUPPORT
421         ret = _gx_utility_utf8_string_character_get(&string_copy, &char_val, GX_NULL);
422 
423         if ((ret != GX_SUCCESS) || (char_val == 0))
424 #else
425         char_val = (GX_CHAR_CODE)(*string_copy.gx_string_ptr);
426         string_copy.gx_string_ptr++;
427         string_copy.gx_string_length--;
428 
429         if (char_val == 0)
430 #endif /* GX_UTF8_SUPPORT */
431         {
432             break;
433         }
434 
435         font_link = font;
436         while (font_link)
437         {
438             if (char_val >= font_link -> gx_font_first_glyph &&
439                 char_val <= font_link -> gx_font_last_glyph)
440             {
441                 break;
442             }
443             font_link = font_link -> gx_font_next_page;
444         }
445         if (font_link)
446         {
447             char_val = (GX_CHAR_CODE)(char_val - font_link -> gx_font_first_glyph);
448             glyph = &font_link -> gx_font_glyphs.gx_font_normal_glyphs[char_val];
449             width += glyph -> gx_glyph_advance;
450         }
451     }
452 
453     /* Setup return width.  */
454     if (width > 0x7fff)
455     {
456         width = 0x7fff;
457     }
458     *return_width =  (GX_VALUE)width;
459 
460     /* Return successful completion.  */
461     return(GX_SUCCESS);
462 }
463 
464