3 // Copyright (C) 2012-2014 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 // build string that gets appended to the `Version' field(s)
34 // return value 1 means allocation error, value 2 too long a string
36 build_version_string(Info_Data
* idata
)
38 // since we use `goto' we have to initialize variables before the jumps
39 unsigned char* info_string
;
40 unsigned char* info_string_wide
;
51 d
= sdscatprintf(d
, TTFAUTOHINT_STRING
" (v%s)", VERSION
);
60 d
= sdscatprintf(d
, " -l %d", idata
->hinting_range_min
);
61 d
= sdscatprintf(d
, " -r %d", idata
->hinting_range_max
);
62 d
= sdscatprintf(d
, " -G %d", idata
->hinting_limit
);
63 d
= sdscatprintf(d
, " -x %d", idata
->increase_x_height
);
64 if (idata
->fallback_stem_width
)
65 d
= sdscatprintf(d
, " -H %d", idata
->fallback_stem_width
);
66 d
= sdscatprintf(d
, " -D %s", idata
->default_script
);
67 d
= sdscatprintf(d
, " -f %s", idata
->fallback_script
);
68 if (idata
->control_name
)
70 char* bn
= base_name(idata
->control_name
);
71 d
= sdscatprintf(d
, " -m \"%s\"", bn
? bn
: idata
->control_name
);
80 if (idata
->gray_strong_stem_width
)
81 strong
[count
++] = 'g';
82 if (idata
->gdi_cleartype_strong_stem_width
)
83 strong
[count
++] = 'G';
84 if (idata
->dw_cleartype_strong_stem_width
)
85 strong
[count
++] = 'D';
87 d
= sdscatprintf(d
, " -w %s", strong
);
89 d
= sdscat(d
, " -w \"\"");
91 if (idata
->windows_compatibility
)
93 if (idata
->adjust_subglyphs
)
95 if (idata
->hint_composites
)
100 d
= sdscat(d
, " -t");
102 if (idata
->x_height_snapping_exceptions_string
)
104 // only set specific value of `ret' for an allocation error,
105 // since syntax errors are handled in TTF_autohint
106 number_range
* x_height_snapping_exceptions
;
107 const char* pos
= number_set_parse(
108 idata
->x_height_snapping_exceptions_string
,
109 &x_height_snapping_exceptions
,
113 if (x_height_snapping_exceptions
== NUMBERSET_ALLOCATION_ERROR
)
118 s
= number_set_show(x_height_snapping_exceptions
, 6, 0x7FFF);
119 number_set_free(x_height_snapping_exceptions
);
121 // ensure UTF16-BE version doesn't get too long
122 if (strlen(s
) > 0xFFFF / 2 - sdslen(d
))
128 d
= sdscatprintf(d
, " -X \"%s\"", s
);
138 info_string
= (unsigned char*)malloc(sdslen(d
) + 1);
144 memcpy(info_string
, d
, sdslen(d
) + 1);
146 idata
->info_string
= info_string
;
147 idata
->info_string_len
= (unsigned short)sdslen(d
);
149 // prepare UTF16-BE version data
150 idata
->info_string_wide_len
= 2 * idata
->info_string_len
;
151 info_string_wide
= (unsigned char*)realloc(idata
->info_string_wide
,
152 idata
->info_string_wide_len
);
153 if (!info_string_wide
)
158 idata
->info_string_wide
= info_string_wide
;
160 dt
= idata
->info_string
;
161 dtw
= idata
->info_string_wide
;
162 for (unsigned short i
= 0; i
< idata
->info_string_len
; i
++)
175 free(idata
->info_string
);
176 free(idata
->info_string_wide
);
178 idata
->info_string
= NULL
;
179 idata
->info_string_wide
= NULL
;
180 idata
->info_string_len
= 0;
181 idata
->info_string_wide_len
= 0;
188 info_name_id_5(unsigned short platform_id
,
189 unsigned short encoding_id
,
194 unsigned char ttfautohint_string
[] = TTFAUTOHINT_STRING
;
195 unsigned char ttfautohint_string_wide
[] = TTFAUTOHINT_STRING_WIDE
;
197 // we use memmem, so don't count the trailing \0 character
198 size_t ttfautohint_string_len
= sizeof (TTFAUTOHINT_STRING
) - 1;
199 size_t ttfautohint_string_wide_len
= sizeof (TTFAUTOHINT_STRING_WIDE
) - 1;
202 unsigned short v_len
;
208 || (platform_id
== 3 && !(encoding_id
== 1
209 || encoding_id
== 10)))
211 // one-byte or multi-byte encodings
212 v
= idata
->info_string
;
213 v_len
= idata
->info_string_len
;
214 s
= ttfautohint_string
;
215 s_len
= ttfautohint_string_len
;
220 // (two-byte) UTF-16BE for everything else
221 v
= idata
->info_string_wide
;
222 v_len
= idata
->info_string_wide_len
;
223 s
= ttfautohint_string_wide
;
224 s_len
= ttfautohint_string_wide_len
;
228 // if we already have an ttfautohint info string,
229 // remove it up to a following `;' character (or end of string)
230 unsigned char* s_start
= (unsigned char*)memmem(*str
, *len
, s
, s_len
);
233 unsigned char* s_end
= s_start
+ offset
;
234 unsigned char* limit
= *str
+ *len
;
236 while (s_end
< limit
)
244 if (*(s_end
- 1) == '\0') // UTF-16BE
255 while (s_end
< limit
)
256 *s_start
++ = *s_end
++;
258 *len
-= s_end
- s_start
;
261 // do nothing if the string would become too long
262 if (*len
> 0xFFFF - v_len
)
265 unsigned short len_new
= *len
+ v_len
;
266 unsigned char* str_new
= (unsigned char*)realloc(*str
, len_new
);
271 memcpy(*str
+ *len
, v
, v_len
);
279 info(unsigned short platform_id
,
280 unsigned short encoding_id
,
281 unsigned short /* language_id */,
282 unsigned short name_id
,
287 Info_Data
* idata
= (Info_Data
*)user
;
289 // if it is a version string, append our data
291 return info_name_id_5(platform_id
, encoding_id
, len
, str
, idata
);