3 // Copyright (C) 2012-2018 by Werner Lemberg.
5 // This file is part of the ttfautohint library, and may only be used,
6 // modified, and distributed under the terms given in `COPYING'. By
7 // continuing to use, modify, or distribute this file you indicate that you
8 // have read `COPYING' and understand and accept it fully.
10 // The file `COPYING' mentioned in the previous paragraph is distributed
11 // with the ttfautohint library.
18 // the next header file is from gnulib defining function `last_component',
19 // which is a replacement for `basename' (but just returning a pointer
20 // without allocating a string) that works on Windows also
25 #include <numberset.h>
28 #define TTFAUTOHINT_STRING "; ttfautohint"
29 #define TTFAUTOHINT_STRING_WIDE "\0;\0 \0t\0t\0f\0a\0u\0t\0o\0h\0i\0n\0t"
34 const char invalid_ps_chars
[96] =
36 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, // 0x20 %, (, ), /
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // 0x30 <, >
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 0x50 [, ]
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, // 0x70 {, }, DEL
46 check_family_suffix(const char* s
)
50 int c
= (signed char)*s
- 0x20;
52 // valid range is 0x20-0x7E minus characters %()/<>[]{}
53 // (well, the space character 0x20 is not valid within a PS name,
54 // but the validity test gets executed before constructing a PS name,
55 // which has all space characters removed)
56 if (c
< 0 || invalid_ps_chars
[c
])
66 // build string that gets appended to the `Version' field(s)
67 // return value 1 means allocation error, value 2 too long a string
69 build_version_string(Info_Data
* idata
)
71 // since we use `goto' we have to declare variables before the jumps
72 unsigned char* info_string
;
73 unsigned char* info_string_wide
;
78 char mode_letters
[] = "nqs";
84 d
= sdscatprintf(d
, TTFAUTOHINT_STRING
" (v%s)", VERSION
);
85 if (!idata
->detailed_info
)
93 d
= sdscatprintf(d
, " -l %d", idata
->hinting_range_min
);
94 d
= sdscatprintf(d
, " -r %d", idata
->hinting_range_max
);
95 d
= sdscatprintf(d
, " -G %d", idata
->hinting_limit
);
96 d
= sdscatprintf(d
, " -x %d", idata
->increase_x_height
);
97 if (idata
->fallback_stem_width
)
98 d
= sdscatprintf(d
, " -H %d", idata
->fallback_stem_width
);
99 d
= sdscatprintf(d
, " -D %s", idata
->default_script
);
100 d
= sdscatprintf(d
, " -f %s", idata
->fallback_script
);
101 if (idata
->control_name
)
103 char* bn
= last_component(idata
->control_name
);
104 d
= sdscatprintf(d
, " -m \"%s\"", bn
? bn
: idata
->control_name
);
106 if (idata
->reference_name
)
108 char* bn
= last_component(idata
->reference_name
);
109 d
= sdscatprintf(d
, " -R \"%s\"", bn
? bn
: idata
->reference_name
);
111 d
= sdscatprintf(d
, " -Z %d", idata
->reference_index
);
113 // `*_stem_width_mode' can have values -1, 0, and 1
114 mode
[0] = mode_letters
[idata
->gray_stem_width_mode
+ 1];
115 mode
[1] = mode_letters
[idata
->gdi_cleartype_stem_width_mode
+ 1];
116 mode
[2] = mode_letters
[idata
->dw_cleartype_stem_width_mode
+ 1];
118 d
= sdscatprintf(d
, " -a %s", mode
);
120 if (idata
->windows_compatibility
)
121 d
= sdscat(d
, " -W");
122 if (idata
->adjust_subglyphs
)
123 d
= sdscat(d
, " -p");
124 if (idata
->hint_composites
)
125 d
= sdscat(d
, " -c");
127 d
= sdscat(d
, " -s");
128 if (idata
->fallback_scaling
)
129 d
= sdscat(d
, " -S");
130 if (idata
->TTFA_info
)
131 d
= sdscat(d
, " -t");
133 if (idata
->x_height_snapping_exceptions_string
)
135 // only set specific value of `ret' for an allocation error,
136 // since syntax errors are handled in TTF_autohint
137 number_range
* x_height_snapping_exceptions
;
138 const char* pos
= number_set_parse(
139 idata
->x_height_snapping_exceptions_string
,
140 &x_height_snapping_exceptions
,
144 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
149 s
= number_set_show(x_height_snapping_exceptions
, 6, 0x7FFF);
150 number_set_free(x_height_snapping_exceptions
);
152 // ensure UTF16-BE version doesn't get too long
153 if (strlen(s
) > 0xFFFF / 2 - sdslen(d
))
159 d
= sdscatprintf(d
, " -X \"%s\"", s
);
169 info_string
= (unsigned char*)malloc(sdslen(d
) + 1);
175 memcpy(info_string
, d
, sdslen(d
) + 1);
177 idata
->info_string
= info_string
;
178 idata
->info_string_len
= (unsigned short)sdslen(d
);
180 // prepare UTF16-BE version data
181 idata
->info_string_wide_len
= 2 * idata
->info_string_len
;
182 info_string_wide
= (unsigned char*)realloc(idata
->info_string_wide
,
183 idata
->info_string_wide_len
);
184 if (!info_string_wide
)
189 idata
->info_string_wide
= info_string_wide
;
191 dt
= idata
->info_string
;
192 dtw
= idata
->info_string_wide
;
193 for (unsigned short i
= 0; i
< idata
->info_string_len
; i
++)
206 free(idata
->info_string
);
207 free(idata
->info_string_wide
);
209 idata
->info_string
= NULL
;
210 idata
->info_string_wide
= NULL
;
211 idata
->info_string_len
= 0;
212 idata
->info_string_wide_len
= 0;
219 info_name_id_5(unsigned short platform_id
,
220 unsigned short encoding_id
,
225 unsigned char ttfautohint_string
[] = TTFAUTOHINT_STRING
;
226 unsigned char ttfautohint_string_wide
[] = TTFAUTOHINT_STRING_WIDE
;
228 // we use memmem, so don't count the trailing \0 character
229 size_t ttfautohint_string_len
= sizeof (TTFAUTOHINT_STRING
) - 1;
230 size_t ttfautohint_string_wide_len
= sizeof (TTFAUTOHINT_STRING_WIDE
) - 1;
233 unsigned short v_len
;
239 || (platform_id
== 3 && !(encoding_id
== 1
240 || encoding_id
== 10)))
242 // one-byte or multi-byte encodings
243 v
= idata
->info_string
;
244 v_len
= idata
->info_string_len
;
245 s
= ttfautohint_string
;
246 s_len
= ttfautohint_string_len
;
251 // (two-byte) UTF-16BE for everything else
252 v
= idata
->info_string_wide
;
253 v_len
= idata
->info_string_wide_len
;
254 s
= ttfautohint_string_wide
;
255 s_len
= ttfautohint_string_wide_len
;
259 // if we already have an ttfautohint info string,
260 // remove it up to a following `;' character (or end of string)
261 unsigned char* s_start
= (unsigned char*)memmem(*str
, *len
, s
, s_len
);
264 unsigned char* s_end
= s_start
+ offset
;
265 unsigned char* limit
= *str
+ *len
;
267 while (s_end
< limit
)
275 if (*(s_end
- 1) == '\0') // UTF-16BE
286 while (s_end
< limit
)
287 *s_start
++ = *s_end
++;
289 *len
-= s_end
- s_start
;
292 // do nothing if the string would become too long
293 if (*len
> 0xFFFF - v_len
)
296 unsigned short len_new
= *len
+ v_len
;
297 unsigned char* str_new
= (unsigned char*)realloc(*str
, len_new
);
302 memcpy(*str
+ *len
, v
, v_len
);
309 // a structure to collect family data for a given
310 // (platform_id, encoding_id, language_id) triplet
312 typedef struct Family_
314 unsigned short platform_id
;
315 unsigned short encoding_id
;
316 unsigned short language_id
;
318 unsigned short* name_id_1_len
;
319 unsigned char** name_id_1_str
;
320 unsigned short* name_id_4_len
;
321 unsigned char** name_id_4_str
;
322 unsigned short* name_id_6_len
;
323 unsigned char** name_id_6_str
;
324 unsigned short* name_id_16_len
;
325 unsigned char** name_id_16_str
;
326 unsigned short* name_id_21_len
;
327 unsigned char** name_id_21_str
;
333 // node structure for collected family data
335 typedef struct Node Node
;
338 LLRB_ENTRY(Node
) entry
;
343 // comparison function for our red-black tree
351 // sort by platform ID ...
352 diff
= e1
->family
.platform_id
- e2
->family
.platform_id
;
356 // ... then by encoding ID ...
357 diff
= e1
->family
.encoding_id
- e2
->family
.encoding_id
;
361 // ... then by language ID
362 diff
= e1
->family
.language_id
- e2
->family
.language_id
;
365 // https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign
366 return (diff
> 0) - (diff
< 0);
370 // the red-black tree function body
371 typedef struct family_data family_data
;
373 LLRB_HEAD(family_data
, Node
);
375 // no trailing semicolon in the next line
376 LLRB_GENERATE_STATIC(family_data
, Node
, entry
, nodecmp
)
380 family_data_free(Info_Data
* idata
)
382 family_data
* family_data_head
= (family_data
*)idata
->family_data_head
;
387 if (!family_data_head
)
390 for (node
= LLRB_MIN(family_data
, family_data_head
);
394 next_node
= LLRB_NEXT(family_data
, family_data_head
, node
);
395 LLRB_REMOVE(family_data
, family_data_head
, node
);
396 sdsfree(node
->family
.family_name
);
400 free(family_data_head
);
405 collect_family_data(unsigned short platform_id
,
406 unsigned short encoding_id
,
407 unsigned short language_id
,
408 unsigned short name_id
,
413 family_data
* family_data_head
= (family_data
*)idata
->family_data_head
;
417 if (!family_data_head
)
419 // first-time initialization
420 family_data_head
= (family_data
*)malloc(sizeof (family_data
));
421 if (!family_data_head
)
424 LLRB_INIT(family_data_head
);
425 idata
->family_data_head
= family_data_head
;
428 node
= (Node
*)malloc(sizeof (Node
));
432 node
->family
.platform_id
= platform_id
;
433 node
->family
.encoding_id
= encoding_id
;
434 node
->family
.language_id
= language_id
;
436 val
= LLRB_INSERT(family_data
, family_data_head
, node
);
439 // we already have an entry in the tree for our triplet
445 // initialize remaining fields
446 node
->family
.name_id_1_len
= NULL
;
447 node
->family
.name_id_1_str
= NULL
;
448 node
->family
.name_id_4_len
= NULL
;
449 node
->family
.name_id_4_str
= NULL
;
450 node
->family
.name_id_6_len
= NULL
;
451 node
->family
.name_id_6_str
= NULL
;
452 node
->family
.name_id_16_len
= NULL
;
453 node
->family
.name_id_16_str
= NULL
;
454 node
->family
.name_id_21_len
= NULL
;
455 node
->family
.name_id_21_str
= NULL
;
457 node
->family
.family_name
= NULL
;
462 node
->family
.name_id_1_len
= len
;
463 node
->family
.name_id_1_str
= str
;
465 else if (name_id
== 4)
467 node
->family
.name_id_4_len
= len
;
468 node
->family
.name_id_4_str
= str
;
470 else if (name_id
== 6)
472 node
->family
.name_id_6_len
= len
;
473 node
->family
.name_id_6_str
= str
;
475 else if (name_id
== 16)
477 node
->family
.name_id_16_len
= len
;
478 node
->family
.name_id_16_str
= str
;
480 else if (name_id
== 21)
482 node
->family
.name_id_21_len
= len
;
483 node
->family
.name_id_21_str
= str
;
490 // `info-callback' function
493 info(unsigned short platform_id
,
494 unsigned short encoding_id
,
495 unsigned short language_id
,
496 unsigned short name_id
,
501 Info_Data
* idata
= (Info_Data
*)user
;
503 // if ID is a version string, append our data
504 if (!idata
->no_info
&& name_id
== 5)
505 return info_name_id_5(platform_id
, encoding_id
, len
, str
, idata
);
507 // if ID is related to a family name, collect the data
508 if (*idata
->family_suffix
514 return collect_family_data(platform_id
,
526 // Insert `suffix' to `str', right after substring `name'.
527 // If `name' isn't a substring of `str', append `suffix' to `str'.
528 // Do nothing in case of allocation error or if resulting string is too long.
531 insert_suffix(sds suffix
,
536 if (!len
|| !*len
|| !str
|| !*str
)
541 // check whether `name' is a substring of `str'
542 unsigned char* s_start
= (unsigned char*)memmem(*str
, *len
,
545 // construct new string
548 size_t substring_end
= size_t(s_start
- *str
) + sdslen(name
);
550 // everything up to the end of the substring
551 s
= sdscatlen(s
, *str
, substring_end
);
553 s
= sdscatsds(s
, suffix
);
555 s
= sdscatlen(s
, *str
+ substring_end
, *len
- substring_end
);
559 s
= sdscatlen(s
, *str
, *len
);
560 s
= sdscatsds(s
, suffix
);
566 if (sdslen(s
) <= 0xFFFF)
568 unsigned short len_new
= (unsigned short)sdslen(s
);
569 unsigned char* str_new
= (unsigned char*)realloc(*str
, len_new
);
573 memcpy(*str
, s
, len_new
);
582 // `info-post-callback' function
585 info_post(void* user
)
587 Info_Data
* idata
= (Info_Data
*)user
;
588 family_data
* family_data_head
= (family_data
*)idata
->family_data_head
;
591 // family_suffix + family_suffix_wide
593 sds family_suffix
= sdsnew(idata
->family_suffix
);
594 size_t family_suffix_len
= sdslen(family_suffix
);
596 sds family_suffix_wide
= sdsempty();
597 size_t family_suffix_wide_len
= 2 * family_suffix_len
;
599 // create sds with given size but uninitialized string data
600 family_suffix_wide
= sdsMakeRoomFor(family_suffix_wide
,
601 family_suffix_wide_len
);
605 // construct `family_suffix_wide' by inserting '\0'
607 char *fsw
= family_suffix_wide
;
608 for (size_t i
= 0; i
< family_suffix_len
; i
++)
613 sdsIncrLen(family_suffix_wide
, (int)family_suffix_wide_len
);
616 // family_ps_suffix + family_ps_suffix_wide
618 sds family_ps_suffix
= sdsempty();
620 // create sds with estimated size but uninitialized string data;
621 // we later set the size to the actual value
622 family_ps_suffix
= sdsMakeRoomFor(family_ps_suffix
,
625 // construct `family_ps_suffix' by removing all space characters
627 char *fps
= family_ps_suffix
;
628 for (size_t i
= 0; i
< family_suffix_len
; i
++)
635 sdsIncrLen(family_ps_suffix
, (int)(fps
- family_ps_suffix
));
637 size_t family_ps_suffix_len
= sdslen(family_ps_suffix
);
639 sds family_ps_suffix_wide
= sdsempty();
640 size_t family_ps_suffix_wide_len
= 2 * family_ps_suffix_len
;
642 // create sds with given size but uninitialized string data
643 family_ps_suffix_wide
= sdsMakeRoomFor(family_ps_suffix_wide
,
644 family_ps_suffix_wide_len
);
646 // construct `family_ps_suffix_wide' by inserting '\0'
647 fps
= family_ps_suffix
;
648 char* fpsw
= family_ps_suffix_wide
;
649 for (size_t i
= 0; i
< family_ps_suffix_len
; i
++)
652 *(fpsw
++) = *(fps
++);
654 sdsIncrLen(family_ps_suffix_wide
, (int)family_ps_suffix_wide_len
);
656 // We try the following algorithm.
658 // 1. If we have a `Preferred Family' (ID 16), use it as the family name,
659 // otherwise use the `Font Family Name' (ID 1). If necessary, search
660 // other language IDs for the current (platform ID, encoding ID) pair
661 // to find a family name.
663 // 2. Append the family suffix to the family substring in the `Font Family
664 // Name' (ID 1), the `Full Font Name' (ID 4), the `Preferred Family'
665 // (ID 16), and the `WWS Family Name' (ID 21). In case the family name
666 // found in step 1 is not a substring, append the suffix to the whole
669 // 3. Remove spaces from the family name and locate this substring in the
670 // `PostScript Name' (ID 6), then append the family suffix, also with
671 // spaces removed. If we don't have a substring, append the stripped
672 // suffix to the whole string.
674 // determine family name for all triplets if available
675 for (Node
* node
= LLRB_MIN(family_data
, family_data_head
);
677 node
= LLRB_NEXT(family_data
, family_data_head
, node
))
679 Family
* family
= &node
->family
;
681 if (family
->name_id_16_len
&& *family
->name_id_16_len
682 && family
->name_id_16_str
&& *family
->name_id_16_str
)
683 family
->family_name
= sdsnewlen(*family
->name_id_16_str
,
684 *family
->name_id_16_len
);
685 else if (family
->name_id_1_len
&& *family
->name_id_1_len
686 && family
->name_id_1_str
&& *family
->name_id_1_str
)
687 family
->family_name
= sdsnewlen(*family
->name_id_1_str
,
688 *family
->name_id_1_len
);
691 sds family_name
= sdsempty();
692 sds family_ps_name
= sdsempty();
694 // process all name ID strings in triplets
695 for (Node
* node
= LLRB_MIN(family_data
, family_data_head
);
697 node
= LLRB_NEXT(family_data
, family_data_head
, node
))
699 Family family
= node
->family
;
702 sdsclear(family_name
);
703 sdsclear(family_ps_name
);
705 if (family
.family_name
)
706 family_name
= sdscatsds(family_name
, family
.family_name
);
711 // use family name from a triplet that actually has one
712 for (n
= LLRB_MIN(family_data
, family_data_head
);
714 n
= LLRB_NEXT(family_data
, family_data_head
, n
))
716 Family f
= n
->family
;
718 if (f
.platform_id
== family
.platform_id
719 && f
.encoding_id
== family
.encoding_id
722 family_name
= sdscatsds(family_name
, f
.family_name
);
728 continue; // no valid family name found
731 if (family
.platform_id
== 1
732 || (family
.platform_id
== 3 && !(family
.encoding_id
== 1
733 || family
.encoding_id
== 10)))
734 is_wide
= false; // one-byte or multi-byte encodings
736 is_wide
= true; // (two-byte) UTF-16BE
738 sds suffix
= is_wide
? family_suffix_wide
: family_suffix
;
739 insert_suffix(suffix
,
741 family
.name_id_1_len
,
742 family
.name_id_1_str
);
743 insert_suffix(suffix
,
745 family
.name_id_4_len
,
746 family
.name_id_4_str
);
747 insert_suffix(suffix
,
749 family
.name_id_16_len
,
750 family
.name_id_16_str
);
751 insert_suffix(suffix
,
753 family
.name_id_21_len
,
754 family
.name_id_21_str
);
756 size_t family_name_len
= sdslen(family_name
);
758 family_name_len
&= ~1U; // ensure even value for the loop below
760 // set sds to estimated size;
761 // we later set the size to the actual value
762 family_ps_name
= sdsMakeRoomFor(family_ps_name
,
765 // construct `family_ps_name' by removing all space characters
766 char *fn
= family_name
;
767 char *fpn
= family_ps_name
;
770 for (size_t i
= 0; i
< family_name_len
; i
+= 2)
774 if (!(c1
== '\0' && c2
== ' '))
783 for (size_t i
= 0; i
< family_name_len
; i
++)
791 sdsIncrLen(family_ps_name
, (int)(fpn
- family_ps_name
));
793 sds ps_suffix
= is_wide
? family_ps_suffix_wide
: family_ps_suffix
;
794 insert_suffix(ps_suffix
,
796 family
.name_id_6_len
,
797 family
.name_id_6_str
);
800 sdsfree(family_suffix
);
801 sdsfree(family_suffix_wide
);
802 sdsfree(family_ps_suffix
);
803 sdsfree(family_ps_suffix_wide
);
804 sdsfree(family_name
);
805 sdsfree(family_ps_name
);
807 family_data_free(idata
);