386BSD 0.1 development
[unix-history] / usr / othersrc / public / ghostscript-2.4.1 / zfont0.c
CommitLineData
c6feef46
WJ
1/* Copyright (C) 1991 Aladdin Enterprises. All rights reserved.
2 Distributed by Free Software Foundation, Inc.
3
4This file is part of Ghostscript.
5
6Ghostscript is distributed in the hope that it will be useful, but
7WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
8to anyone for the consequences of using it or for whether it serves any
9particular purpose or works at all, unless he says so in writing. Refer
10to the Ghostscript General Public License for full details.
11
12Everyone is granted permission to copy, modify and redistribute
13Ghostscript, but only under the conditions described in the Ghostscript
14General Public License. A copy of this license is supposed to have been
15given to you along with Ghostscript so you can know your rights and
16responsibilities. It should be in a file named COPYING. Among other
17things, the copyright notice and this notice must be preserved on all
18copies. */
19
20/* zfont0.c */
21/* Composite font creation operator for Ghostscript */
22#include "ghost.h"
23#include "errors.h"
24#include "oper.h"
25/*
26 * The following lines used to say:
27 * #include "gsmatrix.h"
28 * #include "gxdevice.h" /. for gxfont.h ./
29 * Tony Li says the longer list is necessary to keep the GNU compiler
30 * happy, but this is pretty hard to understand....
31 */
32#include "gxfixed.h"
33#include "gxmatrix.h"
34#include "gzstate.h" /* must precede gxdevice */
35#include "gxdevice.h" /* must precede gxfont */
36#include "gschar.h"
37#include "gxfont.h"
38#include "alloc.h"
39#include "font.h"
40#include "dict.h"
41#include "name.h"
42#include "state.h"
43#include "store.h"
44
45/* Imports */
46extern int build_gs_font(P4(os_ptr, gs_font **, font_type, ref *));
47extern ref name_FID;
48
49/* Forward references */
50private int ensure_char_entry(P4(os_ptr, ref *, byte *, int));
51
52/* Names of system-known keys in type 0 font dictionaries: */
53private ref name_EscChar;
54private ref name_FDepVector;
55private ref name_FMapType;
56private ref name_PrefEnc;
57private ref name_ShiftIn;
58private ref name_ShiftOut;
59private ref name_SubsVector;
60private ref name_Type0BuildChar;
61
62/* Initialize the composite font operators */
63private void
64zfont0_init()
65{ static names_def fnd0[] = {
66 { "EscChar", &name_EscChar },
67 { "FDepVector", &name_FDepVector },
68 { "FMapType", &name_FMapType },
69 { "PrefEnc", &name_PrefEnc },
70 { "ShiftIn", &name_ShiftIn },
71 { "ShiftOut", &name_ShiftOut },
72 { "SubsVector", &name_SubsVector },
73 { "Type0BuildChar", &name_Type0BuildChar },
74 names_def_end
75 };
76 init_names(fnd0);
77
78 /* Make the standard BuildChar procedure executable. */
79 r_set_attrs(&name_Type0BuildChar, a_executable);
80}
81
82/* .buildfont0 */
83/* Build a type 0 (composite) font. */
84int
85zbuildfont0(os_ptr op)
86{ ref *pfmaptype;
87 gs_type0_data data;
88 ref *pfdepvector;
89 ref *pprefenc;
90 ref *psubsvector;
91 gs_font *pfont;
92 font_data *pdata;
93 int i;
94 int code;
95 check_type(*op, t_dictionary);
96 if ( dict_find(op, &name_FMapType, &pfmaptype) <= 0 ||
97 !r_has_type(pfmaptype, t_integer) ||
98 pfmaptype->value.intval < (int)fmap_type_min ||
99 pfmaptype->value.intval > (int)fmap_type_max ||
100 dict_find(op, &name_FDepVector, &pfdepvector) <= 0 ||
101 !r_has_type(pfdepvector, t_array)
102 )
103 return e_invalidfont;
104 data.FMapType = (fmap_type)pfmaptype->value.intval;
105 /* Check that every element of the FDepVector is a font. */
106 data.fdep_size = r_size(pfdepvector);
107 for ( i = 0; i < data.fdep_size; i++ )
108 { ref *pdep = pfdepvector->value.refs + i;
109 ref *pfid;
110 gs_font *psub;
111 if ( !r_has_type(pdep, t_dictionary) ||
112 dict_find(pdep, &name_FID, &pfid) <= 0 ||
113 !r_has_type(pfid, t_fontID)
114 )
115 return e_invalidfont;
116 /*
117 * Check the inheritance rules. Allowed configurations
118 * (paths from root font) are defined by the regular
119 * expression:
120 * (shift | double_escape escape* | escape*)
121 * non_modal* non_composite
122 */
123 psub = pfid->value.pfont;
124 if ( psub->FontType == ft_composite )
125 { fmap_type fmt = psub->data.type0_data.FMapType;
126 if ( fmt == fmap_double_escape ||
127 fmt == fmap_shift ||
128 fmt == fmap_escape &&
129 !(data.FMapType == fmap_escape ||
130 data.FMapType == fmap_double_escape)
131 )
132 return e_invalidfont;
133 }
134 }
135 switch ( data.FMapType )
136 {
137 case fmap_escape: case fmap_double_escape: /* need EscChar */
138 code = ensure_char_entry(op, &name_EscChar, &data.EscChar, 255);
139 break;
140 case fmap_shift: /* need ShiftIn & ShiftOut */
141 code = ensure_char_entry(op, &name_ShiftIn, &data.ShiftIn, 15);
142 if ( code == 0 )
143 code = ensure_char_entry(op, &name_ShiftOut, &data.ShiftOut, 14);
144 break;
145 case fmap_SubsVector: /* need SubsVector */
146 if ( dict_find(op, &name_SubsVector, &psubsvector) <= 0 ||
147 !r_has_type(psubsvector, t_string) ||
148 r_size(psubsvector) == 0 ||
149 (data.subs_width = (int)*psubsvector->value.bytes + 1) > 4 ||
150 (r_size(psubsvector) - 1) % data.subs_width != 0
151 )
152 return e_invalidfont;
153 default:
154 code = 0;
155 }
156 if ( code < 0 ) return code;
157 code = build_gs_font(op, &pfont, ft_composite, &name_Type0BuildChar);
158 if ( code != 0 ) return code;
159 if ( dict_find(op, &name_PrefEnc, &pprefenc) <= 0 )
160 { ref nul;
161 make_null_new(&nul);
162 if ( (code = dict_put(op, &name_PrefEnc, &nul)) < 0 )
163 return code;
164 }
165 /* Fill in the font data */
166 pdata = (font_data *)(pfont->client_data);
167 data.subs_size = (r_size(psubsvector) - 1) / data.subs_width;
168 data.SubsVector = psubsvector->value.bytes + 1;
169 data.encoding_size = r_size(&pdata->Encoding);
170 data.Encoding =
171 (uint *)alloc(data.encoding_size, sizeof(uint),
172 "buildfont0(Encoding)");
173 /* Fill in the encoding vector, checking to make sure that */
174 /* each element is an integer between 0 and fdep_size-1. */
175 for ( i = 0; i < data.encoding_size; i++ )
176 { ref *penc = pdata->Encoding.value.refs + i;
177 if ( !r_has_type(penc, t_integer) ||
178 (ulong)penc->value.intval >= data.fdep_size
179 )
180 return e_invalidfont;
181 data.Encoding[i] = (uint)penc->value.intval;
182 }
183 data.FDepVector =
184 (gs_font **)alloc(data.fdep_size, sizeof(gs_font *),
185 "buildfont0(FDepVector)");
186 for ( i = 0; i < data.fdep_size; i++ )
187 { ref *pfid;
188 /* The lookup can't fail, because of the pre-check above. */
189 dict_find(pfdepvector->value.refs + i, &name_FID, &pfid);
190 data.FDepVector[i] = pfid->value.pfont;
191 }
192 pfont->data.type0_data = data;
193 return 0;
194}
195/* Private routine to find or add an integer entry in a font dictionary. */
196private int
197ensure_char_entry(os_ptr op, ref *pname, byte *pvalue, int default_value)
198{ ref *pentry;
199 if ( dict_find(op, pname, &pentry) <= 0 )
200 { ref ent;
201 make_int(&ent, default_value);
202 return dict_put(op, pname, &ent);
203 }
204 else
205 if ( !r_has_type(pentry, t_integer) ||
206 (ulong)(pentry->value.intval) > 255
207 )
208 return e_invalidfont;
209 *pvalue = (byte)pentry->value.intval;
210 return 0;
211}
212
213/* ------ Initialization procedure ------ */
214
215op_def zfont0_op_defs[] = {
216 {"1.buildfont0", zbuildfont0},
217 op_def_end(zfont0_init)
218};