1 /* Copyright (C) 2001-2012 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134, San Rafael,
13    CA  94903, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* CIDFontType 0 operators */
18 #include "memory_.h"
19 #include "ghost.h"
20 #include "oper.h"
21 #include "gsmatrix.h"
22 #include "gsccode.h"
23 #include "gsstruct.h"
24 #include "gxfcid.h"
25 #include "gxfont1.h"
26 #include "gxalloc.h"		/* for gs_ref_memory_t */
27 #include "stream.h"		/* for files.h */
28 #include "bfont.h"
29 #include "files.h"
30 #include "ichar.h"
31 #include "ichar1.h"
32 #include "icid.h"
33 #include "idict.h"
34 #include "idparam.h"
35 #include "ifcid.h"
36 #include "ifont1.h"
37 #include "ifont2.h"
38 #include "ifont42.h"
39 #include "store.h"
40 #include "imain.h"
41 #include "iapi.h"
42 #include "iminst.h"
43 
44 /* Type 1 font procedures (defined in zchar1.c) */
45 font_proc_glyph_outline(zcharstring_glyph_outline);
46 
47 /* ---------------- CIDFontType 0 (FontType 9) ---------------- */
48 
49 /* ------ Accessing ------ */
50 
51 /* Parse a multi-byte integer from a string. */
52 static int
get_index(gs_glyph_data_t * pgd,int count,ulong * pval)53 get_index(gs_glyph_data_t *pgd, int count, ulong *pval)
54 {
55     int i;
56 
57     if (pgd->bits.size < count)
58         return_error(e_rangecheck);
59     *pval = 0;
60     for (i = 0; i < count; ++i)
61         *pval = (*pval << 8) + pgd->bits.data[i];
62     pgd->bits.data += count;
63     pgd->bits.size -= count;
64     return 0;
65 }
66 
67 /* Get bytes from GlyphData or DataSource. */
68 static int
cid0_read_bytes(gs_font_cid0 * pfont,ulong base,uint count,byte * buf,gs_glyph_data_t * pgd)69 cid0_read_bytes(gs_font_cid0 *pfont, ulong base, uint count, byte *buf,
70                 gs_glyph_data_t *pgd)
71 {
72     const font_data *pfdata = pfont_data(pfont);
73     byte *data = buf;
74     gs_font *gdfont = 0;	/* pfont if newly allocated, 0 if not */
75     int code = 0;
76 
77     /* Check for overflow. */
78     if (base != (long)base || base > base + count)
79         return_error(e_rangecheck);
80     if (r_has_type(&pfdata->u.cid0.DataSource, t_null)) {
81         /* Get the bytes from GlyphData (a string or array of strings). */
82         const ref *pgdata = &pfdata->u.cid0.GlyphData;
83 
84         if (r_has_type(pgdata, t_string)) {  /* single string */
85             uint size = r_size(pgdata);
86 
87             if (base >= size || count > size - base)
88                 return_error(e_rangecheck);
89             data = pgdata->value.bytes + base;
90         } else {		/* array of strings */
91             /*
92              * The algorithm is similar to the one in
93              * string_array_access_proc in zfont42.c, but it also has to
94              * deal with the case where the requested string crosses array
95              * elements.
96              */
97             ulong skip = base;
98             uint copied = 0;
99             uint index = 0;
100             ref rstr;
101             uint size;
102 
103             for (;; skip -= size, ++index) {
104                 int code = array_get(pfont->memory, pgdata, index, &rstr);
105 
106                 if (code < 0)
107                     return code;
108                 if (!r_has_type(&rstr, t_string))
109                     return_error(e_typecheck);
110                 size = r_size(&rstr);
111                 if (skip < size)
112                     break;
113             }
114             size -= skip;
115             if (count <= size) {
116                 data = rstr.value.bytes + skip;
117             } else {		/* multiple strings needed */
118                 if (data == 0) {  /* no buffer provided */
119                     data = gs_alloc_string(pfont->memory, count,
120                                            "cid0_read_bytes");
121                     if (data == 0)
122                         return_error(e_VMerror);
123                     gdfont = (gs_font *)pfont; /* newly allocated */
124                 }
125                 memcpy(data, rstr.value.bytes + skip, size);
126                 copied = size;
127                 while (copied < count) {
128                     int code = array_get(pfont->memory, pgdata, ++index, &rstr);
129 
130                     if (code < 0)
131                         goto err;
132                     if (!r_has_type(&rstr, t_string)) {
133                         code = gs_note_error(e_typecheck);
134                         goto err;
135                     }
136                     size = r_size(&rstr);
137                     if (size > count - copied)
138                         size = count - copied;
139                     memcpy(data + copied, rstr.value.bytes, size);
140                     copied += size;
141                 }
142             }
143         }
144     } else {
145         /* Get the bytes from DataSource (a stream). */
146         stream *s;
147         uint nread;
148         i_ctx_t *i_ctx_p = get_minst_from_memory(pfont->memory)->i_ctx_p;
149 
150         check_read_known_file(i_ctx_p, s, &pfdata->u.cid0.DataSource, return_error);
151         if (sseek(s, base) < 0)
152             return_error(e_ioerror);
153         if (data == 0) {	/* no buffer provided */
154             data = gs_alloc_string(pfont->memory, count, "cid0_read_bytes");
155             if (data == 0)
156                 return_error(e_VMerror);
157             gdfont = (gs_font *)pfont; /* newly allocated */
158         }
159         if (sgets(s, data, count, &nread) < 0 || nread != count) {
160             code = gs_note_error(e_ioerror);
161             goto err;
162         }
163     }
164     gs_glyph_data_from_string(pgd, data, count, gdfont);
165     return code;
166  err:
167     if (data != buf)
168         gs_free_string(pfont->memory, data, count, "cid0_read_bytes");
169     return code;
170 }
171 
172 /* Get the CharString data for a CIDFontType 0 font. */
173 /* This is the glyph_data procedure in the font itself. */
174 /* Note that pgd may be NULL. */
175 static int
z9_glyph_data(gs_font_base * pbfont,gs_glyph glyph,gs_glyph_data_t * pgd,int * pfidx)176 z9_glyph_data(gs_font_base *pbfont, gs_glyph glyph, gs_glyph_data_t *pgd,
177               int *pfidx)
178 {
179     gs_font_cid0 *pfont = (gs_font_cid0 *)pbfont;
180     const font_data *pfdata = pfont_data(pfont);
181     long glyph_index = (long)(glyph - gs_min_cid_glyph);
182     gs_glyph_data_t gdata;
183     ulong fidx;
184     int code;
185 
186     gdata.memory = pfont->memory;
187     if (!r_has_type(&pfdata->u.cid0.GlyphDirectory, t_null)) {
188         code = font_gdir_get_outline(pfont->memory,
189                                      &pfdata->u.cid0.GlyphDirectory,
190                                      glyph_index, &gdata);
191         if (code < 0)
192             return code;
193         /* Get the definition from GlyphDirectory. */
194         if (!gdata.bits.data)
195             return_error(e_rangecheck);
196         code = get_index(&gdata, pfont->cidata.FDBytes, &fidx);
197         if (code < 0)
198             return code;
199         if (fidx >= pfont->cidata.FDArray_size)
200             return_error(e_rangecheck);
201         if (pgd)
202             *pgd = gdata;
203         *pfidx = (int)fidx;
204         return code;
205     }
206     /* Get the definition from the binary data (GlyphData or DataSource). */
207     if (glyph_index < 0 || glyph_index >= pfont->cidata.common.CIDCount) {
208         *pfidx = 0;
209         if (pgd)
210             gs_glyph_data_from_null(pgd);
211         return_error(e_rangecheck);
212     }
213     {
214         byte fd_gd[(MAX_FDBytes + MAX_GDBytes) * 2];
215         uint num_bytes = pfont->cidata.FDBytes + pfont->cidata.common.GDBytes;
216         ulong base = pfont->cidata.CIDMapOffset + glyph_index * num_bytes;
217         ulong gidx, fidx_next, gidx_next;
218         int rcode = cid0_read_bytes(pfont, base, (ulong)(num_bytes * 2), fd_gd,
219                                     &gdata);
220         gs_glyph_data_t orig_data;
221 
222         if (rcode < 0)
223             return rcode;
224         orig_data = gdata;
225         if ((code = get_index(&gdata, pfont->cidata.FDBytes, &fidx)) < 0 ||
226             (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx)) < 0 ||
227             (code = get_index(&gdata, pfont->cidata.FDBytes, &fidx_next)) < 0 ||
228             (code = get_index(&gdata, pfont->cidata.common.GDBytes, &gidx_next)) < 0
229             )
230             DO_NOTHING;
231         gs_glyph_data_free(&orig_data, "z9_glyph_data");
232         if (code < 0)
233             return code;
234         /*
235          * Some CID fonts (from Adobe!) have invalid font indexes for
236          * missing glyphs.  Handle this now.
237          */
238         if (gidx_next <= gidx) { /* missing glyph */
239             *pfidx = 0;
240             if (pgd)
241                 gs_glyph_data_from_null(pgd);
242             return_error(e_undefined);
243         }
244         if (fidx >= pfont->cidata.FDArray_size)
245             return_error(e_rangecheck);
246         *pfidx = (int)fidx;
247         if (pgd == 0)
248             return 0;
249         return cid0_read_bytes(pfont, gidx, gidx_next - gidx, NULL, pgd);
250     }
251 }
252 
253 /* Get the outline of a CIDFontType 0 glyph. */
254 static int
z9_glyph_outline(gs_font * font,int WMode,gs_glyph glyph,const gs_matrix * pmat,gx_path * ppath,double sbw[4])255 z9_glyph_outline(gs_font *font, int WMode, gs_glyph glyph, const gs_matrix *pmat,
256                  gx_path *ppath, double sbw[4])
257 {
258     gs_font_cid0 *const pfcid = (gs_font_cid0 *)font;
259     ref gref;
260     gs_glyph_data_t gdata;
261     int code, fidx, ocode;
262 
263     gdata.memory = font->memory;
264     code = pfcid->cidata.glyph_data((gs_font_base *)pfcid, glyph, &gdata,
265                                     &fidx);
266     if (code < 0)
267         return code;
268     glyph_ref(font->memory, glyph, &gref);
269     ocode = zcharstring_outline(pfcid->cidata.FDArray[fidx], WMode, &gref, &gdata,
270                                 pmat, ppath, sbw);
271     gs_glyph_data_free(&gdata, "z9_glyph_outline");
272     return ocode;
273 }
274 
275 static int
z9_glyph_info(gs_font * font,gs_glyph glyph,const gs_matrix * pmat,int members,gs_glyph_info_t * info)276 z9_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
277                      int members, gs_glyph_info_t *info)
278 {   /* fixme : same as z11_glyph_info. */
279     int wmode = (members & GLYPH_INFO_WIDTH0 ? 0 : 1);
280 
281     return z1_glyph_info_generic(font, glyph, pmat, members, info,
282                                     &gs_default_glyph_info, wmode);
283 }
284 
285 /*
286  * The "fonts" in the FDArray don't have access to their outlines -- the
287  * outlines are always provided externally.  Replace the accessor procedures
288  * with ones that will give an error if called.
289  */
290 static int
z9_FDArray_glyph_data(gs_font_type1 * pfont,gs_glyph glyph,gs_glyph_data_t * pgd)291 z9_FDArray_glyph_data(gs_font_type1 * pfont, gs_glyph glyph,
292                       gs_glyph_data_t *pgd)
293 {
294     return_error(e_invalidfont);
295 }
296 static int
z9_FDArray_seac_data(gs_font_type1 * pfont,int ccode,gs_glyph * pglyph,gs_const_string * gstr,gs_glyph_data_t * pgd)297 z9_FDArray_seac_data(gs_font_type1 *pfont, int ccode, gs_glyph *pglyph,
298                      gs_const_string *gstr, gs_glyph_data_t *pgd)
299 {
300     return_error(e_invalidfont);
301 }
302 
303 /* ------ Defining ------ */
304 
305 /* Get one element of a FDArray. */
306 static int
fd_array_element(i_ctx_t * i_ctx_p,gs_font_type1 ** ppfont,ref * prfd)307 fd_array_element(i_ctx_t *i_ctx_p, gs_font_type1 **ppfont, ref *prfd)
308 {
309     charstring_font_refs_t refs;
310     gs_type1_data data1;
311     build_proc_refs build;
312     gs_font_base *pbfont;
313     gs_font_type1 *pfont;
314     /*
315      * Standard CIDFontType 0 fonts have Type 1 fonts in the FDArray, but
316      * CFF CIDFontType 0 fonts have Type 2 fonts there.
317      */
318     int fonttype = 1;		/* default */
319     int code = charstring_font_get_refs(prfd, &refs);
320 
321     if (code < 0 ||
322         (code = dict_int_param(prfd, "FontType", 1, 2, 1, &fonttype)) < 0
323         )
324         return code;
325     /*
326      * We don't handle the alternate Subr representation (SubrCount,
327      * SDBytes, SubrMapOffset) here: currently that is handled in
328      * PostScript code (lib/gs_cidfn.ps).
329      */
330     switch (fonttype) {
331     case 1:
332         data1.interpret = gs_type1_interpret;
333         data1.subroutineNumberBias = 0;
334         data1.lenIV = DEFAULT_LENIV_1;
335         code = charstring_font_params(imemory, prfd, &refs, &data1);
336         if (code < 0)
337             return code;
338         code = build_proc_name_refs(imemory, &build,
339                                     "%Type1BuildChar", "%Type1BuildGlyph");
340         break;
341     case 2:
342         code = type2_font_params(prfd, &refs, &data1);
343         if (code < 0)
344             return code;
345         code = charstring_font_params(imemory, prfd, &refs, &data1);
346         if (code < 0)
347             return code;
348         code = build_proc_name_refs(imemory, &build,
349                                     "%Type2BuildChar", "%Type2BuildGlyph");
350         break;
351     default:			/* can't happen */
352         return_error(e_Fatal);
353     }
354     if (code < 0)
355         return code;
356     code = build_gs_FDArray_font(i_ctx_p, prfd, &pbfont, fonttype,
357                                  &st_gs_font_type1, &build);
358     if (code < 0)
359         return code;
360     pfont = (gs_font_type1 *)pbfont;
361     pbfont->FAPI = NULL;
362     pbfont->FAPI_font_data = NULL;
363     charstring_font_init(pfont, &refs, &data1);
364     pfont->data.procs.glyph_data = z9_FDArray_glyph_data;
365     pfont->data.procs.seac_data = z9_FDArray_seac_data;
366     *ppfont = pfont;
367     return 0;
368 }
369 
370 static 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 static 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(i_ctx_p, 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_outline_font(i_ctx_p, op, &pfont, ft_CID_encrypted,
472                                 &st_gs_font_cid0, &build,
473                                 bf_Encoding_optional | bf_UniqueID_ignored,
474                                 build_gs_simple_font);
475     if (code < 0)
476         goto fail;
477     if (code == 1) {
478         /* The font already has a FID, don't need to build it again.
479            Release FDArray and return normally.
480            fixme: FDArray fonts are thrown for garbager.
481            We're not safe to build them after
482            build_gs_simple_font(..., &pfont, ...),
483            because a failure in building them would throw
484            an underbuilt font with unclear consequences.
485          */
486         ifree_object(FDArray, "buildfont9(FDarray)");
487         return 0;
488     }
489     pfont->procs.enumerate_glyph = gs_font_cid0_enumerate_glyph;
490     pfont->procs.glyph_outline = z9_glyph_outline;
491     pfont->procs.glyph_info = z9_glyph_info;
492     pfcid = (gs_font_cid0 *)pfont;
493     pfcid->cidata.common = common;
494     pfcid->cidata.CIDMapOffset = CIDMapOffset;
495     pfcid->cidata.FDArray = FDArray;
496     pfcid->cidata.FDArray_size = FDArray_size;
497     pfcid->cidata.FDBytes = FDBytes;
498     pfcid->cidata.glyph_data = z9_glyph_data;
499     pfcid->cidata.proc_data = 0;	/* for GC */
500     if (pfcid->font_name.size == 0) {
501         get_font_name(imemory, &cfnstr, &CIDFontName);
502         copy_font_name(&pfcid->font_name, &cfnstr);
503     }
504     ref_assign(&pfont_data(pfont)->u.cid0.GlyphDirectory, &GlyphDirectory);
505     ref_assign(&pfont_data(pfont)->u.cid0.GlyphData, &GlyphData);
506     ref_assign(&pfont_data(pfont)->u.cid0.DataSource, &DataSource);
507     code = define_gs_font(i_ctx_p, (gs_font *)pfont);
508     if (code >= 0)
509        code = gs_notify_register(&pfont->notify_list, notify_remove_font_type9, pfont);
510     if (code >= 0) {
511         for (i = 0; i < FDArray_size; ++i) {
512             FDArray[i]->dir = pfont->dir;
513             FDArray[i]->data.parent = pfont;
514         }
515         return code;
516     }
517  fail:
518     ifree_object(FDArray, "buildfont9(FDarray)");
519     return code;
520 }
521 
522 /* <cid9font> <cid> .type9mapcid <charstring> <font_index> */
523 int
ztype9mapcid(i_ctx_t * i_ctx_p)524 ztype9mapcid(i_ctx_t *i_ctx_p)
525 {
526     os_ptr op = osp;
527     gs_font *pfont;
528     gs_font_cid0 *pfcid;
529     int code = font_param(op - 1, &pfont);
530     gs_glyph_data_t gdata;
531     int fidx;
532 
533     if (code < 0)
534         return code;
535     if (pfont->FontType != ft_CID_encrypted)
536         return_error(e_invalidfont);
537     check_type(*op, t_integer);
538     pfcid = (gs_font_cid0 *)pfont;
539     gdata.memory = pfont->memory;
540     code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
541                         (gs_glyph)(gs_min_cid_glyph + op->value.intval),
542                                     &gdata, &fidx);
543 
544     /* return code; original error-sensitive & fragile code */
545     if (code < 0) { /* failed to load glyph data, put CID 0 */
546        int default_fallback_CID = 0 ;
547 
548        if_debug2('J', "[J]ztype9cidmap() use CID %d instead of glyph-missing CID %d\n", default_fallback_CID, op->value.intval);
549 
550        op->value.intval = default_fallback_CID;
551 
552        /* reload glyph for default_fallback_CID */
553 
554        code = pfcid->cidata.glyph_data((gs_font_base *)pfcid,
555                     (gs_glyph)(gs_min_cid_glyph + default_fallback_CID),
556                                    &gdata, &fidx);
557 
558        if (code < 0) {
559            if_debug1('J', "[J]ztype9cidmap() could not load default glyph (CID %d)\n", op->value.intval);
560            return_error(e_invalidfont);
561        }
562 
563     }
564 
565     /****** FOLLOWING IS NOT GENERAL W.R.T. ALLOCATION OF GLYPH DATA ******/
566     make_const_string(op - 1,
567                       a_readonly | imemory_space((gs_ref_memory_t *)pfont->memory),
568                       gdata.bits.size,
569                       gdata.bits.data);
570     make_int(op, fidx);
571     return code;
572 }
573 
574 /* ------ Initialization procedure ------ */
575 
576 const op_def zfcid0_op_defs[] =
577 {
578     {"2.buildfont9", zbuildfont9},
579     {"2.type9mapcid", ztype9mapcid},
580     op_def_end(0)
581 };
582