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
get_index(gs_glyph_data_t * pgd,int count,ulong * pval)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
cid0_read_bytes(gs_font_cid0 * pfont,ulong base,uint count,byte * buf,gs_glyph_data_t * pgd)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
z9_glyph_data(gs_font_base * pbfont,gs_glyph glyph,gs_glyph_data_t * pgd,int * pfidx)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
z9_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])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
z9_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)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
z9_FDArray_glyph_data(gs_font_type1 * pfont,gs_glyph glyph,gs_glyph_data_t * pgd)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
z9_FDArray_seac_data(gs_font_type1 * pfont,int ccode,gs_glyph * pglyph,gs_const_string * gstr,gs_glyph_data_t * pgd)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
fd_array_element(i_ctx_t * i_ctx_p,gs_font_type1 ** ppfont,ref * prfd)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
notify_remove_font_type9(void * proc_data,void * event_data)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
zbuildfont9(i_ctx_t * i_ctx_p)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
ztype9mapcid(i_ctx_t * i_ctx_p)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 };
568