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) 1996, 1997, 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: zcharout.c,v 1.13 2004/09/22 13:52:33 igor Exp $ */
18
/* Common code for outline (Type 1 / 4 / 42) fonts */
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "gscrypt1.h"
23
#include "gstext.h"
24
#include "gxdevice.h"		/* for gxfont.h */
25
#include "gxfont.h"
26
#include "gxfont1.h"
27
#include "dstack.h"		/* only for systemdict */
28
#include "estack.h"
29
#include "ichar.h"
30
#include "icharout.h"
31
#include "idict.h"
32
#include "ifont.h"
33
#include "igstate.h"
34
#include "iname.h"
35
#include "store.h"
36
 
37
/*
38
 * Execute an outline defined by a PostScript procedure.
39
 * The top elements of the stack are:
40
 *      <font> <code|name> <name> <outline_id>
41
 */
42
int
43
zchar_exec_char_proc(i_ctx_t *i_ctx_p)
44
{
45
    os_ptr op = osp;
46
	/*
47
	 * The definition is a PostScript procedure.  Execute
48
	 *      <code|name> proc
49
	 * within a systemdict begin/end and a font begin/end.
50
	 */
51
    es_ptr ep;
52
 
53
    check_estack(5);
54
    ep = esp += 5;
55
    make_op_estack(ep - 4, zend);
56
    make_op_estack(ep - 3, zend);
57
    ref_assign(ep - 2, op);
58
    make_op_estack(ep - 1, zbegin);
59
    make_op_estack(ep, zbegin);
60
    ref_assign(op - 1, systemdict);
61
    {
62
	ref rfont;
63
 
64
	ref_assign(&rfont, op - 3);
65
	ref_assign(op - 3, op - 2);
66
	ref_assign(op - 2, &rfont);
67
    }
68
    pop(1);
69
    return o_push_estack;
70
}
71
 
72
/*
73
 * Get the metrics for a character from the Metrics dictionary of a base
74
 * font.  If present, store the l.s.b. in psbw[0,1] and the width in
75
 * psbw[2,3].
76
 */
77
int				/*metrics_present*/
78
zchar_get_metrics(const gs_font_base * pbfont, const ref * pcnref,
79
		  double psbw[4])
80
{
81
    const ref *pfdict = &pfont_data(gs_font_parent(pbfont))->dict;
82
    ref *pmdict;
83
 
84
    if (dict_find_string(pfdict, "Metrics", &pmdict) > 0) {
85
	ref *pmvalue;
86
 
87
	check_type_only(*pmdict, t_dictionary);
88
	check_dict_read(*pmdict);
89
	if (dict_find(pmdict, pcnref, &pmvalue) > 0) {
90
	    if (num_params(pmvalue, 1, psbw + 2) >= 0) {	/* <wx> only */
91
		psbw[3] = 0;
92
		return metricsWidthOnly;
93
	    } else {
94
		int code;
95
 
96
		check_read_type_only(*pmvalue, t_array);
97
		switch (r_size(pmvalue)) {
98
		    case 2:	/* [<sbx> <wx>] */
99
			code = num_params(pmvalue->value.refs + 1,
100
					  2, psbw);
101
			psbw[2] = psbw[1];
102
			psbw[1] = psbw[3] = 0;
103
			break;
104
		    case 4:	/* [<sbx> <sby> <wx> <wy>] */
105
			code = num_params(pmvalue->value.refs + 3,
106
					  4, psbw);
107
			break;
108
		    default:
109
			return_error(e_rangecheck);
110
		}
111
		if (code < 0)
112
		    return code;
113
		return metricsSideBearingAndWidth;
114
	    }
115
	}
116
    }
117
    return metricsNone;
118
}
119
 
120
/* Get the vertical metrics for a character from Metrics2, if present. */
121
int
122
zchar_get_metrics2(const gs_font_base * pbfont, const ref * pcnref,
123
		   double pwv[4])
124
{
125
    const ref *pfdict = &pfont_data(gs_font_parent(pbfont))->dict;
126
    ref *pmdict;
127
 
128
    if (dict_find_string(pfdict, "Metrics2", &pmdict) > 0) {
129
	ref *pmvalue;
130
 
131
	check_type_only(*pmdict, t_dictionary);
132
	check_dict_read(*pmdict);
133
	if (dict_find(pmdict, pcnref, &pmvalue) > 0) {
134
	    check_read_type_only(*pmvalue, t_array);
135
	    if (r_size(pmvalue) == 4) {
136
		int code = num_params(pmvalue->value.refs + 3, 4, pwv);
137
 
138
		return (code < 0 ? code : metricsSideBearingAndWidth);
139
	    }
140
	}
141
    }
142
    return metricsNone;
143
}
144
 
145
/*
146
 * Get CDevProc.
147
 */
148
bool
149
zchar_get_CDevProc(const gs_font_base * pbfont, ref **ppcdevproc)
150
{
151
    const ref *pfdict = &pfont_data(gs_font_parent(pbfont))->dict;
152
 
153
    return dict_find_string(pfdict, "CDevProc", ppcdevproc) > 0;
154
}
155
 
156
/*
157
 * Consult Metrics2 and CDevProc, and call setcachedevice[2].  Return
158
 * o_push_estack if we had to call a CDevProc, or if we are skipping the
159
 * rendering process (only getting the metrics).
160
 * Returns exec_cont - a function, which must be called by caller after this function.
161
 */
162
int
163
zchar_set_cache(i_ctx_t *i_ctx_p, const gs_font_base * pbfont,
164
		const ref * pcnref, const double psb[2],
165
		const double pwidth[2], const gs_rect * pbbox,
166
		op_proc_t cont, op_proc_t *exec_cont,
167
		const double Metrics2_sbw_default[4])
168
{
169
    os_ptr op = osp;
170
    ref *pcdevproc;
171
    int have_cdevproc;
172
    ref rpop;
173
    bool metrics2;
174
    bool metrics2_use_default = false;
175
    double w2[10];
176
    gs_text_enum_t *penum = op_show_find(i_ctx_p);
177
 
178
    w2[0] = pwidth[0], w2[1] = pwidth[1];
179
 
180
    /* Adjust the bounding box for stroking if needed. */
181
 
182
    w2[2] = pbbox->p.x, w2[3] = pbbox->p.y;
183
    w2[4] = pbbox->q.x, w2[5] = pbbox->q.y;
184
    if (pbfont->PaintType != 0) {
185
	double expand = max(1.415, gs_currentmiterlimit(igs)) *
186
	gs_currentlinewidth(igs) / 2;
187
 
188
	w2[2] -= expand, w2[3] -= expand;
189
	w2[4] += expand, w2[5] += expand;
190
    }
191
 
192
    /* Check for Metrics2. */
193
 
194
    {
195
	int code = zchar_get_metrics2(pbfont, pcnref, w2 + 6);
196
 
197
	if (code < 0)
198
	    return code;
199
	metrics2 = code > 0;
200
    }
201
 
202
    /*
203
     * For FontType 9 and 11, if Metrics2 is missing, the caller provides
204
     * default Metrics2 values derived from the FontBBox.
205
     */
206
    if (!metrics2 && Metrics2_sbw_default != NULL) {
207
        w2[6] = Metrics2_sbw_default[2];
208
        w2[7] = Metrics2_sbw_default[3];
209
        w2[8] = Metrics2_sbw_default[0];
210
        w2[9] = Metrics2_sbw_default[1];
211
	metrics2 = true;
212
	metrics2_use_default = true;
213
    }
214
 
215
    /* Check for CDevProc or "short-circuiting". */
216
 
217
    have_cdevproc = zchar_get_CDevProc(pbfont, &pcdevproc);
218
    if (have_cdevproc || zchar_show_width_only(penum)) {
219
	int i;
220
	op_proc_t zsetc;
221
	int nparams;
222
 
223
	if (have_cdevproc) {
224
	    check_proc_only(*pcdevproc);
225
	    zsetc = zsetcachedevice2;
226
 
227
	    /* If we have cdevproc and the font type is CID type 0,
228
	       we'll throw away Metrics2_sbw_default that is calculated 
229
	       from FontBBox. */
230
	    if (!metrics2 
231
		|| (penum->current_font->FontType == ft_CID_encrypted
232
		    && metrics2_use_default)) {
233
		w2[6] = w2[0], w2[7] = w2[1];
234
		w2[8] = w2[9] = 0;
235
	    }
236
	    nparams = 10;
237
	} else {
238
	    make_oper(&rpop, 0, zpop);
239
	    pcdevproc = &rpop;
240
	    if (metrics2)
241
		zsetc = zsetcachedevice2, nparams = 10;
242
	    else
243
		zsetc = zsetcachedevice, nparams = 6;
244
	}
245
	check_estack(3);
246
	/* Push the l.s.b. for .type1addpath if necessary. */
247
	if (psb != 0) {
248
	    push(nparams + 3);
249
	    make_real(op - (nparams + 2), psb[0]);
250
	    make_real(op - (nparams + 1), psb[1]);
251
	} else {
252
	    push(nparams + 1);
253
	}
254
	for (i = 0; i < nparams; ++i)
255
	    make_real(op - nparams + i, w2[i]);
256
	ref_assign(op, pcnref);
257
	push_op_estack(cont);
258
	push_op_estack(zsetc);
259
	++esp;
260
	ref_assign(esp, pcdevproc);
261
	return o_push_estack;
262
    } {
263
	int code =
264
	    (metrics2 ? gs_text_setcachedevice2(penum, w2) :
265
	     gs_text_setcachedevice(penum, w2));
266
 
267
	if (code < 0)
268
	    return code;
269
    }
270
 
271
    /* No metrics modification, do the stroke or fill now. */
272
 
273
    /* Push the l.s.b. for .type1addpath if necessary. */
274
    if (psb != 0) {
275
	push(2);
276
	make_real(op - 1, psb[0]);
277
	make_real(op, psb[1]);
278
    }
279
    *exec_cont = cont;
280
    return 0;
281
}
282
 
283
/*
284
 * Get the CharString data corresponding to a glyph.  Return typecheck
285
 * if it isn't a string.
286
 */
287
private bool charstring_is_notdef_proc(const gs_memory_t *mem, const ref *);
288
private int charstring_make_notdef(gs_glyph_data_t *, gs_font *);
289
int
290
zchar_charstring_data(gs_font *font, const ref *pgref, gs_glyph_data_t *pgd)
291
{
292
    ref *pcstr;
293
 
294
    if (dict_find(&pfont_data(font)->CharStrings, pgref, &pcstr) <= 0)
295
	return_error(e_undefined);
296
    if (!r_has_type(pcstr, t_string)) {
297
	/*
298
	 * The ADOBEPS4 Windows driver replaces the .notdef entry of
299
	 * otherwise normal Type 1 fonts with the procedure
300
	 *	{pop 0 0 setcharwidth}
301
	 * To prevent this from making the font unembeddable in PDF files
302
	 * (with our present font-writing code), we recognize this as a
303
	 * special case and return a Type 1 CharString consisting of
304
	 *	0 0 hsbw endchar
305
	 */
306
	if (font->FontType == ft_encrypted &&
307
	    charstring_is_notdef_proc(font->memory, pcstr)
308
	    )
309
	    return charstring_make_notdef(pgd, font);
310
	else
311
	    return_error(e_typecheck);
312
    }
313
    gs_glyph_data_from_string(pgd, pcstr->value.const_bytes, r_size(pcstr),
314
			      NULL);
315
    return 0;
316
}
317
private bool
318
charstring_is_notdef_proc(const gs_memory_t *mem, const ref *pcstr)
319
{
320
    if (r_is_array(pcstr) && r_size(pcstr) == 4) {
321
	ref elts[4];
322
	long i;
323
 
324
	for (i = 0; i < 4; ++i)
325
	    array_get(mem, pcstr, i, &elts[i]);
326
	if (r_has_type(&elts[0], t_name) &&
327
	    r_has_type(&elts[1], t_integer) && elts[1].value.intval == 0 &&
328
	    r_has_type(&elts[2], t_integer) && elts[2].value.intval == 0 &&
329
	    r_has_type(&elts[3], t_name)
330
	    ) {
331
	    ref nref;
332
 
333
	    name_enter_string(mem, "pop", &nref);
334
	    if (name_eq(&elts[0], &nref)) {
335
	        name_enter_string(mem, "setcharwidth", &nref);
336
		if (name_eq(&elts[3], &nref))
337
		    return true;
338
	    }
339
	}
340
    }
341
    return false;
342
}
343
private int
344
charstring_make_notdef(gs_glyph_data_t *pgd, gs_font *font)
345
{
346
    gs_font_type1 *const pfont = (gs_font_type1 *)font;
347
    static const byte char_data[4] = {
348
	139,			/* 0 */
349
	139,			/* 0 */
350
	c1_hsbw,
351
	cx_endchar
352
    };
353
    uint len = max(pfont->data.lenIV, 0) + sizeof(char_data);
354
    byte *chars = gs_alloc_string(font->memory, len, "charstring_make_notdef");
355
 
356
    if (chars == 0)
357
	return_error(e_VMerror);
358
    gs_glyph_data_from_string(pgd, chars, len, font);
359
    if (pfont->data.lenIV < 0)
360
	memcpy(chars, char_data, sizeof(char_data));
361
    else {
362
	crypt_state state = crypt_charstring_seed;
363
 
364
	memcpy(chars + pfont->data.lenIV, char_data, sizeof(char_data));
365
	gs_type1_encrypt(chars, chars, len, &state);
366
    }
367
    return 0;
368
}
369
 
370
/*
371
 * Enumerate the next glyph from a directory.  This is essentially a
372
 * wrapper around dict_first/dict_next to implement the enumerate_glyph
373
 * font procedure.
374
 *
375
 * Note that *prdict will be null if the font is a subfont of a
376
 * CIDFontType 0 CIDFont.
377
 */
378
int
379
zchar_enumerate_glyph(const gs_memory_t *mem, const ref *prdict, int *pindex, gs_glyph *pglyph)
380
{
381
    int index = *pindex - 1;
382
    ref elt[2];
383
 
384
    if (!r_has_type(prdict, t_dictionary))
385
	return 0;		/* *pindex was 0, is still 0 */
386
    if (index < 0)
387
	index = dict_first(prdict);
388
next:
389
    index = dict_next(prdict, index, elt);
390
    *pindex = index + 1;
391
    if (index >= 0) {
392
	switch (r_type(elt)) {
393
	    case t_integer:
394
		*pglyph = gs_min_cid_glyph + elt[0].value.intval;
395
		break;
396
	    case t_name:
397
	        *pglyph = name_index(mem, elt);
398
		break;
399
	    default:		/* can't handle it */
400
		goto next;
401
	}
402
    }
403
    return 0;
404
}