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) 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: zfont.c,v 1.12 2004/08/19 19:33:09 stefan Exp $ */
18
/* Generic font operators */
19
#include "ghost.h"
20
#include "oper.h"
21
#include "gsstruct.h"		/* for registering root */
22
#include "gzstate.h"		/* must precede gxdevice */
23
#include "gxdevice.h"		/* must precede gxfont */
24
#include "gxfont.h"
25
#include "gxfcache.h"
26
#include "bfont.h"
27
#include "ialloc.h"
28
#include "iddict.h"
29
#include "igstate.h"
30
#include "iname.h"		/* for name_mark_index */
31
#include "isave.h"
32
#include "store.h"
33
#include "ivmspace.h"
34
 
35
/* Forward references */
36
private int make_font(i_ctx_t *, const gs_matrix *);
37
private void make_uint_array(os_ptr, const uint *, int);
38
private int setup_unicode_decoder(i_ctx_t *i_ctx_p, ref *Decoding);
39
 
40
/* The (global) font directory */
41
gs_font_dir *ifont_dir = 0;	/* needed for buildfont */
42
 
43
/* Mark a glyph as a PostScript name (if it isn't a CID). */
44
bool
45
zfont_mark_glyph_name(const gs_memory_t *mem, gs_glyph glyph, void *ignore_data)
46
{
47
    return (glyph >= gs_min_cid_glyph || glyph == gs_no_glyph ? false :
48
	    name_mark_index(mem, (uint) glyph));
49
}
50
 
51
/* Get a global glyph code.  */
52
private int 
53
zfont_global_glyph_code(const gs_memory_t *mem, gs_const_string *gstr, gs_glyph *pglyph)
54
{
55
    ref v;
56
    int code = name_ref(mem, gstr->data, gstr->size, &v, 0);
57
 
58
    if (code < 0)
59
	return code;
60
    *pglyph = (gs_glyph)name_index(mem, &v);
61
    return 0;
62
}
63
 
64
/* Initialize the font operators */
65
private int
66
zfont_init(i_ctx_t *i_ctx_p)
67
{
68
    ifont_dir = gs_font_dir_alloc2(imemory, imemory->non_gc_memory);
69
    ifont_dir->ccache.mark_glyph = zfont_mark_glyph_name;
70
    ifont_dir->global_glyph_code = zfont_global_glyph_code;
71
    return gs_register_struct_root(imemory, NULL, (void **)&ifont_dir,
72
				   "ifont_dir");
73
}
74
 
75
/* <font> <scale> scalefont <new_font> */
76
private int
77
zscalefont(i_ctx_t *i_ctx_p)
78
{
79
    os_ptr op = osp;
80
    int code;
81
    double scale;
82
    gs_matrix mat;
83
 
84
    if ((code = real_param(op, &scale)) < 0)
85
	return code;
86
    if ((code = gs_make_scaling(scale, scale, &mat)) < 0)
87
	return code;
88
    return make_font(i_ctx_p, &mat);
89
}
90
 
91
/* <font> <matrix> makefont <new_font> */
92
private int
93
zmakefont(i_ctx_t *i_ctx_p)
94
{
95
    os_ptr op = osp;
96
    int code;
97
    gs_matrix mat;
98
 
99
    if ((code = read_matrix(imemory, op, &mat)) < 0)
100
	return code;
101
    return make_font(i_ctx_p, &mat);
102
}
103
 
104
/* <font> setfont - */
105
int
106
zsetfont(i_ctx_t *i_ctx_p)
107
{
108
    os_ptr op = osp;
109
    gs_font *pfont;
110
    int code = font_param(op, &pfont);
111
 
112
    if (code < 0 || (code = gs_setfont(igs, pfont)) < 0)
113
	return code;
114
    pop(1);
115
    return code;
116
}
117
 
118
/* - currentfont <font> */
119
private int
120
zcurrentfont(i_ctx_t *i_ctx_p)
121
{
122
    os_ptr op = osp;
123
 
124
    push(1);
125
    *op = *pfont_dict(gs_currentfont(igs));
126
    return 0;
127
}
128
 
129
/* - cachestatus <mark> <bsize> <bmax> <msize> <mmax> <csize> <cmax> <blimit> */
130
private int
131
zcachestatus(i_ctx_t *i_ctx_p)
132
{
133
    os_ptr op = osp;
134
    uint status[7];
135
 
136
    gs_cachestatus(ifont_dir, status);
137
    push(7);
138
    make_uint_array(op - 6, status, 7);
139
    return 0;
140
}
141
 
142
/* <blimit> setcachelimit - */
143
private int
144
zsetcachelimit(i_ctx_t *i_ctx_p)
145
{
146
    os_ptr op = osp;
147
 
148
    check_int_leu(*op, max_uint);
149
    gs_setcachelimit(ifont_dir, (uint) op->value.intval);
150
    pop(1);
151
    return 0;
152
}
153
 
154
/* <mark> <size> <lower> <upper> setcacheparams - */
155
private int
156
zsetcacheparams(i_ctx_t *i_ctx_p)
157
{
158
    os_ptr op = osp;
159
    uint params[3];
160
    int i, code;
161
    os_ptr opp = op;
162
 
163
    for (i = 0; i < 3 && !r_has_type(opp, t_mark); i++, opp--) {
164
	check_int_leu(*opp, max_uint);
165
	params[i] = opp->value.intval;
166
    }
167
    switch (i) {
168
	case 3:
169
	    if ((code = gs_setcachesize(ifont_dir, params[2])) < 0)
170
		return code;
171
	case 2:
172
	    if ((code = gs_setcachelower(ifont_dir, params[1])) < 0)
173
		return code;
174
	case 1:
175
	    if ((code = gs_setcacheupper(ifont_dir, params[0])) < 0)
176
		return code;
177
	case 0:;
178
    }
179
    return zcleartomark(i_ctx_p);
180
}
181
 
182
/* - currentcacheparams <mark> <size> <lower> <upper> */
183
private int
184
zcurrentcacheparams(i_ctx_t *i_ctx_p)
185
{
186
    os_ptr op = osp;
187
    uint params[3];
188
 
189
    params[0] = gs_currentcachesize(ifont_dir);
190
    params[1] = gs_currentcachelower(ifont_dir);
191
    params[2] = gs_currentcacheupper(ifont_dir);
192
    push(4);
193
    make_mark(op - 3);
194
    make_uint_array(op - 2, params, 3);
195
    return 0;
196
}
197
 
198
/* <font> .registerfont - */
199
private int
200
zregisterfont(i_ctx_t *i_ctx_p)
201
{
202
    os_ptr op = osp;
203
    gs_font *pfont;
204
    int code = font_param(op, &pfont);
205
 
206
    if (code < 0)
207
	return code;
208
    pfont->is_resource = true;
209
    pop(1);
210
    return 0;
211
}
212
 
213
 
214
/* <Decoding> .setupUnicodeDecoder - */
215
private int
216
zsetupUnicodeDecoder(i_ctx_t *i_ctx_p)
217
{   /* The allocation mode must be global. */
218
    os_ptr op = osp;
219
    int code;
220
 
221
    check_type(*op, t_dictionary);
222
    code = setup_unicode_decoder(i_ctx_p, op);
223
    if (code < 0)
224
	return code;
225
    pop(1);
226
    return 0;
227
}
228
 
229
/* ------ Initialization procedure ------ */
230
 
231
const op_def zfont_op_defs[] =
232
{
233
    {"0currentfont", zcurrentfont},
234
    {"2makefont", zmakefont},
235
    {"2scalefont", zscalefont},
236
    {"1setfont", zsetfont},
237
    {"0cachestatus", zcachestatus},
238
    {"1setcachelimit", zsetcachelimit},
239
    {"1setcacheparams", zsetcacheparams},
240
    {"0currentcacheparams", zcurrentcacheparams},
241
    {"1.registerfont", zregisterfont},
242
    {"1.setupUnicodeDecoder", zsetupUnicodeDecoder},
243
    op_def_end(zfont_init)
244
};
245
 
246
/* ------ Subroutines ------ */
247
 
248
/* Validate a font parameter. */
249
int
250
font_param(const ref * pfdict, gs_font ** ppfont)
251
{	/*
252
	 * Check that pfdict is a read-only dictionary, that it has a FID
253
	 * entry whose value is a fontID, and that the fontID points to a
254
	 * gs_font structure whose associated PostScript dictionary is
255
	 * pfdict.
256
	 */
257
    ref *pid;
258
    gs_font *pfont;
259
    const font_data *pdata;
260
 
261
    check_type(*pfdict, t_dictionary);
262
    if (dict_find_string(pfdict, "FID", &pid) <= 0 ||
263
	!r_has_type(pid, t_fontID)
264
	)
265
	return_error(e_invalidfont);
266
    pfont = r_ptr(pid, gs_font);
267
    pdata = pfont->client_data;
268
    if (!obj_eq(pfont->memory, &pdata->dict, pfdict))
269
	return_error(e_invalidfont);
270
    *ppfont = pfont;
271
    if (pfont == 0)
272
	return_error(e_invalidfont);	/* unregistered font */
273
    return 0;
274
}
275
 
276
/* Add the FID entry to a font dictionary. */
277
/* Note that i_ctx_p may be NULL. */
278
int
279
add_FID(i_ctx_t *i_ctx_p, ref * fp /* t_dictionary */ , gs_font * pfont,
280
	gs_ref_memory_t *imem)
281
{
282
    ref fid;
283
 
284
    make_tav(&fid, t_fontID,
285
	     a_readonly | imemory_space(imem) | imemory_new_mask(imem),
286
	     pstruct, (void *)pfont);
287
    return (i_ctx_p ? idict_put_string(fp, "FID", &fid) :
288
	    dict_put_string(fp, "FID", &fid, NULL));
289
}
290
 
291
/* Make a transformed font (common code for makefont/scalefont). */
292
private int
293
make_font(i_ctx_t *i_ctx_p, const gs_matrix * pmat)
294
{
295
    os_ptr op = osp;
296
    os_ptr fp = op - 1;
297
    gs_font *oldfont, *newfont;
298
    int code;
299
    ref *pencoding = 0;
300
 
301
    code = font_param(fp, &oldfont);
302
    if (code < 0)
303
	return code;
304
    {
305
	uint space = ialloc_space(idmemory);
306
 
307
	ialloc_set_space(idmemory, r_space(fp));
308
	if (dict_find_string(fp, "Encoding", &pencoding) > 0 &&
309
	    !r_is_array(pencoding)
310
	    )
311
	    code = gs_note_error(e_invalidfont);
312
	else {
313
		/*
314
		 * Temporarily substitute the new dictionary
315
		 * for the old one, in case the Encoding changed.
316
		 */
317
	    ref olddict;
318
 
319
	    olddict = *pfont_dict(oldfont);
320
	    *pfont_dict(oldfont) = *fp;
321
	    code = gs_makefont(ifont_dir, oldfont, pmat, &newfont);
322
	    *pfont_dict(oldfont) = olddict;
323
	}
324
	ialloc_set_space(idmemory, space);
325
    }
326
    if (code < 0)
327
	return code;
328
    /*
329
     * We have to allow for the possibility that the font's Encoding
330
     * is different from that of the base font.  Note that the
331
     * font_data of the new font was simply copied from the old one.
332
     */
333
    if (pencoding != 0 &&
334
	!obj_eq(imemory, pencoding, &pfont_data(newfont)->Encoding)
335
	) {
336
	if (newfont->FontType == ft_composite)
337
	    return_error(e_rangecheck);
338
	/* We should really do validity checking here.... */
339
	ref_assign(&pfont_data(newfont)->Encoding, pencoding);
340
	lookup_gs_simple_font_encoding((gs_font_base *) newfont);
341
    }
342
    *fp = *pfont_dict(newfont);
343
    pop(1);
344
    return 0;
345
}
346
/* Create the transformed font dictionary. */
347
/* This is the make_font completion procedure for all non-composite fonts */
348
/* created at the interpreter level (see build_gs_simple_font in zbfont.c.) */
349
int
350
zbase_make_font(gs_font_dir * pdir, const gs_font * oldfont,
351
		const gs_matrix * pmat, gs_font ** ppfont)
352
{
353
    /*
354
     * We must call gs_base_make_font so that the XUID gets copied
355
     * if necessary.
356
     */
357
    int code = gs_base_make_font(pdir, oldfont, pmat, ppfont);
358
 
359
    if (code < 0)
360
	return code;
361
    return zdefault_make_font(pdir, oldfont, pmat, ppfont);
362
}
363
int
364
zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont,
365
		   const gs_matrix * pmat, gs_font ** ppfont)
366
{
367
    gs_font *newfont = *ppfont;
368
    gs_memory_t *mem = newfont->memory;
369
    /* HACK: we know this font was allocated by the interpreter. */
370
    gs_ref_memory_t *imem = (gs_ref_memory_t *)mem;
371
    ref *fp = pfont_dict(oldfont);
372
    font_data *pdata;
373
    ref newdict, newmat, scalemat;
374
    uint dlen = dict_maxlength(fp);
375
    uint mlen = dict_length(fp) + 3;	/* FontID, OrigFont, ScaleMatrix */
376
    int code;
377
 
378
    if (dlen < mlen)
379
	dlen = mlen;
380
    if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data,
381
				 "make_font(font_data)")) == 0
382
	)
383
	return_error(e_VMerror);
384
    /*
385
     * This dictionary is newly created: it's safe to pass NULL as the
386
     * dstack pointer to dict_copy and dict_put_string.
387
     */
388
    if ((code = dict_alloc(imem, dlen, &newdict)) < 0 ||
389
	(code = dict_copy(fp, &newdict, NULL)) < 0 ||
390
	(code = gs_alloc_ref_array(imem, &newmat, a_all, 12,
391
				   "make_font(matrices)")) < 0
392
	)
393
	return code;
394
    refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem));
395
    ref_assign(&scalemat, &newmat);
396
    r_set_size(&scalemat, 6);
397
    scalemat.value.refs += 6;
398
    /*
399
     * Create the scaling matrix.  We could do this several different
400
     * ways: by "dividing" the new FontMatrix by the base FontMatrix, by
401
     * multiplying the current scaling matrix by a ScaleMatrix kept in
402
     * the gs_font, or by multiplying the current scaling matrix by the
403
     * ScaleMatrix from the font dictionary.  We opt for the last of
404
     * these.
405
     */
406
    {
407
	gs_matrix scale, prev_scale;
408
	ref *ppsm;
409
 
410
	if (!(dict_find_string(fp, "ScaleMatrix", &ppsm) > 0 &&
411
	      read_matrix(mem, ppsm, &prev_scale) >= 0 &&
412
	      gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0)
413
	    )
414
	    scale = *pmat;
415
	write_matrix_new(&scalemat, &scale, imem);
416
    }
417
    r_clear_attrs(&scalemat, a_write);
418
    r_set_size(&newmat, 6);
419
    write_matrix_new(&newmat, &newfont->FontMatrix, imem);
420
    r_clear_attrs(&newmat, a_write);
421
    if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 ||
422
	(code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 ||
423
	(code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 ||
424
	(code = add_FID(NULL, &newdict, newfont, imem)) < 0
425
	)
426
	return code;
427
    newfont->client_data = pdata;
428
    *pdata = *pfont_data(oldfont);
429
    pdata->dict = newdict;
430
    r_clear_attrs(dict_access_ref(&newdict), a_write);
431
    return 0;
432
}
433
 
434
/* Convert an array of (unsigned) integers to stack form. */
435
private void
436
make_uint_array(register os_ptr op, const uint * intp, int count)
437
{
438
    int i;
439
 
440
    for (i = 0; i < count; i++, op++, intp++)
441
	make_int(op, *intp);
442
}
443
 
444
/* Remove scaled font and character cache entries that would be */
445
/* invalidated by a restore. */
446
private bool
447
purge_if_name_removed(const gs_memory_t *mem, cached_char * cc, void *vsave)
448
{
449
    return alloc_name_index_is_since_save(mem, cc->code, vsave);
450
}
451
 
452
/* Remove entries from font and character caches. */
453
void
454
font_restore(const alloc_save_t * save)
455
{
456
    gs_font_dir *pdir = ifont_dir;
457
    const gs_memory_t *mem = 0;
458
 
459
    if (pdir == 0)		/* not initialized yet */
460
	return;
461
 
462
    /* Purge original (unscaled) fonts. */
463
 
464
    {
465
	gs_font *pfont;
466
 
467
otop:
468
	for (pfont = pdir->orig_fonts; pfont != 0;
469
	     pfont = pfont->next
470
	    ) {
471
	    mem = pfont->memory;
472
	    if (alloc_is_since_save((char *)pfont, save)) {
473
		gs_purge_font(pfont);
474
		goto otop;
475
	    }
476
	}
477
    }
478
 
479
    /* Purge cached scaled fonts. */
480
 
481
    {
482
	gs_font *pfont;
483
 
484
top:
485
	for (pfont = pdir->scaled_fonts; pfont != 0;
486
	     pfont = pfont->next
487
	    ) {
488
	    if (alloc_is_since_save((char *)pfont, save)) {
489
		gs_purge_font(pfont);
490
		goto top;
491
	    }
492
	}
493
    }
494
 
495
    /* Purge xfonts and uncached scaled fonts. */
496
 
497
    {
498
	cached_fm_pair *pair;
499
	uint n;
500
 
501
	for (pair = pdir->fmcache.mdata, n = pdir->fmcache.mmax;
502
	     n > 0; pair++, n--
503
	    )
504
	    if (!fm_pair_is_free(pair)) {
505
		if ((uid_is_XUID(&pair->UID) &&
506
		     alloc_is_since_save((char *)pair->UID.xvalues,
507
					 save))
508
		    ) {
509
		    gs_purge_fm_pair(pdir, pair, 0);
510
		    continue;
511
		}
512
		if (pair->font != 0 &&
513
		    alloc_is_since_save((char *)pair->font, save)
514
		    ) {
515
		    if (!uid_is_valid(&pair->UID)) {
516
			gs_purge_fm_pair(pdir, pair, 0);
517
			continue;
518
		    }
519
		    /* Don't discard pairs with a surviving UID. */
520
		    pair->font = 0;
521
		}
522
		if (pair->xfont != 0 &&
523
		    alloc_is_since_save((char *)pair->xfont, save)
524
		    )
525
		    gs_purge_fm_pair(pdir, pair, 1);
526
	    }
527
    }
528
 
529
    /* Purge characters with names about to be removed. */
530
    /* We only need to do this if any new names have been created */
531
    /* since the save. */
532
 
533
    if (alloc_any_names_since_save(save))
534
	gx_purge_selected_cached_chars(pdir, purge_if_name_removed,
535
				       (void *)save);
536
 
537
}
538
 
539
/* ------ Font procedures for PostScript fonts ------ */
540
 
541
/* font_info procedure */
542
private bool
543
zfont_info_has(const ref *pfidict, const char *key, gs_const_string *pmember)
544
{
545
    ref *pvalue;
546
 
547
    if (dict_find_string(pfidict, key, &pvalue) > 0 &&
548
	r_has_type(pvalue, t_string)
549
	) {
550
	pmember->data = pvalue->value.const_bytes;
551
	pmember->size = r_size(pvalue);
552
	return true;
553
    }
554
    return false;
555
}
556
int
557
zfont_info(gs_font *font, const gs_point *pscale, int members,
558
	   gs_font_info_t *info)
559
{
560
    int code = gs_default_font_info(font, pscale, members &
561
		    ~(FONT_INFO_COPYRIGHT | FONT_INFO_NOTICE |
562
		      FONT_INFO_FAMILY_NAME | FONT_INFO_FULL_NAME),
563
				    info);
564
    const ref *pfdict;
565
    ref *pfontinfo;
566
 
567
    if (code < 0)
568
	return code;
569
    pfdict = &pfont_data(font)->dict;
570
    if (dict_find_string(pfdict, "FontInfo", &pfontinfo) <= 0 ||
571
	!r_has_type(pfontinfo, t_dictionary))
572
	return 0;
573
    if ((members & FONT_INFO_COPYRIGHT) &&
574
	zfont_info_has(pfontinfo, "Copyright", &info->Copyright))
575
	info->members |= FONT_INFO_COPYRIGHT;
576
    if ((members & FONT_INFO_NOTICE) &&
577
	zfont_info_has(pfontinfo, "Notice", &info->Notice))
578
	info->members |= FONT_INFO_NOTICE;
579
    if ((members & FONT_INFO_FAMILY_NAME) &&
580
	zfont_info_has(pfontinfo, "FamilyName", &info->FamilyName))
581
	info->members |= FONT_INFO_FAMILY_NAME;
582
    if ((members & FONT_INFO_FULL_NAME) &&
583
	zfont_info_has(pfontinfo, "FullName", &info->FullName))
584
	info->members |= FONT_INFO_FULL_NAME;
585
    return code;
586
}
587
 
588
/* -------------------- Utilities --------------*/
589
 
590
typedef struct gs_unicode_decoder_s {
591
    ref data;
592
} gs_unicode_decoder;
593
 
594
/* GC procedures */
595
private 
596
CLEAR_MARKS_PROC(unicode_decoder_clear_marks)
597
{   gs_unicode_decoder *const pptr = vptr;
598
 
599
    r_clear_attrs(&pptr->data, l_mark);
600
}
601
private 
602
ENUM_PTRS_WITH(unicode_decoder_enum_ptrs, gs_unicode_decoder *pptr) return 0;
603
case 0:
604
ENUM_RETURN_REF(&pptr->data);
605
ENUM_PTRS_END
606
private RELOC_PTRS_WITH(unicode_decoder_reloc_ptrs, gs_unicode_decoder *pptr);
607
RELOC_REF_VAR(pptr->data);
608
r_clear_attrs(&pptr->data, l_mark);
609
RELOC_PTRS_END
610
 
611
gs_private_st_complex_only(st_unicode_decoder, gs_unicode_decoder,\
612
    "unicode_decoder", unicode_decoder_clear_marks, unicode_decoder_enum_ptrs, 
613
    unicode_decoder_reloc_ptrs, 0);
614
 
615
/* Get the Unicode value for a glyph. */
616
const ref *
617
zfont_get_to_unicode_map(gs_font_dir *dir)
618
{
619
    const gs_unicode_decoder *pud = (gs_unicode_decoder *)dir->glyph_to_unicode_table;
620
 
621
    return (pud == NULL ? NULL : &pud->data);
622
}
623
 
624
private int
625
setup_unicode_decoder(i_ctx_t *i_ctx_p, ref *Decoding)
626
{
627
    gs_unicode_decoder *pud = gs_alloc_struct(imemory, gs_unicode_decoder, 
628
                             &st_unicode_decoder, "setup_unicode_decoder");
629
    if (pud == NULL)
630
	return_error(e_VMerror);
631
    ref_assign_new(&pud->data, Decoding);
632
    ifont_dir->glyph_to_unicode_table = pud;
633
    return 0;
634
}