1 /* Copyright (C) 2001-2006 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, modified
8 or distributed except as expressly authorized under the terms of that
9 license. Refer to licensing information at http://www.artifex.com/
10 or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11 San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
12 */
13
14 /* $Id: gdevpsf1.c 9386 2009-01-22 13:53:18Z ken $ */
15 /* Write an embedded Type 1 font */
16 #include "memory_.h"
17 #include "gx.h"
18 #include "gserrors.h"
19 #include "gsccode.h"
20 #include "gsmatrix.h"
21 #include "gxfixed.h"
22 #include "gxfont.h"
23 #include "gxfont1.h"
24 #include "gxmatrix.h" /* for gxtype1.h */
25 #include "gxtype1.h"
26 #include "strimpl.h" /* required by Watcom compiler (why?) */
27 #include "stream.h"
28 #include "sfilter.h"
29 #include "spsdf.h"
30 #include "sstring.h"
31 #include "spprint.h"
32 #include "gdevpsf.h"
33
34 /* ------ Utilities shared with CFF writer ------ */
35
36 /* Gather glyph information for a Type 1 or Type 2 font. */
37 int
psf_type1_glyph_data(gs_font_base * pbfont,gs_glyph glyph,gs_glyph_data_t * pgd,gs_font_type1 ** ppfont)38 psf_type1_glyph_data(gs_font_base *pbfont, gs_glyph glyph,
39 gs_glyph_data_t *pgd, gs_font_type1 **ppfont)
40 {
41 gs_font_type1 *const pfont = (gs_font_type1 *)pbfont;
42
43 *ppfont = pfont;
44 return pfont->data.procs.glyph_data(pfont, glyph, pgd);
45 }
46 int
psf_get_type1_glyphs(psf_outline_glyphs_t * pglyphs,gs_font_type1 * pfont,gs_glyph * subset_glyphs,uint subset_size)47 psf_get_type1_glyphs(psf_outline_glyphs_t *pglyphs, gs_font_type1 *pfont,
48 gs_glyph *subset_glyphs, uint subset_size)
49 {
50 return psf_get_outline_glyphs(pglyphs, (gs_font_base *)pfont,
51 subset_glyphs, subset_size,
52 psf_type1_glyph_data);
53 }
54
55 /* ------ Main program ------ */
56
57 /* Write a (named) array of floats. */
58 static int
write_float_array(gs_param_list * plist,const char * key,const float * values,int count)59 write_float_array(gs_param_list *plist, const char *key, const float *values,
60 int count)
61 {
62 if (count != 0) {
63 gs_param_float_array fa;
64
65 fa.persistent = false;
66 fa.size = count;
67 fa.data = values;
68 return param_write_float_array(plist, key, &fa);
69 }
70 return 0;
71 }
72
73 /* Write a UniqueID and/or XUID. */
74 static void
write_uid(stream * s,const gs_uid * puid)75 write_uid(stream *s, const gs_uid *puid)
76 {
77 if (uid_is_UniqueID(puid))
78 pprintld1(s, "/UniqueID %ld def\n", puid->id);
79 else if (uid_is_XUID(puid)) {
80 uint i, n = uid_XUID_size(puid);
81
82 stream_puts(s, "/XUID [");
83 for (i = 0; i < n; ++i)
84 pprintld1(s, "%ld ", uid_XUID_values(puid)[i]);
85 stream_puts(s, "] readonly def\n");
86 }
87 }
88
89 /* Write the font name. */
90 static void
write_font_name(stream * s,const gs_font_type1 * pfont,const gs_const_string * alt_font_name,bool as_name)91 write_font_name(stream *s, const gs_font_type1 *pfont,
92 const gs_const_string *alt_font_name, bool as_name)
93 {
94 const byte *c;
95 const byte *name = (alt_font_name ? alt_font_name->data : pfont->font_name.chars);
96 int n = (alt_font_name ? alt_font_name->size : pfont->font_name.size);
97
98 if (n == 0)
99 /* empty name, may need to write it as empty string */
100 stream_puts(s, (as_name ? "/" : "()"));
101 else {
102 for (c = (byte *)"()<>[]{}/% \n\r\t\b\f\004\033"; *c; c++)
103 if (memchr(name, *c, n))
104 break;
105 if (*c || memchr(name, 0, n)) {
106 /* name contains whitespace (NUL included) or a PostScript separator */
107 byte pssebuf[1 + 4 * gs_font_name_max + 1]; /* "(" + "\ooo" * gs_font_name_max + ")" */
108 stream_cursor_read r;
109 stream_cursor_write w;
110
111 pssebuf[0] = '(';
112 r.limit = (r.ptr = name - 1) + n;
113 w.limit = (w.ptr = pssebuf) + sizeof pssebuf - 1;
114 s_PSSE_template.process(NULL, &r, &w, true);
115 stream_write(s, pssebuf, w.ptr - pssebuf + 1);
116 if (as_name)
117 stream_puts(s, " cvn");
118 } else {
119 /* name without any special characters */
120 if (as_name)
121 stream_putc(s, '/');
122 stream_write(s, name, n);
123 }
124 }
125 }
126 /*
127 * Write the Encoding array. This is a separate procedure only for
128 * readability.
129 */
130 static int
write_Encoding(stream * s,gs_font_type1 * pfont,int options,gs_glyph * subset_glyphs,uint subset_size,gs_glyph notdef)131 write_Encoding(stream *s, gs_font_type1 *pfont, int options,
132 gs_glyph *subset_glyphs, uint subset_size, gs_glyph notdef)
133 {
134 stream_puts(s, "/Encoding ");
135 switch (pfont->encoding_index) {
136 case ENCODING_INDEX_STANDARD:
137 stream_puts(s, "StandardEncoding");
138 break;
139 case ENCODING_INDEX_ISOLATIN1:
140 /* ATM only recognizes StandardEncoding. */
141 if (options & WRITE_TYPE1_POSTSCRIPT) {
142 stream_puts(s, "ISOLatin1Encoding");
143 break;
144 }
145 default:{
146 gs_char i;
147
148 stream_puts(s, "256 array\n");
149 stream_puts(s, "0 1 255 {1 index exch /.notdef put} for\n");
150 for (i = 0; i < 256; ++i) {
151 gs_glyph glyph =
152 (*pfont->procs.encode_char)
153 ((gs_font *)pfont, (gs_char)i, GLYPH_SPACE_NAME);
154 gs_const_string namestr;
155
156 if (subset_glyphs && subset_size) {
157 /*
158 * Only write Encoding entries for glyphs in the
159 * subset. Use binary search to check each glyph,
160 * since subset_glyphs are sorted.
161 */
162 if (!psf_sorted_glyphs_include(subset_glyphs,
163 subset_size, glyph))
164 continue;
165 }
166 if (glyph != gs_no_glyph && glyph != notdef &&
167 pfont->procs.glyph_name((gs_font *)pfont, glyph,
168 &namestr) >= 0
169 ) {
170 pprintd1(s, "dup %d /", (int)i);
171 stream_write(s, namestr.data, namestr.size);
172 stream_puts(s, " put\n");
173 }
174 }
175 stream_puts(s, "readonly");
176 }
177 }
178 stream_puts(s, " def\n");
179 return 0;
180 }
181
182 /*
183 * Write the Private dictionary. This is a separate procedure only for
184 * readability. write_CharString is a parameter so that we can encrypt
185 * Subrs and CharStrings when the font's lenIV == -1 but we are writing
186 * the font with lenIV = 0.
187 */
188 static int
write_Private(stream * s,gs_font_type1 * pfont,gs_glyph * subset_glyphs,uint subset_size,gs_glyph notdef,int lenIV,int (* write_CharString)(stream *,const void *,uint),const param_printer_params_t * ppp)189 write_Private(stream *s, gs_font_type1 *pfont,
190 gs_glyph *subset_glyphs, uint subset_size,
191 gs_glyph notdef, int lenIV,
192 int (*write_CharString)(stream *, const void *, uint),
193 const param_printer_params_t *ppp)
194 {
195 const gs_type1_data *const pdata = &pfont->data;
196 printer_param_list_t rlist;
197 gs_param_list *const plist = (gs_param_list *)&rlist;
198 int code = s_init_param_printer(&rlist, ppp, s);
199
200 if (code < 0)
201 return 0;
202 stream_puts(s, "dup /Private 17 dict dup begin\n");
203 stream_puts(s, "/-|{string currentfile exch readstring pop}executeonly def\n");
204 stream_puts(s, "/|-{noaccess def}executeonly def\n");
205 stream_puts(s, "/|{noaccess put}executeonly def\n");
206 {
207 static const gs_param_item_t private_items[] = {
208 {"BlueFuzz", gs_param_type_int,
209 offset_of(gs_type1_data, BlueFuzz)},
210 {"BlueScale", gs_param_type_float,
211 offset_of(gs_type1_data, BlueScale)},
212 {"BlueShift", gs_param_type_float,
213 offset_of(gs_type1_data, BlueShift)},
214 {"ExpansionFactor", gs_param_type_float,
215 offset_of(gs_type1_data, ExpansionFactor)},
216 {"ForceBold", gs_param_type_bool,
217 offset_of(gs_type1_data, ForceBold)},
218 {"LanguageGroup", gs_param_type_int,
219 offset_of(gs_type1_data, LanguageGroup)},
220 {"RndStemUp", gs_param_type_bool,
221 offset_of(gs_type1_data, RndStemUp)},
222 gs_param_item_end
223 };
224 gs_type1_data defaults;
225
226 defaults.BlueFuzz = 1;
227 defaults.BlueScale = (float)0.039625;
228 defaults.BlueShift = 7.0;
229 defaults.ExpansionFactor = (float)0.06;
230 defaults.ForceBold = false;
231 defaults.LanguageGroup = 0;
232 defaults.RndStemUp = true;
233 code = gs_param_write_items(plist, pdata, &defaults, private_items);
234 if (code < 0)
235 return code;
236 if (lenIV != 4) {
237 code = param_write_int(plist, "lenIV", &lenIV);
238 if (code < 0)
239 return code;
240 }
241 write_float_array(plist, "BlueValues", pdata->BlueValues.values,
242 pdata->BlueValues.count);
243 write_float_array(plist, "OtherBlues", pdata->OtherBlues.values,
244 pdata->OtherBlues.count);
245 write_float_array(plist, "FamilyBlues", pdata->FamilyBlues.values,
246 pdata->FamilyBlues.count);
247 write_float_array(plist, "FamilyOtherBlues", pdata->FamilyOtherBlues.values,
248 pdata->FamilyOtherBlues.count);
249 write_float_array(plist, "StdHW", pdata->StdHW.values,
250 pdata->StdHW.count);
251 write_float_array(plist, "StdVW", pdata->StdVW.values,
252 pdata->StdVW.count);
253 write_float_array(plist, "StemSnapH", pdata->StemSnapH.values,
254 pdata->StemSnapH.count);
255 write_float_array(plist, "StemSnapV", pdata->StemSnapV.values,
256 pdata->StemSnapV.count);
257 }
258 write_uid(s, &pfont->UID);
259 stream_puts(s, "/MinFeature{16 16} def\n");
260 stream_puts(s, "/password 5839 def\n");
261
262 /*
263 * Write the Subrs. We always write them all, even for subsets.
264 * (We will fix this someday.)
265 */
266
267 {
268 int n, i;
269 gs_glyph_data_t gdata;
270 int code;
271
272 gdata.memory = pfont->memory;
273 for (n = 0;
274 (code = pdata->procs.subr_data(pfont, n, false, &gdata)) !=
275 gs_error_rangecheck;
276 ) {
277 ++n;
278 if (code >= 0)
279 gs_glyph_data_free(&gdata, "write_Private(Subrs)");
280 }
281 pprintd1(s, "/Subrs %d array\n", n);
282 for (i = 0; i < n; ++i)
283 if ((code = pdata->procs.subr_data(pfont, i, false, &gdata)) >= 0) {
284 char buf[50];
285
286 if (gdata.bits.size) {
287 sprintf(buf, "dup %d %u -| ", i, gdata.bits.size);
288 stream_puts(s, buf);
289 write_CharString(s, gdata.bits.data, gdata.bits.size);
290 stream_puts(s, " |\n");
291 }
292 gs_glyph_data_free(&gdata, "write_Private(Subrs)");
293 }
294 stream_puts(s, "|-\n");
295 }
296
297 /* We don't write OtherSubrs -- there had better not be any! */
298
299 /* Write the CharStrings. */
300
301 {
302 int num_chars = 0;
303 gs_glyph glyph;
304 psf_glyph_enum_t genum;
305 gs_glyph_data_t gdata;
306 int code;
307
308 gdata.memory = pfont->memory;
309 psf_enumerate_glyphs_begin(&genum, (gs_font *)pfont, subset_glyphs,
310 (subset_glyphs ? subset_size : 0),
311 GLYPH_SPACE_NAME);
312 for (glyph = gs_no_glyph;
313 (code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1;
314 )
315 if (code == 0 &&
316 (code = pdata->procs.glyph_data(pfont, glyph, &gdata)) >= 0
317 ) {
318 ++num_chars;
319 gs_glyph_data_free(&gdata, "write_Private(CharStrings)");
320 }
321 pprintd1(s, "2 index /CharStrings %d dict dup begin\n", num_chars);
322 psf_enumerate_glyphs_reset(&genum);
323 for (glyph = gs_no_glyph;
324 (code = psf_enumerate_glyphs_next(&genum, &glyph)) != 1;
325 )
326 if (code == 0 &&
327 (code = pdata->procs.glyph_data(pfont, glyph, &gdata)) >= 0
328 ) {
329 gs_const_string gstr;
330 int code;
331
332 code = pfont->procs.glyph_name((gs_font *)pfont, glyph, &gstr);
333 if (code < 0)
334 return code;
335 stream_puts(s, "/");
336 stream_write(s, gstr.data, gstr.size);
337 pprintd1(s, " %d -| ", gdata.bits.size);
338 write_CharString(s, gdata.bits.data, gdata.bits.size);
339 stream_puts(s, " |-\n");
340 gs_glyph_data_free(&gdata, "write_Private(CharStrings)");
341 }
342 }
343
344 /* Wrap up. */
345
346 stream_puts(s, "end\nend\nreadonly put\nnoaccess put\n");
347 s_release_param_printer(&rlist);
348 return 0;
349 }
350
351 /* Encrypt and write a CharString. */
352 static int
stream_write_encrypted(stream * s,const void * ptr,uint count)353 stream_write_encrypted(stream *s, const void *ptr, uint count)
354 {
355 const byte *const data = ptr;
356 crypt_state state = crypt_charstring_seed;
357 byte buf[50]; /* arbitrary */
358 uint left, n;
359 int code = 0;
360
361 for (left = count; left > 0; left -= n) {
362 n = min(left, sizeof(buf));
363 gs_type1_encrypt(buf, data + count - left, n, &state);
364 code = stream_write(s, buf, n);
365 }
366 return code;
367 }
368
369 /* Write one FontInfo entry. */
370 static void
write_font_info(stream * s,const char * key,const gs_const_string * pvalue,int do_write)371 write_font_info(stream *s, const char *key, const gs_const_string *pvalue,
372 int do_write)
373 {
374 if (do_write) {
375 pprints1(s, "\n/%s ", key);
376 s_write_ps_string(s, pvalue->data, pvalue->size, PRINT_HEX_NOT_OK);
377 stream_puts(s, " def");
378 }
379 }
380
381 /* Write the definition of a Type 1 font. */
382 int
psf_write_type1_font(stream * s,gs_font_type1 * pfont,int options,gs_glyph * orig_subset_glyphs,uint orig_subset_size,const gs_const_string * alt_font_name,int lengths[3])383 psf_write_type1_font(stream *s, gs_font_type1 *pfont, int options,
384 gs_glyph *orig_subset_glyphs, uint orig_subset_size,
385 const gs_const_string *alt_font_name, int lengths[3])
386 {
387 stream *es = s;
388 long start = stell(s);
389 param_printer_params_t ppp;
390 printer_param_list_t rlist;
391 gs_param_list *const plist = (gs_param_list *)&rlist;
392 stream AXE_stream;
393 stream_AXE_state AXE_state;
394 byte AXE_buf[200]; /* arbitrary */
395 stream exE_stream;
396 stream_exE_state exE_state;
397 byte exE_buf[200]; /* arbitrary */
398 psf_outline_glyphs_t glyphs;
399 int lenIV = pfont->data.lenIV;
400 int (*write_CharString)(stream *, const void *, uint) = stream_write;
401 int code = psf_get_type1_glyphs(&glyphs, pfont, orig_subset_glyphs,
402 orig_subset_size);
403
404 if (code < 0)
405 return code;
406
407 /* Initialize the parameter printer. */
408
409 ppp = param_printer_params_default;
410 ppp.item_suffix = " def\n";
411 ppp.print_ok =
412 (options & WRITE_TYPE1_ASCIIHEX ? 0 : PRINT_BINARY_OK) |
413 PRINT_HEX_NOT_OK;
414 code = s_init_param_printer(&rlist, &ppp, s);
415 if (code < 0)
416 return code;
417
418 /* Write the font header. */
419
420 stream_puts(s, "%!FontType1-1.0: ");
421 write_font_name(s, pfont, alt_font_name, false);
422 stream_puts(s, "\n11 dict begin\n");
423
424 /* Write FontInfo. */
425
426 stream_puts(s, "/FontInfo 5 dict dup begin");
427 {
428 gs_font_info_t info;
429 int code = pfont->procs.font_info((gs_font *)pfont, NULL,
430 (FONT_INFO_COPYRIGHT | FONT_INFO_NOTICE |
431 FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME),
432 &info);
433
434 if (code >= 0) {
435 write_font_info(s, "Copyright", &info.Copyright,
436 info.members & FONT_INFO_COPYRIGHT);
437 write_font_info(s, "Notice", &info.Notice,
438 info.members & FONT_INFO_NOTICE);
439 write_font_info(s, "FamilyName", &info.FamilyName,
440 info.members & FONT_INFO_FAMILY_NAME);
441 write_font_info(s, "FullName", &info.FullName,
442 info.members & FONT_INFO_FULL_NAME);
443 }
444 }
445 stream_puts(s, "\nend readonly def\n");
446
447 /* Write the main font dictionary. */
448
449 stream_puts(s, "/FontName ");
450 write_font_name(s, pfont, alt_font_name, true);
451 stream_puts(s, " def\n");
452 code = write_Encoding(s, pfont, options, glyphs.subset_glyphs,
453 glyphs.subset_size, glyphs.notdef);
454 if (code < 0)
455 return code;
456 pprintg6(s, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
457 pfont->FontMatrix.xx, pfont->FontMatrix.xy,
458 pfont->FontMatrix.yx, pfont->FontMatrix.yy,
459 pfont->FontMatrix.tx, pfont->FontMatrix.ty);
460 write_uid(s, &pfont->UID);
461 pprintg4(s, "/FontBBox {%g %g %g %g} readonly def\n",
462 pfont->FontBBox.p.x, pfont->FontBBox.p.y,
463 pfont->FontBBox.q.x, pfont->FontBBox.q.y);
464 {
465 static const gs_param_item_t font_items[] = {
466 {"FontType", gs_param_type_int,
467 offset_of(gs_font_type1, FontType)},
468 {"PaintType", gs_param_type_int,
469 offset_of(gs_font_type1, PaintType)},
470 {"StrokeWidth", gs_param_type_float,
471 offset_of(gs_font_type1, StrokeWidth)},
472 gs_param_item_end
473 };
474
475 code = gs_param_write_items(plist, pfont, NULL, font_items);
476 if (code < 0)
477 return code;
478 }
479 {
480 const gs_type1_data *const pdata = &pfont->data;
481
482 write_float_array(plist, "WeightVector", pdata->WeightVector.values,
483 pdata->WeightVector.count);
484 }
485 stream_puts(s, "currentdict end\n");
486
487 /* Write the Private dictionary. */
488
489 if (lenIV < 0 && (options & WRITE_TYPE1_WITH_LENIV)) {
490 /* We'll have to encrypt the CharStrings. */
491 lenIV = 0;
492 write_CharString = stream_write_encrypted;
493 }
494 if (options & WRITE_TYPE1_EEXEC) {
495 stream_puts(s, "currentfile eexec\n");
496 lengths[0] = stell(s) - start;
497 start = stell(s);
498 if (options & WRITE_TYPE1_ASCIIHEX) {
499 s_init(&AXE_stream, s->memory);
500 s_init_state((stream_state *)&AXE_state, &s_AXE_template, NULL);
501 AXE_state.EndOfData = false;
502 s_init_filter(&AXE_stream, (stream_state *)&AXE_state,
503 AXE_buf, sizeof(AXE_buf), es);
504 es = &AXE_stream;
505 }
506 s_init(&exE_stream, s->memory);
507 s_init_state((stream_state *)&exE_state, &s_exE_template, NULL);
508 exE_state.cstate = 55665;
509 s_init_filter(&exE_stream, (stream_state *)&exE_state,
510 exE_buf, sizeof(exE_buf), es);
511 es = &exE_stream;
512 /*
513 * Note: eexec encryption always writes/skips 4 initial bytes, not
514 * the number of initial bytes given by pdata->lenIV.
515 */
516 stream_puts(es, "****");
517 }
518 code = write_Private(es, pfont, glyphs.subset_glyphs, glyphs.subset_size,
519 glyphs.notdef, lenIV, write_CharString, &ppp);
520 if (code < 0)
521 return code;
522 stream_puts(es, "dup/FontName get exch definefont pop\n");
523 if (options & WRITE_TYPE1_EEXEC) {
524 if (options & (WRITE_TYPE1_EEXEC_PAD | WRITE_TYPE1_EEXEC_MARK))
525 stream_puts(es, "mark ");
526 stream_puts(es, "currentfile closefile\n");
527 s_close_filters(&es, s);
528 lengths[1] = stell(s) - start;
529 start = stell(s);
530 if (options & WRITE_TYPE1_EEXEC_PAD) {
531 int i;
532
533 for (i = 0; i < 8; ++i)
534 stream_puts(s, "\n0000000000000000000000000000000000000000000000000000000000000000");
535 stream_puts(s, "\ncleartomark\n");
536 }
537 lengths[2] = stell(s) - start;
538 } else {
539 lengths[0] = stell(s) - start;
540 lengths[1] = lengths[2] = 0;
541 }
542
543 /* Wrap up. */
544
545 s_release_param_printer(&rlist);
546 return 0;
547 }
548