Synchronize with FreeType.
[ttfautohint.git] / frontend / info.cpp
blob0099674e6ac26e027ff0a3258fdd09e1ea509a81
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, " -D %s", idata->default_script);
67 d += sprintf(d, " -f %s", idata->fallback_script);
69 count = 0;
70 strong[0] = '\0';
71 strong[1] = '\0';
72 strong[2] = '\0';
73 strong[3] = '\0';
74 if (idata->gray_strong_stem_width)
75 strong[count++] = 'g';
76 if (idata->gdi_cleartype_strong_stem_width)
77 strong[count++] = 'G';
78 if (idata->dw_cleartype_strong_stem_width)
79 strong[count++] = 'D';
80 if (*strong)
81 d += sprintf(d, " -w %s", strong);
82 else
83 d += sprintf(d, " -w \"\"");
85 if (idata->windows_compatibility)
86 d += sprintf(d, " -W");
87 if (idata->pre_hinting)
88 d += sprintf(d, " -p");
89 if (idata->hint_composites)
90 d += sprintf(d, " -c");
91 if (idata->symbol)
92 d += sprintf(d, " -s");
93 if (idata->x_height_snapping_exceptions)
94 d += sprintf(d, " -X \"\""); // fill in data later
96 Dehint_only:
97 idata->data_len = d - (char*)idata->data;
99 if (idata->x_height_snapping_exceptions)
101 s = number_set_show(idata->x_height_snapping_exceptions, 6, 0x7FFF);
102 if (!s)
104 ret = 1;
105 goto Fail;
108 // ensure UTF16-BE version doesn't get too long
109 s_len = strlen(s);
110 if (s_len > 0xFFFF / 2 - 128)
112 ret = 2;
113 goto Fail;
116 else
117 s_len = 0;
119 // we now reallocate to the real size
120 // (plus one byte so that `sprintf' works)
121 data_new_len = idata->data_len + s_len;
122 data_new = (unsigned char*)realloc(idata->data, data_new_len + 1);
123 if (!data_new)
125 ret = 1;
126 goto Fail;
129 if (idata->x_height_snapping_exceptions)
131 // overwrite second doublequote and append it instead
132 d = (char*)(data_new + idata->data_len - 1);
133 sprintf(d, "%s\"", s);
136 idata->data = data_new;
137 idata->data_len = data_new_len;
139 // prepare UTF16-BE version data
140 idata->data_wide_len = 2 * idata->data_len;
141 data_new = (unsigned char*)realloc(idata->data_wide,
142 idata->data_wide_len);
143 if (!data_new)
145 ret = 1;
146 goto Fail;
148 idata->data_wide = data_new;
150 d = (char*)idata->data;
151 dw = (char*)idata->data_wide;
152 for (unsigned short i = 0; i < idata->data_len; i++)
154 *(dw++) = '\0';
155 *(dw++) = *(d++);
158 Exit:
159 free(s);
161 return ret;
163 Fail:
164 free(idata->data);
165 free(idata->data_wide);
167 idata->data = NULL;
168 idata->data_wide = NULL;
169 idata->data_len = 0;
170 idata->data_wide_len = 0;
172 goto Exit;
177 info(unsigned short platform_id,
178 unsigned short encoding_id,
179 unsigned short /* language_id */,
180 unsigned short name_id,
181 unsigned short* len,
182 unsigned char** str,
183 void* user)
185 Info_Data* idata = (Info_Data*)user;
186 unsigned char ttfautohint_string[] = TTFAUTOHINT_STRING;
187 unsigned char ttfautohint_string_wide[] = TTFAUTOHINT_STRING_WIDE;
189 // we use memmem, so don't count the trailing \0 character
190 size_t ttfautohint_string_len = sizeof (TTFAUTOHINT_STRING) - 1;
191 size_t ttfautohint_string_wide_len = sizeof (TTFAUTOHINT_STRING_WIDE) - 1;
193 unsigned char* v;
194 unsigned short v_len;
195 unsigned char* s;
196 size_t s_len;
197 size_t offset;
199 // if it is a version string, append our data
200 if (name_id != 5)
201 return 0;
203 if (platform_id == 1
204 || (platform_id == 3 && !(encoding_id == 1
205 || encoding_id == 10)))
207 // one-byte or multi-byte encodings
208 v = idata->data;
209 v_len = idata->data_len;
210 s = ttfautohint_string;
211 s_len = ttfautohint_string_len;
212 offset = 2;
214 else
216 // (two-byte) UTF-16BE for everything else
217 v = idata->data_wide;
218 v_len = idata->data_wide_len;
219 s = ttfautohint_string_wide;
220 s_len = ttfautohint_string_wide_len;
221 offset = 4;
224 // if we already have an ttfautohint info string,
225 // remove it up to a following `;' character (or end of string)
226 unsigned char* s_start = (unsigned char*)memmem(*str, *len, s, s_len);
227 if (s_start)
229 unsigned char* s_end = s_start + offset;
230 unsigned char* limit = *str + *len;
232 while (s_end < limit)
234 if (*s_end == ';')
236 if (offset == 2)
237 break;
238 else
240 if (*(s_end - 1) == '\0') // UTF-16BE
242 s_end--;
243 break;
248 s_end++;
251 while (s_end < limit)
252 *s_start++ = *s_end++;
254 *len -= s_end - s_start;
257 // do nothing if the string would become too long
258 if (*len > 0xFFFF - v_len)
259 return 0;
261 unsigned short len_new = *len + v_len;
262 unsigned char* str_new = (unsigned char*)realloc(*str, len_new);
263 if (!str_new)
264 return 1;
266 *str = str_new;
267 memcpy(*str + *len, v, v_len);
268 *len = len_new;
270 return 0;
273 } // extern "C"
275 // end of info.cpp