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