Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1989, 1995, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: zbfont.c,v 1.30 2005/07/27 11:24:38 igor Exp $ */
18
/* Font creation utilities */
19
#include "memory_.h"
20
#include "string_.h"
21
#include "ghost.h"
22
#include "oper.h"
23
#include "gxfixed.h"
24
#include "gscencs.h"
25
#include "gsmatrix.h"
26
#include "gxdevice.h"
27
#include "gxfont.h"
28
#include "bfont.h"
29
#include "ialloc.h"
30
#include "idict.h"
31
#include "idparam.h"
32
#include "ilevel.h"
33
#include "iname.h"
34
#include "inamedef.h"		/* for inlining name_index */
35
#include "interp.h"		/* for initial_enter_name */
36
#include "ipacked.h"
37
#include "istruct.h"
38
#include "store.h"
39
 
40
/* Structure descriptor */
41
public_st_font_data();
42
 
43
/* <string|name> <font_dict> .buildfont3 <string|name> <font> */
44
/* Build a type 3 (user-defined) font. */
45
private int
46
zbuildfont3(i_ctx_t *i_ctx_p)
47
{
48
    os_ptr op = osp;
49
    int code;
50
    build_proc_refs build;
51
    gs_font_base *pfont;
52
 
53
    check_type(*op, t_dictionary);
54
    code = build_gs_font_procs(op, &build);
55
    if (code < 0)
56
	return code;
57
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_user_defined,
58
				&st_gs_font_base, &build, bf_options_none);
59
    if (code < 0)
60
	return code;
61
    return define_gs_font((gs_font *) pfont);
62
}
63
 
64
/* Encode a character. */
65
gs_glyph
66
zfont_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t gspace)
67
{
68
    font_data *pdata = pfont_data(pfont);
69
    const ref *pencoding = &pdata->Encoding;
70
    ulong index = chr;	/* work around VAX widening bug */
71
    ref cname;
72
    int code = array_get(pfont->memory, pencoding, (long)index, &cname);
73
 
74
    if (code < 0 || !r_has_type(&cname, t_name))
75
	return gs_no_glyph;
76
    if (pfont->FontType == ft_user_defined && r_type(&pdata->BuildGlyph) == t_null) {
77
	ref nsref, tname;
78
 
79
	name_string_ref(pfont->memory, &cname, &nsref);
80
	if (r_size(&nsref) == 7 && 
81
	    !memcmp(nsref.value.const_bytes, ".notdef", r_size(&nsref))) {
82
	    /* A special support for high level devices.
83
	       They need a glyph name but the font doesn't provide one
84
	       due to an instandard BuildChar.
85
	       Such fonts don't conform to PLRM section 5.3.7,
86
	       but we've got real examples that we want to handle (Bug 686982).
87
	       Construct a name here.
88
	       Low level devices don't pass here, because regular PS interpretation 
89
	       doesn't need such names.
90
	    */
91
	    char buf[20];
92
	    int code;
93
 
94
	    if (gspace == GLYPH_SPACE_NOGEN)
95
		return gs_no_glyph;    
96
	    sprintf(buf, "j%ld", chr); /* 'j' is arbutrary. */
97
	    code = name_ref(pfont->memory, (const byte *)buf, strlen(buf), &tname, 1);
98
	    if (code < 0) {
99
		/* Can't propagate the error due to interface limitation,
100
		   return with .notdef */
101
	    } else
102
		cname = tname;
103
	}
104
    }
105
    return (gs_glyph)name_index(pfont->memory, &cname);
106
}
107
 
108
/* Get the name of a glyph. */
109
private int
110
zfont_glyph_name(gs_font *font, gs_glyph index, gs_const_string *pstr)
111
{
112
    ref nref, sref;
113
 
114
    if (index >= gs_min_cid_glyph) {	/* Fabricate a numeric name. */
115
	char cid_name[sizeof(gs_glyph) * 3 + 1];
116
	int code;
117
 
118
	sprintf(cid_name, "%lu", (ulong) index);
119
	code = name_ref(font->memory, (const byte *)cid_name, strlen(cid_name),
120
			&nref, 1);
121
	if (code < 0)
122
	    return code;
123
    } else
124
	name_index_ref(font->memory, index, &nref);
125
    name_string_ref(font->memory, &nref, &sref);
126
    pstr->data = sref.value.const_bytes;
127
    pstr->size = r_size(&sref);
128
    return 0;
129
}
130
 
131
private gs_char 
132
gs_font_map_glyph_by_dict(const gs_memory_t *mem, const ref *map, gs_glyph glyph)
133
{
134
    ref *v, n;
135
    if (glyph >= gs_min_cid_glyph) {
136
	uint cid = glyph - gs_min_cid_glyph;
137
 
138
	if (dict_find_string(map, "CIDCount", &v) > 0) {
139
	    /* This is a CIDDEcoding resource. */
140
	    make_int(&n, cid / 256);
141
	    if (dict_find(map, &n, &v) > 0) {
142
		ref vv;
143
 
144
		if (array_get(mem, v, cid % 256, &vv) == 0 && r_type(&vv) == t_integer)
145
		    return vv.value.intval;
146
	    }
147
	    return GS_NO_CHAR; /* Absent in the map. */
148
	}
149
	/* This is GlyphNames2Unicode dictionary. */
150
	make_int(&n, cid);
151
    } else
152
	name_index_ref(mem, glyph, &n);
153
    if (dict_find(map, &n, &v) > 0) {
154
	if (r_has_type(v, t_string)) {
155
	    int i, l = r_size(v);
156
	    gs_char c = 0;
157
 
158
	    for (i = 0; i < l; i++)
159
		c = (c << 8) | v->value.const_bytes[i];
160
	    return c;
161
	}
162
	if (r_type(v) == t_integer)
163
	    return v->value.intval;
164
    }
165
    return GS_NO_CHAR; /* Absent in the map. */
166
}
167
 
168
/* Get Unicode UTF-16 code for a glyph. */
169
gs_char 
170
gs_font_map_glyph_to_unicode(gs_font *font, gs_glyph glyph)
171
{
172
    font_data *pdata = pfont_data(font);
173
    const ref *UnicodeDecoding;
174
 
175
    if (r_type(&pdata->GlyphNames2Unicode) == t_dictionary) {
176
	gs_char c = gs_font_map_glyph_by_dict(font->memory, 
177
					      &pdata->GlyphNames2Unicode, glyph);
178
 
179
	if (c != GS_NO_CHAR)
180
	    return c;
181
	/* 
182
	 * Fall through, because test.ps for SF bug #529103 requres 
183
	 * to examine both tables. Due to that the Unicode Decoding resource 
184
	 * can't be a default value for FontInfo.GlyphNames2Unicode .
185
	 */
186
    }
187
    UnicodeDecoding = zfont_get_to_unicode_map(font->dir);
188
    if (UnicodeDecoding != NULL && r_type(UnicodeDecoding) == t_dictionary)
189
	return gs_font_map_glyph_by_dict(font->memory, UnicodeDecoding, glyph);
190
    return GS_NO_CHAR; /* No map. */
191
}
192
 
193
/* ------ Initialization procedure ------ */
194
 
195
const op_def zbfont_op_defs[] =
196
{
197
    {"2.buildfont3", zbuildfont3},
198
    op_def_end(0)
199
};
200
 
201
/* ------ Subroutines ------ */
202
 
203
/* Convert strings to executable names for build_proc_refs. */
204
int
205
build_proc_name_refs(const gs_memory_t *mem, build_proc_refs * pbuild,
206
		     const char *bcstr, const char *bgstr)
207
{
208
    int code;
209
 
210
    if (!bcstr)
211
	make_null(&pbuild->BuildChar);
212
    else {
213
	if ((code = name_ref(mem, (const byte *)bcstr, 
214
			     strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
215
	    return code;
216
	r_set_attrs(&pbuild->BuildChar, a_executable);
217
    }
218
    if (!bgstr)
219
	make_null(&pbuild->BuildGlyph);
220
    else {
221
	if ((code = name_ref(mem, (const byte *)bgstr, 
222
			     strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
223
	    return code;
224
	r_set_attrs(&pbuild->BuildGlyph, a_executable);
225
    }
226
    return 0;
227
}
228
 
229
/* Get the BuildChar and/or BuildGlyph routines from a (base) font. */
230
int
231
build_gs_font_procs(os_ptr op, build_proc_refs * pbuild)
232
{
233
    int ccode, gcode;
234
    ref *pBuildChar;
235
    ref *pBuildGlyph;
236
 
237
    check_type(*op, t_dictionary);
238
    ccode = dict_find_string(op, "BuildChar", &pBuildChar);
239
    gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
240
    if (ccode <= 0) {
241
	if (gcode <= 0)
242
	    return_error(e_invalidfont);
243
	make_null(&pbuild->BuildChar);
244
    } else {
245
	check_proc(*pBuildChar);
246
	pbuild->BuildChar = *pBuildChar;
247
    }
248
    if (gcode <= 0)
249
	make_null(&pbuild->BuildGlyph);
250
    else {
251
	check_proc(*pBuildGlyph);
252
	pbuild->BuildGlyph = *pBuildGlyph;
253
    }
254
    return 0;
255
}
256
 
257
private int font_with_same_UID_and_another_metrics(const gs_font *pfont0, const gs_font *pfont1)
258
{
259
    const gs_font_base *pbfont0 = (const gs_font_base *)pfont0;
260
    const gs_font_base *pbfont1 = (const gs_font_base *)pfont1;
261
 
262
 
263
    if (uid_equal(&pbfont0->UID, &pbfont1->UID)) {
264
	const ref *pfdict0 = &pfont_data(gs_font_parent(pbfont0))->dict;
265
	const ref *pfdict1 = &pfont_data(gs_font_parent(pbfont1))->dict;
266
	ref *pmdict0, *pmdict1;
267
 
268
	if (pbfont0->WMode || dict_find_string(pfdict0, "Metrics", &pmdict0) <= 0)
269
	    pmdict0 = NULL;
270
	if (pbfont1->WMode || dict_find_string(pfdict1, "Metrics", &pmdict1) <= 0)
271
	    pmdict1 = NULL;
272
	if (!pmdict0 != !pmdict1)
273
	    return 1;
274
	if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
275
	    return 1;
276
	if (!pbfont0->WMode || dict_find_string(pfdict0, "Metrics2", &pmdict0) <= 0)
277
	    pmdict0 = NULL;
278
	if (!pbfont0->WMode || dict_find_string(pfdict1, "Metrics2", &pmdict1) <= 0)
279
	    pmdict1 = NULL;
280
	if (!pmdict0 != !pmdict1)
281
	    return 1;
282
	if (pmdict0 != NULL && !obj_eq(pfont0->memory, pmdict0, pmdict1))
283
	    return 1;
284
    }
285
    return 0;
286
}
287
 
288
/* Do the common work for building a primitive font -- one whose execution */
289
/* algorithm is implemented in C (Type 1, Type 2, Type 4, or Type 42). */
290
/* The caller guarantees that *op is a dictionary. */
291
int
292
build_gs_primitive_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
293
			font_type ftype, gs_memory_type_ptr_t pstype,
294
			const build_proc_refs * pbuild,
295
			build_font_options_t options)
296
{
297
    ref *pcharstrings = 0;
298
    ref CharStrings;
299
    gs_font_base *pfont;
300
    font_data *pdata;
301
    int code;
302
 
303
    if (dict_find_string(op, "CharStrings", &pcharstrings) <= 0) {
304
	if (!(options & bf_CharStrings_optional))
305
	    return_error(e_invalidfont);
306
    } else {
307
	ref *ignore;
308
 
309
	if (!r_has_type(pcharstrings, t_dictionary))
310
	    return_error(e_invalidfont);
311
	if ((options & bf_notdef_required) != 0 &&
312
	    dict_find_string(pcharstrings, ".notdef", &ignore) <= 0
313
	    )
314
	    return_error(e_invalidfont);
315
	/*
316
	 * Since build_gs_simple_font may resize the dictionary and cause
317
	 * pointers to become invalid, save CharStrings.
318
	 */
319
	CharStrings = *pcharstrings;
320
    }
321
    code = build_gs_outline_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
322
				 options, build_gs_simple_font);
323
    if (code != 0)
324
	return code;
325
    pfont = *ppfont;
326
    pdata = pfont_data(pfont);
327
    if (pcharstrings)
328
	ref_assign(&pdata->CharStrings, &CharStrings);
329
    else
330
	make_null(&pdata->CharStrings);
331
    /* Check that the UniqueIDs match.  This is part of the */
332
    /* Adobe protection scheme, but we may as well emulate it. */
333
    if (uid_is_valid(&pfont->UID) &&
334
	!dict_check_uid_param(op, &pfont->UID)
335
	)
336
	uid_set_invalid(&pfont->UID);
337
    if (uid_is_valid(&pfont->UID)) {
338
	const gs_font *pfont0 = (const gs_font *)pfont;
339
 
340
	code = gs_font_find_similar(ifont_dir, &pfont0, 
341
		       font_with_same_UID_and_another_metrics);
342
	if (code < 0)
343
	    return code; /* Must not happen. */
344
	if (code)
345
	    uid_set_invalid(&pfont->UID);
346
    }
347
    return 0;
348
}
349
 
350
/* Build a FDArray entry for a CIDFontType 0 font. */
351
/* Note that as of Adobe PostScript version 3011, this may be either */
352
/* a Type 1 or Type 2 font. */
353
private int
354
build_FDArray_sub_font(i_ctx_t *i_ctx_p, ref *op,
355
		       gs_font_base **ppfont,
356
		       font_type ftype, gs_memory_type_ptr_t pstype,
357
		       const build_proc_refs * pbuild,
358
		       build_font_options_t ignore_options)
359
{
360
    gs_font *pfont;
361
    int code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype, pbuild,
362
				 NULL, op);
363
 
364
    if (code >= 0)
365
	*ppfont = (gs_font_base *)pfont;
366
    return code;
367
}
368
int
369
build_gs_FDArray_font(i_ctx_t *i_ctx_p, ref *op,
370
		      gs_font_base **ppfont,
371
		      font_type ftype, gs_memory_type_ptr_t pstype,
372
		      const build_proc_refs * pbuild)
373
{
374
    gs_font_base *pfont;
375
    font_data *pdata;
376
    int code = build_gs_outline_font(i_ctx_p, op, &pfont, ftype, pstype,
377
				     pbuild, bf_options_none,
378
				     build_FDArray_sub_font);
379
    static const double bbox[4] = { 0, 0, 0, 0 };
380
    gs_uid uid;
381
 
382
    if (code < 0)
383
	return code;
384
    pdata = pfont_data(pfont);
385
    /* Fill in members normally set by build_gs_primitive_font. */
386
    make_null(&pdata->CharStrings);
387
    /* Fill in members normally set by build_gs_simple_font. */
388
    uid_set_invalid(&uid);
389
    init_gs_simple_font(pfont, bbox, &uid);
390
    pfont->encoding_index = ENCODING_INDEX_UNKNOWN;
391
    pfont->nearest_encoding_index = ENCODING_INDEX_UNKNOWN;
392
    /* Fill in members normally set by build_gs_font. */
393
    pfont->key_name = pfont->font_name;
394
    *ppfont = pfont;
395
    return 0;
396
}
397
 
398
/* Do the common work for building an outline font -- a non-composite font */
399
/* for which PaintType and StrokeWidth are meaningful. */
400
/* The caller guarantees that *op is a dictionary. */
401
int
402
build_gs_outline_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
403
		      font_type ftype, gs_memory_type_ptr_t pstype,
404
		      const build_proc_refs * pbuild,
405
		      build_font_options_t options,
406
		      build_base_font_proc_t build_base_font)
407
{
408
    int painttype;
409
    float strokewidth;
410
    gs_font_base *pfont;
411
    int code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
412
 
413
    if (code < 0)
414
	return code;
415
    code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
416
    if (code < 0)
417
	return code;
418
    code = build_base_font(i_ctx_p, op, ppfont, ftype, pstype, pbuild,
419
			   options);
420
    if (code != 0)
421
	return code;
422
    pfont = *ppfont;
423
    pfont->PaintType = painttype;
424
    pfont->StrokeWidth = strokewidth;
425
    return 0;
426
}
427
 
428
/* Do the common work for building a font of any non-composite FontType. */
429
/* The caller guarantees that *op is a dictionary. */
430
int
431
build_gs_simple_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font_base ** ppfont,
432
		     font_type ftype, gs_memory_type_ptr_t pstype,
433
		     const build_proc_refs * pbuild,
434
		     build_font_options_t options)
435
{
436
    double bbox[4];
437
    gs_uid uid;
438
    int code;
439
    gs_font_base *pfont;
440
    ref *pfontinfo, *g2u = NULL, Glyph2Unicode;
441
 
442
    if (dict_find_string(op, "FontInfo", &pfontinfo) <= 0 ||
443
	    !r_has_type(pfontinfo, t_dictionary) ||
444
	    dict_find_string(pfontinfo, "GlyphNames2Unicode", &g2u) <= 0 ||
445
	    !r_has_type(pfontinfo, t_dictionary))
446
	g2u = NULL;
447
    else
448
	/*
449
	 * Since build_gs_font may resize the dictionary and cause
450
	 * pointers to become invalid, save Glyph2Unicode
451
	 */
452
	Glyph2Unicode = *g2u;
453
    code = font_bbox_param(imemory, op, bbox);
454
    if (code < 0)
455
	return code;
456
    code = dict_uid_param(op, &uid, 0, imemory, i_ctx_p);
457
    if (code < 0)
458
	return code;
459
    if ((options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid))
460
	uid_set_invalid(&uid);
461
    code = build_gs_font(i_ctx_p, op, (gs_font **) ppfont, ftype, pstype,
462
			 pbuild, options);
463
    if (code != 0)		/* invalid or scaled font */
464
	return code;
465
    pfont = *ppfont;
466
    pfont->procs.init_fstack = gs_default_init_fstack;
467
    pfont->procs.define_font = gs_no_define_font;
468
    pfont->procs.decode_glyph = gs_font_map_glyph_to_unicode;
469
    pfont->procs.make_font = zbase_make_font;
470
    pfont->procs.next_char_glyph = gs_default_next_char_glyph;
471
    pfont->FAPI = 0;
472
    pfont->FAPI_font_data = 0;
473
    init_gs_simple_font(pfont, bbox, &uid);
474
    lookup_gs_simple_font_encoding(pfont);
475
    if (g2u != NULL) {
476
	font_data *pdata = pfont_data(pfont);
477
 
478
	ref_assign_new(&pdata->GlyphNames2Unicode, &Glyph2Unicode);
479
    }
480
    return 0;
481
}
482
 
483
/* Initialize the FontBBox and UID of a non-composite font. */
484
void
485
init_gs_simple_font(gs_font_base *pfont, const double bbox[4],
486
		    const gs_uid *puid)
487
{
488
    pfont->FontBBox.p.x = bbox[0];
489
    pfont->FontBBox.p.y = bbox[1];
490
    pfont->FontBBox.q.x = bbox[2];
491
    pfont->FontBBox.q.y = bbox[3];
492
    pfont->UID = *puid;
493
}
494
 
495
/* Compare the encoding of a simple font with the registered encodings. */
496
void
497
lookup_gs_simple_font_encoding(gs_font_base * pfont)
498
{
499
    const ref *pfe = &pfont_data(pfont)->Encoding;
500
    int index = -1;
501
 
502
    pfont->encoding_index = index;
503
    if (r_type(pfe) == t_array && r_size(pfe) <= 256) {
504
	/* Look for an encoding that's "close". */
505
	uint esize = r_size(pfe);
506
	int near_index = -1;
507
	uint best = esize / 3;	/* must match at least this many */
508
	gs_const_string fstrs[256];
509
	int i;
510
 
511
	/* Get the string names of the glyphs in the font's Encoding. */
512
	for (i = 0; i < esize; ++i) {
513
	    ref fchar;
514
 
515
	    if (array_get(pfont->memory, pfe, (long)i, &fchar) < 0 ||
516
		!r_has_type(&fchar, t_name)
517
		)
518
		fstrs[i].data = 0, fstrs[i].size = 0;
519
	    else {
520
		ref nsref;
521
 
522
		name_string_ref(pfont->memory, &fchar, &nsref);
523
		fstrs[i].data = nsref.value.const_bytes;
524
		fstrs[i].size = r_size(&nsref);
525
	    }
526
	}
527
	/* Compare them against the known encodings. */
528
	for (index = 0; index < NUM_KNOWN_REAL_ENCODINGS; ++index) {
529
	    uint match = esize;
530
 
531
	    for (i = esize; --i >= 0;) {
532
		gs_const_string rstr;
533
 
534
		gs_c_glyph_name(gs_c_known_encode((gs_char)i, index), &rstr);
535
		if (rstr.size == fstrs[i].size &&
536
		    !memcmp(rstr.data, fstrs[i].data, rstr.size)
537
		    )
538
		    continue;
539
		if (--match <= best)
540
		    break;
541
	    }
542
	    if (match > best) {
543
		best = match;
544
		near_index = index;
545
		/* If we have a perfect match, stop now. */
546
		if (best == esize)
547
		    break;
548
	    }
549
	}
550
	index = near_index;
551
	if (best == esize)
552
	    pfont->encoding_index = index;
553
    }
554
    pfont->nearest_encoding_index = index;
555
}
556
 
557
/* Get FontMatrix and FontName parameters. */
558
private int
559
sub_font_params(const gs_memory_t *mem, const ref *op, gs_matrix *pmat, gs_matrix *pomat, ref *pfname)
560
{
561
    ref *pmatrix;
562
    ref *pfontname;
563
    ref *porigfont;
564
 
565
    if (dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
566
	read_matrix(mem, pmatrix, pmat) < 0
567
	)
568
	return_error(e_invalidfont);
569
    if (dict_find_string(op, ".OrigFont", &porigfont) <= 0)
570
	porigfont = NULL;
571
    if (pomat!= NULL) {
572
	if (porigfont == NULL ||
573
	    dict_find_string(porigfont, "FontMatrix", &pmatrix) <= 0 ||
574
	    read_matrix(mem, pmatrix, pomat) < 0
575
	    )
576
	    memset(pomat, 0, sizeof(*pomat));
577
    }
578
    /* Use the FontInfo/OrigFontName key preferrentially (created by MS PSCRIPT driver) */
579
    if ((dict_find_string((porigfont != NULL ? porigfont : op), "FontInfo", &pfontname) > 0) &&
580
        (dict_find_string(pfontname, "OrigFontName", &pfontname) > 0)) {
581
	get_font_name(mem, pfname, pfontname);
582
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), ".Alias", &pfontname) > 0) {
583
        /* If we emulate the font, we want the requested name rather than a substitute. */
584
	get_font_name(mem, pfname, pfontname);
585
    } else if (dict_find_string((porigfont != NULL ? porigfont : op), "FontName", &pfontname) > 0) {
586
	get_font_name(mem, pfname, pfontname);
587
    } else
588
	make_empty_string(pfname, a_readonly);
589
    return 0;
590
}
591
 
592
/* Do the common work for building a font of any FontType. */
593
/* The caller guarantees that *op is a dictionary. */
594
/* op[-1] must be the key under which the font is being registered */
595
/* in FontDirectory, normally a name or string. */
596
/* Return 0 for a new font, 1 for a font made by makefont or scalefont, */
597
/* or a negative error code. */
598
int
599
build_gs_font(i_ctx_t *i_ctx_p, os_ptr op, gs_font ** ppfont, font_type ftype,
600
	      gs_memory_type_ptr_t pstype, const build_proc_refs * pbuild,
601
	      build_font_options_t options)
602
{
603
    ref kname;			/* t_string */
604
    ref *pftype;
605
    ref *pencoding = 0;
606
    bool bitmapwidths;
607
    int exactsize, inbetweensize, transformedchar;
608
    int wmode;
609
    int code;
610
    gs_font *pfont;
611
    ref *pfid;
612
    ref *aop = dict_access_ref(op);
613
 
614
    get_font_name(imemory, &kname, op - 1);
615
    if (dict_find_string(op, "FontType", &pftype) <= 0 ||
616
	!r_has_type(pftype, t_integer) ||
617
	pftype->value.intval != (int)ftype
618
	)
619
	return_error(e_invalidfont);
620
    if (dict_find_string(op, "Encoding", &pencoding) <= 0) {
621
	if (!(options & bf_Encoding_optional))
622
	    return_error(e_invalidfont);
623
	pencoding = 0;
624
    } else {
625
	if (!r_is_array(pencoding))
626
	    return_error(e_invalidfont);
627
    }
628
    if ((code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
629
	(code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
630
	(code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
631
	(code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
632
	(code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
633
	)
634
	return code;
635
    code = dict_find_string(op, "FID", &pfid);
636
    if (code > 0) {
637
	if (!r_has_type(pfid, t_fontID))
638
	    return_error(e_invalidfont);
639
	/*
640
	 * If this font has a FID entry already, it might be a scaled font
641
	 * made by makefont or scalefont; in a Level 2 environment, it might
642
	 * be an existing font being registered under a second name, or a
643
	 * re-encoded font (which was invalid in Level 1, but dvips did it
644
	 * anyway).
645
	 */
646
	pfont = r_ptr(pfid, gs_font);
647
	if (pfont->base == pfont) {	/* original font */
648
	    if (!level2_enabled)
649
		return_error(e_invalidfont);
650
	    if (obj_eq(pfont->memory, pfont_dict(pfont), op)) {
651
		*ppfont = pfont;
652
		return 1;
653
	    }
654
	    /*
655
	     * This is a re-encoded font, or some other
656
	     * questionable situation in which the FID
657
	     * was preserved.  Pretend the FID wasn't there.
658
	     */
659
	} else {		/* This was made by makefont or scalefont. */
660
	    /* Just insert the new name. */
661
	    gs_matrix mat;
662
	    ref fname;			/* t_string */
663
 
664
	    code = sub_font_params(imemory, op, &mat, NULL, &fname);
665
	    if (code < 0)
666
		return code;
667
	    code = 1;
668
	    copy_font_name(&pfont->font_name, &fname);
669
	    goto set_name;
670
	}
671
    }
672
    /* This is a new font. */
673
    if (!r_has_attr(aop, a_write))
674
	return_error(e_invalidaccess);
675
    {
676
	ref encoding;
677
 
678
	/*
679
	 * Since add_FID may resize the dictionary and cause
680
	 * pencoding to become invalid, save the Encoding.
681
	 */
682
	if (pencoding) {
683
	    encoding = *pencoding;
684
	    pencoding = &encoding;
685
	}
686
	code = build_gs_sub_font(i_ctx_p, op, &pfont, ftype, pstype,
687
				 pbuild, pencoding, op);
688
	if (code < 0)
689
	    return code;
690
    }
691
    pfont->BitmapWidths = bitmapwidths;
692
    pfont->ExactSize = (fbit_type)exactsize;
693
    pfont->InBetweenSize = (fbit_type)inbetweensize;
694
    pfont->TransformedChar = (fbit_type)transformedchar;
695
    pfont->WMode = wmode;
696
    pfont->procs.font_info = zfont_info;
697
    code = 0;
698
set_name:
699
    copy_font_name(&pfont->key_name, &kname);
700
    *ppfont = pfont;
701
    return code;
702
}
703
 
704
/* Create a sub-font -- a font or an entry in the FDArray of a CIDFontType 0 */
705
/* font.  Default BitmapWidths, ExactSize, InBetweenSize, TransformedChar, */
706
/* and WMode; do not fill in key_name. */
707
/* The caller guarantees that *op is a dictionary. */
708
int
709
build_gs_sub_font(i_ctx_t *i_ctx_p, const ref *op, gs_font **ppfont,
710
		  font_type ftype, gs_memory_type_ptr_t pstype,
711
		  const build_proc_refs * pbuild, const ref *pencoding,
712
		  ref *fid_op)
713
{
714
    gs_matrix mat, omat;
715
    ref fname;			/* t_string */
716
    gs_font *pfont;
717
    font_data *pdata;
718
    /*
719
     * Make sure that we allocate the font data
720
     * in the same VM as the font dictionary.
721
     */
722
    uint space = ialloc_space(idmemory);
723
    int code = sub_font_params(imemory, op, &mat, &omat, &fname);
724
 
725
    if (code < 0)
726
	return code;
727
    ialloc_set_space(idmemory, r_space(op));
728
    pfont = gs_font_alloc(imemory, pstype, &gs_font_procs_default, NULL,
729
			  "buildfont(font)");
730
    pdata = ialloc_struct(font_data, &st_font_data,
731
			  "buildfont(data)");
732
    if (pfont == 0 || pdata == 0)
733
	code = gs_note_error(e_VMerror);
734
    else if (fid_op)
735
	code = add_FID(i_ctx_p, fid_op, pfont, iimemory);
736
    if (code < 0) {
737
	ifree_object(pdata, "buildfont(data)");
738
	ifree_object(pfont, "buildfont(font)");
739
	ialloc_set_space(idmemory, space);
740
	return code;
741
    }
742
    refset_null((ref *) pdata, sizeof(font_data) / sizeof(ref));
743
    ref_assign_new(&pdata->dict, op);
744
    ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
745
    ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
746
    if (pencoding)
747
	ref_assign_new(&pdata->Encoding, pencoding);
748
    pfont->client_data = pdata;
749
    pfont->FontType = ftype;
750
    pfont->FontMatrix = mat;
751
    pfont->orig_FontMatrix = omat;
752
    pfont->BitmapWidths = false;
753
    pfont->ExactSize = fbit_use_bitmaps;
754
    pfont->InBetweenSize = fbit_use_outlines;
755
    pfont->TransformedChar = fbit_use_outlines;
756
    pfont->WMode = 0;
757
    pfont->procs.encode_char = zfont_encode_char;
758
    pfont->procs.glyph_name = zfont_glyph_name;
759
    ialloc_set_space(idmemory, space);
760
    copy_font_name(&pfont->font_name, &fname);
761
    *ppfont = pfont;
762
    return 0;
763
}
764
 
765
/* Get the string corresponding to a font name. */
766
/* If the font name isn't a name or a string, return an empty string. */
767
void
768
get_font_name(const gs_memory_t *mem, ref * pfname, const ref * op)
769
{
770
    switch (r_type(op)) {
771
	case t_string:
772
	    *pfname = *op;
773
	    break;
774
	case t_name:
775
	    name_string_ref(mem, op, pfname);
776
	    break;
777
	default:
778
	    /* This is weird, but legal.... */
779
	    make_empty_string(pfname, a_readonly);
780
    }
781
}
782
 
783
/* Copy a font name into the gs_font structure. */
784
void
785
copy_font_name(gs_font_name * pfstr, const ref * pfname)
786
{
787
    uint size = r_size(pfname);
788
 
789
    if (size > gs_font_name_max)
790
	size = gs_font_name_max;
791
    memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
792
    /* Following is only for debugging printout. */
793
    pfstr->chars[size] = 0;
794
    pfstr->size = size;
795
}
796
 
797
/* Finish building a font, by calling gs_definefont if needed. */
798
int
799
define_gs_font(gs_font * pfont)
800
{
801
    return (pfont->base == pfont && pfont->dir == 0 ?
802
	    /* i.e., unregistered original font */
803
	    gs_definefont(ifont_dir, pfont) :
804
	    0);
805
}