]> git.ipfire.org Git - thirdparty/cups.git/blob - pstoraster/zfont0.c
Import cups.org releases
[thirdparty/cups.git] / pstoraster / zfont0.c
1 /* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998 Aladdin Enterprises. All rights reserved.
2
3 This file is part of GNU Ghostscript.
4
5 GNU Ghostscript is distributed in the hope that it will be useful, but
6 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
7 to anyone for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing. Refer
9 to the GNU General Public License for full details.
10
11 Everyone is granted permission to copy, modify and redistribute GNU
12 Ghostscript, but only under the conditions described in the GNU General
13 Public License. A copy of this license is supposed to have been given
14 to you along with GNU Ghostscript so you can know your rights and
15 responsibilities. It should be in a file named COPYING. Among other
16 things, the copyright notice and this notice must be preserved on all
17 copies.
18
19 Aladdin Enterprises supports the work of the GNU Project, but is not
20 affiliated with the Free Software Foundation or the GNU Project. GNU
21 Ghostscript, as distributed by Aladdin Enterprises, does not require any
22 GNU software to build or run it.
23 */
24
25 /*$Id$ */
26 /* Composite font creation operator */
27 #include "ghost.h"
28 #include "oper.h"
29 #include "gsstruct.h"
30 /*
31 * The following lines used to say:
32 * #include "gsmatrix.h"
33 * #include "gxdevice.h" /. for gxfont.h ./
34 * Tony Li says the longer list is necessary to keep the GNU compiler
35 * happy, but this is pretty hard to understand....
36 */
37 #include "gxfixed.h"
38 #include "gxmatrix.h"
39 #include "gzstate.h" /* must precede gxdevice */
40 #include "gxdevice.h" /* must precede gxfont */
41 #include "gschar.h"
42 #include "gxfcmap.h"
43 #include "gxfont.h"
44 #include "gxfont0.h"
45 #include "bfont.h"
46 #include "ialloc.h"
47 #include "idict.h"
48 #include "idparam.h"
49 #include "igstate.h"
50 #include "iname.h"
51 #include "store.h"
52
53 /* Composite font procedures */
54 extern font_proc_init_fstack(gs_type0_init_fstack);
55 extern font_proc_define_font(gs_type0_define_font);
56 extern font_proc_make_font(gs_type0_make_font);
57 extern font_proc_next_glyph(gs_type0_next_glyph);
58
59 /* Imported from zfcmap.c */
60 int ztype0_get_cmap(P3(const gs_cmap ** ppcmap, const ref * pfdepvector,
61 const ref * op));
62
63 /* Forward references */
64 private font_proc_define_font(ztype0_define_font);
65 private font_proc_make_font(ztype0_make_font);
66 private int ensure_char_entry(P4(os_ptr, const char *, byte *, int));
67
68 /* <string|name> <font_dict> .buildfont0 <string|name> <font> */
69 /* Build a type 0 (composite) font. */
70 private int
71 zbuildfont0(os_ptr op)
72 {
73 gs_type0_data data;
74 ref fdepvector;
75 ref *pprefenc;
76 gs_font_type0 *pfont;
77 font_data *pdata;
78 ref save_FID;
79 int i;
80 int code = 0;
81
82 check_type(*op, t_dictionary);
83 {
84 ref *pfmaptype;
85 ref *pfdepvector;
86
87 if (dict_find_string(op, "FMapType", &pfmaptype) <= 0 ||
88 !r_has_type(pfmaptype, t_integer) ||
89 pfmaptype->value.intval < (int)fmap_type_min ||
90 pfmaptype->value.intval > (int)fmap_type_max ||
91 dict_find_string(op, "FDepVector", &pfdepvector) <= 0 ||
92 !r_is_array(pfdepvector)
93 )
94 return_error(e_invalidfont);
95 data.FMapType = (fmap_type) pfmaptype->value.intval;
96 /*
97 * Adding elements below could cause the font dictionary to be
98 * resized, which would invalidate pfdepvector.
99 */
100 fdepvector = *pfdepvector;
101 }
102 /* Check that every element of the FDepVector is a font. */
103 data.fdep_size = r_size(&fdepvector);
104 for (i = 0; i < data.fdep_size; i++) {
105 ref fdep;
106 gs_font *psub;
107
108 array_get(&fdepvector, i, &fdep);
109 if ((code = font_param(&fdep, &psub)) < 0)
110 return code;
111 /*
112 * Check the inheritance rules. Allowed configurations
113 * (paths from root font) are defined by the regular
114 * expression:
115 * (shift | double_escape escape* | escape*)
116 * non_modal* non_composite
117 */
118 if (psub->FontType == ft_composite) {
119 const gs_font_type0 *const psub0 = (const gs_font_type0 *)psub;
120 fmap_type fmt = psub0->data.FMapType;
121
122 if (fmt == fmap_double_escape ||
123 fmt == fmap_shift ||
124 (fmt == fmap_escape &&
125 !(data.FMapType == fmap_escape ||
126 data.FMapType == fmap_double_escape))
127 )
128 return_error(e_invalidfont);
129 }
130 }
131 switch (data.FMapType) {
132 case fmap_escape:
133 case fmap_double_escape: /* need EscChar */
134 code = ensure_char_entry(op, "EscChar", &data.EscChar, 255);
135 break;
136 case fmap_shift: /* need ShiftIn & ShiftOut */
137 code = ensure_char_entry(op, "ShiftIn", &data.ShiftIn, 15);
138 if (code >= 0)
139 code = ensure_char_entry(op, "ShiftOut", &data.ShiftOut, 14);
140 break;
141 case fmap_SubsVector: /* need SubsVector */
142 {
143 ref *psubsvector;
144 uint svsize;
145
146 if (dict_find_string(op, "SubsVector", &psubsvector) <= 0 ||
147 !r_has_type(psubsvector, t_string) ||
148 (svsize = r_size(psubsvector)) == 0 ||
149 (data.subs_width = (int)*psubsvector->value.bytes + 1) > 4 ||
150 (svsize - 1) % data.subs_width != 0
151 )
152 return_error(e_invalidfont);
153 data.subs_size = (svsize - 1) / data.subs_width;
154 data.SubsVector.data = psubsvector->value.bytes + 1;
155 data.SubsVector.size = svsize - 1;
156 } break;
157 case fmap_CMap: /* need CMap */
158 code = ztype0_get_cmap(&data.CMap, (const ref *)&fdepvector,
159 (const ref *)op);
160 break;
161 default:
162 ;
163 }
164 if (code < 0)
165 return code;
166 /*
167 * Save the old FID in case we have to back out.
168 * build_gs_font will return an error if there is a FID entry
169 * but it doesn't reference a valid font.
170 */
171 {
172 ref *pfid;
173
174 if (dict_find_string(op, "FID", &pfid) <= 0)
175 make_null(&save_FID);
176 else
177 save_FID = *pfid;
178 }
179 {
180 build_proc_refs build;
181
182 code = build_proc_name_refs(&build,
183 "%Type0BuildChar", "%Type0BuildGlyph");
184 if (code < 0)
185 return code;
186 code = build_gs_font(op, (gs_font **) & pfont,
187 ft_composite, &st_gs_font_type0, &build,
188 bf_options_none);
189 }
190 if (code != 0)
191 return code;
192 /* Fill in the rest of the basic font data. */
193 pfont->procs.init_fstack = gs_type0_init_fstack;
194 pfont->procs.next_char = 0; /* superseded by next_glyph */
195 pfont->procs.define_font = ztype0_define_font;
196 pfont->procs.make_font = ztype0_make_font;
197 pfont->procs.next_glyph = gs_type0_next_glyph;
198 if (dict_find_string(op, "PrefEnc", &pprefenc) <= 0) {
199 ref nul;
200
201 make_null_new(&nul);
202 if ((code = dict_put_string(op, "PrefEnc", &nul)) < 0)
203 goto fail;
204 }
205 /* Fill in the font data */
206 pdata = pfont_data(pfont);
207 data.encoding_size = r_size(&pdata->Encoding);
208 data.Encoding =
209 (uint *) ialloc_byte_array(data.encoding_size, sizeof(uint),
210 "buildfont0(Encoding)");
211 if (data.Encoding == 0) {
212 code = gs_note_error(e_VMerror);
213 goto fail;
214 }
215 /* Fill in the encoding vector, checking to make sure that */
216 /* each element is an integer between 0 and fdep_size-1. */
217 for (i = 0; i < data.encoding_size; i++) {
218 ref enc;
219
220 array_get(&pdata->Encoding, i, &enc);
221 if (!r_has_type(&enc, t_integer)) {
222 code = gs_note_error(e_typecheck);
223 goto fail;
224 }
225 if ((ulong) enc.value.intval >= data.fdep_size) {
226 code = gs_note_error(e_rangecheck);
227 goto fail;
228 }
229 data.Encoding[i] = (uint) enc.value.intval;
230 }
231 data.FDepVector =
232 ialloc_struct_array(data.fdep_size, gs_font *,
233 &st_gs_font_ptr_element,
234 "buildfont0(FDepVector)");
235 if (data.FDepVector == 0) {
236 code = gs_note_error(e_VMerror);
237 goto fail;
238 }
239 for (i = 0; i < data.fdep_size; i++) {
240 ref fdep;
241 ref *pfid;
242
243 array_get(&fdepvector, i, &fdep);
244 /* The lookup can't fail, because of the pre-check above. */
245 dict_find_string(&fdep, "FID", &pfid);
246 data.FDepVector[i] = r_ptr(pfid, gs_font);
247 }
248 pfont->data = data;
249 code = define_gs_font((gs_font *) pfont);
250 if (code >= 0)
251 return code;
252 fail:
253 /* Undo the insertion of the FID entry in the dictionary. */
254 if (r_has_type(&save_FID, t_null)) {
255 ref rnfid;
256
257 name_enter_string("FID", &rnfid);
258 dict_undef(op, &rnfid);
259 } else
260 dict_put_string(op, "FID", &save_FID);
261 gs_free_object(pfont->memory, pfont, "buildfont0(font)");
262 return code;
263 }
264 /* If a newly defined or scaled composite font had to scale */
265 /* any composite sub-fonts, adjust the parent font's FDepVector. */
266 /* This is called only if gs_type0_define/make_font */
267 /* actually changed the FDepVector. */
268 private int
269 ztype0_adjust_FDepVector(gs_font_type0 * pfont)
270 {
271 gs_font **pdep = pfont->data.FDepVector;
272 ref newdep;
273 uint fdep_size = pfont->data.fdep_size;
274 ref *prdep;
275 uint i;
276 int code = ialloc_ref_array(&newdep, a_readonly, fdep_size,
277 "ztype0_adjust_matrix");
278
279 if (code < 0)
280 return code;
281 for (prdep = newdep.value.refs, i = 0; i < fdep_size; i++, prdep++) {
282 const ref *pdict = pfont_dict(pdep[i]);
283
284 ref_assign_new(prdep, pdict);
285 }
286 return dict_put_string(pfont_dict(pfont), "FDepVector", &newdep);
287 }
288 private int
289 ztype0_define_font(gs_font_dir * pdir, gs_font * pfont)
290 {
291 gs_font_type0 *const pfont0 = (gs_font_type0 *)pfont;
292 gs_font **pdep = pfont0->data.FDepVector;
293 int code = gs_type0_define_font(pdir, pfont);
294
295 if (code < 0 || pfont0->data.FDepVector == pdep)
296 return code;
297 return ztype0_adjust_FDepVector(pfont0);
298 }
299 private int
300 ztype0_make_font(gs_font_dir * pdir, const gs_font * pfont,
301 const gs_matrix * pmat, gs_font ** ppfont)
302 {
303 gs_font_type0 **const ppfont0 = (gs_font_type0 **)ppfont;
304 gs_font **pdep = (*ppfont0)->data.FDepVector;
305 int code;
306
307 code = zdefault_make_font(pdir, pfont, pmat, ppfont);
308 if (code < 0)
309 return code;
310 code = gs_type0_make_font(pdir, pfont, pmat, ppfont);
311 if (code < 0)
312 return code;
313 if ((*ppfont0)->data.FDepVector == pdep)
314 return 0;
315 return ztype0_adjust_FDepVector(*ppfont0);
316 }
317
318 /* ------ Internal routines ------ */
319
320 /* Find or add a character entry in a font dictionary. */
321 private int
322 ensure_char_entry(os_ptr op, const char *kstr,
323 byte * pvalue, int default_value)
324 {
325 ref *pentry;
326
327 if (dict_find_string(op, kstr, &pentry) <= 0) {
328 ref ent;
329
330 make_int(&ent, default_value);
331 *pvalue = (byte) default_value;
332 return dict_put_string(op, kstr, &ent);
333 } else {
334 check_int_leu_only(*pentry, 255);
335 *pvalue = (byte) pentry->value.intval;
336 return 0;
337 }
338 }
339
340 /* ------ Initialization procedure ------ */
341
342 const op_def zfont0_op_defs[] =
343 {
344 {"2.buildfont0", zbuildfont0},
345 op_def_end(0)
346 };