Run `update-copyright'.
[ttfautohint.git] / frontend / info.cpp
blobc3fd04c29a85a94607440535b68e3d9fac8d1a0d
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 d += sprintf(d, " -l %d", idata->hinting_range_min);
57 d += sprintf(d, " -r %d", idata->hinting_range_max);
58 d += sprintf(d, " -G %d", idata->hinting_limit);
59 d += sprintf(d, " -x %d", idata->increase_x_height);
61 count = 0;
62 strong[0] = '\0';
63 strong[1] = '\0';
64 strong[2] = '\0';
65 strong[3] = '\0';
66 if (idata->gray_strong_stem_width)
67 strong[count++] = 'g';
68 if (idata->gdi_cleartype_strong_stem_width)
69 strong[count++] = 'G';
70 if (idata->dw_cleartype_strong_stem_width)
71 strong[count++] = 'D';
72 d += sprintf(d, " -w \"%s\"", strong);
74 if (idata->windows_compatibility)
75 d += sprintf(d, " -W");
76 if (idata->pre_hinting)
77 d += sprintf(d, " -p");
78 if (!idata->hint_with_components)
79 d += sprintf(d, " -c");
80 if (idata->latin_fallback)
81 d += sprintf(d, " -f");
82 if (idata->symbol)
83 d += sprintf(d, " -s");
84 if (idata->x_height_snapping_exceptions)
85 d += sprintf(d, " -X \"\""); // fill in data later
87 idata->data_len = d - (char*)idata->data;
89 if (idata->x_height_snapping_exceptions)
91 s = number_set_show(idata->x_height_snapping_exceptions, 6, 0x7FFF);
92 if (!s)
94 ret = 1;
95 goto Fail;
98 // ensure UTF16-BE version doesn't get too long
99 s_len = strlen(s);
100 if (s_len > 0xFFFF / 2 - 128)
102 ret = 2;
103 goto Fail;
106 else
107 s_len = 0;
109 // we now reallocate to the real size
110 // (plus one byte so that `sprintf' works)
111 data_new_len = idata->data_len + s_len;
112 data_new = (unsigned char*)realloc(idata->data, data_new_len + 1);
113 if (!data_new)
115 ret = 1;
116 goto Fail;
119 if (idata->x_height_snapping_exceptions)
121 // overwrite second doublequote and append it instead
122 d = (char*)(data_new + idata->data_len - 1);
123 sprintf(d, "%s\"", s);
126 idata->data = data_new;
127 idata->data_len = data_new_len;
129 // prepare UTF16-BE version data
130 idata->data_wide_len = 2 * idata->data_len;
131 data_new = (unsigned char*)realloc(idata->data_wide,
132 idata->data_wide_len);
133 if (!data_new)
135 ret = 1;
136 goto Fail;
138 idata->data_wide = data_new;
140 d = (char*)idata->data;
141 dw = (char*)idata->data_wide;
142 for (unsigned short i = 0; i < idata->data_len; i++)
144 *(dw++) = '\0';
145 *(dw++) = *(d++);
148 Exit:
149 free(s);
151 return ret;
153 Fail:
154 free(idata->data);
155 free(idata->data_wide);
157 idata->data = NULL;
158 idata->data_wide = NULL;
159 idata->data_len = 0;
160 idata->data_wide_len = 0;
162 goto Exit;
167 info(unsigned short platform_id,
168 unsigned short encoding_id,
169 unsigned short /* language_id */,
170 unsigned short name_id,
171 unsigned short* len,
172 unsigned char** str,
173 void* user)
175 Info_Data* idata = (Info_Data*)user;
176 unsigned char ttfautohint_string[] = TTFAUTOHINT_STRING;
177 unsigned char ttfautohint_string_wide[] = TTFAUTOHINT_STRING_WIDE;
179 // we use memmem, so don't count the trailing \0 character
180 size_t ttfautohint_string_len = sizeof (TTFAUTOHINT_STRING) - 1;
181 size_t ttfautohint_string_wide_len = sizeof (TTFAUTOHINT_STRING_WIDE) - 1;
183 unsigned char* v;
184 unsigned short v_len;
185 unsigned char* s;
186 size_t s_len;
187 size_t offset;
189 // if it is a version string, append our data
190 if (name_id != 5)
191 return 0;
193 if (platform_id == 1
194 || (platform_id == 3 && !(encoding_id == 1
195 || encoding_id == 10)))
197 // one-byte or multi-byte encodings
198 v = idata->data;
199 v_len = idata->data_len;
200 s = ttfautohint_string;
201 s_len = ttfautohint_string_len;
202 offset = 2;
204 else
206 // (two-byte) UTF-16BE for everything else
207 v = idata->data_wide;
208 v_len = idata->data_wide_len;
209 s = ttfautohint_string_wide;
210 s_len = ttfautohint_string_wide_len;
211 offset = 4;
214 // if we already have an ttfautohint info string,
215 // remove it up to a following `;' character (or end of string)
216 unsigned char* s_start = (unsigned char*)memmem(*str, *len, s, s_len);
217 if (s_start)
219 unsigned char* s_end = s_start + offset;
220 unsigned char* limit = *str + *len;
222 while (s_end < limit)
224 if (*s_end == ';')
226 if (offset == 2)
227 break;
228 else
230 if (*(s_end - 1) == '\0') // UTF-16BE
232 s_end--;
233 break;
238 s_end++;
241 while (s_end < limit)
242 *s_start++ = *s_end++;
244 *len -= s_end - s_start;
247 // do nothing if the string would become too long
248 if (*len > 0xFFFF - v_len)
249 return 0;
251 unsigned short len_new = *len + v_len;
252 unsigned char* str_new = (unsigned char*)realloc(*str, len_new);
253 if (!str_new)
254 return 1;
256 *str = str_new;
257 memcpy(*str + *len, v, v_len);
258 *len = len_new;
260 return 0;
263 } // extern "C"
265 // end of info.cpp