3 // Copyright (C) 2012-2016 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 `base_name',
19 // which is a replacement for `basename' that works on Windows also
24 #include <numberset.h>
27 #define TTFAUTOHINT_STRING "; ttfautohint"
28 #define TTFAUTOHINT_STRING_WIDE "\0;\0 \0t\0t\0f\0a\0u\0t\0o\0h\0i\0n\0t"
33 const char invalid_ps_chars
[96] =
35 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, // 0x20 %, (, ), /
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // 0x30 <, >
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, // 0x50 [, ]
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, // 0x70 {, }, DEL
45 check_family_suffix(const char* s
)
49 int c
= (signed char)*s
- 0x20;
51 // valid range is 0x20-0x7E minus characters %()/<>[]{}
52 // (well, the space character 0x20 is not valid within a PS name,
53 // but the validity test gets executed before constructing a PS name,
54 // which has all space characters removed)
55 if (c
< 0 || invalid_ps_chars
[c
])
65 // build string that gets appended to the `Version' field(s)
66 // return value 1 means allocation error, value 2 too long a string
68 build_version_string(Info_Data
* idata
)
70 // since we use `goto' we have to initialize variables before the jumps
71 unsigned char* info_string
;
72 unsigned char* info_string_wide
;
83 d
= sdscatprintf(d
, TTFAUTOHINT_STRING
" (v%s)", VERSION
);
84 if (!idata
->detailed_info
)
92 d
= sdscatprintf(d
, " -l %d", idata
->hinting_range_min
);
93 d
= sdscatprintf(d
, " -r %d", idata
->hinting_range_max
);
94 d
= sdscatprintf(d
, " -G %d", idata
->hinting_limit
);
95 d
= sdscatprintf(d
, " -x %d", idata
->increase_x_height
);
96 if (idata
->fallback_stem_width
)
97 d
= sdscatprintf(d
, " -H %d", idata
->fallback_stem_width
);
98 d
= sdscatprintf(d
, " -D %s", idata
->default_script
);
99 d
= sdscatprintf(d
, " -f %s", idata
->fallback_script
);
100 if (idata
->control_name
)
102 char* bn
= base_name(idata
->control_name
);
103 d
= sdscatprintf(d
, " -m \"%s\"", bn
? bn
: idata
->control_name
);
112 if (idata
->gray_strong_stem_width
)
113 strong
[count
++] = 'g';
114 if (idata
->gdi_cleartype_strong_stem_width
)
115 strong
[count
++] = 'G';
116 if (idata
->dw_cleartype_strong_stem_width
)
117 strong
[count
++] = 'D';
119 d
= sdscatprintf(d
, " -w %s", strong
);
121 d
= sdscat(d
, " -w \"\"");
123 if (idata
->windows_compatibility
)
124 d
= sdscat(d
, " -W");
125 if (idata
->adjust_subglyphs
)
126 d
= sdscat(d
, " -p");
127 if (idata
->hint_composites
)
128 d
= sdscat(d
, " -c");
130 d
= sdscat(d
, " -s");
131 if (idata
->fallback_scaling
)
132 d
= sdscat(d
, " -S");
133 if (idata
->TTFA_info
)
134 d
= sdscat(d
, " -t");
136 if (idata
->x_height_snapping_exceptions_string
)
138 // only set specific value of `ret' for an allocation error,
139 // since syntax errors are handled in TTF_autohint
140 number_range
* x_height_snapping_exceptions
;
141 const char* pos
= number_set_parse(
142 idata
->x_height_snapping_exceptions_string
,
143 &x_height_snapping_exceptions
,
147 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
152 s
= number_set_show(x_height_snapping_exceptions
, 6, 0x7FFF);
153 number_set_free(x_height_snapping_exceptions
);
155 // ensure UTF16-BE version doesn't get too long
156 if (strlen(s
) > 0xFFFF / 2 - sdslen(d
))
162 d
= sdscatprintf(d
, " -X \"%s\"", s
);
172 info_string
= (unsigned char*)malloc(sdslen(d
) + 1);
178 memcpy(info_string
, d
, sdslen(d
) + 1);
180 idata
->info_string
= info_string
;
181 idata
->info_string_len
= (unsigned short)sdslen(d
);
183 // prepare UTF16-BE version data
184 idata
->info_string_wide_len
= 2 * idata
->info_string_len
;
185 info_string_wide
= (unsigned char*)realloc(idata
->info_string_wide
,
186 idata
->info_string_wide_len
);
187 if (!info_string_wide
)
192 idata
->info_string_wide
= info_string_wide
;
194 dt
= idata
->info_string
;
195 dtw
= idata
->info_string_wide
;
196 for (unsigned short i
= 0; i
< idata
->info_string_len
; i
++)
209 free(idata
->info_string
);
210 free(idata
->info_string_wide
);
212 idata
->info_string
= NULL
;
213 idata
->info_string_wide
= NULL
;
214 idata
->info_string_len
= 0;
215 idata
->info_string_wide_len
= 0;
222 info_name_id_5(unsigned short platform_id
,
223 unsigned short encoding_id
,
228 unsigned char ttfautohint_string
[] = TTFAUTOHINT_STRING
;
229 unsigned char ttfautohint_string_wide
[] = TTFAUTOHINT_STRING_WIDE
;
231 // we use memmem, so don't count the trailing \0 character
232 size_t ttfautohint_string_len
= sizeof (TTFAUTOHINT_STRING
) - 1;
233 size_t ttfautohint_string_wide_len
= sizeof (TTFAUTOHINT_STRING_WIDE
) - 1;
236 unsigned short v_len
;
242 || (platform_id
== 3 && !(encoding_id
== 1
243 || encoding_id
== 10)))
245 // one-byte or multi-byte encodings
246 v
= idata
->info_string
;
247 v_len
= idata
->info_string_len
;
248 s
= ttfautohint_string
;
249 s_len
= ttfautohint_string_len
;
254 // (two-byte) UTF-16BE for everything else
255 v
= idata
->info_string_wide
;
256 v_len
= idata
->info_string_wide_len
;
257 s
= ttfautohint_string_wide
;
258 s_len
= ttfautohint_string_wide_len
;
262 // if we already have an ttfautohint info string,
263 // remove it up to a following `;' character (or end of string)
264 unsigned char* s_start
= (unsigned char*)memmem(*str
, *len
, s
, s_len
);
267 unsigned char* s_end
= s_start
+ offset
;
268 unsigned char* limit
= *str
+ *len
;
270 while (s_end
< limit
)
278 if (*(s_end
- 1) == '\0') // UTF-16BE
289 while (s_end
< limit
)
290 *s_start
++ = *s_end
++;
292 *len
-= s_end
- s_start
;
295 // do nothing if the string would become too long
296 if (*len
> 0xFFFF - v_len
)
299 unsigned short len_new
= *len
+ v_len
;
300 unsigned char* str_new
= (unsigned char*)realloc(*str
, len_new
);
305 memcpy(*str
+ *len
, v
, v_len
);
312 // a structure to collect family data for a given
313 // (platform_id, encoding_id, language_id) triplet
315 typedef struct Family_
317 unsigned short platform_id
;
318 unsigned short encoding_id
;
319 unsigned short language_id
;
321 unsigned short* name_id_1_len
;
322 unsigned char** name_id_1_str
;
323 unsigned short* name_id_4_len
;
324 unsigned char** name_id_4_str
;
325 unsigned short* name_id_6_len
;
326 unsigned char** name_id_6_str
;
327 unsigned short* name_id_16_len
;
328 unsigned char** name_id_16_str
;
329 unsigned short* name_id_21_len
;
330 unsigned char** name_id_21_str
;
336 // node structure for collected family data
338 typedef struct Node Node
;
341 LLRB_ENTRY(Node
) entry
;
346 // comparison function for our red-black tree
354 // sort by platform ID ...
355 diff
= e1
->family
.platform_id
- e2
->family
.platform_id
;
359 // ... then by encoding ID ...
360 diff
= e1
->family
.encoding_id
- e2
->family
.encoding_id
;
364 // ... then by language ID
365 diff
= e1
->family
.language_id
- e2
->family
.language_id
;
368 // https://graphics.stanford.edu/~seander/bithacks.html#CopyIntegerSign
369 return (diff
> 0) - (diff
< 0);
373 // the red-black tree function body
374 typedef struct family_data family_data
;
376 LLRB_HEAD(family_data
, Node
);
378 // no trailing semicolon in the next line
379 LLRB_GENERATE_STATIC(family_data
, Node
, entry
, nodecmp
)
383 family_data_free(Info_Data
* idata
)
385 family_data
* family_data_head
= (family_data
*)idata
->family_data_head
;
390 if (!family_data_head
)
393 for (node
= LLRB_MIN(family_data
, family_data_head
);
397 next_node
= LLRB_NEXT(family_data
, family_data_head
, node
);
398 LLRB_REMOVE(family_data
, family_data_head
, node
);
399 sdsfree(node
->family
.family_name
);
403 free(family_data_head
);
408 collect_family_data(unsigned short platform_id
,
409 unsigned short encoding_id
,
410 unsigned short language_id
,
411 unsigned short name_id
,
416 family_data
* family_data_head
= (family_data
*)idata
->family_data_head
;
420 if (!family_data_head
)
422 // first-time initialization
423 family_data_head
= (family_data
*)malloc(sizeof (family_data
));
424 if (!family_data_head
)
427 LLRB_INIT(family_data_head
);
428 idata
->family_data_head
= family_data_head
;
431 node
= (Node
*)malloc(sizeof (Node
));
435 node
->family
.platform_id
= platform_id
;
436 node
->family
.encoding_id
= encoding_id
;
437 node
->family
.language_id
= language_id
;
439 val
= LLRB_INSERT(family_data
, family_data_head
, node
);
442 // we already have an entry in the tree for our triplet
448 // initialize remaining fields
449 node
->family
.name_id_1_len
= NULL
;
450 node
->family
.name_id_1_str
= NULL
;
451 node
->family
.name_id_4_len
= NULL
;
452 node
->family
.name_id_4_str
= NULL
;
453 node
->family
.name_id_6_len
= NULL
;
454 node
->family
.name_id_6_str
= NULL
;
455 node
->family
.name_id_16_len
= NULL
;
456 node
->family
.name_id_16_str
= NULL
;
457 node
->family
.name_id_21_len
= NULL
;
458 node
->family
.name_id_21_str
= NULL
;
460 node
->family
.family_name
= NULL
;
465 node
->family
.name_id_1_len
= len
;
466 node
->family
.name_id_1_str
= str
;
468 else if (name_id
== 4)
470 node
->family
.name_id_4_len
= len
;
471 node
->family
.name_id_4_str
= str
;
473 else if (name_id
== 6)
475 node
->family
.name_id_6_len
= len
;
476 node
->family
.name_id_6_str
= str
;
478 else if (name_id
== 16)
480 node
->family
.name_id_16_len
= len
;
481 node
->family
.name_id_16_str
= str
;
483 else if (name_id
== 21)
485 node
->family
.name_id_21_len
= len
;
486 node
->family
.name_id_21_str
= str
;
493 // `info-callback' function
496 info(unsigned short platform_id
,
497 unsigned short encoding_id
,
498 unsigned short language_id
,
499 unsigned short name_id
,
504 Info_Data
* idata
= (Info_Data
*)user
;
506 // if ID is a version string, append our data
507 if (!idata
->no_info
&& name_id
== 5)
508 return info_name_id_5(platform_id
, encoding_id
, len
, str
, idata
);
510 // if ID is related to a family name, collect the data
511 if (*idata
->family_suffix
517 return collect_family_data(platform_id
,
529 // Insert `suffix' to `str', right after substring `name'.
530 // If `name' isn't a substring of `str', append `suffix' to `str'.
531 // Do nothing in case of allocation error or if resulting string is too long.
534 insert_suffix(sds suffix
,
539 if (!len
|| !*len
|| !str
|| !*str
)
544 // check whether `name' is a substring of `str'
545 unsigned char* s_start
= (unsigned char*)memmem(*str
, *len
,
548 // construct new string
551 size_t substring_end
= size_t(s_start
- *str
) + sdslen(name
);
553 // everything up to the end of the substring
554 s
= sdscatlen(s
, *str
, substring_end
);
556 s
= sdscatsds(s
, suffix
);
558 s
= sdscatlen(s
, *str
+ substring_end
, *len
- substring_end
);
562 s
= sdscatlen(s
, *str
, *len
);
563 s
= sdscatsds(s
, suffix
);
569 if (sdslen(s
) <= 0xFFFF)
571 unsigned short len_new
= (unsigned short)sdslen(s
);
572 unsigned char* str_new
= (unsigned char*)realloc(*str
, len_new
);
576 memcpy(*str
, s
, len_new
);
585 // `info-post-callback' function
588 info_post(void* user
)
590 Info_Data
* idata
= (Info_Data
*)user
;
591 family_data
* family_data_head
= (family_data
*)idata
->family_data_head
;
594 // family_suffix + family_suffix_wide
596 sds family_suffix
= sdsnew(idata
->family_suffix
);
597 size_t family_suffix_len
= sdslen(family_suffix
);
599 sds family_suffix_wide
= sdsempty();
600 size_t family_suffix_wide_len
= 2 * family_suffix_len
;
602 // create sds with given size but uninitialized string data
603 family_suffix_wide
= sdsMakeRoomFor(family_suffix_wide
,
604 family_suffix_wide_len
);
608 // construct `family_suffix_wide' by inserting '\0'
610 char *fsw
= family_suffix_wide
;
611 for (size_t i
= 0; i
< family_suffix_len
; i
++)
616 sdsIncrLen(family_suffix_wide
, (int)family_suffix_wide_len
);
619 // family_ps_suffix + family_ps_suffix_wide
621 sds family_ps_suffix
= sdsempty();
623 // create sds with estimated size but uninitialized string data;
624 // we later set the size to the actual value
625 family_ps_suffix
= sdsMakeRoomFor(family_ps_suffix
,
628 // construct `family_ps_suffix' by removing all space characters
630 char *fps
= family_ps_suffix
;
631 for (size_t i
= 0; i
< family_suffix_len
; i
++)
638 sdsIncrLen(family_ps_suffix
, fps
- family_ps_suffix
);
640 size_t family_ps_suffix_len
= sdslen(family_ps_suffix
);
642 sds family_ps_suffix_wide
= sdsempty();
643 size_t family_ps_suffix_wide_len
= 2 * family_ps_suffix_len
;
645 // create sds with given size but uninitialized string data
646 family_ps_suffix_wide
= sdsMakeRoomFor(family_ps_suffix_wide
,
647 family_ps_suffix_wide_len
);
649 // construct `family_ps_suffix_wide' by inserting '\0'
650 fps
= family_ps_suffix
;
651 char* fpsw
= family_ps_suffix_wide
;
652 for (size_t i
= 0; i
< family_ps_suffix_len
; i
++)
655 *(fpsw
++) = *(fps
++);
657 sdsIncrLen(family_ps_suffix_wide
, (int)family_ps_suffix_wide_len
);
659 // We try the following algorithm.
661 // 1. If we have a `Preferred Family' (ID 16), use it as the family name,
662 // otherwise use the `Font Family Name' (ID 1). If necessary, search
663 // other language IDs for the current (platform ID, encoding ID) pair
664 // to find a family name.
666 // 2. Append the family suffix to the family substring in the `Font Family
667 // Name' (ID 1), the `Full Font Name' (ID 4), the `Preferred Family'
668 // (ID 16), and the `WWS Family Name' (ID 21). In case the family name
669 // found in step 1 is not a substring, append the suffix to the whole
672 // 3. Remove spaces from the family name and locate this substring in the
673 // `PostScript Name' (ID 6), then append the family suffix, also with
674 // spaces removed. If we don't have a substring, append the stripped
675 // suffix to the whole string.
677 // determine family name for all triplets if available
678 for (Node
* node
= LLRB_MIN(family_data
, family_data_head
);
680 node
= LLRB_NEXT(family_data
, family_data_head
, node
))
682 Family
* family
= &node
->family
;
684 if (family
->name_id_16_len
&& *family
->name_id_16_len
685 && family
->name_id_16_str
&& *family
->name_id_16_str
)
686 family
->family_name
= sdsnewlen(*family
->name_id_16_str
,
687 *family
->name_id_16_len
);
688 else if (family
->name_id_1_len
&& *family
->name_id_1_len
689 && family
->name_id_1_str
&& *family
->name_id_1_str
)
690 family
->family_name
= sdsnewlen(*family
->name_id_1_str
,
691 *family
->name_id_1_len
);
694 sds family_name
= sdsempty();
695 sds family_ps_name
= sdsempty();
697 // process all name ID strings in triplets
698 for (Node
* node
= LLRB_MIN(family_data
, family_data_head
);
700 node
= LLRB_NEXT(family_data
, family_data_head
, node
))
702 Family family
= node
->family
;
705 sdsclear(family_name
);
706 sdsclear(family_ps_name
);
708 if (family
.family_name
)
709 family_name
= sdscatsds(family_name
, family
.family_name
);
714 // use family name from a triplet that actually has one
715 for (n
= LLRB_MIN(family_data
, family_data_head
);
717 n
= LLRB_NEXT(family_data
, family_data_head
, n
))
719 Family f
= n
->family
;
721 if (f
.platform_id
== family
.platform_id
722 && f
.encoding_id
== family
.encoding_id
725 family_name
= sdscatsds(family_name
, f
.family_name
);
731 continue; // no valid family name found
734 if (family
.platform_id
== 1
735 || (family
.platform_id
== 3 && !(family
.encoding_id
== 1
736 || family
.encoding_id
== 10)))
737 is_wide
= false; // one-byte or multi-byte encodings
739 is_wide
= true; // (two-byte) UTF-16BE
741 sds suffix
= is_wide
? family_suffix_wide
: family_suffix
;
742 insert_suffix(suffix
,
744 family
.name_id_1_len
,
745 family
.name_id_1_str
);
746 insert_suffix(suffix
,
748 family
.name_id_4_len
,
749 family
.name_id_4_str
);
750 insert_suffix(suffix
,
752 family
.name_id_16_len
,
753 family
.name_id_16_str
);
754 insert_suffix(suffix
,
756 family
.name_id_21_len
,
757 family
.name_id_21_str
);
759 size_t family_name_len
= sdslen(family_name
);
761 family_name_len
&= ~1U; // ensure even value for the loop below
763 // set sds to estimated size;
764 // we later set the size to the actual value
765 family_ps_name
= sdsMakeRoomFor(family_ps_name
,
768 // construct `family_ps_name' by removing all space characters
769 char *fn
= family_name
;
770 char *fpn
= family_ps_name
;
773 for (size_t i
= 0; i
< family_name_len
; i
+= 2)
777 if (!(c1
== '\0' && c2
== ' '))
786 for (size_t i
= 0; i
< family_name_len
; i
++)
794 sdsIncrLen(family_ps_name
, fpn
- family_ps_name
);
796 sds ps_suffix
= is_wide
? family_ps_suffix_wide
: family_ps_suffix
;
797 insert_suffix(ps_suffix
,
799 family
.name_id_6_len
,
800 family
.name_id_6_str
);
803 sdsfree(family_suffix
);
804 sdsfree(family_suffix_wide
);
805 sdsfree(family_ps_suffix
);
806 sdsfree(family_ps_suffix_wide
);
807 sdsfree(family_name
);
808 sdsfree(family_ps_name
);
810 family_data_free(idata
);