Add option `-t' / `--ttfa-info' to front-ends.
[ttfautohint.git] / frontend / info.cpp
blobe9f7a4f0dea6a9aa1056dd80a31d81781f3fefd6
1 // info.cpp
3 // Copyright (C) 2012-2014 by Werner Lemberg.
4 //
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.
9 //
10 // The file `COPYING' mentioned in the previous paragraph is distributed
11 // with the ttfautohint library.
14 #include <config.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
19 #include "info.h"
20 #include <sds.h>
21 #include <numberset.h>
24 #define TTFAUTOHINT_STRING "; ttfautohint"
25 #define TTFAUTOHINT_STRING_WIDE "\0;\0 \0t\0t\0f\0a\0u\0t\0o\0h\0i\0n\0t"
27 // build string that gets appended to the `Version' field(s)
29 extern "C" {
31 // return value 1 means allocation error, value 2 too long a string
33 int
34 build_version_string(Info_Data* idata)
36 // since we use `goto' we have to initialize variables before the jumps
37 unsigned char* data;
38 unsigned char* data_wide;
39 unsigned char* dt;
40 unsigned char* dtw;
41 char* s = NULL;
42 char strong[4];
43 int count;
44 int ret = 0;
45 sds d;
47 d = sdsempty();
49 d = sdscatprintf(d, TTFAUTOHINT_STRING " (v%s)", VERSION);
50 if (idata->dehint)
52 d = sdscat(d, " -d");
53 goto Dehint_only;
55 d = sdscatprintf(d, " -l %d", idata->hinting_range_min);
56 d = sdscatprintf(d, " -r %d", idata->hinting_range_max);
57 d = sdscatprintf(d, " -G %d", idata->hinting_limit);
58 d = sdscatprintf(d, " -x %d", idata->increase_x_height);
59 if (idata->fallback_stem_width)
60 d = sdscatprintf(d, " -H %d", idata->fallback_stem_width);
61 d = sdscatprintf(d, " -D %s", idata->default_script);
62 d = sdscatprintf(d, " -f %s", idata->fallback_script);
63 if (idata->deltas_name)
64 d = sdscatprintf(d, " -m \"%s\"", idata->deltas_name);
66 count = 0;
67 strong[0] = '\0';
68 strong[1] = '\0';
69 strong[2] = '\0';
70 strong[3] = '\0';
71 if (idata->gray_strong_stem_width)
72 strong[count++] = 'g';
73 if (idata->gdi_cleartype_strong_stem_width)
74 strong[count++] = 'G';
75 if (idata->dw_cleartype_strong_stem_width)
76 strong[count++] = 'D';
77 if (*strong)
78 d = sdscatprintf(d, " -w %s", strong);
79 else
80 d = sdscat(d, " -w \"\"");
82 if (idata->windows_compatibility)
83 d = sdscat(d, " -W");
84 if (idata->adjust_subglyphs)
85 d = sdscat(d, " -p");
86 if (idata->hint_composites)
87 d = sdscat(d, " -c");
88 if (idata->symbol)
89 d = sdscat(d, " -s");
90 if (idata->TTFA_info)
91 d = sdscat(d, " -t");
93 if (idata->x_height_snapping_exceptions_string)
95 // only set specific value of `ret' for an allocation error,
96 // since syntax errors are handled in TTF_autohint
97 number_range* x_height_snapping_exceptions;
98 const char* pos = number_set_parse(
99 idata->x_height_snapping_exceptions_string,
100 &x_height_snapping_exceptions,
101 6, 0x7FFF);
102 if (*pos)
104 if (x_height_snapping_exceptions == NUMBERSET_ALLOCATION_ERROR)
105 ret = 1;
106 goto Fail;
109 s = number_set_show(x_height_snapping_exceptions, 6, 0x7FFF);
110 number_set_free(x_height_snapping_exceptions);
112 // ensure UTF16-BE version doesn't get too long
113 if (strlen(s) > 0xFFFF / 2 - sdslen(d))
115 ret = 2;
116 goto Fail;
119 d = sdscatprintf(d, " -X \"%s\"", s);
122 Dehint_only:
123 if (!d)
125 ret = 1;
126 goto Fail;
129 data = (unsigned char*)malloc(sdslen(d) + 1);
130 if (!data)
132 ret = 1;
133 goto Fail;
135 memcpy(data, d, sdslen(d) + 1);
137 idata->data = data;
138 idata->data_len = (unsigned short)sdslen(d);
140 // prepare UTF16-BE version data
141 idata->data_wide_len = 2 * idata->data_len;
142 data_wide = (unsigned char*)realloc(idata->data_wide,
143 idata->data_wide_len);
144 if (!data_wide)
146 ret = 1;
147 goto Fail;
149 idata->data_wide = data_wide;
151 dt = idata->data;
152 dtw = idata->data_wide;
153 for (unsigned short i = 0; i < idata->data_len; i++)
155 *(dtw++) = '\0';
156 *(dtw++) = *(dt++);
159 Exit:
160 free(s);
161 sdsfree(d);
163 return ret;
165 Fail:
166 free(idata->data);
167 free(idata->data_wide);
169 idata->data = NULL;
170 idata->data_wide = NULL;
171 idata->data_len = 0;
172 idata->data_wide_len = 0;
174 goto Exit;
179 info(unsigned short platform_id,
180 unsigned short encoding_id,
181 unsigned short /* language_id */,
182 unsigned short name_id,
183 unsigned short* len,
184 unsigned char** str,
185 void* user)
187 Info_Data* idata = (Info_Data*)user;
188 unsigned char ttfautohint_string[] = TTFAUTOHINT_STRING;
189 unsigned char ttfautohint_string_wide[] = TTFAUTOHINT_STRING_WIDE;
191 // we use memmem, so don't count the trailing \0 character
192 size_t ttfautohint_string_len = sizeof (TTFAUTOHINT_STRING) - 1;
193 size_t ttfautohint_string_wide_len = sizeof (TTFAUTOHINT_STRING_WIDE) - 1;
195 unsigned char* v;
196 unsigned short v_len;
197 unsigned char* s;
198 size_t s_len;
199 size_t offset;
201 // if it is a version string, append our data
202 if (name_id != 5)
203 return 0;
205 if (platform_id == 1
206 || (platform_id == 3 && !(encoding_id == 1
207 || encoding_id == 10)))
209 // one-byte or multi-byte encodings
210 v = idata->data;
211 v_len = idata->data_len;
212 s = ttfautohint_string;
213 s_len = ttfautohint_string_len;
214 offset = 2;
216 else
218 // (two-byte) UTF-16BE for everything else
219 v = idata->data_wide;
220 v_len = idata->data_wide_len;
221 s = ttfautohint_string_wide;
222 s_len = ttfautohint_string_wide_len;
223 offset = 4;
226 // if we already have an ttfautohint info string,
227 // remove it up to a following `;' character (or end of string)
228 unsigned char* s_start = (unsigned char*)memmem(*str, *len, s, s_len);
229 if (s_start)
231 unsigned char* s_end = s_start + offset;
232 unsigned char* limit = *str + *len;
234 while (s_end < limit)
236 if (*s_end == ';')
238 if (offset == 2)
239 break;
240 else
242 if (*(s_end - 1) == '\0') // UTF-16BE
244 s_end--;
245 break;
250 s_end++;
253 while (s_end < limit)
254 *s_start++ = *s_end++;
256 *len -= s_end - s_start;
259 // do nothing if the string would become too long
260 if (*len > 0xFFFF - v_len)
261 return 0;
263 unsigned short len_new = *len + v_len;
264 unsigned char* str_new = (unsigned char*)realloc(*str, len_new);
265 if (!str_new)
266 return 1;
268 *str = str_new;
269 memcpy(*str + *len, v, v_len);
270 *len = len_new;
272 return 0;
275 } // extern "C"
277 // end of info.cpp