home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1989, 1990, 1991 Aladdin Enterprises. All rights reserved.
- Distributed by Free Software Foundation, Inc.
-
- This file is part of Ghostscript.
-
- Ghostscript is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
- to anyone for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing. Refer
- to the Ghostscript General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute
- Ghostscript, but only under the conditions described in the Ghostscript
- General Public License. A copy of this license is supposed to have been
- given to you along with Ghostscript so you can know your rights and
- responsibilities. It should be in a file named COPYING. Among other
- things, the copyright notice and this notice must be preserved on all
- copies. */
-
- /* zfont2.c */
- /* Font creation operator for Ghostscript */
- #include "ghost.h"
- #include "errors.h"
- #include "oper.h"
- #include "gxfixed.h"
- #include "gsmatrix.h"
- #include "gxdevice.h"
- #include "gschar.h"
- #include "gxfont.h"
- #include "alloc.h"
- #include "dict.h"
- #include "font.h"
- #include "name.h"
- #include "packed.h"
- #include "store.h"
-
- /* Imported procedures */
- int add_FID(P2(ref *, gs_font *)); /* in zfont */
- int buildfont0(P3(os_ptr, ref **, gs_font **)); /* in zfont0 */
-
- /* Forward references */
- private int buildfont1(P3(os_ptr, ref **, gs_font **));
- private int buildfont3(P3(os_ptr, ref **, gs_font **));
- private int build_gs_simple_font(P2(os_ptr, gs_font **));
- int build_gs_font(P2(os_ptr, gs_font **)); /* buildfont0 needs this */
-
- /* Type 1 auxiliary procedures (defined in zchar.c) */
- extern int z1_subr_proc(P3(gs_type1_data *, int, byte **));
- extern int z1_pop_proc(P2(gs_type1_data *, fixed *));
-
- /* Global font-related objects */
- /* Names of system-known keys in font dictionaries: */
- extern ref name_FID; /* in zfont.c */
- extern ref name_FontMatrix; /* in zfont.c */
- private ref name_FontType;
- private ref name_FontBBox;
- private ref name_Encoding;
- private ref name_PaintType;
- private ref name_UniqueID;
- private ref name_BuildChar;
- private ref name_Type1BuildChar;
- private ref name_Private;
- private ref name_CharStrings; /* only needed for seac */
- /* Names of system-known keys in type 1 font Private dictionary: */
- private ref name_Subrs;
- private ref name_lenIV;
-
- /* The global font directory */
- extern gs_font_dir *ifont_dir;
-
- /* Default value of lenIV */
- #define default_lenIV 4
-
- /* Initialize the font building operators */
- private void
- zfont2_init()
- { static names_def fnd2[] = {
-
- /* Create the names of the standard elements of */
- /* a font dictionary. */
- { "FontType", &name_FontType },
- { "FontBBox", &name_FontBBox },
- { "Encoding", &name_Encoding },
- { "PaintType", &name_PaintType },
- { "UniqueID", &name_UniqueID },
- { "BuildChar", &name_BuildChar },
- { "Type1BuildChar", &name_Type1BuildChar },
- { "Private", &name_Private },
- { "CharStrings", &name_CharStrings },
-
- /* Create the names of the known entries in */
- /* a type 1 font Private dictionary. */
- { "Subrs", &name_Subrs },
- { "lenIV", &name_lenIV },
-
- /* Mark the end of the initalized name list. */
- names_def_end
- };
-
- init_names(fnd2);
-
- /* Make the standard BuildChar procedures executable. */
- r_set_attrs(&name_Type1BuildChar, a_executable);
- }
-
- /* .buildfont */
- int
- zbuildfont(register os_ptr op)
- { int code;
- ref *ptype;
- ref *pbuildchar;
- gs_font *pfont;
- /* Validate and unpack the font. */
- check_type(*op, t_dictionary);
- if ( dict_find(op, &name_FontType, &ptype) <= 0 ||
- !r_has_type(ptype, t_integer) ||
- (ulong)(ptype->value.intval) > 3
- )
- return e_invalidfont;
- /* Different FontTypes demand different checking. */
- switch ( (int)(ptype->value.intval) )
- {
- case (int)ft_composite:
- code = buildfont0(op, &pbuildchar, &pfont);
- break;
- case (int)ft_encrypted:
- code = buildfont1(op, &pbuildchar, &pfont);
- break;
- case (int)ft_user_defined:
- code = buildfont3(op, &pbuildchar, &pfont);
- break;
- default:
- return e_invalidfont;
- }
- switch ( code )
- {
- case 0: /* new font */
- pfont->FontType = (font_type)ptype->value.intval;
- ref_assign(&((font_data *)(pfont->client_data))->BuildChar,
- pbuildchar);
- case 1: /* made by makefont/scalefont */
- break;
- default:
- return code;
- }
- return 0;
- }
- /* Build a type 1 (Adobe encrypted) font. */
- private int
- buildfont1(os_ptr op, ref **ppbuildchar, gs_font **ppfont)
- { ref *ppainttype;
- int paint_type;
- ref *psubrs;
- ref *pcharstrings;
- ref *pprivate;
- ref *plenIV;
- int lenIV;
- ref *puniqueid;
- static ref no_subrs;
- gs_font *pfont;
- font_data *pdata;
- int code;
- /* If no PaintType entry, set the paint_type member to 0. */
- if ( dict_find(op, &name_PaintType, &ppainttype) <= 0 )
- paint_type = 0;
- else
- { if ( !(r_has_type(ppainttype, t_integer) &&
- ppainttype->value.intval >= 0 &&
- ppainttype->value.intval <= 2)
- )
- return e_invalidfont;
- paint_type = (int)ppainttype->value.intval;
- }
- if ( dict_find(op, &name_CharStrings, &pcharstrings) <= 0 ||
- !r_has_type(pcharstrings, t_dictionary) ||
- dict_find(op, &name_Private, &pprivate) <= 0 ||
- !r_has_type(pprivate, t_dictionary)
- )
- return e_invalidfont;
- if ( dict_find(pprivate, &name_Subrs, &psubrs) > 0 )
- { check_array_else(*psubrs, e_invalidfont);
- }
- else
- { make_tasv(&no_subrs, t_string, 0, 0, bytes, (byte *)0),
- psubrs = &no_subrs;
- }
- if ( dict_find(pprivate, &name_lenIV, &plenIV) > 0 )
- { if ( !r_has_type(plenIV, t_integer) ||
- (ulong)(plenIV->value.intval) > 255 /* arbitrary */
- )
- return e_invalidfont;
- lenIV = plenIV->value.intval;
- }
- else
- lenIV = default_lenIV;
- *ppbuildchar = &name_Type1BuildChar;
- /* Do the work common to all non-composite font types. */
- code = build_gs_simple_font(op, ppfont);
- if ( code != 0 ) return code;
- /* This is a new font, fill it in. */
- pfont = *ppfont;
- pdata = (font_data *)pfont->client_data;
- ref_assign(&pdata->CharStrings, pcharstrings);
- ref_assign(&pdata->Subrs, psubrs);
- pfont->data.base.type1_data.subr_proc = z1_subr_proc;
- pfont->data.base.type1_data.pop_proc = z1_pop_proc;
- pfont->data.base.type1_data.proc_data = (char *)pdata;
- pfont->data.base.type1_data.lenIV = lenIV;
- /* Check that the UniqueIDs match. This is part of the */
- /* Adobe protection scheme, but we may as well emulate it. */
- if ( pfont->data.base.UniqueID >= 0 )
- { if ( dict_find(pprivate, &name_UniqueID, &puniqueid) <= 0 ||
- !r_has_type(puniqueid, t_integer) ||
- puniqueid->value.intval != pfont->data.base.UniqueID
- )
- pfont->data.base.UniqueID = -1;
- }
- pfont->data.base.type1_data.PaintType = paint_type;
- return 0;
- }
- /* Build a type 3 (user-defined) font. */
- private int
- buildfont3(os_ptr op, ref **ppbuildchar, gs_font **ppfont)
- { int code;
- code = dict_find(op, &name_BuildChar, ppbuildchar);
- if ( code <= 0 ) return e_invalidfont;
- check_proc(**ppbuildchar);
- code = build_gs_simple_font(op, ppfont);
- if ( code != 0 ) return code;
- return 0;
- }
-
- /* ------ Initialization procedure ------ */
-
- op_def zfont2_op_defs[] = {
- {"1.buildfont", zbuildfont},
- op_def_end(zfont2_init)
- };
-
- /* ------ Subroutines ------ */
-
- /* Do the common work for building a font of any non-composite FontType. */
- /* The caller guarantees that *op is a dictionary. */
- private int
- build_gs_simple_font(os_ptr op, gs_font **ppfont)
- { ref *pbbox;
- float bbox[4];
- long unique_id;
- ref *puniqueid;
- int code;
- gs_font *pfont;
- if ( dict_find(op, &name_FontBBox, &pbbox) <= 0 )
- return e_invalidfont;
- switch ( r_type(pbbox) )
- {
- default: return e_invalidfont;
- case t_array: case t_mixedarray: case t_shortarray: ;
- if ( r_size(pbbox) != 4 ) return e_invalidfont;
- }
- { ushort *pbe = pbbox->value.packed;
- ref rbe[4];
- int i;
- for ( i = 0; i < 4; i++ )
- { packed_get(pbe, rbe + i);
- pbe = packed_next(pbe);
- }
- if ( num_params(rbe + 3, 4, bbox) < 0 )
- return e_invalidfont;
- }
- /* If no UniqueID entry, set the UniqueID member to -1, */
- /* because UniqueID need not be present in all fonts, */
- /* and if it is, the legal range is 0 to 2^24-1. */
- if ( dict_find(op, &name_UniqueID, &puniqueid) <= 0 )
- unique_id = -1;
- else
- { if ( !r_has_type(puniqueid, t_integer) ||
- puniqueid->value.intval < 0 ||
- puniqueid->value.intval > ((1L << 24) - 1)
- )
- return e_invalidfont;
- unique_id = puniqueid->value.intval;
- }
- code = build_gs_font(op, ppfont);
- if ( code != 0 ) return code; /* invalid or scaled font */
- pfont = *ppfont;
- pfont->data.base.FontBBox.p.x = bbox[0];
- pfont->data.base.FontBBox.p.y = bbox[1];
- pfont->data.base.FontBBox.q.x = bbox[2];
- pfont->data.base.FontBBox.q.y = bbox[3];
- pfont->data.base.UniqueID = unique_id;
- return 0;
- }
-
- /* Do the common work for building a font of any FontType. */
- /* The caller guarantees that *op is a dictionary. */
- /* Return 0 for a new font, 1 for a font made by makefont or scalefont, */
- /* or a negative error code. */
- int
- build_gs_font(os_ptr op, gs_font **ppfont)
- { ref *pmatrix;
- gs_matrix mat;
- ref *pencoding;
- int code;
- gs_font *pfont;
- ref *pfid;
- ref *aop = dict_access_ref(op);
- if ( dict_find(op, &name_FontMatrix, &pmatrix) <= 0 ||
- dict_find(op, &name_Encoding, &pencoding) <= 0 ||
- read_matrix(pmatrix, &mat) < 0
- )
- return e_invalidfont;
- switch ( r_type(pencoding) )
- {
- default: return e_invalidfont;
- case t_array: case t_mixedarray: case t_shortarray: ;
- }
- code = dict_find(op, &name_FID, &pfid);
- if ( r_has_attrs(aop, a_write) )
- { /* Assume this is a new font */
- font_data *pdata;
- if ( code > 0 ) return e_invalidfont; /* has FID already */
- if ( (pfont = (gs_font *)alloc(1, sizeof(gs_font), "buildfont(font)")) == 0 ||
- (pdata = (font_data *)alloc(1, sizeof(font_data), "buildfont(data)")) == 0
- )
- return e_VMerror;
- if ( (code = add_FID(op, pfont)) < 0 ) return code;
- ref_assign(&pdata->dict, op);
- ref_assign(&pdata->Encoding, pencoding);
- pfont->base = pfont;
- pfont->dir = ifont_dir;
- pfont->client_data = (char *)pdata;
- pfont->FontMatrix = mat;
- pfont->build_char_proc = gs_no_build_char_proc;
- }
- else
- { /* Assume this was made by makefont or scalefont */
- if ( code <= 0 || !r_has_type(pfid, t_fontID) )
- return e_invalidfont;
- pfont = pfid->value.pfont;
- }
- *ppfont = pfont;
- return 0;
- }
-