Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/gs/src/zfcid0.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 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: zfcid0.c,v 1.25 2004/11/19 04:39:11 ray Exp $ */
18
/* CIDFontType 0 operators */
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "oper.h"
22
#include "gsmatrix.h"
23
#include "gsccode.h"
24
#include "gsstruct.h"
25
#include "gxfcid.h"
26
#include "gxfont1.h"
27
#include "gxalloc.h"		/* for gs_ref_memory_t */
28
#include "stream.h"		/* for files.h */
29
#include "bfont.h"
30
#include "files.h"
31
#include "ichar.h"
32
#include "ichar1.h"
33
#include "icid.h"
34
#include "idict.h"
35
#include "idparam.h"
36
#include "ifcid.h"
37
#include "ifont1.h"
38
#include "ifont2.h"
39
#include "ifont42.h"
40
#include "store.h"
41
 
42
/* Type 1 font procedures (defined in zchar1.c) */
43
font_proc_glyph_outline(zcharstring_glyph_outline);
44
 
45
/* ---------------- CIDFontType 0 (FontType 9) ---------------- */
46
 
47
/* ------ Accessing ------ */
48
 
49
/* Parse a multi-byte integer from a string. */
50
private int
51
get_index(gs_glyph_data_t *pgd, int count, ulong *pval)
52
{
53
    int i;
54
 
55
    if (pgd->bits.size < count)
56
	return_error(e_rangecheck);
57
    *pval = 0;
58
    for (i = 0; i < count; ++i)
59
	*pval = (*pval << 8) + pgd->bits.data[i];
60
    pgd->bits.data += count;
61
    pgd->bits.size -= count;
62
    return 0;
63
}
64
 
65
/* Get bytes from GlyphData or DataSource. */
66
private int
67
cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf,
68
		gs_glyph_data_t *pgd)
69
{
70
    const font_data *pfdata = pfont_data(pfont);
71
    byte *data = buf;
72
    gs_font *gdfont = 0;	/* pfont if newly allocated, 0 if not */
73
    int code = 0;
74
 
75
    /* Check for overflow. */
76
    if (base != (long)base || base > base + count)
77
	return_error(e_rangecheck);
78
    if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) {
79
	/* Get the bytes from GlyphData (a string or array of strings). */
80
	const ref *pgdata = &pfdata->u.cid0.GlyphData;
81
 
82
	if (r_has_type(pgdata, t_string)) {  /* single string */
83
	    uint size = r_size(pgdata);
84
 
85
	    if (base >= size || count > size - base)
86
		return_error(e_rangecheck);
87
	    data = pgdata->value.bytes + base;
88
	} else {		/* array of strings */
89
	    /*
90
	     * The algorithm is similar to the one in
91
	     * string_array_access_proc in zfont42.c, but it also has to
92
	     * deal with the case where the requested string crosses array
93
	     * elements.
94
	     */
95
	    ulong skip = base;
96
	    uint copied = 0;
97
	    uint index = 0;
98
	    ref rstr;
99
	    uint size;
100
 
101
	    for (;; skip -= size, ++index) {
102
		int code = array_get(pfont->memory, pgdata, index, &rstr);
103
 
104
		if (code < 0)
105
		    return code;
106
		if (!r_has_type(&rstr, t_string))
107
		    return_error(e_typecheck);
108
		size = r_size(&rstr);
109
		if (skip < size)
110
		    break;
111
	    }
112
	    size -= skip;
113
	    if (count <= size) {
114
		data = rstr.value.bytes + skip;
115
	    } else {		/* multiple strings needed */
116
		if (data == 0) {  /* no buffer provided */
117
		    data = gs_alloc_string(pfont->memory, count,
118
					   "cid0_read_bytes");
119
		    if (data == 0)
120
			return_error(e_VMerror);
121
		    gdfont = (gs_font *)pfont; /* newly allocated */
122
		}
123
		memcpy(data, rstr.value.bytes + skip, size);
124
		copied = size;
125
		while (copied < count) {
126
		    int code = array_get(pfont->memory, pgdata, ++index, &rstr);
127
 
128
		    if (code < 0)
129
			goto err;
130
		    if (!r_has_type(&rstr, t_string)) {
131
			code = gs_note_error(e_typecheck);
132
			goto err;
133
		    }
134
		    size = r_size(&rstr);
135
		    if (size > count - copied)
136
			size = count - copied;
137
		    memcpy(data + copied, rstr.value.bytes, size);
138
		    copied += size;
139
		}
140
	    }
141
	}
142
    } else {
143
	/* Get the bytes from DataSource (a stream). */
144
	stream *s;
145
	uint nread;
146
 
147
	check_read_known_file(s, &pfdata->u.cid0.DataSource, return_error);
148
	if (sseek(s, base) < 0)
149
	    return_error(e_ioerror);
150
	if (data == 0) {	/* no buffer provided */
151
	    data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes");
152
	    if (data == 0)
153
		return_error(e_VMerror);
154
	    gdfont = (gs_font *)pfont; /* newly allocated */
155
	}
156
	if (sgets(s, data, count, &nread) < 0 || nread != count) {
157
	    code = gs_note_error(e_ioerror);
158
	    goto err;
159
	}
160
    }
161
    gs_glyph_data_from_string(pgd, data, count, gdfont);
162
    return code;
163
 err:
164
    if (data != buf)
165
	gs_free_string(pfont->memory, data, count, "cid0_read_bytes");
166
    return code;
167
}
168
 
169
/* Get the CharString data for a CIDFontType 0 font. */
170
/* This is the glyph_data procedure in the font itself. */
171
/* Note that pgd may be NULL. */
172
private int
173
z9_glyph_data(gs_font_base *pbfont, gs_glyph glyph, gs_glyph_data_t *pgd,
174
	      int *pfidx)
175
{
176
    gs_font_cid0 *pfont = (gs_font_cid0 *)pbfont;
177
    const font_data *pfdata = pfont_data(pfont);
178
    long glyph_index = (long)(glyph - gs_min_cid_glyph);
179
    gs_glyph_data_t gdata;
180
    ulong fidx;
181
    int code;
182
 
183
    gdata.memory = pfont->memory;
184
    if (!r_has_type(&pfdata->u.cid0.GlyphDirectory, t_null)) {
185
        code = font_gdir_get_outline(pfont->memory,
186
				     &pfdata->u.cid0.GlyphDirectory,
187
				     glyph_index, &gdata);
188
	if (code < 0)
189
	    return code;
190
	/* Get the definition from GlyphDirectory. */
191
	if (!gdata.bits.data)
192
	    return_error(e_rangecheck);
193
	code = get_index(&gdata, pfont->cidata.FDBytes, &fidx);
194
	if (code < 0)
195
	    return code;
196
	if (fidx >= pfont->cidata.FDArray_size)
197
	    return_error(e_rangecheck);
198
	if (pgd)
199
	    *pgd = gdata;
200
	*pfidx = (int)fidx;
201
	return code;
202
    }
203
    /* Get the definition from the binary data (GlyphData or DataSource). */
204
    if (glyph_index < 0 || glyph_index >= pfont->cidata.common.CIDCount) {
205
	*pfidx = 0;
206
	if (pgd)
207
	    gs_glyph_data_from_null(pgd);
208
	return_error(e_rangecheck);
209
    }
210
    {
211
	byte fd_gd[(MAX_FDBytes + MAX_GDBytes) * 2];
212
	uint num_bytes = pfont->cidata.FDBytes + pfont->cidata.common.GDBytes;
213
	ulong base = pfont->cidata.CIDMapOffset + glyph_index * num_bytes;
214
	ulong gidx, fidx_next, gidx_next;
215
	int rcode = cid0_read_bytes(pfont, base, (ulong)(num_bytes * 2), fd_gd,
216
				    &gdata);
217
	gs_glyph_data_t orig_data;
218
 
219
	if (rcode < 0)
220
	    return rcode;
221
	orig_data = gdata;
222
	if ((code = get_index(&gdata, pfont->cidata.FDBytes, &fidx)) < 0 ||
223
	    (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx)) < 0 ||
224
	    (code = get_index(&gdata, pfont->cidata.FDBytes, &fidx_next)) < 0 ||
225
	    (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx_next)) < 0
226
	    )
227
	    DO_NOTHING;
228
	gs_glyph_data_free(&orig_data, "z9_glyph_data");
229
	if (code < 0)
230
	    return code;
231
	/*
232
	 * Some CID fonts (from Adobe!) have invalid font indexes for
233
	 * missing glyphs.  Handle this now.
234
	 */
235
	if (gidx_next <= gidx) { /* missing glyph */
236
	    *pfidx = 0;
237
	    if (pgd)
238
		gs_glyph_data_from_null(pgd);
239
	    return_error(e_undefined);
240
	}
241
	if (fidx >= pfont->cidata.FDArray_size)
242
	    return_error(e_rangecheck);
243
	*pfidx = (int)fidx;
244
	if (pgd == 0)
245
	    return 0;
246
	return cid0_read_bytes(pfont, gidx, gidx_next - gidx, NULL, pgd);
247
    }
248
}
249
 
250
/* Get the outline of a CIDFontType 0 glyph. */
251
private int
252
z9_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
253
		 gx_path *ppath, double sbw[4])
254
{
255
    gs_font_cid0 *const pfcid = (gs_font_cid0 *)font;
256
    ref gref;
257
    gs_glyph_data_t gdata;
258
    int code, fidx, ocode;
259
 
260
    gdata.memory = font->memory;
261
    code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, glyph, &gdata,
262
				    &fidx);
263
    if (code < 0)
264
	return code;
265
    glyph_ref(font->memory, glyph, &gref);
266
    ocode = zcharstring_outline(pfcid->cidata.FDArray[fidx], WMode, &gref, &gdata,
267
				pmat, ppath, sbw);
268
    gs_glyph_data_free(&gdata, "z9_glyph_outline");
269
    return ocode;
270
}
271
 
272
private int
273
z9_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
274
		     int members, gs_glyph_info_t *info)
275
{   /* fixme : same as z11_glyph_info. */
276
    int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1);
277
 
278
    return z1_glyph_info_generic(font, glyph, pmat, members, info, 
279
				    &gs_default_glyph_info, wmode);
280
}
281
 
282
 
283
/*
284
 * The "fonts" in the FDArray don't have access to their outlines -- the
285
 * outlines are always provided externally.  Replace the accessor procedures
286
 * with ones that will give an error if called.
287
 */
288
private int
289
z9_FDArray_glyph_data(gs_font_type1 * pfont, gs_glyph glyph,
290
		      gs_glyph_data_t *pgd)
291
{
292
    return_error(e_invalidfont);
293
}
294
private int
295
z9_FDArray_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph,
296
		     gs_const_string *gstr, gs_glyph_data_t *pgd)
297
{
298
    return_error(e_invalidfont);
299
}
300
 
301
/* ------ Defining ------ */
302
 
303
/* Get one element of a FDArray. */
304
private int
305
fd_array_element(i_ctx_t *i_ctx_p, gs_font_type1 **ppfont, ref *prfd)
306
{
307
    charstring_font_refs_t refs;
308
    gs_type1_data data1;
309
    build_proc_refs build;
310
    gs_font_base *pbfont;
311
    gs_font_type1 *pfont;
312
    /*
313
     * Standard CIDFontType 0 fonts have Type 1 fonts in the FDArray, but
314
     * CFF CIDFontType 0 fonts have Type 2 fonts there.
315
     */
316
    int fonttype = 1;		/* default */
317
    int code = charstring_font_get_refs(prfd, &refs);
318
 
319
    if (code < 0 ||
320
	(code = dict_int_param(prfd, "FontType", 1, 2, 1, &fonttype)) < 0
321
	)
322
	return code;
323
    /*
324
     * We don't handle the alternate Subr representation (SubrCount,
325
     * SDBytes, SubrMapOffset) here: currently that is handled in
326
     * PostScript code (lib/gs_cidfn.ps).
327
     */
328
    switch (fonttype) {
329
    case 1:
330
	data1.interpret = gs_type1_interpret;
331
	data1.subroutineNumberBias = 0;
332
	data1.lenIV = DEFAULT_LENIV_1;
333
	code = charstring_font_params(imemory, prfd, &refs, &data1);
334
	if (code < 0)
335
	    return code;
336
	code = build_proc_name_refs(imemory, &build,
337
				    "%Type1BuildChar", "%Type1BuildGlyph");
338
	break;
339
    case 2:
340
	code = type2_font_params(prfd, &refs, &data1);
341
	if (code < 0)
342
	    return code;
343
	code = charstring_font_params(imemory, prfd, &refs, &data1);
344
	if (code < 0)
345
	    return code;
346
	code = build_proc_name_refs(imemory, &build,
347
				    "%Type2BuildChar", "%Type2BuildGlyph");
348
	break;
349
    default:			/* can't happen */
350
	return_error(e_Fatal);
351
    }
352
    if (code < 0)
353
	return code;
354
    code = build_gs_FDArray_font(i_ctx_p, prfd, &pbfont, fonttype,
355
				 &st_gs_font_type1, &build);
356
    if (code < 0)
357
	return code;
358
    pfont = (gs_font_type1 *)pbfont;
359
    pbfont->FAPI = NULL;
360
    pbfont->FAPI_font_data = NULL;
361
    charstring_font_init(pfont, &refs, &data1);
362
    pfont->data.procs.glyph_data = z9_FDArray_glyph_data;
363
    pfont->data.procs.seac_data = z9_FDArray_seac_data;
364
    *ppfont = pfont;
365
    return 0;
366
}
367
 
368
 
369
 
370
private int 
371
notify_remove_font_type9(void *proc_data, void *event_data)
372
{  /* Likely type 9 font descendents are never released explicitly.
373
      So releaseing a type 9 font we must reset pointers in descendents.
374
    */
375
    /* gs_font_finalize passes event_data == NULL, so check it here. */
376
    if (event_data == NULL) {
377
        gs_font_cid0 *pfcid = proc_data;
378
	int i;
379
 
380
	for (i = 0; i < pfcid->cidata.FDArray_size; ++i) {
381
	    if (pfcid->cidata.FDArray[i]->data.parent == (gs_font_base *)pfcid)
382
		pfcid->cidata.FDArray[i]->data.parent = NULL;
383
	}
384
    }
385
    return 0;
386
}
387
 
388
/* <string|name> <font_dict> .buildfont9 <string|name> <font> */
389
private int
390
zbuildfont9(i_ctx_t *i_ctx_p)
391
{
392
    os_ptr op = osp;
393
    build_proc_refs build;
394
    int code = build_proc_name_refs(imemory, &build, NULL, "%Type9BuildGlyph");
395
    gs_font_cid_data common;
396
    ref GlyphDirectory, GlyphData, DataSource;
397
    ref *prfda, cfnstr;
398
    ref *pCIDFontName, CIDFontName;
399
    gs_font_type1 **FDArray;
400
    uint FDArray_size;
401
    int FDBytes;
402
    uint CIDMapOffset;
403
    gs_font_base *pfont;
404
    gs_font_cid0 *pfcid;
405
    uint i;
406
 
407
    /*
408
     * If the CIDFont's data have been loaded into VM, GlyphData will be
409
     * a string or an array of strings; if they are loaded incrementally
410
     * from a file, GlyphData will be an integer, and DataSource will be
411
     * a (reusable) stream.
412
     */
413
    if (code < 0 ||
414
	(code = cid_font_data_param(op, &common, &GlyphDirectory)) < 0 ||
415
	(code = dict_find_string(op, "FDArray", &prfda)) < 0 ||
416
	(code = dict_find_string(op, "CIDFontName", &pCIDFontName)) <= 0 ||
417
	(code = dict_int_param(op, "FDBytes", 0, MAX_FDBytes, -1, &FDBytes)) < 0
418
	)
419
	return code;
420
    /*
421
     * Since build_gs_simple_font may resize the dictionary and cause
422
     * pointers to become invalid, save CIDFontName
423
     */
424
    CIDFontName = *pCIDFontName;
425
    if (r_has_type(&GlyphDirectory, t_null)) {
426
	/* Standard CIDFont, require GlyphData and CIDMapOffset. */
427
	ref *pGlyphData;
428
 
429
	if ((code = dict_find_string(op, "GlyphData", &pGlyphData)) < 0 ||
430
	    (code = dict_uint_param(op, "CIDMapOffset", 0, max_uint - 1,
431
				    max_uint, &CIDMapOffset)) < 0)
432
	    return code;
433
	GlyphData = *pGlyphData;
434
	if (r_has_type(&GlyphData, t_integer)) {
435
	    ref *pds;
436
	    stream *ignore_s;
437
 
438
	    if ((code = dict_find_string(op, "DataSource", &pds)) < 0)
439
		return code;
440
	    check_read_file(ignore_s, pds);
441
	    DataSource = *pds;
442
	} else {
443
	    if (!r_has_type(&GlyphData, t_string) && !r_is_array(&GlyphData))
444
		return_error(e_typecheck);
445
	    make_null(&DataSource);
446
	}
447
    } else {
448
	make_null(&GlyphData);
449
	make_null(&DataSource);
450
	CIDMapOffset = 0;
451
    }
452
    if (!r_is_array(prfda))
453
	return_error(e_invalidfont);
454
    FDArray_size = r_size(prfda);
455
    if (FDArray_size == 0)
456
	return_error(e_invalidfont);
457
    FDArray = ialloc_struct_array(FDArray_size, gs_font_type1 *,
458
				  &st_gs_font_type1_ptr_element,
459
				  "buildfont9(FDarray)");
460
    if (FDArray == 0)
461
	return_error(e_VMerror);
462
    memset(FDArray, 0, sizeof(gs_font_type1 *) * FDArray_size);
463
    for (i = 0; i < FDArray_size; ++i) {
464
	ref rfd;
465
 
466
	array_get(imemory, prfda, (long)i, &rfd);
467
	code = fd_array_element(i_ctx_p, &FDArray[i], &rfd);
468
	if (code < 0)
469
	    goto fail;
470
    }
471
    code = build_gs_simple_font(i_ctx_p, op, &pfont, ft_CID_encrypted,
472
				&st_gs_font_cid0, &build,
473
				bf_Encoding_optional |
474
				bf_UniqueID_ignored);
475
    if (code < 0)
476
	goto fail;
477
    pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph;
478
    pfont->procs.glyph_outline = z9_glyph_outline;
479
    pfont->procs.glyph_info = z9_glyph_info;
480
    pfcid = (gs_font_cid0 *)pfont;
481
    pfcid->cidata.common = common;
482
    pfcid->cidata.CIDMapOffset = CIDMapOffset;
483
    pfcid->cidata.FDArray = FDArray;
484
    pfcid->cidata.FDArray_size = FDArray_size;
485
    pfcid->cidata.FDBytes = FDBytes;
486
    pfcid->cidata.glyph_data = z9_glyph_data;
487
    pfcid->cidata.proc_data = 0;	/* for GC */
488
    get_font_name(imemory, &cfnstr, &CIDFontName);
489
    copy_font_name(&pfcid->font_name, &cfnstr);
490
    ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory);
491
    ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData);
492
    ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource);
493
    code = define_gs_font((gs_font *)pfont);
494
    if (code >= 0)
495
       code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont);
496
    if (code >= 0) {
497
	for (i = 0; i < FDArray_size; ++i) {
498
	    FDArray[i]->dir = pfont->dir;
499
	    FDArray[i]->data.parent = pfont;
500
	}
501
	return code;
502
    }
503
 fail:
504
    ifree_object(FDArray, "buildfont9(FDarray)");
505
    return code;
506
}
507
 
508
/* <cid9font> <cid> .type9mapcid <charstring> <font_index> */
509
int
510
ztype9mapcid(i_ctx_t *i_ctx_p)
511
{
512
    os_ptr op = osp;
513
    gs_font *pfont;
514
    gs_font_cid0 *pfcid;
515
    int code = font_param(op - 1, &pfont);
516
    gs_glyph_data_t gdata;
517
    int fidx;
518
 
519
    if (code < 0)
520
	return code;
521
    if (pfont->FontType != ft_CID_encrypted)
522
	return_error(e_invalidfont);
523
    check_type(*op, t_integer);
524
    pfcid = (gs_font_cid0 *)pfont;
525
    gdata.memory = pfont->memory;
526
    code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
527
			(gs_glyph)(gs_min_cid_glyph + op->value.intval),
528
				    &gdata, &fidx);
529
 
530
    /* return code; original error-sensitive & fragile code */
531
    if (code < 0) { /* failed to load glyph data, put CID 0 */
532
       int default_fallback_CID = 0 ;
533
 
534
       if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);
535
 
536
       op->value.intval = default_fallback_CID;
537
 
538
       /* reload glyph for default_fallback_CID */
539
 
540
       code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
541
                    (gs_glyph)(gs_min_cid_glyph + default_fallback_CID),
542
                                   &gdata, &fidx);
543
 
544
       if (code < 0) {
545
           if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval);
546
           return_error(e_invalidfont);
547
       }
548
 
549
    }
550
 
551
    /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/
552
    make_const_string(op - 1, 
553
		      a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory), 
554
		      gdata.bits.size, 
555
		      gdata.bits.data);
556
    make_int(op, fidx);
557
    return code;
558
}
559
 
560
/* ------ Initialization procedure ------ */
561
 
562
const op_def zfcid0_op_defs[] =
563
{
564
    {"2.buildfont9", zbuildfont9},
565
    {"2.type9mapcid", ztype9mapcid},
566
    op_def_end(0)
567
};