s/--components/--composites/, s/hint-with-components/hint-composites/.
[ttfautohint.git] / frontend / info.cpp
blob30eec8b33a6d0566cf3f8ce27e131e16df5714bf
1 // info.cpp
3 // Copyright (C) 2012-2013 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"
22 #define TTFAUTOHINT_STRING "; ttfautohint"
23 #define TTFAUTOHINT_STRING_WIDE "\0;\0 \0t\0t\0f\0a\0u\0t\0o\0h\0i\0n\0t"
25 // build string which gets appended to the `Version' field(s)
27 extern "C" {
29 // return value 1 means allocation error, value 2 too long a string
31 int
32 build_version_string(Info_Data* idata)
34 char* d;
35 char* dw;
36 char* s = NULL;
37 size_t s_len;
38 unsigned char* data_new;
39 unsigned short data_new_len;
40 char strong[4];
41 int count;
42 int ret = 0;
44 // 128 bytes certainly hold the following options except -X
45 data_new = (unsigned char*)realloc(idata->data, 128);
46 if (!data_new)
48 ret = 1;
49 goto Fail;
51 idata->data = data_new;
53 d = (char*)idata->data;
54 d += sprintf(d, TTFAUTOHINT_STRING " (v%s)", VERSION);
56 if (idata->dehint)
58 d += sprintf(d, " -d");
59 goto Dehint_only;
62 d += sprintf(d, " -l %d", idata->hinting_range_min);
63 d += sprintf(d, " -r %d", idata->hinting_range_max);
64 d += sprintf(d, " -G %d", idata->hinting_limit);
65 d += sprintf(d, " -x %d", idata->increase_x_height);
67 count = 0;
68 strong[0] = '\0';
69 strong[1] = '\0';
70 strong[2] = '\0';
71 strong[3] = '\0';
72 if (idata->gray_strong_stem_width)
73 strong[count++] = 'g';
74 if (idata->gdi_cleartype_strong_stem_width)
75 strong[count++] = 'G';
76 if (idata->dw_cleartype_strong_stem_width)
77 strong[count++] = 'D';
78 d += sprintf(d, " -w \"%s\"", strong);
80 if (idata->windows_compatibility)
81 d += sprintf(d, " -W");
82 if (idata->pre_hinting)
83 d += sprintf(d, " -p");
84 if (!idata->hint_composites)
85 d += sprintf(d, " -c");
86 if (idata->latin_fallback)
87 d += sprintf(d, " -f");
88 if (idata->symbol)
89 d += sprintf(d, " -s");
90 if (idata->x_height_snapping_exceptions)
91 d += sprintf(d, " -X \"\""); // fill in data later
93 Dehint_only:
94 idata->data_len = d - (char*)idata->data;
96 if (idata->x_height_snapping_exceptions)
98 s = number_set_show(idata->x_height_snapping_exceptions, 6, 0x7FFF);
99 if (!s)
101 ret = 1;
102 goto Fail;
105 // ensure UTF16-BE version doesn't get too long
106 s_len = strlen(s);
107 if (s_len > 0xFFFF / 2 - 128)
109 ret = 2;
110 goto Fail;
113 else
114 s_len = 0;
116 // we now reallocate to the real size
117 // (plus one byte so that `sprintf' works)
118 data_new_len = idata->data_len + s_len;
119 data_new = (unsigned char*)realloc(idata->data, data_new_len + 1);
120 if (!data_new)
122 ret = 1;
123 goto Fail;
126 if (idata->x_height_snapping_exceptions)
128 // overwrite second doublequote and append it instead
129 d = (char*)(data_new + idata->data_len - 1);
130 sprintf(d, "%s\"", s);
133 idata->data = data_new;
134 idata->data_len = data_new_len;
136 // prepare UTF16-BE version data
137 idata->data_wide_len = 2 * idata->data_len;
138 data_new = (unsigned char*)realloc(idata->data_wide,
139 idata->data_wide_len);
140 if (!data_new)
142 ret = 1;
143 goto Fail;
145 idata->data_wide = data_new;
147 d = (char*)idata->data;
148 dw = (char*)idata->data_wide;
149 for (unsigned short i = 0; i < idata->data_len; i++)
151 *(dw++) = '\0';
152 *(dw++) = *(d++);
155 Exit:
156 free(s);
158 return ret;
160 Fail:
161 free(idata->data);
162 free(idata->data_wide);
164 idata->data = NULL;
165 idata->data_wide = NULL;
166 idata->data_len = 0;
167 idata->data_wide_len = 0;
169 goto Exit;
174 info(unsigned short platform_id,
175 unsigned short encoding_id,
176 unsigned short /* language_id */,
177 unsigned short name_id,
178 unsigned short* len,
179 unsigned char** str,
180 void* user)
182 Info_Data* idata = (Info_Data*)user;
183 unsigned char ttfautohint_string[] = TTFAUTOHINT_STRING;
184 unsigned char ttfautohint_string_wide[] = TTFAUTOHINT_STRING_WIDE;
186 // we use memmem, so don't count the trailing \0 character
187 size_t ttfautohint_string_len = sizeof (TTFAUTOHINT_STRING) - 1;
188 size_t ttfautohint_string_wide_len = sizeof (TTFAUTOHINT_STRING_WIDE) - 1;
190 unsigned char* v;
191 unsigned short v_len;
192 unsigned char* s;
193 size_t s_len;
194 size_t offset;
196 // if it is a version string, append our data
197 if (name_id != 5)
198 return 0;
200 if (platform_id == 1
201 || (platform_id == 3 && !(encoding_id == 1
202 || encoding_id == 10)))
204 // one-byte or multi-byte encodings
205 v = idata->data;
206 v_len = idata->data_len;
207 s = ttfautohint_string;
208 s_len = ttfautohint_string_len;
209 offset = 2;
211 else
213 // (two-byte) UTF-16BE for everything else
214 v = idata->data_wide;
215 v_len = idata->data_wide_len;
216 s = ttfautohint_string_wide;
217 s_len = ttfautohint_string_wide_len;
218 offset = 4;
221 // if we already have an ttfautohint info string,
222 // remove it up to a following `;' character (or end of string)
223 unsigned char* s_start = (unsigned char*)memmem(*str, *len, s, s_len);
224 if (s_start)
226 unsigned char* s_end = s_start + offset;
227 unsigned char* limit = *str + *len;
229 while (s_end < limit)
231 if (*s_end == ';')
233 if (offset == 2)
234 break;
235 else
237 if (*(s_end - 1) == '\0') // UTF-16BE
239 s_end--;
240 break;
245 s_end++;
248 while (s_end < limit)
249 *s_start++ = *s_end++;
251 *len -= s_end - s_start;
254 // do nothing if the string would become too long
255 if (*len > 0xFFFF - v_len)
256 return 0;
258 unsigned short len_new = *len + v_len;
259 unsigned char* str_new = (unsigned char*)realloc(*str, len_new);
260 if (!str_new)
261 return 1;
263 *str = str_new;
264 memcpy(*str + *len, v, v_len);
265 *len = len_new;
267 return 0;
270 } // extern "C"
272 // end of info.cpp