xref: /plan9/sys/src/cmd/gs/src/zfont1.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1991, 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: zfont1.c,v 1.13 2004/09/22 13:52:33 igor Exp $ */
18 /* Type 1 and Type 4 font creation operators */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gxfixed.h"
23 #include "gsmatrix.h"
24 #include "gxdevice.h"
25 #include "gxfont.h"
26 #include "gxfont1.h"
27 #include "bfont.h"
28 #include "ialloc.h"
29 #include "icharout.h"
30 #include "ichar1.h"
31 #include "idict.h"
32 #include "idparam.h"
33 #include "ifont1.h"
34 #include "iname.h"		/* for name_index in enumerate_glyph */
35 #include "store.h"
36 
37 /* Type 1 font procedures (defined in zchar1.c) */
38 extern const gs_type1_data_procs_t z1_data_procs;
39 font_proc_glyph_info(z1_glyph_info);
40 /* Font procedures defined here */
41 private font_proc_same_font(z1_same_font);
42 
43 /* ------ Private utilities ------ */
44 
45 private void
find_zone_height(float * pmax_height,int count,const float * values)46 find_zone_height(float *pmax_height, int count, const float *values)
47 {
48     int i;
49     float zone_height;
50 
51     for (i = 0; i < count; i += 2)
52 	if ((zone_height = values[i + 1] - values[i]) > *pmax_height)
53 	    *pmax_height = zone_height;
54 }
55 
56 /* ------ Font procedures ------ */
57 
58 private int
z1_enumerate_glyph(gs_font * pfont,int * pindex,gs_glyph_space_t ignored,gs_glyph * pglyph)59 z1_enumerate_glyph(gs_font * pfont, int *pindex, gs_glyph_space_t ignored,
60 		   gs_glyph * pglyph)
61 {
62     const gs_font_type1 *const pfont1 = (gs_font_type1 *)pfont;
63     const ref *pcsdict = &pfont_data(pfont1)->CharStrings;
64 
65     return zchar_enumerate_glyph(pfont->memory, pcsdict, pindex, pglyph);
66 }
67 
68 /* ------ Public procedures ------ */
69 
70 /* Extract pointers to internal structures. */
71 int
charstring_font_get_refs(const_os_ptr op,charstring_font_refs_t * pfr)72 charstring_font_get_refs(const_os_ptr op, charstring_font_refs_t *pfr)
73 {
74     check_type(*op, t_dictionary);
75     if (dict_find_string(op, "Private", &pfr->Private) <= 0 ||
76 	!r_has_type(pfr->Private, t_dictionary)
77 	)
78 	return_error(e_invalidfont);
79     make_empty_array(&pfr->no_subrs, 0);
80     if (dict_find_string(pfr->Private, "OtherSubrs", &pfr->OtherSubrs) > 0) {
81 	if (!r_is_array(pfr->OtherSubrs))
82 	    return_error(e_typecheck);
83     } else
84 	pfr->OtherSubrs = &pfr->no_subrs;
85     if (dict_find_string(pfr->Private, "Subrs", &pfr->Subrs) > 0) {
86 	if (!r_is_array(pfr->Subrs))
87 	    return_error(e_typecheck);
88     } else
89 	pfr->Subrs = &pfr->no_subrs;
90     pfr->GlobalSubrs = &pfr->no_subrs;
91     return 0;
92 }
93 
94 /* Get the parameters of a CharString-based font or a FDArray entry. */
95 int
charstring_font_params(const gs_memory_t * mem,const_os_ptr op,charstring_font_refs_t * pfr,gs_type1_data * pdata1)96 charstring_font_params(const gs_memory_t *mem,
97 		       const_os_ptr op, charstring_font_refs_t *pfr,
98 		       gs_type1_data *pdata1)
99 {
100     const ref *pprivate = pfr->Private;
101     int code;
102 
103     /* Get the rest of the information from the Private dictionary. */
104     if ((code = dict_int_param(pprivate, "lenIV", -1, 255, pdata1->lenIV,
105 			       &pdata1->lenIV)) < 0 ||
106 	(code = dict_uint_param(pprivate, "subroutineNumberBias",
107 				0, max_uint, pdata1->subroutineNumberBias,
108 				&pdata1->subroutineNumberBias)) < 0 ||
109 	(code = dict_int_param(pprivate, "BlueFuzz", 0, 1999, 1,
110 			       &pdata1->BlueFuzz)) < 0 ||
111 	(code = dict_float_param(pprivate, "BlueScale", 0.039625,
112 				 &pdata1->BlueScale)) < 0 ||
113 	(code = dict_float_param(pprivate, "BlueShift", 7.0,
114 				 &pdata1->BlueShift)) < 0 ||
115 	(code = pdata1->BlueValues.count =
116 	 dict_float_array_param(mem, pprivate, "BlueValues", max_BlueValues * 2,
117 				&pdata1->BlueValues.values[0], NULL)) < 0 ||
118 	(code = dict_float_param(pprivate, "ExpansionFactor", 0.06,
119 				 &pdata1->ExpansionFactor)) < 0 ||
120 	(code = pdata1->FamilyBlues.count =
121 	 dict_float_array_param(mem, pprivate, "FamilyBlues", max_FamilyBlues * 2,
122 				&pdata1->FamilyBlues.values[0], NULL)) < 0 ||
123 	(code = pdata1->FamilyOtherBlues.count =
124 	 dict_float_array_param(mem, pprivate,
125 				"FamilyOtherBlues", max_FamilyOtherBlues * 2,
126 			    &pdata1->FamilyOtherBlues.values[0], NULL)) < 0 ||
127 	(code = dict_bool_param(pprivate, "ForceBold", false,
128 				&pdata1->ForceBold)) < 0 ||
129     /*
130      * We've seen a few fonts with out-of-range LanguageGroup values;
131      * if it weren't for this, the only legal values should be 0 or 1.
132      */
133 	(code = dict_int_param(pprivate, "LanguageGroup", min_int, max_int, 0,
134 			       &pdata1->LanguageGroup)) < 0 ||
135 	(code = pdata1->OtherBlues.count =
136 	 dict_float_array_param(mem, pprivate, "OtherBlues", max_OtherBlues * 2,
137 				&pdata1->OtherBlues.values[0], NULL)) < 0 ||
138 	(code = dict_bool_param(pprivate, "RndStemUp", true,
139 				&pdata1->RndStemUp)) < 0 ||
140 	(code = pdata1->StdHW.count =
141 	 dict_float_array_check_param(mem, pprivate, "StdHW", 1,
142 				      &pdata1->StdHW.values[0], NULL,
143 				      0, e_rangecheck)) < 0 ||
144 	(code = pdata1->StdVW.count =
145 	 dict_float_array_check_param(mem, pprivate, "StdVW", 1,
146 				      &pdata1->StdVW.values[0], NULL,
147 				      0, e_rangecheck)) < 0 ||
148 	(code = pdata1->StemSnapH.count =
149 	 dict_float_array_param(mem, pprivate, "StemSnapH", max_StemSnap,
150 				&pdata1->StemSnapH.values[0], NULL)) < 0 ||
151 	(code = pdata1->StemSnapV.count =
152 	 dict_float_array_param(mem, pprivate, "StemSnapV", max_StemSnap,
153 				&pdata1->StemSnapV.values[0], NULL)) < 0 ||
154     /* The WeightVector is in the font dictionary, not Private. */
155 	(code = pdata1->WeightVector.count =
156 	 dict_float_array_param(mem, op, "WeightVector", max_WeightVector,
157 				pdata1->WeightVector.values, NULL)) < 0
158 	)
159 	return code;
160     /*
161      * According to section 5.6 of the "Adobe Type 1 Font Format",
162      * there is a requirement that BlueScale times the maximum
163      * alignment zone height must be less than 1.  Some fonts
164      * produced by Fontographer have ridiculously large BlueScale
165      * values, so we force BlueScale back into range here.
166      */
167     {
168 	float max_zone_height = 1.0;
169 
170 #define SCAN_ZONE(z)\
171     find_zone_height(&max_zone_height, pdata1->z.count, pdata1->z.values);
172 
173 	SCAN_ZONE(BlueValues);
174 	SCAN_ZONE(OtherBlues);
175 	SCAN_ZONE(FamilyBlues);
176 	SCAN_ZONE(FamilyOtherBlues);
177 
178 #undef SCAN_ZONE
179 
180 	if (pdata1->BlueScale * max_zone_height > 1.0)
181 	    pdata1->BlueScale = 1.0 / max_zone_height;
182     }
183     /*
184      * According to the same Adobe book, section 5.11, only values
185      * 0 and 1 are allowed for LanguageGroup and we have encountered
186      * fonts with other values. If the value is anything else, map it to 0
187      * so that the remainder of the graphics library won't see an
188      * unexpected value.
189      */
190     if (pdata1->LanguageGroup > 1 || pdata1->LanguageGroup < 0)
191 	pdata1->LanguageGroup = 0;
192     return 0;
193 }
194 
195 /* Fill in a newly built CharString-based font or FDArray entry. */
196 int
charstring_font_init(gs_font_type1 * pfont,const charstring_font_refs_t * pfr,const gs_type1_data * pdata1)197 charstring_font_init(gs_font_type1 *pfont, const charstring_font_refs_t *pfr,
198 		     const gs_type1_data *pdata1)
199 {
200     font_data *pdata;
201 
202     pdata = pfont_data(pfont);
203     pfont->data = *pdata1;
204     pfont->data.parent = NULL;
205     ref_assign(&pdata->u.type1.OtherSubrs, pfr->OtherSubrs);
206     ref_assign(&pdata->u.type1.Subrs, pfr->Subrs);
207     ref_assign(&pdata->u.type1.GlobalSubrs, pfr->GlobalSubrs);
208     pfont->data.procs = z1_data_procs;
209     pfont->data.proc_data = (char *)pdata;
210     pfont->procs.same_font = z1_same_font;
211     pfont->procs.glyph_info = z1_glyph_info;
212     pfont->procs.enumerate_glyph = z1_enumerate_glyph;
213     pfont->procs.glyph_outline = zchar1_glyph_outline;
214     return 0;
215 }
216 
217 /* Build a Type 1, Type 2, or Type 4 font. */
218 int
build_charstring_font(i_ctx_t * i_ctx_p,os_ptr op,build_proc_refs * pbuild,font_type ftype,charstring_font_refs_t * pfr,gs_type1_data * pdata1,build_font_options_t options)219 build_charstring_font(i_ctx_t *i_ctx_p, os_ptr op, build_proc_refs *pbuild,
220 		      font_type ftype, charstring_font_refs_t *pfr,
221 		      gs_type1_data *pdata1, build_font_options_t options)
222 {
223     int code = charstring_font_params(imemory, op, pfr, pdata1);
224     gs_font_type1 *pfont;
225 
226     if (code < 0)
227 	return code;
228     code = build_gs_primitive_font(i_ctx_p, op, (gs_font_base **)&pfont, ftype,
229 				   &st_gs_font_type1, pbuild, options);
230     if (code != 0)
231 	return code;
232     /* This is a new font, fill it in. */
233     charstring_font_init(pfont, pfr, pdata1);
234     return define_gs_font((gs_font *)pfont);
235 }
236 
237 /* ------ Operators ------ */
238 
239 /* Build a Type 1 or Type 4 font. */
240 private int
buildfont1or4(i_ctx_t * i_ctx_p,os_ptr op,build_proc_refs * pbuild,font_type ftype,build_font_options_t options)241 buildfont1or4(i_ctx_t *i_ctx_p, os_ptr op, build_proc_refs * pbuild,
242 	      font_type ftype, build_font_options_t options)
243 {
244     charstring_font_refs_t refs;
245     int code = charstring_font_get_refs(op, &refs);
246     gs_type1_data data1;
247 
248     if (code < 0)
249 	return code;
250     data1.interpret = gs_type1_interpret;
251     data1.subroutineNumberBias = 0;
252     data1.lenIV = DEFAULT_LENIV_1;
253     return build_charstring_font(i_ctx_p, op, pbuild, ftype, &refs, &data1,
254 				 options);
255 }
256 
257 /* <string|name> <font_dict> .buildfont1 <string|name> <font> */
258 /* Build a type 1 (Adobe encrypted) font. */
259 private int
zbuildfont1(i_ctx_t * i_ctx_p)260 zbuildfont1(i_ctx_t *i_ctx_p)
261 {
262     os_ptr op = osp;
263     build_proc_refs build;
264     int code = build_proc_name_refs(imemory, &build,
265 				    "%Type1BuildChar", "%Type1BuildGlyph");
266 
267     if (code < 0)
268 	return code;
269     return buildfont1or4(i_ctx_p, op, &build, ft_encrypted,
270 			 bf_notdef_required);
271 }
272 
273 /* <string|name> <font_dict> .buildfont4 <string|name> <font> */
274 /* Build a type 4 (disk-based Adobe encrypted) font. */
275 private int
zbuildfont4(i_ctx_t * i_ctx_p)276 zbuildfont4(i_ctx_t *i_ctx_p)
277 {
278     os_ptr op = osp;
279     build_proc_refs build;
280     int code = build_gs_font_procs(op, &build);
281 
282     if (code < 0)
283 	return code;
284     return buildfont1or4(i_ctx_p, op, &build, ft_disk_based, bf_options_none);
285 }
286 
287 /* ------ Initialization procedure ------ */
288 
289 const op_def zfont1_op_defs[] =
290 {
291     {"2.buildfont1", zbuildfont1},
292     {"2.buildfont4", zbuildfont4},
293     op_def_end(0)
294 };
295 
296 /* ------ Font procedures for Type 1 fonts ------ */
297 
298 /* same_font procedure */
299 private bool
same_font_dict(const font_data * pdata,const font_data * podata,const char * key)300 same_font_dict(const font_data *pdata, const font_data *podata,
301 	       const char *key)
302 {
303     ref *pvalue;
304     bool present = dict_find_string(&pdata->dict, key, &pvalue) > 0;
305     ref *povalue;
306     bool opresent = dict_find_string(&podata->dict, key, &povalue) > 0;
307     dict *pdict = (&(podata->dict))->value.pdict;
308 
309     return (present == opresent &&
310 	    (present <= 0 || obj_eq(dict_mem(pdict), pvalue, povalue)));
311 }
312 private int
z1_same_font(const gs_font * font,const gs_font * ofont,int mask)313 z1_same_font(const gs_font *font, const gs_font *ofont, int mask)
314 {
315     if (ofont->FontType != font->FontType)
316 	return 0;
317     while (font->base != font)
318 	font = font->base;
319     while (ofont->base != ofont)
320 	ofont = ofont->base;
321     if (ofont == font)
322 	return mask;
323     {
324 	int same = gs_base_same_font(font, ofont, mask);
325 	int check = mask & ~same;
326 	const gs_font_type1 *const pfont1 = (const gs_font_type1 *)font;
327 	const font_data *const pdata = pfont_data(pfont1);
328 	const gs_font_type1 *pofont1 = (const gs_font_type1 *)ofont;
329 	const font_data *const podata = pfont_data(pofont1);
330 
331 	if ((check & (FONT_SAME_OUTLINES | FONT_SAME_METRICS)) &&
332 	    !memcmp(&pofont1->data.procs, &z1_data_procs, sizeof(z1_data_procs)) &&
333 	    obj_eq(font->memory, &pdata->CharStrings, &podata->CharStrings) &&
334 	    /*
335 	     * We use same_font_dict for convenience: we know that
336 	     * both fonts do have Private dictionaries.
337 	     */
338 	    same_font_dict(pdata, podata, "Private")
339 	    )
340 	    same |= FONT_SAME_OUTLINES;
341 
342 	if ((check & FONT_SAME_METRICS) && (same & FONT_SAME_OUTLINES) &&
343 	    !memcmp(&pofont1->data.procs, &z1_data_procs, sizeof(z1_data_procs)) &&
344 	    /* Metrics may be affected by CDevProc, Metrics, Metrics2. */
345 	    same_font_dict(pdata, podata, "Metrics") &&
346 	    same_font_dict(pdata, podata, "Metrics2") &&
347 	    same_font_dict(pdata, podata, "CDevProc")
348 	    )
349 	    same |= FONT_SAME_METRICS;
350 
351 	if ((check & FONT_SAME_ENCODING) &&
352 	    pofont1->procs.same_font == z1_same_font &&
353 	    obj_eq(font->memory, &pdata->Encoding, &podata->Encoding)
354 	    )
355 	    same |= FONT_SAME_ENCODING;
356 
357 	return same & mask;
358     }
359 }
360 
361