Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1991, 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: zfont0.c,v 1.7 2004/08/04 19:36:13 stefan Exp $ */
18
/* Composite font creation operator */
19
#include "ghost.h"
20
#include "oper.h"
21
#include "gsstruct.h"
22
/*
23
 * The following lines used to say:
24
 *      #include "gsmatrix.h"
25
 *      #include "gxdevice.h"           /. for gxfont.h ./
26
 * Tony Li says the longer list is necessary to keep the GNU compiler
27
 * happy, but this is pretty hard to understand....
28
 */
29
#include "gxfixed.h"
30
#include "gxmatrix.h"
31
#include "gzstate.h"		/* must precede gxdevice */
32
#include "gxdevice.h"		/* must precede gxfont */
33
#include "gxfcmap.h"
34
#include "gxfont.h"
35
#include "gxfont0.h"
36
#include "bfont.h"
37
#include "ialloc.h"
38
#include "iddict.h"
39
#include "idparam.h"
40
#include "igstate.h"
41
#include "iname.h"
42
#include "store.h"
43
 
44
/* Imported from zfcmap.c */
45
int ztype0_get_cmap(const gs_cmap_t ** ppcmap, const ref * pfdepvector,
46
		    const ref * op, gs_memory_t *imem);
47
 
48
/* Forward references */
49
private font_proc_define_font(ztype0_define_font);
50
private font_proc_make_font(ztype0_make_font);
51
private int ensure_char_entry(i_ctx_t *, os_ptr, const char *, byte *, int);
52
 
53
/* <string|name> <font_dict> .buildfont0 <string|name> <font> */
54
/* Build a type 0 (composite) font. */
55
private int
56
zbuildfont0(i_ctx_t *i_ctx_p)
57
{
58
    os_ptr op = osp;
59
    gs_type0_data data;
60
    ref fdepvector;
61
    ref *pprefenc;
62
    gs_font_type0 *pfont;
63
    font_data *pdata;
64
    ref save_FID;
65
    int i;
66
    int code = 0;
67
 
68
    check_type(*op, t_dictionary);
69
    {
70
	ref *pfmaptype;
71
	ref *pfdepvector;
72
 
73
	if (dict_find_string(op, "FMapType", &pfmaptype) <= 0 ||
74
	    !r_has_type(pfmaptype, t_integer) ||
75
	    pfmaptype->value.intval < (int)fmap_type_min ||
76
	    pfmaptype->value.intval > (int)fmap_type_max ||
77
	    dict_find_string(op, "FDepVector", &pfdepvector) <= 0 ||
78
	    !r_is_array(pfdepvector)
79
	    )
80
	    return_error(e_invalidfont);
81
	data.FMapType = (fmap_type) pfmaptype->value.intval;
82
	/*
83
	 * Adding elements below could cause the font dictionary to be
84
	 * resized, which would invalidate pfdepvector.
85
	 */
86
	fdepvector = *pfdepvector;
87
    }
88
    /* Check that every element of the FDepVector is a font. */
89
    data.fdep_size = r_size(&fdepvector);
90
    for (i = 0; i < data.fdep_size; i++) {
91
	ref fdep;
92
	gs_font *psub;
93
 
94
	array_get(imemory, &fdepvector, i, &fdep);
95
	if ((code = font_param(&fdep, &psub)) < 0)
96
	    return code;
97
	/*
98
	 * Check the inheritance rules.  Allowed configurations
99
	 * (paths from root font) are defined by the regular
100
	 * expression:
101
	 *      (shift | double_escape escape* | escape*)
102
	 *        non_modal* non_composite
103
	 */
104
	if (psub->FontType == ft_composite) {
105
	    const gs_font_type0 *const psub0 = (const gs_font_type0 *)psub;
106
	    fmap_type fmt = psub0->data.FMapType;
107
 
108
	    if (fmt == fmap_double_escape ||
109
		fmt == fmap_shift ||
110
		(fmt == fmap_escape &&
111
		 !(data.FMapType == fmap_escape ||
112
		   data.FMapType == fmap_double_escape))
113
		)
114
		return_error(e_invalidfont);
115
	}
116
    }
117
    switch (data.FMapType) {
118
	case fmap_escape:
119
	case fmap_double_escape:	/* need EscChar */
120
	    code = ensure_char_entry(i_ctx_p, op, "EscChar", &data.EscChar, 255);
121
	    break;
122
	case fmap_shift:	/* need ShiftIn & ShiftOut */
123
	    code = ensure_char_entry(i_ctx_p, op, "ShiftIn", &data.ShiftIn, 15);
124
	    if (code >= 0)
125
		code = ensure_char_entry(i_ctx_p, op, "ShiftOut", &data.ShiftOut, 14);
126
	    break;
127
	case fmap_SubsVector:	/* need SubsVector */
128
	    {
129
		ref *psubsvector;
130
		uint svsize;
131
 
132
		if (dict_find_string(op, "SubsVector", &psubsvector) <= 0 ||
133
		    !r_has_type(psubsvector, t_string) ||
134
		    (svsize = r_size(psubsvector)) == 0 ||
135
		(data.subs_width = (int)*psubsvector->value.bytes + 1) > 4 ||
136
		    (svsize - 1) % data.subs_width != 0
137
		    )
138
		    return_error(e_invalidfont);
139
		data.subs_size = (svsize - 1) / data.subs_width;
140
		data.SubsVector.data = psubsvector->value.bytes + 1;
141
		data.SubsVector.size = svsize - 1;
142
	    } break;
143
	case fmap_CMap:	/* need CMap */
144
	    code = ztype0_get_cmap(&data.CMap, (const ref *)&fdepvector,
145
				   (const ref *)op, imemory);
146
	    break;
147
	default:
148
	    ;
149
    }
150
    if (code < 0)
151
	return code;
152
    /*
153
     * Save the old FID in case we have to back out.
154
     * build_gs_font will return an error if there is a FID entry
155
     * but it doesn't reference a valid font.
156
     */
157
    {
158
	ref *pfid;
159
 
160
	if (dict_find_string(op, "FID", &pfid) <= 0)
161
	    make_null(&save_FID);
162
	else
163
	    save_FID = *pfid;
164
    }
165
    {
166
	build_proc_refs build;
167
 
168
	code = build_proc_name_refs(imemory, &build,
169
				    "%Type0BuildChar", "%Type0BuildGlyph");
170
	if (code < 0)
171
	    return code;
172
	code = build_gs_font(i_ctx_p, op, (gs_font **) & pfont,
173
			     ft_composite, &st_gs_font_type0, &build,
174
			     bf_options_none);
175
    }
176
    if (code != 0)
177
	return code;
178
    /* Fill in the rest of the basic font data. */
179
    pfont->procs.init_fstack = gs_type0_init_fstack;
180
    pfont->procs.define_font = ztype0_define_font;
181
    pfont->procs.make_font = ztype0_make_font;
182
    pfont->procs.next_char_glyph = gs_type0_next_char_glyph;
183
    if (dict_find_string(op, "PrefEnc", &pprefenc) <= 0) {
184
	ref nul;
185
 
186
	make_null_new(&nul);
187
	if ((code = idict_put_string(op, "PrefEnc", &nul)) < 0)
188
	    goto fail;
189
    }
190
    /* Fill in the font data */
191
    pdata = pfont_data(pfont);
192
    data.encoding_size = r_size(&pdata->Encoding);
193
    data.Encoding =
194
	(uint *) ialloc_byte_array(data.encoding_size, sizeof(uint),
195
				   "buildfont0(Encoding)");
196
    if (data.Encoding == 0) {
197
	code = gs_note_error(e_VMerror);
198
	goto fail;
199
    }
200
    /* Fill in the encoding vector, checking to make sure that */
201
    /* each element is an integer between 0 and fdep_size-1. */
202
    for (i = 0; i < data.encoding_size; i++) {
203
	ref enc;
204
 
205
	array_get(imemory, &pdata->Encoding, i, &enc);
206
	if (!r_has_type(&enc, t_integer)) {
207
	    code = gs_note_error(e_typecheck);
208
	    goto fail;
209
	}
210
	if ((ulong) enc.value.intval >= data.fdep_size) {
211
	    code = gs_note_error(e_rangecheck);
212
	    goto fail;
213
	}
214
	data.Encoding[i] = (uint) enc.value.intval;
215
    }
216
    data.FDepVector =
217
	ialloc_struct_array(data.fdep_size, gs_font *,
218
			    &st_gs_font_ptr_element,
219
			    "buildfont0(FDepVector)");
220
    if (data.FDepVector == 0) {
221
	code = gs_note_error(e_VMerror);
222
	goto fail;
223
    }
224
    for (i = 0; i < data.fdep_size; i++) {
225
	ref fdep;
226
	ref *pfid;
227
 
228
	array_get(pfont->memory, &fdepvector, i, &fdep);
229
	/* The lookup can't fail, because of the pre-check above. */
230
	dict_find_string(&fdep, "FID", &pfid);
231
	data.FDepVector[i] = r_ptr(pfid, gs_font);
232
    }
233
    pfont->data = data;
234
    code = define_gs_font((gs_font *) pfont);
235
    if (code >= 0)
236
	return code;
237
fail:
238
	/* Undo the insertion of the FID entry in the dictionary. */
239
    if (r_has_type(&save_FID, t_null)) {
240
	ref rnfid;
241
 
242
	name_enter_string(pfont->memory, "FID", &rnfid);
243
	idict_undef(op, &rnfid);
244
    } else
245
	idict_put_string(op, "FID", &save_FID);
246
    gs_free_object(pfont->memory, pfont, "buildfont0(font)");
247
    return code;
248
}
249
/* If a newly defined or scaled composite font had to scale */
250
/* any composite sub-fonts, adjust the parent font's FDepVector. */
251
/* This is called only if gs_type0_define/make_font */
252
/* actually changed the FDepVector. */
253
private int
254
ztype0_adjust_FDepVector(gs_font_type0 * pfont)
255
{
256
    gs_memory_t *mem = pfont->memory;
257
    /* HACK: We know the font was allocated by the interpreter. */
258
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
259
    gs_font **pdep = pfont->data.FDepVector;
260
    ref newdep;
261
    uint fdep_size = pfont->data.fdep_size;
262
    ref *prdep;
263
    uint i;
264
    int code = gs_alloc_ref_array(imem, &newdep, a_readonly, fdep_size,
265
				  "ztype0_adjust_matrix");
266
 
267
    if (code < 0)
268
	return code;
269
    for (prdep = newdep.value.refs, i = 0; i < fdep_size; i++, prdep++) {
270
	const ref *pdict = pfont_dict(pdep[i]);
271
 
272
	ref_assign(prdep, pdict);
273
	r_set_attrs(prdep, imemory_new_mask(imem));
274
    }
275
    /*
276
     * The FDepVector is an existing key in the parent's dictionary,
277
     * so it's safe to pass NULL as the dstack pointer to dict_put_string.
278
     */
279
    return dict_put_string(pfont_dict(pfont), "FDepVector", &newdep, NULL);
280
}
281
private int
282
ztype0_define_font(gs_font_dir * pdir, gs_font * pfont)
283
{
284
    gs_font_type0 *const pfont0 = (gs_font_type0 *)pfont;
285
    gs_font **pdep = pfont0->data.FDepVector;
286
    int code = gs_type0_define_font(pdir, pfont);
287
 
288
    if (code < 0 || pfont0->data.FDepVector == pdep)
289
	return code;
290
    return ztype0_adjust_FDepVector(pfont0);
291
}
292
private int
293
ztype0_make_font(gs_font_dir * pdir, const gs_font * pfont,
294
		 const gs_matrix * pmat, gs_font ** ppfont)
295
{
296
    gs_font_type0 **const ppfont0 = (gs_font_type0 **)ppfont;
297
    gs_font **pdep = (*ppfont0)->data.FDepVector;
298
    int code;
299
 
300
    code = zdefault_make_font(pdir, pfont, pmat, ppfont);
301
    if (code < 0)
302
	return code;
303
    code = gs_type0_make_font(pdir, pfont, pmat, ppfont);
304
    if (code < 0)
305
	return code;
306
    if ((*ppfont0)->data.FDepVector == pdep)
307
	return 0;
308
    return ztype0_adjust_FDepVector(*ppfont0);
309
}
310
 
311
/* ------ Internal routines ------ */
312
 
313
/* Find or add a character entry in a font dictionary. */
314
private int
315
ensure_char_entry(i_ctx_t *i_ctx_p, os_ptr op, const char *kstr,
316
		  byte * pvalue, int default_value)
317
{
318
    ref *pentry;
319
 
320
    if (dict_find_string(op, kstr, &pentry) <= 0) {
321
	ref ent;
322
 
323
	make_int(&ent, default_value);
324
	*pvalue = (byte) default_value;
325
	return idict_put_string(op, kstr, &ent);
326
    } else {
327
	check_int_leu_only(*pentry, 255);
328
	*pvalue = (byte) pentry->value.intval;
329
	return 0;
330
    }
331
}
332
 
333
/* ------ Initialization procedure ------ */
334
 
335
const op_def zfont0_op_defs[] =
336
{
337
    {"2.buildfont0", zbuildfont0},
338
    op_def_end(0)
339
};