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