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) 1992-2004 artofcode LLC.  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: iccfont.c,v 1.11 2004/10/26 02:50:56 giles Exp $ */
18
/* Initialization support for compiled fonts */
19
 
20
#include "string_.h"
21
#include "ghost.h"
22
#include "gsstruct.h"		/* for iscan.h */
23
#include "gscencs.h"
24
#include "gsmatrix.h"
25
#include "gxfont.h"		/* for ifont.h */
26
#include "ccfont.h"
27
#include "ierrors.h"
28
#include "ialloc.h"
29
#include "idict.h"
30
#include "ifont.h"
31
#include "iname.h"
32
#include "isave.h"		/* for ialloc_ref_array */
33
#include "iutil.h"
34
#include "oper.h"
35
#include "ostack.h"		/* for iscan.h */
36
#include "store.h"
37
#include "stream.h"		/* for iscan.h */
38
#include "strimpl.h"		/* for sfilter.h for picky compilers */
39
#include "sfilter.h"		/* for iscan.h */
40
#include "iscan.h"
41
 
42
/* ------ Private code ------ */
43
 
44
/* Forward references */
45
private int cfont_ref_from_string(i_ctx_t *, ref *, const char *, uint);
46
 
47
typedef struct {
48
    i_ctx_t *i_ctx_p;
49
    const char *str_array;
50
    ref next;
51
} str_enum;
52
 
53
inline private void
54
init_str_enum(str_enum *pse, i_ctx_t *i_ctx_p, const char *ksa)
55
{
56
    pse->i_ctx_p = i_ctx_p;
57
    pse->str_array = ksa;
58
}
59
 
60
typedef struct {
61
    cfont_dict_keys keys;
62
    str_enum strings;
63
} key_enum;
64
 
65
inline private void
66
init_key_enum(key_enum *pke, i_ctx_t *i_ctx_p, const cfont_dict_keys *pkeys,
67
	      const char *ksa)
68
{
69
    pke->keys = *pkeys;
70
    init_str_enum(&pke->strings, i_ctx_p, ksa);
71
}
72
 
73
/* Check for reaching the end of the keys. */
74
inline private bool
75
more_keys(const key_enum *pke)
76
{
77
    return (pke->keys.num_enc_keys | pke->keys.num_str_keys);
78
}
79
 
80
/* Get the next string from a string array. */
81
/* Return 1 if it was a string, 0 if it was something else, */
82
/* or an error code. */
83
private int
84
cfont_next_string(str_enum * pse)
85
{
86
    const byte *str = (const byte *)pse->str_array;
87
    uint len = (str[0] << 8) + str[1];
88
 
89
    if (len == 0xffff) {
90
	make_null(&pse->next);
91
	pse->str_array += 2;
92
	return 0;
93
    } else if (len >= 0xff00) {
94
	int code;
95
 
96
	len = ((len & 0xff) << 8) + str[2];
97
	code = cfont_ref_from_string(pse->i_ctx_p, &pse->next,
98
				     pse->str_array + 3, len);
99
	if (code < 0)
100
	    return code;
101
	pse->str_array += 3 + len;
102
	return 0;
103
    }
104
    make_const_string(&pse->next, avm_foreign, len, str + 2);
105
    pse->str_array += 2 + len;
106
    return 1;
107
}
108
 
109
/* Put the next entry into a dictionary. */
110
/* We know that more_keys(kp) is true. */
111
private int
112
cfont_put_next(ref * pdict, key_enum * kep, const ref * pvalue)
113
{
114
    i_ctx_t *i_ctx_p = kep->strings.i_ctx_p;
115
    cfont_dict_keys * const kp = &kep->keys;
116
    ref kname;
117
    int code;
118
 
119
    if (pdict->value.pdict == 0) {
120
	/* First time, create the dictionary. */
121
	code = dict_create(kp->num_enc_keys + kp->num_str_keys +
122
			   kp->extra_slots, pdict);
123
	if (code < 0)
124
	    return code;
125
    }
126
    if (kp->num_enc_keys) {
127
	const charindex *skp = kp->enc_keys++;
128
	gs_glyph glyph = gs_c_known_encode((gs_char)skp->charx, skp->encx);
129
	gs_const_string gstr;
130
 
131
	if (glyph == GS_NO_GLYPH)
132
	    code = gs_note_error(e_undefined);
133
	else if ((code = gs_c_glyph_name(glyph, &gstr)) >= 0)
134
	    code = name_ref(imemory, gstr.data, gstr.size, &kname, 0);
135
	kp->num_enc_keys--;
136
    } else {			/* must have kp->num_str_keys != 0 */
137
	code = cfont_next_string(&kep->strings);
138
	if (code != 1)
139
	    return (code < 0 ? code : gs_note_error(e_Fatal));
140
	code = name_ref(imemory, kep->strings.next.value.const_bytes,
141
			r_size(&kep->strings.next), &kname, 0);
142
	kp->num_str_keys--;
143
    }
144
    if (code < 0)
145
	return code;
146
    return dict_put(pdict, &kname, pvalue, &i_ctx_p->dict_stack);
147
}
148
 
149
/* ------ Routines called from compiled font initialization ------ */
150
 
151
/* Create a dictionary with general ref values. */
152
private int
153
cfont_ref_dict_create(i_ctx_t *i_ctx_p, ref *pdict,
154
		      const cfont_dict_keys *kp, cfont_string_array ksa,
155
		      const ref *values)
156
{
157
    key_enum kenum;
158
    const ref *vp = values;
159
 
160
    init_key_enum(&kenum, i_ctx_p, kp, ksa);
161
    pdict->value.pdict = 0;
162
    while (more_keys(&kenum)) {
163
	const ref *pvalue = vp++;
164
	int code = cfont_put_next(pdict, &kenum, pvalue);
165
 
166
	if (code < 0)
167
	    return code;
168
    }
169
    r_store_attrs(dict_access_ref(pdict), a_all, kp->dict_attrs);
170
    return 0;
171
}
172
 
173
/* Create a dictionary with string/null values. */
174
private int
175
cfont_string_dict_create(i_ctx_t *i_ctx_p, ref *pdict,
176
			 const cfont_dict_keys *kp, cfont_string_array ksa,
177
			 cfont_string_array kva)
178
{
179
    key_enum kenum;
180
    str_enum senum;
181
    uint attrs = kp->value_attrs;
182
 
183
    init_key_enum(&kenum, i_ctx_p, kp, ksa);
184
    init_str_enum(&senum, i_ctx_p, kva);
185
    pdict->value.pdict = 0;
186
    while (more_keys(&kenum)) {
187
	int code = cfont_next_string(&senum);
188
 
189
	switch (code) {
190
	    default:		/* error */
191
		return code;
192
	    case 1:		/* string */
193
		r_set_attrs(&senum.next, attrs);
194
	    case 0:		/* other */
195
		;
196
	}
197
	code = cfont_put_next(pdict, &kenum, &senum.next);
198
	if (code < 0)
199
	    return code;
200
    }
201
    r_store_attrs(dict_access_ref(pdict), a_all, kp->dict_attrs);
202
    return 0;
203
}
204
 
205
/* Create a dictionary with number values. */
206
private int
207
cfont_num_dict_create(i_ctx_t *i_ctx_p, ref * pdict,
208
		      const cfont_dict_keys * kp, cfont_string_array ksa,
209
		      const ref * values, const char *lengths)
210
{
211
    key_enum kenum;
212
    const ref *vp = values;
213
    const char *lp = lengths;
214
    ref vnum;
215
 
216
    init_key_enum(&kenum, i_ctx_p, kp, ksa);
217
    pdict->value.pdict = 0;
218
    while (more_keys(&kenum)) {
219
	int len = (lp == 0 ? 0 : *lp++);
220
	int code;
221
 
222
	if (len == 0)
223
	    vnum = *vp++;
224
	else {
225
	    --len;
226
	    make_const_array(&vnum, avm_foreign | a_readonly, len, vp);
227
	    vp += len;
228
	}
229
	code = cfont_put_next(pdict, &kenum, &vnum);
230
	if (code < 0)
231
	    return code;
232
    }
233
    r_store_attrs(dict_access_ref(pdict), a_all, kp->dict_attrs);
234
    return 0;
235
}
236
 
237
/* Create an array with name values. */
238
private int
239
cfont_name_array_create(i_ctx_t *i_ctx_p, ref * parray, cfont_string_array ksa,
240
			int size)
241
{
242
    int code = ialloc_ref_array(parray, a_readonly, size,
243
				"cfont_name_array_create");
244
    ref *aptr = parray->value.refs;
245
    int i;
246
    str_enum senum;
247
 
248
    if (code < 0)
249
	return code;
250
    init_str_enum(&senum, i_ctx_p, ksa);
251
    for (i = 0; i < size; i++, aptr++) {
252
	ref nref;
253
	int code = cfont_next_string(&senum);
254
 
255
	if (code != 1)
256
	    return (code < 0 ? code : gs_note_error(e_Fatal));
257
	code = name_ref(imemory, senum.next.value.const_bytes,
258
			r_size(&senum.next), &nref, 0);
259
	if (code < 0)
260
	    return code;
261
	ref_assign_new(aptr, &nref);
262
    }
263
    return 0;
264
}
265
 
266
/* Create an array with string/null values. */
267
private int
268
cfont_string_array_create(i_ctx_t *i_ctx_p, ref * parray,
269
			  cfont_string_array ksa, int size, uint attrs)
270
{
271
    int code = ialloc_ref_array(parray, a_readonly, size,
272
				"cfont_string_array_create");
273
    ref *aptr = parray->value.refs;
274
    int i;
275
    str_enum senum;
276
 
277
    if (code < 0)
278
	return code;
279
    init_str_enum(&senum, i_ctx_p, ksa);
280
    for (i = 0; i < size; i++, aptr++) {
281
	int code = cfont_next_string(&senum);
282
 
283
	switch (code) {
284
	    default:		/* error */
285
		return code;
286
	    case 1:		/* string */
287
		r_set_attrs(&senum.next, attrs);
288
	    case 0:		/* other */
289
		;
290
	}
291
	ref_mark_new(&senum.next);
292
	*aptr = senum.next;
293
    }
294
    return 0;
295
}
296
 
297
/* Create an array with scalar values. */
298
private int
299
cfont_scalar_array_create(i_ctx_t *i_ctx_p, ref * parray,
300
			  const ref *va, int size, uint attrs)
301
{
302
    int code = ialloc_ref_array(parray, attrs, size,
303
				"cfont_scalar_array_create");
304
    ref *aptr = parray->value.refs;
305
    uint elt_attrs = attrs | ialloc_new_mask;
306
    int i;
307
 
308
    if (code < 0)
309
	return code;
310
    memcpy(aptr, va, size * sizeof(ref));
311
    for (i = 0; i < size; i++, aptr++)
312
	r_set_attrs(aptr, elt_attrs);
313
    return 0;
314
}
315
 
316
/* Create a name. */
317
private int
318
cfont_name_create(i_ctx_t *i_ctx_p, ref * pnref, const char *str)
319
{
320
    return name_ref(imemory, (const byte *)str, strlen(str), pnref, 0);
321
}
322
 
323
/* Create an object by parsing a string. */
324
private int
325
cfont_ref_from_string(i_ctx_t *i_ctx_p, ref * pref, const char *str, uint len)
326
{
327
    scanner_state sstate;
328
    stream s;
329
    int code;
330
 
331
    scanner_state_init(&sstate, false);
332
    s_init(&s, imemory);
333
    sread_string(&s, (const byte *)str, len);
334
    code = scan_token(i_ctx_p, &s, pref, &sstate);
335
    return (code <= 0 ? code : gs_note_error(e_Fatal));
336
}
337
 
338
/* ------ Initialization ------ */
339
 
340
/* Procedure vector passed to font initialization procedures. */
341
private const cfont_procs ccfont_procs = {
342
    cfont_ref_dict_create,
343
    cfont_string_dict_create,
344
    cfont_num_dict_create,
345
    cfont_name_array_create,
346
    cfont_string_array_create,
347
    cfont_scalar_array_create,
348
    cfont_name_create,
349
    cfont_ref_from_string
350
};
351
 
352
/* null    .getccfont    <number-of-fonts> */
353
/* <int>   .getccfont    <font-object> */
354
private int
355
zgetccfont(i_ctx_t *i_ctx_p)
356
{
357
    os_ptr op = osp;
358
    int code;
359
    const ccfont_fproc *fprocs;
360
    int nfonts;
361
    int index;
362
 
363
    code = ccfont_fprocs(&nfonts, &fprocs);
364
    if (code != ccfont_version)
365
	return_error(e_invalidfont);
366
 
367
    if (r_has_type(op, t_null)) {
368
	make_int(op, nfonts);
369
	return 0;
370
    }
371
    check_type(*op, t_integer);
372
    index = op->value.intval;
373
    if (index < 0 || index >= nfonts)
374
	return_error(e_rangecheck);
375
 
376
    return (*fprocs[index]) (i_ctx_p, &ccfont_procs, op);
377
}
378
 
379
/* Operator table initialization */
380
 
381
const op_def ccfonts_op_defs[] =
382
{
383
    {"0.getccfont", zgetccfont},
384
    op_def_end(0)
385
};