/src/ghostpdl/base/write_t1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | /* |
17 | | Functions to serialize a type 1 font as PostScript code that can then be |
18 | | passed to FreeType via the FAPI FreeType bridge. |
19 | | Started by Graham Asher, 26th July 2002. |
20 | | */ |
21 | | |
22 | | #include <stdio.h> |
23 | | #include "wrfont.h" |
24 | | #include "write_t1.h" |
25 | | |
26 | | /* |
27 | | Public structures and functions in this file are prefixed with FF_ because they are part of |
28 | | the FAPI FreeType implementation. |
29 | | */ |
30 | | |
31 | | static int |
32 | | write_word_entry(gs_fapi_font * a_fapi_font, WRF_output * a_output, |
33 | | const char *a_name, int a_index, int a_divisor) |
34 | 321k | { |
35 | 321k | short x; |
36 | 321k | int code; |
37 | | |
38 | 321k | WRF_wbyte(a_fapi_font->memory, a_output, '/'); |
39 | 321k | WRF_wstring(a_fapi_font->memory, a_output, a_name); |
40 | 321k | WRF_wbyte(a_fapi_font->memory, a_output, ' '); |
41 | | |
42 | | /* Get the value and convert it from unsigned to signed by assigning it to a short. */ |
43 | 321k | code = a_fapi_font->get_word(a_fapi_font, a_index, 0, (unsigned short *)&x); |
44 | 321k | if (code < 0) |
45 | 0 | return code; |
46 | | |
47 | | /* Divide by the divisor to bring it back to font units. */ |
48 | 321k | x = (short)(x / a_divisor); |
49 | 321k | WRF_wint(a_fapi_font->memory, a_output, x); |
50 | 321k | WRF_wstring(a_fapi_font->memory, a_output, " def\n"); |
51 | | |
52 | 321k | return 0; |
53 | 321k | } |
54 | | |
55 | | static int |
56 | | write_array_entry_with_count(gs_fapi_font * a_fapi_font, |
57 | | WRF_output * a_output, const char *a_name, |
58 | | int a_index, int a_count, int a_divisor) |
59 | 856k | { |
60 | 856k | int i, code;; |
61 | | |
62 | 856k | if (a_count <= 0) |
63 | 323k | return 0; |
64 | | |
65 | 532k | WRF_wbyte(a_fapi_font->memory, a_output, '/'); |
66 | 532k | WRF_wstring(a_fapi_font->memory, a_output, a_name); |
67 | 532k | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
68 | 3.77M | for (i = 0; i < a_count; i++) { |
69 | | /* Get the value and convert it from unsigned to signed by assigning it to a short. */ |
70 | 3.24M | short x; |
71 | 3.24M | code = a_fapi_font->get_word(a_fapi_font, a_index, i, (unsigned short *)&x); |
72 | 3.24M | if (code < 0) |
73 | 0 | return code; |
74 | | |
75 | | /* Divide by the divisor to bring it back to font units. */ |
76 | 3.24M | x = (short)(x / a_divisor); |
77 | 3.24M | WRF_wint(a_fapi_font->memory, a_output, x); |
78 | 3.24M | WRF_wbyte(a_fapi_font->memory, a_output, (byte) (i == a_count - 1 ? ']' : ' ')); |
79 | 3.24M | } |
80 | 532k | WRF_wstring(a_fapi_font->memory, a_output, " def\n"); |
81 | | |
82 | 532k | return 0; |
83 | 532k | } |
84 | | |
85 | | static int |
86 | | write_array_entry(gs_fapi_font * a_fapi_font, WRF_output * a_output, |
87 | | const char *a_name, int a_index, int a_divisor) |
88 | 642k | { |
89 | | /* NOTE that the feature index must be preceded by the count index for this to work. */ |
90 | 642k | unsigned short count; |
91 | 642k | int code = a_fapi_font->get_word(a_fapi_font, a_index - 1, 0, &count); |
92 | | |
93 | 642k | if (code < 0) |
94 | 0 | return code; |
95 | | |
96 | 642k | return write_array_entry_with_count(a_fapi_font, a_output, a_name, a_index, |
97 | 642k | count, a_divisor); |
98 | 642k | } |
99 | | |
100 | | static int |
101 | | write_subrs(gs_fapi_font * a_fapi_font, WRF_output * a_output, int raw) |
102 | 107k | { |
103 | 107k | int i; |
104 | 107k | unsigned short count; |
105 | 107k | int code = a_fapi_font->get_word(a_fapi_font, gs_fapi_font_feature_Subrs_count, |
106 | 107k | 0, &count); |
107 | 107k | if (code < 0) |
108 | 0 | return code; |
109 | | |
110 | 107k | if (count > 0) { |
111 | 106k | WRF_wstring(a_fapi_font->memory, a_output, "/Subrs "); |
112 | 106k | WRF_wint(a_fapi_font->memory, a_output, count); |
113 | 106k | WRF_wstring(a_fapi_font->memory, a_output, " array\n"); |
114 | | |
115 | 746k | for (i = 0; i < count; i++) { |
116 | 640k | int length; |
117 | 640k | int buffer_size; |
118 | | |
119 | | |
120 | 640k | if (raw) |
121 | 0 | length = a_fapi_font->get_raw_subr(a_fapi_font, i, 0, 0); |
122 | 640k | else |
123 | 640k | length = a_fapi_font->get_subr(a_fapi_font, i, 0, 0); |
124 | 640k | if (length < 0) |
125 | 0 | return length; |
126 | | |
127 | 640k | WRF_wstring(a_fapi_font->memory, a_output, "dup "); |
128 | 640k | WRF_wint(a_fapi_font->memory, a_output, i); |
129 | 640k | WRF_wbyte(a_fapi_font->memory, a_output, ' '); |
130 | 640k | WRF_wint(a_fapi_font->memory, a_output, length); |
131 | 640k | WRF_wstring(a_fapi_font->memory, a_output, " RD "); |
132 | | |
133 | | /* Get the subroutine into the buffer and encrypt it in place. */ |
134 | 640k | buffer_size = a_output->m_limit - a_output->m_count; |
135 | 640k | if (buffer_size >= length) { |
136 | 320k | int l2; |
137 | | |
138 | 320k | if (raw) |
139 | 0 | l2 = a_fapi_font->get_raw_subr(a_fapi_font, i, a_output->m_pos, |
140 | 0 | (ushort) length); |
141 | 320k | else |
142 | 320k | l2 = a_fapi_font->get_subr(a_fapi_font, i, a_output->m_pos, |
143 | 320k | (ushort) length); |
144 | 320k | if (l2 < 0) |
145 | 0 | return l2; |
146 | | |
147 | 320k | WRF_wtext(a_fapi_font->memory, a_output, a_output->m_pos, length); |
148 | 320k | } else |
149 | 320k | a_output->m_count += length; |
150 | | |
151 | 640k | WRF_wstring(a_fapi_font->memory, a_output, " NP\n"); |
152 | 640k | } |
153 | | |
154 | 106k | WRF_wstring(a_fapi_font->memory, a_output, "ND\n"); |
155 | 106k | } |
156 | 107k | return 0; |
157 | 107k | } |
158 | | |
159 | | static int |
160 | | write_charstrings(gs_fapi_font * a_fapi_font, WRF_output * a_output) |
161 | 0 | { |
162 | 0 | int length; |
163 | 0 | int buffer_size; |
164 | 0 | int i; |
165 | 0 | unsigned short count; |
166 | 0 | int code = a_fapi_font->get_word(a_fapi_font, |
167 | 0 | gs_fapi_font_feature_CharStrings_count, |
168 | 0 | 0, &count); |
169 | 0 | char NameBuf[256]; |
170 | |
|
171 | 0 | if (code < 0) |
172 | 0 | return code; |
173 | | |
174 | 0 | if (count > 0) { |
175 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "2 index /CharStrings "); |
176 | 0 | WRF_wint(a_fapi_font->memory, a_output, count); |
177 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " dict dup begin\n"); |
178 | 0 | for (i = 0; i < count; i++) { |
179 | 0 | length = |
180 | 0 | a_fapi_font->get_charstring_name(a_fapi_font, i, |
181 | 0 | (byte *) & NameBuf, 256); |
182 | 0 | if (length < 0) |
183 | 0 | return length; |
184 | | |
185 | 0 | if (length > 0) { |
186 | 0 | length = a_fapi_font->get_charstring(a_fapi_font, i, 0, 0); |
187 | 0 | if (length < 0) |
188 | 0 | return length; |
189 | | |
190 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, '/'); |
191 | 0 | WRF_wstring(a_fapi_font->memory, a_output, (const char *)&NameBuf); |
192 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, ' '); |
193 | 0 | WRF_wint(a_fapi_font->memory, a_output, length); |
194 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " RD "); |
195 | | |
196 | | /* Get the CharString into the buffer and encrypt it in place. */ |
197 | 0 | buffer_size = a_output->m_limit - a_output->m_count; |
198 | 0 | if (buffer_size >= length) { |
199 | 0 | int l2; |
200 | 0 | l2 = a_fapi_font->get_charstring(a_fapi_font, i, a_output->m_pos, |
201 | 0 | (ushort) length); |
202 | 0 | if (l2 < 0) |
203 | 0 | return l2; |
204 | | |
205 | 0 | WRF_wtext(a_fapi_font->memory, a_output, a_output->m_pos, length); |
206 | 0 | } else |
207 | 0 | a_output->m_count += length; |
208 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ND\n"); |
209 | 0 | } |
210 | 0 | } |
211 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " end"); |
212 | 0 | } |
213 | 0 | return 0; |
214 | 0 | } |
215 | | |
216 | | static bool |
217 | | is_MM_font(gs_fapi_font * a_fapi_font) |
218 | 214k | { |
219 | 214k | unsigned short db; |
220 | 214k | int code = a_fapi_font->get_word(a_fapi_font, gs_fapi_font_feature_DollarBlend, 0, &db); |
221 | | |
222 | 214k | if (code >= 0 && db == 1) |
223 | 0 | return true; |
224 | | |
225 | 214k | return false; |
226 | 214k | } |
227 | | |
228 | | static int |
229 | | write_private_blend_dictionary(gs_fapi_font * a_fapi_font, WRF_output * a_output) |
230 | 107k | { |
231 | 107k | short x, x1, x2, i, j, acc; |
232 | 107k | int code; |
233 | | |
234 | 107k | if (is_MM_font(a_fapi_font)) { |
235 | |
|
236 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "3 index /Blend get /Private get begin\n"); |
237 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
238 | 0 | gs_fapi_font_feature_BlendBlueValues_length, 0, (unsigned short *)&x); |
239 | 0 | if (code < 0) |
240 | 0 | return code; |
241 | | |
242 | 0 | if (x > 0) { |
243 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlueValues ["); |
244 | 0 | acc = 0; |
245 | 0 | for (i = 0; i < x; i++) { |
246 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
247 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
248 | 0 | gs_fapi_font_feature_BlendBlueValues_count, i, (unsigned short *)&x1); |
249 | 0 | if (code < 0) |
250 | 0 | return code; |
251 | | |
252 | 0 | for (j = 0; j < x1; j++) { |
253 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
254 | 0 | gs_fapi_font_feature_BlendBlueValues, acc++, (unsigned short *)&x2); |
255 | 0 | if (code < 0) |
256 | 0 | return code; |
257 | | |
258 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
259 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
260 | 0 | } |
261 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]"); |
262 | 0 | } |
263 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
264 | 0 | } |
265 | | |
266 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
267 | 0 | gs_fapi_font_feature_BlendOtherBlues_length, 0, (unsigned short *)&x); |
268 | 0 | if (code < 0) |
269 | 0 | return code; |
270 | | |
271 | 0 | if (x > 0) { |
272 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/OtherBlues ["); |
273 | 0 | acc = 0; |
274 | 0 | for (i = 0; i < x; i++) { |
275 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
276 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
277 | 0 | gs_fapi_font_feature_BlendOtherBlues_count, i, (unsigned short *)&x1); |
278 | 0 | if (code < 0) |
279 | 0 | return code; |
280 | | |
281 | 0 | for (j = 0; j < x1; j++) { |
282 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
283 | 0 | gs_fapi_font_feature_BlendOtherBlues, acc++, (unsigned short *)&x2); |
284 | 0 | if (code < 0) |
285 | 0 | return code; |
286 | | |
287 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
288 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
289 | 0 | } |
290 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]"); |
291 | 0 | } |
292 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
293 | 0 | } |
294 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
295 | 0 | gs_fapi_font_feature_BlendBlueScale_count, 0, (unsigned short *)&x); |
296 | 0 | if (code < 0) |
297 | 0 | return 0; |
298 | | |
299 | 0 | if (x > 0) { |
300 | 0 | float v; |
301 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlueScale ["); |
302 | 0 | for (i =0; i < x; i++) { |
303 | 0 | code = a_fapi_font->get_float(a_fapi_font, |
304 | 0 | gs_fapi_font_feature_BlendBlueScale, i, &v); |
305 | 0 | if (code < 0) |
306 | 0 | return code; |
307 | | |
308 | 0 | WRF_wfloat(a_fapi_font->memory, a_output, v); |
309 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
310 | 0 | } |
311 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
312 | 0 | } |
313 | | |
314 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
315 | 0 | gs_fapi_font_feature_BlendBlueShift_count, 0, (unsigned short *)&x); |
316 | 0 | if (code < 0) |
317 | 0 | return code; |
318 | | |
319 | 0 | if (x > 0) { |
320 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlueShift ["); |
321 | 0 | for (i =0; i < x; i++) { |
322 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
323 | 0 | gs_fapi_font_feature_BlendBlueShift, i, (unsigned short *)&x2); |
324 | 0 | if (code < 0) |
325 | 0 | return code; |
326 | | |
327 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
328 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
329 | 0 | } |
330 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
331 | 0 | } |
332 | | |
333 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
334 | 0 | gs_fapi_font_feature_BlendBlueFuzz_count, 0, (unsigned short *)&x); |
335 | 0 | if (code < 0) |
336 | 0 | return code; |
337 | | |
338 | 0 | if (x > 0) { |
339 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlueFuzz ["); |
340 | 0 | for (i =0; i < x; i++) { |
341 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
342 | 0 | gs_fapi_font_feature_BlendBlueFuzz, i, (unsigned short *)&x2); |
343 | 0 | if (code < 0) |
344 | 0 | return code; |
345 | | |
346 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
347 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
348 | 0 | } |
349 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
350 | 0 | } |
351 | | |
352 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
353 | 0 | gs_fapi_font_feature_BlendForceBold_count, 0, (unsigned short *)&x); |
354 | 0 | if (code < 0) |
355 | 0 | return code; |
356 | | |
357 | 0 | if (x > 0) { |
358 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/ForceBold ["); |
359 | 0 | for (i =0; i < x; i++) { |
360 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
361 | 0 | gs_fapi_font_feature_BlendForceBold, i, (unsigned short *)&x2); |
362 | 0 | if (code < 0) |
363 | 0 | return code; |
364 | | |
365 | 0 | WRF_wstring(a_fapi_font->memory, a_output, x2 ? "/true" : "/false"); |
366 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
367 | 0 | } |
368 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
369 | 0 | } |
370 | | |
371 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
372 | 0 | gs_fapi_font_feature_BlendStdHW_length, 0, (unsigned short *)&x); |
373 | 0 | if (code < 0) |
374 | 0 | return code; |
375 | | |
376 | 0 | if (x > 0) { |
377 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/StdHW ["); |
378 | 0 | acc = 0; |
379 | 0 | for (i = 0; i < x; i++) { |
380 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
381 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
382 | 0 | gs_fapi_font_feature_BlendStdHW_count, i, (unsigned short *)&x1); |
383 | 0 | if (code < 0) |
384 | 0 | return code; |
385 | | |
386 | 0 | for (j = 0; j < x1; j++) { |
387 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
388 | 0 | gs_fapi_font_feature_BlendStdHW, acc++, (unsigned short *)&x2); |
389 | 0 | if (code < 0) |
390 | 0 | return code; |
391 | | |
392 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
393 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
394 | 0 | } |
395 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]"); |
396 | 0 | } |
397 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
398 | 0 | } |
399 | | |
400 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
401 | 0 | gs_fapi_font_feature_BlendStdVW_length, 0, (unsigned short *)&x); |
402 | 0 | if (code < 0) |
403 | 0 | return code; |
404 | | |
405 | 0 | if (x > 0) { |
406 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/StdVW ["); |
407 | 0 | acc = 0; |
408 | 0 | for (i = 0; i < x; i++) { |
409 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
410 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
411 | 0 | gs_fapi_font_feature_BlendStdVW_count, i, (unsigned short *)&x1); |
412 | 0 | if (code < 0) |
413 | 0 | return code; |
414 | | |
415 | 0 | for (j = 0; j < x1; j++) { |
416 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
417 | 0 | gs_fapi_font_feature_BlendStdVW, acc++, (unsigned short *)&x2); |
418 | 0 | if (code < 0) |
419 | 0 | return code; |
420 | | |
421 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
422 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
423 | 0 | } |
424 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]"); |
425 | 0 | } |
426 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
427 | 0 | } |
428 | | |
429 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
430 | 0 | gs_fapi_font_feature_BlendStemSnapH_length, 0, (unsigned short *)&x); |
431 | 0 | if (code < 0) |
432 | 0 | return code; |
433 | | |
434 | 0 | if (x > 0) { |
435 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/StemSnapH ["); |
436 | 0 | acc = 0; |
437 | 0 | for (i = 0; i < x; i++) { |
438 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
439 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
440 | 0 | gs_fapi_font_feature_BlendStemSnapH_count, i, (unsigned short *)&x1); |
441 | 0 | if (code < 0) |
442 | 0 | return code; |
443 | | |
444 | 0 | for (j = 0; j < x1; j++) { |
445 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
446 | 0 | gs_fapi_font_feature_BlendStemSnapH, acc++, (unsigned short *)&x2); |
447 | 0 | if (code < 0) |
448 | 0 | return code; |
449 | | |
450 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
451 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
452 | 0 | } |
453 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]"); |
454 | 0 | } |
455 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
456 | 0 | } |
457 | | |
458 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
459 | 0 | gs_fapi_font_feature_BlendStemSnapV_length, 0, (unsigned short *)&x); |
460 | 0 | if (code < 0) |
461 | 0 | return code; |
462 | | |
463 | 0 | if (x > 0) { |
464 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/StemSnapV ["); |
465 | 0 | acc = 0; |
466 | 0 | for (i = 0; i < x; i++) { |
467 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ["); |
468 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
469 | 0 | gs_fapi_font_feature_BlendStemSnapV_count, i, (unsigned short *)&x1); |
470 | 0 | if (code < 0) |
471 | 0 | return code; |
472 | | |
473 | 0 | for (j = 0; j < x1; j++) { |
474 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
475 | 0 | gs_fapi_font_feature_BlendStemSnapV, acc++, (unsigned short *)&x2); |
476 | 0 | if (code < 0) |
477 | 0 | return code; |
478 | | |
479 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
480 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
481 | 0 | } |
482 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]"); |
483 | 0 | } |
484 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " ]\n"); |
485 | 0 | } |
486 | | |
487 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "end\n"); |
488 | 0 | } |
489 | 107k | return 0; |
490 | 107k | } |
491 | | |
492 | | static int |
493 | | write_private_dictionary(gs_fapi_font * a_fapi_font, WRF_output * a_output, |
494 | | int Write_CharStrings) |
495 | 107k | { |
496 | 107k | int code; |
497 | 107k | unsigned long ulval; |
498 | 107k | a_output->m_encrypt = true; |
499 | | |
500 | | /* Write 4 bytes that must encrypt to at least one character that cannot be a valid hexadecimal character. */ |
501 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "XXXX"); |
502 | | |
503 | | /*+ to do: correct size of dictionary from 8. */ |
504 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "dup /Private 8 dict dup begin\n"); |
505 | | |
506 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/MinFeature {16 16} def\n"); |
507 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/password 5839 def\n"); |
508 | 107k | if (Write_CharStrings) { |
509 | 0 | code = write_word_entry(a_fapi_font, a_output, "lenIV", gs_fapi_font_feature_lenIV, 1); |
510 | 0 | if (code < 0) |
511 | 0 | return code; |
512 | 0 | } |
513 | 107k | else { |
514 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/lenIV -1 def\n"); /* indicate that /subrs are not encoded. */ |
515 | 107k | } |
516 | 107k | code = write_word_entry(a_fapi_font, a_output, "BlueFuzz", gs_fapi_font_feature_BlueFuzz, 16); |
517 | 107k | if (code < 0) |
518 | 0 | return code; |
519 | | |
520 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/BlueScale "); |
521 | 107k | code = a_fapi_font->get_long(a_fapi_font,gs_fapi_font_feature_BlueScale, 0, &ulval); |
522 | 107k | if (code < 0) |
523 | 0 | return code; |
524 | | |
525 | 107k | WRF_wfloat(a_fapi_font->memory, a_output, (float)ulval/65536.0); |
526 | | |
527 | 107k | WRF_wstring(a_fapi_font->memory, a_output, " def\n"); |
528 | | |
529 | 107k | code = write_word_entry(a_fapi_font, a_output, "BlueShift", gs_fapi_font_feature_BlueShift, 16); |
530 | 107k | if (code < 0) |
531 | 0 | return code; |
532 | | |
533 | 107k | code = write_array_entry(a_fapi_font, a_output, "BlueValues", |
534 | 107k | gs_fapi_font_feature_BlueValues, 16); |
535 | 107k | if (code < 0) |
536 | 0 | return code; |
537 | | |
538 | 107k | code = write_array_entry(a_fapi_font, a_output, "OtherBlues", |
539 | 107k | gs_fapi_font_feature_OtherBlues, 16); |
540 | 107k | if (code < 0) |
541 | 0 | return code; |
542 | | |
543 | 107k | code = write_array_entry(a_fapi_font, a_output, "FamilyBlues", |
544 | 107k | gs_fapi_font_feature_FamilyBlues, 16); |
545 | 107k | if (code < 0) |
546 | 0 | return code; |
547 | | |
548 | 107k | code = write_array_entry(a_fapi_font, a_output, "FamilyOtherBlues", |
549 | 107k | gs_fapi_font_feature_FamilyOtherBlues, 16); |
550 | 107k | if (code < 0) |
551 | 0 | return code; |
552 | | |
553 | 107k | code = write_word_entry(a_fapi_font, a_output, "ForceBold", gs_fapi_font_feature_ForceBold, 1); |
554 | 107k | if (code < 0) |
555 | 0 | return code; |
556 | | |
557 | 107k | code = write_array_entry_with_count(a_fapi_font, a_output, "StdHW", |
558 | 107k | gs_fapi_font_feature_StdHW, 1, 16); |
559 | 107k | if (code < 0) |
560 | 0 | return code; |
561 | | |
562 | 107k | code = write_array_entry_with_count(a_fapi_font, a_output, "StdVW", |
563 | 107k | gs_fapi_font_feature_StdVW, 1, 16); |
564 | 107k | if (code < 0) |
565 | 0 | return code; |
566 | | |
567 | 107k | code = write_array_entry(a_fapi_font, a_output, "StemSnapH", |
568 | 107k | gs_fapi_font_feature_StemSnapH, 16); |
569 | 107k | if (code < 0) |
570 | 0 | return code; |
571 | | |
572 | 107k | code = write_array_entry(a_fapi_font, a_output, "StemSnapV", |
573 | 107k | gs_fapi_font_feature_StemSnapV, 16); |
574 | 107k | if (code < 0) |
575 | 0 | return code; |
576 | | |
577 | 107k | code = write_private_blend_dictionary(a_fapi_font, a_output); |
578 | 107k | if (code < 0) |
579 | 0 | return code; |
580 | | |
581 | 107k | if (Write_CharStrings) |
582 | 0 | code = write_subrs(a_fapi_font, a_output, 1); |
583 | 107k | else |
584 | 107k | code = write_subrs(a_fapi_font, a_output, 0); |
585 | 107k | if (code < 0) |
586 | 0 | return code; |
587 | | |
588 | 107k | if (Write_CharStrings) |
589 | 0 | code = write_charstrings(a_fapi_font, a_output); |
590 | | |
591 | 107k | return code; |
592 | 107k | } |
593 | | |
594 | | static int |
595 | | write_main_dictionary(gs_fapi_font * a_fapi_font, WRF_output * a_output, int Write_CharStrings) |
596 | 107k | { |
597 | 107k | int i, code; |
598 | 107k | float fval; |
599 | | |
600 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "5 dict begin\n"); |
601 | | |
602 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/FontType 1 def\n"); |
603 | | |
604 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/FontMatrix ["); |
605 | 749k | for (i = 0; i < 6; i++) { |
606 | 642k | code = a_fapi_font->get_float(a_fapi_font, gs_fapi_font_feature_FontMatrix, i, &fval); |
607 | 642k | if (code < 0) |
608 | 0 | return code; |
609 | | |
610 | 642k | WRF_wfloat(a_fapi_font->memory, a_output, fval); |
611 | 642k | WRF_wbyte(a_fapi_font->memory, a_output, (byte) (i == 5 ? ']' : ' ')); |
612 | 642k | } |
613 | 107k | WRF_wbyte(a_fapi_font->memory, a_output, '\n'); |
614 | | /* For now, specify standard encoding - I think GS will pass glyph indices so doesn't matter. */ |
615 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/Encoding StandardEncoding def\n"); |
616 | | |
617 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "/FontBBox {"); |
618 | 535k | for (i = 0; i < 4; i++) { |
619 | 428k | short x; |
620 | 428k | code = a_fapi_font->get_word(a_fapi_font, gs_fapi_font_feature_FontBBox, |
621 | 428k | i, (unsigned short *)&x); |
622 | 428k | if (code < 0) |
623 | 0 | return code; |
624 | | |
625 | 428k | WRF_wint(a_fapi_font->memory, a_output, x); |
626 | 428k | WRF_wbyte(a_fapi_font->memory, a_output, (byte) (i == 3 ? '}' : ' ')); |
627 | 428k | } |
628 | 107k | WRF_wbyte(a_fapi_font->memory, a_output, '\n'); |
629 | 107k | if (is_MM_font(a_fapi_font)) { |
630 | 0 | short x, x2; |
631 | 0 | unsigned short ux; |
632 | 0 | float x1; |
633 | 0 | uint i, j, entries; |
634 | 0 | char Buffer[255]; |
635 | |
|
636 | 0 | entries = 0; |
637 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
638 | 0 | gs_fapi_font_feature_BlendAxisTypes_count, |
639 | 0 | 0, (unsigned short *)&x); |
640 | 0 | if (code < 0) |
641 | 0 | return code; |
642 | | |
643 | 0 | if (x) |
644 | 0 | entries++; |
645 | |
|
646 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
647 | 0 | gs_fapi_font_feature_BlendDesignPositionsArrays_count, |
648 | 0 | 0, (unsigned short *)&x); |
649 | 0 | if (code < 0) |
650 | 0 | return code; |
651 | | |
652 | 0 | if (x) |
653 | 0 | entries++; |
654 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
655 | 0 | gs_fapi_font_feature_BlendDesignMapArrays_count, |
656 | 0 | 0, (unsigned short *)&x); |
657 | 0 | if (code < 0) |
658 | 0 | return code; |
659 | 0 | if (x) |
660 | | |
661 | 0 | entries++; |
662 | |
|
663 | 0 | gs_snprintf(Buffer, sizeof(Buffer), "/FontInfo %d dict dup begin\n", entries); |
664 | 0 | WRF_wstring(a_fapi_font->memory, a_output, Buffer); |
665 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
666 | 0 | gs_fapi_font_feature_BlendAxisTypes_count, |
667 | 0 | 0, (unsigned short *)&x); |
668 | 0 | if (code < 0) |
669 | 0 | return code; |
670 | | |
671 | 0 | if (x) { |
672 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlendAxisTypes ["); |
673 | 0 | for (i = 0; i < x; i++) { |
674 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " /"); |
675 | 0 | code = a_fapi_font->get_name(a_fapi_font, |
676 | 0 | gs_fapi_font_feature_BlendAxisTypes, i, |
677 | 0 | (char *)&Buffer, 255); |
678 | 0 | if (code < 0) |
679 | 0 | return code; |
680 | | |
681 | 0 | WRF_wstring(a_fapi_font->memory, a_output, Buffer); |
682 | 0 | } |
683 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "] def\n"); |
684 | 0 | } |
685 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
686 | 0 | gs_fapi_font_feature_BlendDesignPositionsArrays_count, |
687 | 0 | 0, (unsigned short *)&x); |
688 | 0 | if (code < 0) |
689 | 0 | return code; |
690 | | |
691 | 0 | if (x) { |
692 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlendDesignPositions ["); |
693 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
694 | 0 | gs_fapi_font_feature_BlendAxisTypes_count, |
695 | 0 | 0, (unsigned short *)&x2); |
696 | 0 | if (code < 0) |
697 | 0 | return code; |
698 | | |
699 | 0 | for (i = 0; i < x; i++) { |
700 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "["); |
701 | 0 | for (j = 0; j < x2; j++) { |
702 | 0 | code = a_fapi_font->get_float(a_fapi_font, |
703 | 0 | gs_fapi_font_feature_BlendDesignPositionsArrayValue, |
704 | 0 | i * 8 + j, &x1); |
705 | 0 | if (code < 0) |
706 | 0 | return code; |
707 | | |
708 | 0 | gs_snprintf(Buffer, sizeof(Buffer), "%f ", x1); |
709 | 0 | WRF_wstring(a_fapi_font->memory, a_output, Buffer); |
710 | 0 | } |
711 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "]"); |
712 | 0 | } |
713 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "] def\n"); |
714 | 0 | } |
715 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
716 | 0 | gs_fapi_font_feature_BlendDesignMapArrays_count, |
717 | 0 | 0, (unsigned short *)&x); |
718 | 0 | if (code < 0) |
719 | 0 | return code; |
720 | 0 | if (x) { |
721 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/BlendDesignMap ["); |
722 | 0 | for (i = 0; i < x; i++) { |
723 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
724 | 0 | gs_fapi_font_feature_BlendDesignMapSubArrays_count, |
725 | 0 | i, (unsigned short *)&x2); |
726 | 0 | if (code < 0) |
727 | 0 | return code; |
728 | | |
729 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "["); |
730 | 0 | for (j = 0; j < x2; j++) { |
731 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "["); |
732 | 0 | code = a_fapi_font->get_float(a_fapi_font, |
733 | 0 | gs_fapi_font_feature_BlendDesignPositionsArrayValue, |
734 | 0 | i * 64 + j * 64, &x1); |
735 | 0 | if (code < 0) |
736 | 0 | return code; |
737 | | |
738 | 0 | gs_snprintf(Buffer, sizeof(Buffer), "%f ", x1); |
739 | 0 | WRF_wstring(a_fapi_font->memory, a_output, Buffer); |
740 | 0 | code = a_fapi_font->get_float(a_fapi_font, |
741 | 0 | gs_fapi_font_feature_BlendDesignPositionsArrayValue, |
742 | 0 | i * 64 + j * 64 + 1, &x1); |
743 | 0 | if (code < 0) |
744 | 0 | return code; |
745 | 0 | gs_snprintf(Buffer, sizeof(Buffer), "%f ", x1); |
746 | 0 | WRF_wstring(a_fapi_font->memory, a_output, Buffer); |
747 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "]"); |
748 | 0 | } |
749 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "]"); |
750 | 0 | } |
751 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "] def\n"); |
752 | 0 | } |
753 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "end readonly def\n"); |
754 | | |
755 | | /* Previously we tried to write $Blend twice - the "real" one from the font, |
756 | | * and the boiler plate one below. |
757 | | * For now, I assume there was a good reason for including the second, but it may |
758 | | * be because the "get_proc" method below was missing the code to handle PS name |
759 | | * objects. |
760 | | */ |
761 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
762 | 0 | gs_fapi_font_feature_DollarBlend_length, |
763 | 0 | 0, &ux); |
764 | 0 | if (code < 0) |
765 | 0 | return code; |
766 | | |
767 | 0 | if (ux > 0) { |
768 | 0 | int len; |
769 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/$Blend {"); |
770 | |
|
771 | 0 | if (a_output->m_count) |
772 | 0 | a_output->m_count += ux; |
773 | 0 | len = a_fapi_font->get_proc(a_fapi_font, |
774 | 0 | gs_fapi_font_feature_DollarBlend, 0, |
775 | 0 | (char *)a_output->m_pos); |
776 | 0 | if (a_output->m_pos && len > 0) |
777 | 0 | a_output->m_pos += len; |
778 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "} def\n"); |
779 | 0 | } else { |
780 | 0 | WRF_wstring(a_fapi_font->memory, a_output, |
781 | 0 | "/$Blend {0.1 mul exch 0.45 mul add exch 0.17 mul add add} def\n"); |
782 | 0 | } |
783 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/WeightVector ["); |
784 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
785 | 0 | gs_fapi_font_feature_WeightVector_count, 0, (unsigned short *)&x); |
786 | 0 | if (code < 0) |
787 | 0 | return code; |
788 | | |
789 | 0 | for (i = 0; i < x; i++) { |
790 | 0 | code = a_fapi_font->get_float(a_fapi_font, |
791 | 0 | gs_fapi_font_feature_WeightVector, i, &x1); |
792 | 0 | if (code < 0) |
793 | 0 | return code; |
794 | | |
795 | 0 | gs_snprintf(Buffer, sizeof(Buffer), "%f ", x1); |
796 | 0 | WRF_wstring(a_fapi_font->memory, a_output, Buffer); |
797 | 0 | } |
798 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "] def\n"); |
799 | |
|
800 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/Blend 3 dict dup begin\n"); |
801 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/FontBBox {"); |
802 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
803 | 0 | gs_fapi_font_feature_BlendFontBBox_length , 0, (unsigned short *)&x); |
804 | 0 | if (code < 0) |
805 | 0 | return code; |
806 | | |
807 | 0 | for (i = 0; i < 4; i++) { |
808 | 0 | int j; |
809 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " {"); |
810 | 0 | for (j = 0; j < x; j++) { |
811 | 0 | code = a_fapi_font->get_word(a_fapi_font, |
812 | 0 | gs_fapi_font_feature_BlendFontBBox, |
813 | 0 | j + (i * 4), (unsigned short *)&x2); |
814 | 0 | if (code < 0) |
815 | 0 | return code; |
816 | | |
817 | 0 | WRF_wint(a_fapi_font->memory, a_output, x2); |
818 | 0 | WRF_wbyte(a_fapi_font->memory, a_output, (byte)' '); |
819 | 0 | } |
820 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "}"); |
821 | 0 | } |
822 | 0 | WRF_wstring(a_fapi_font->memory, a_output, " } def\n"); |
823 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "/Private 14 dict def\n"); |
824 | 0 | WRF_wstring(a_fapi_font->memory, a_output, "end def\n"); |
825 | 0 | #undef TEMP_BUF_LEN |
826 | 0 | } |
827 | 107k | WRF_wstring(a_fapi_font->memory, a_output, "currentdict end\ncurrentfile eexec\n"); |
828 | | |
829 | 107k | return write_private_dictionary(a_fapi_font, a_output, Write_CharStrings); |
830 | 107k | } |
831 | | |
832 | | /** |
833 | | Write a Type 1 font in textual format and return its length in bytes. |
834 | | If a_buffer_size is less than the total length, only a_buffer_size bytes are written, but the total |
835 | | length is returned correctly. |
836 | | |
837 | | The PostScript is non-standard. The main dictionary contains no /Charstrings dictionary. This |
838 | | is supplied to FreeType using the incremental interface, There is also no /PaintType entry. This is required |
839 | | by PostScript but FreeType doesn't use it. |
840 | | */ |
841 | | long |
842 | | gs_fapi_serialize_type1_font(gs_fapi_font * a_fapi_font, |
843 | | unsigned char *a_buffer, long a_buffer_size) |
844 | 107k | { |
845 | 107k | int code; |
846 | 107k | WRF_output output; |
847 | | |
848 | 107k | WRF_init(&output, a_buffer, a_buffer_size); |
849 | | |
850 | | /* Leading comment identifying a Type 1 font. */ |
851 | 107k | WRF_wstring(a_fapi_font->memory, &output, "%!PS-AdobeFont-1\n"); |
852 | | |
853 | 107k | code = write_main_dictionary(a_fapi_font, &output, 0); |
854 | 107k | if (code < 0) |
855 | 0 | return (long)code; |
856 | | #if 0 |
857 | | { |
858 | | extern FILE *stdout; |
859 | | if (a_buffer && a_buffer_size >= output.m_count) { |
860 | | fwrite(a_buffer, 1, output.m_count, stdout); |
861 | | } |
862 | | } |
863 | | #endif |
864 | | |
865 | 107k | return output.m_count; |
866 | 107k | } |
867 | | |
868 | | long |
869 | | gs_fapi_serialize_type1_font_complete(gs_fapi_font * a_fapi_font, |
870 | | unsigned char *a_buffer, |
871 | | long a_buffer_size) |
872 | 0 | { |
873 | 0 | int code; |
874 | 0 | WRF_output output; |
875 | |
|
876 | 0 | WRF_init(&output, a_buffer, a_buffer_size); |
877 | | |
878 | | /* Leading comment identifying a Type 1 font. */ |
879 | 0 | WRF_wstring(a_fapi_font->memory, &output, "%!PS-AdobeFont-1\n"); |
880 | |
|
881 | 0 | code = write_main_dictionary(a_fapi_font, &output, 1); |
882 | 0 | if (code < 0) |
883 | 0 | return (long)code; |
884 | | |
885 | 0 | return output.m_count; |
886 | 0 | } |