Update file `no-copyright' and run `update-copyright'.
[ttfautohint.git] / frontend / info.cpp
blobb82dac7213e2c86e90b89ec309e4e2914ea4e2f5
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"
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 that 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);
66 d += sprintf(d, " -f %s", idata->fallback_script);
68 count = 0;
69 strong[0] = '\0';
70 strong[1] = '\0';
71 strong[2] = '\0';
72 strong[3] = '\0';
73 if (idata->gray_strong_stem_width)
74 strong[count++] = 'g';
75 if (idata->gdi_cleartype_strong_stem_width)
76 strong[count++] = 'G';
77 if (idata->dw_cleartype_strong_stem_width)
78 strong[count++] = 'D';
79 if (*strong)
80 d += sprintf(d, " -w %s", strong);
81 else
82 d += sprintf(d, " -w \"\"");
84 if (idata->windows_compatibility)
85 d += sprintf(d, " -W");
86 if (idata->pre_hinting)
87 d += sprintf(d, " -p");
88 if (idata->hint_composites)
89 d += sprintf(d, " -c");
90 if (idata->symbol)
91 d += sprintf(d, " -s");
92 if (idata->x_height_snapping_exceptions)
93 d += sprintf(d, " -X \"\""); // fill in data later
95 Dehint_only:
96 idata->data_len = d - (char*)idata->data;
98 if (idata->x_height_snapping_exceptions)
100 s = number_set_show(idata->x_height_snapping_exceptions, 6, 0x7FFF);
101 if (!s)
103 ret = 1;
104 goto Fail;
107 // ensure UTF16-BE version doesn't get too long
108 s_len = strlen(s);
109 if (s_len > 0xFFFF / 2 - 128)
111 ret = 2;
112 goto Fail;
115 else
116 s_len = 0;
118 // we now reallocate to the real size
119 // (plus one byte so that `sprintf' works)
120 data_new_len = idata->data_len + s_len;
121 data_new = (unsigned char*)realloc(idata->data, data_new_len + 1);
122 if (!data_new)
124 ret = 1;
125 goto Fail;
128 if (idata->x_height_snapping_exceptions)
130 // overwrite second doublequote and append it instead
131 d = (char*)(data_new + idata->data_len - 1);
132 sprintf(d, "%s\"", s);
135 idata->data = data_new;
136 idata->data_len = data_new_len;
138 // prepare UTF16-BE version data
139 idata->data_wide_len = 2 * idata->data_len;
140 data_new = (unsigned char*)realloc(idata->data_wide,
141 idata->data_wide_len);
142 if (!data_new)
144 ret = 1;
145 goto Fail;
147 idata->data_wide = data_new;
149 d = (char*)idata->data;
150 dw = (char*)idata->data_wide;
151 for (unsigned short i = 0; i < idata->data_len; i++)
153 *(dw++) = '\0';
154 *(dw++) = *(d++);
157 Exit:
158 free(s);
160 return ret;
162 Fail:
163 free(idata->data);
164 free(idata->data_wide);
166 idata->data = NULL;
167 idata->data_wide = NULL;
168 idata->data_len = 0;
169 idata->data_wide_len = 0;
171 goto Exit;
176 info(unsigned short platform_id,
177 unsigned short encoding_id,
178 unsigned short /* language_id */,
179 unsigned short name_id,
180 unsigned short* len,
181 unsigned char** str,
182 void* user)
184 Info_Data* idata = (Info_Data*)user;
185 unsigned char ttfautohint_string[] = TTFAUTOHINT_STRING;
186 unsigned char ttfautohint_string_wide[] = TTFAUTOHINT_STRING_WIDE;
188 // we use memmem, so don't count the trailing \0 character
189 size_t ttfautohint_string_len = sizeof (TTFAUTOHINT_STRING) - 1;
190 size_t ttfautohint_string_wide_len = sizeof (TTFAUTOHINT_STRING_WIDE) - 1;
192 unsigned char* v;
193 unsigned short v_len;
194 unsigned char* s;
195 size_t s_len;
196 size_t offset;
198 // if it is a version string, append our data
199 if (name_id != 5)
200 return 0;
202 if (platform_id == 1
203 || (platform_id == 3 && !(encoding_id == 1
204 || encoding_id == 10)))
206 // one-byte or multi-byte encodings
207 v = idata->data;
208 v_len = idata->data_len;
209 s = ttfautohint_string;
210 s_len = ttfautohint_string_len;
211 offset = 2;
213 else
215 // (two-byte) UTF-16BE for everything else
216 v = idata->data_wide;
217 v_len = idata->data_wide_len;
218 s = ttfautohint_string_wide;
219 s_len = ttfautohint_string_wide_len;
220 offset = 4;
223 // if we already have an ttfautohint info string,
224 // remove it up to a following `;' character (or end of string)
225 unsigned char* s_start = (unsigned char*)memmem(*str, *len, s, s_len);
226 if (s_start)
228 unsigned char* s_end = s_start + offset;
229 unsigned char* limit = *str + *len;
231 while (s_end < limit)
233 if (*s_end == ';')
235 if (offset == 2)
236 break;
237 else
239 if (*(s_end - 1) == '\0') // UTF-16BE
241 s_end--;
242 break;
247 s_end++;
250 while (s_end < limit)
251 *s_start++ = *s_end++;
253 *len -= s_end - s_start;
256 // do nothing if the string would become too long
257 if (*len > 0xFFFF - v_len)
258 return 0;
260 unsigned short len_new = *len + v_len;
261 unsigned char* str_new = (unsigned char*)realloc(*str, len_new);
262 if (!str_new)
263 return 1;
265 *str = str_new;
266 memcpy(*str + *len, v, v_len);
267 *len = len_new;
269 return 0;
272 } // extern "C"
274 // end of info.cpp