Minor.
[ttfautohint.git] / frontend / info.cpp
blob39400d86ff1357d3bbeaaedd5722e7bd593b557a
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 <numberset.h>
23 #define TTFAUTOHINT_STRING "; ttfautohint"
24 #define TTFAUTOHINT_STRING_WIDE "\0;\0 \0t\0t\0f\0a\0u\0t\0o\0h\0i\0n\0t"
26 // build string that gets appended to the `Version' field(s)
28 extern "C" {
30 // return value 1 means allocation error, value 2 too long a string
32 int
33 build_version_string(Info_Data* idata)
35 char* d;
36 char* dw;
37 char* s = NULL;
38 size_t s_len;
39 unsigned char* data_new;
40 unsigned short data_new_len;
41 char strong[4];
42 int count;
43 int ret = 0;
45 // 128 bytes certainly hold the following options except -X
46 data_new = (unsigned char*)realloc(idata->data, 128);
47 if (!data_new)
49 ret = 1;
50 goto Fail;
52 idata->data = data_new;
54 d = (char*)idata->data;
55 d += sprintf(d, TTFAUTOHINT_STRING " (v%s)", VERSION);
57 if (idata->dehint)
59 d += sprintf(d, " -d");
60 goto Dehint_only;
63 d += sprintf(d, " -l %d", idata->hinting_range_min);
64 d += sprintf(d, " -r %d", idata->hinting_range_max);
65 d += sprintf(d, " -G %d", idata->hinting_limit);
66 d += sprintf(d, " -x %d", idata->increase_x_height);
67 if (idata->fallback_stem_width)
68 d += sprintf(d, " -H %d", idata->fallback_stem_width);
69 d += sprintf(d, " -D %s", idata->default_script);
70 d += sprintf(d, " -f %s", idata->fallback_script);
72 count = 0;
73 strong[0] = '\0';
74 strong[1] = '\0';
75 strong[2] = '\0';
76 strong[3] = '\0';
77 if (idata->gray_strong_stem_width)
78 strong[count++] = 'g';
79 if (idata->gdi_cleartype_strong_stem_width)
80 strong[count++] = 'G';
81 if (idata->dw_cleartype_strong_stem_width)
82 strong[count++] = 'D';
83 if (*strong)
84 d += sprintf(d, " -w %s", strong);
85 else
86 d += sprintf(d, " -w \"\"");
88 if (idata->windows_compatibility)
89 d += sprintf(d, " -W");
90 if (idata->adjust_subglyphs)
91 d += sprintf(d, " -p");
92 if (idata->hint_composites)
93 d += sprintf(d, " -c");
94 if (idata->symbol)
95 d += sprintf(d, " -s");
96 if (idata->x_height_snapping_exceptions_string)
97 d += sprintf(d, " -X \"\""); // fill in data later
99 Dehint_only:
100 idata->data_len = d - (char*)idata->data;
102 if (idata->x_height_snapping_exceptions_string)
104 number_range* x_height_snapping_exceptions;
105 const char* pos;
107 // only set specific value of `ret' for an allocation error,
108 // since syntax errors are handled in TTF_autohint
109 pos = number_set_parse(idata->x_height_snapping_exceptions_string,
110 &x_height_snapping_exceptions,
111 6, 0x7FFF);
112 if (*pos)
114 if (x_height_snapping_exceptions == NUMBERSET_ALLOCATION_ERROR)
115 ret = 1;
116 goto Fail;
119 s = number_set_show(x_height_snapping_exceptions, 6, 0x7FFF);
120 number_set_free(x_height_snapping_exceptions);
122 if (!s)
124 ret = 1;
125 goto Fail;
128 // ensure UTF16-BE version doesn't get too long
129 s_len = strlen(s);
130 if (s_len > 0xFFFF / 2 - 128)
132 ret = 2;
133 goto Fail;
136 else
137 s_len = 0;
139 // we now reallocate to the real size
140 // (plus one byte so that `sprintf' works)
141 data_new_len = idata->data_len + s_len;
142 data_new = (unsigned char*)realloc(idata->data, data_new_len + 1);
143 if (!data_new)
145 ret = 1;
146 goto Fail;
149 if (idata->x_height_snapping_exceptions_string)
151 // overwrite second doublequote and append it instead
152 d = (char*)(data_new + idata->data_len - 1);
153 sprintf(d, "%s\"", s);
156 idata->data = data_new;
157 idata->data_len = data_new_len;
159 // prepare UTF16-BE version data
160 idata->data_wide_len = 2 * idata->data_len;
161 data_new = (unsigned char*)realloc(idata->data_wide,
162 idata->data_wide_len);
163 if (!data_new)
165 ret = 1;
166 goto Fail;
168 idata->data_wide = data_new;
170 d = (char*)idata->data;
171 dw = (char*)idata->data_wide;
172 for (unsigned short i = 0; i < idata->data_len; i++)
174 *(dw++) = '\0';
175 *(dw++) = *(d++);
178 Exit:
179 free(s);
181 return ret;
183 Fail:
184 free(idata->data);
185 free(idata->data_wide);
187 idata->data = NULL;
188 idata->data_wide = NULL;
189 idata->data_len = 0;
190 idata->data_wide_len = 0;
192 goto Exit;
197 info(unsigned short platform_id,
198 unsigned short encoding_id,
199 unsigned short /* language_id */,
200 unsigned short name_id,
201 unsigned short* len,
202 unsigned char** str,
203 void* user)
205 Info_Data* idata = (Info_Data*)user;
206 unsigned char ttfautohint_string[] = TTFAUTOHINT_STRING;
207 unsigned char ttfautohint_string_wide[] = TTFAUTOHINT_STRING_WIDE;
209 // we use memmem, so don't count the trailing \0 character
210 size_t ttfautohint_string_len = sizeof (TTFAUTOHINT_STRING) - 1;
211 size_t ttfautohint_string_wide_len = sizeof (TTFAUTOHINT_STRING_WIDE) - 1;
213 unsigned char* v;
214 unsigned short v_len;
215 unsigned char* s;
216 size_t s_len;
217 size_t offset;
219 // if it is a version string, append our data
220 if (name_id != 5)
221 return 0;
223 if (platform_id == 1
224 || (platform_id == 3 && !(encoding_id == 1
225 || encoding_id == 10)))
227 // one-byte or multi-byte encodings
228 v = idata->data;
229 v_len = idata->data_len;
230 s = ttfautohint_string;
231 s_len = ttfautohint_string_len;
232 offset = 2;
234 else
236 // (two-byte) UTF-16BE for everything else
237 v = idata->data_wide;
238 v_len = idata->data_wide_len;
239 s = ttfautohint_string_wide;
240 s_len = ttfautohint_string_wide_len;
241 offset = 4;
244 // if we already have an ttfautohint info string,
245 // remove it up to a following `;' character (or end of string)
246 unsigned char* s_start = (unsigned char*)memmem(*str, *len, s, s_len);
247 if (s_start)
249 unsigned char* s_end = s_start + offset;
250 unsigned char* limit = *str + *len;
252 while (s_end < limit)
254 if (*s_end == ';')
256 if (offset == 2)
257 break;
258 else
260 if (*(s_end - 1) == '\0') // UTF-16BE
262 s_end--;
263 break;
268 s_end++;
271 while (s_end < limit)
272 *s_start++ = *s_end++;
274 *len -= s_end - s_start;
277 // do nothing if the string would become too long
278 if (*len > 0xFFFF - v_len)
279 return 0;
281 unsigned short len_new = *len + v_len;
282 unsigned char* str_new = (unsigned char*)realloc(*str, len_new);
283 if (!str_new)
284 return 1;
286 *str = str_new;
287 memcpy(*str + *len, v, v_len);
288 *len = len_new;
290 return 0;
293 } // extern "C"
295 // end of info.cpp