1 /* Copyright (C) 1991, 2000 artofcode LLC. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2 of the License, or (at your
6 option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along
14 with this program; if not, write to the Free Software Foundation, Inc.,
15 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16
17 */
18
19 /*$Id: zfont1.c,v 1.9.4.1.2.1 2003/01/17 00:49:06 giles Exp $ */
20 /* Type 1 and Type 4 font creation operators */
21 #include "memory_.h"
22 #include "ghost.h"
23 #include "oper.h"
24 #include "gxfixed.h"
25 #include "gsmatrix.h"
26 #include "gxdevice.h"
27 #include "gxfont.h"
28 #include "gxfont1.h"
29 #include "bfont.h"
30 #include "ialloc.h"
31 #include "icharout.h"
32 #include "ichar1.h"
33 #include "idict.h"
34 #include "idparam.h"
35 #include "ifont1.h"
36 #include "iname.h" /* for name_index in enumerate_glyph */
37 #include "store.h"
38
39 /* Type 1 font procedures (defined in zchar1.c) */
40 extern const gs_type1_data_procs_t z1_data_procs;
41 font_proc_glyph_info(z1_glyph_info);
42 /* Font procedures defined here */
43 private font_proc_same_font(z1_same_font);
44
45 /* ------ Private utilities ------ */
46
47 private void
find_zone_height(float * pmax_height,int count,const float * values)48 find_zone_height(float *pmax_height, int count, const float *values)
49 {
50 int i;
51 float zone_height;
52
53 for (i = 0; i < count; i += 2)
54 if ((zone_height = values[i + 1] - values[i]) > *pmax_height)
55 *pmax_height = zone_height;
56 }
57
58 /* ------ Font procedures ------ */
59
60 private int
z1_enumerate_glyph(gs_font * pfont,int * pindex,gs_glyph_space_t ignored,gs_glyph * pglyph)61 z1_enumerate_glyph(gs_font * pfont, int *pindex, gs_glyph_space_t ignored,
62 gs_glyph * pglyph)
63 {
64 const gs_font_type1 *const pfont1 = (gs_font_type1 *)pfont;
65 const ref *pcsdict = &pfont_data(pfont1)->CharStrings;
66
67 return zchar_enumerate_glyph(pcsdict, pindex, pglyph);
68 }
69
70 /* ------ Public procedures ------ */
71
72 /* Extract pointers to internal structures. */
73 int
charstring_font_get_refs(const_os_ptr op,charstring_font_refs_t * pfr)74 charstring_font_get_refs(const_os_ptr op, charstring_font_refs_t *pfr)
75 {
76 check_type(*op, t_dictionary);
77 if (dict_find_string(op, "Private", &pfr->Private) <= 0 ||
78 !r_has_type(pfr->Private, t_dictionary)
79 )
80 return_error(e_invalidfont);
81 make_empty_array(&pfr->no_subrs, 0);
82 if (dict_find_string(pfr->Private, "OtherSubrs", &pfr->OtherSubrs) > 0) {
83 if (!r_is_array(pfr->OtherSubrs))
84 return_error(e_typecheck);
85 } else
86 pfr->OtherSubrs = &pfr->no_subrs;
87 if (dict_find_string(pfr->Private, "Subrs", &pfr->Subrs) > 0) {
88 if (!r_is_array(pfr->Subrs))
89 return_error(e_typecheck);
90 } else
91 pfr->Subrs = &pfr->no_subrs;
92 pfr->GlobalSubrs = &pfr->no_subrs;
93 return 0;
94 }
95
96 /* Get the parameters of a CharString-based font or a FDArray entry. */
97 int
charstring_font_params(const_os_ptr op,charstring_font_refs_t * pfr,gs_type1_data * pdata1)98 charstring_font_params(const_os_ptr op, charstring_font_refs_t *pfr,
99 gs_type1_data *pdata1)
100 {
101 const ref *pprivate = pfr->Private;
102 int code;
103
104 /* Get the rest of the information from the Private dictionary. */
105 if ((code = dict_int_param(pprivate, "lenIV", -1, 255, pdata1->lenIV,
106 &pdata1->lenIV)) < 0 ||
107 (code = dict_uint_param(pprivate, "subroutineNumberBias",
108 0, max_uint, pdata1->subroutineNumberBias,
109 &pdata1->subroutineNumberBias)) < 0 ||
110 (code = dict_int_param(pprivate, "BlueFuzz", 0, 1999, 1,
111 &pdata1->BlueFuzz)) < 0 ||
112 (code = dict_float_param(pprivate, "BlueScale", 0.039625,
113 &pdata1->BlueScale)) < 0 ||
114 (code = dict_float_param(pprivate, "BlueShift", 7.0,
115 &pdata1->BlueShift)) < 0 ||
116 (code = pdata1->BlueValues.count =
117 dict_float_array_param(pprivate, "BlueValues", max_BlueValues * 2,
118 &pdata1->BlueValues.values[0], NULL)) < 0 ||
119 (code = dict_float_param(pprivate, "ExpansionFactor", 0.06,
120 &pdata1->ExpansionFactor)) < 0 ||
121 (code = pdata1->FamilyBlues.count =
122 dict_float_array_param(pprivate, "FamilyBlues", max_FamilyBlues * 2,
123 &pdata1->FamilyBlues.values[0], NULL)) < 0 ||
124 (code = pdata1->FamilyOtherBlues.count =
125 dict_float_array_param(pprivate,
126 "FamilyOtherBlues", max_FamilyOtherBlues * 2,
127 &pdata1->FamilyOtherBlues.values[0], NULL)) < 0 ||
128 (code = dict_bool_param(pprivate, "ForceBold", false,
129 &pdata1->ForceBold)) < 0 ||
130 /*
131 * We've seen a few fonts with out-of-range LanguageGroup values;
132 * if it weren't for this, the only legal values should be 0 or 1.
133 */
134 (code = dict_int_param(pprivate, "LanguageGroup", min_int, max_int, 0,
135 &pdata1->LanguageGroup)) < 0 ||
136 (code = pdata1->OtherBlues.count =
137 dict_float_array_param(pprivate, "OtherBlues", max_OtherBlues * 2,
138 &pdata1->OtherBlues.values[0], NULL)) < 0 ||
139 (code = dict_bool_param(pprivate, "RndStemUp", true,
140 &pdata1->RndStemUp)) < 0 ||
141 (code = pdata1->StdHW.count =
142 dict_float_array_check_param(pprivate, "StdHW", 1,
143 &pdata1->StdHW.values[0], NULL,
144 0, e_rangecheck)) < 0 ||
145 (code = pdata1->StdVW.count =
146 dict_float_array_check_param(pprivate, "StdVW", 1,
147 &pdata1->StdVW.values[0], NULL,
148 0, e_rangecheck)) < 0 ||
149 (code = pdata1->StemSnapH.count =
150 dict_float_array_param(pprivate, "StemSnapH", max_StemSnap,
151 &pdata1->StemSnapH.values[0], NULL)) < 0 ||
152 (code = pdata1->StemSnapV.count =
153 dict_float_array_param(pprivate, "StemSnapV", max_StemSnap,
154 &pdata1->StemSnapV.values[0], NULL)) < 0 ||
155 /* The WeightVector is in the font dictionary, not Private. */
156 (code = pdata1->WeightVector.count =
157 dict_float_array_param(op, "WeightVector", max_WeightVector,
158 pdata1->WeightVector.values, NULL)) < 0
159 )
160 return code;
161 /*
162 * According to section 5.6 of the "Adobe Type 1 Font Format",
163 * there is a requirement that BlueScale times the maximum
164 * alignment zone height must be less than 1. Some fonts
165 * produced by Fontographer have ridiculously large BlueScale
166 * values, so we force BlueScale back into range here.
167 */
168 {
169 float max_zone_height = 1.0;
170
171 #define SCAN_ZONE(z)\
172 find_zone_height(&max_zone_height, pdata1->z.count, pdata1->z.values);
173
174 SCAN_ZONE(BlueValues);
175 SCAN_ZONE(OtherBlues);
176 SCAN_ZONE(FamilyBlues);
177 SCAN_ZONE(FamilyOtherBlues);
178
179 #undef SCAN_ZONE
180
181 if (pdata1->BlueScale * max_zone_height > 1.0)
182 pdata1->BlueScale = 1.0 / max_zone_height;
183 }
184 /*
185 * According to the same Adobe book, section 5.11, only values
186 * 0 and 1 are allowed for LanguageGroup and we have encountered
187 * fonts with other values. If the value is anything else, map it to 0
188 * so that the remainder of the graphics library won't see an
189 * unexpected value.
190 */
191 if (pdata1->LanguageGroup > 1 || pdata1->LanguageGroup < 0)
192 pdata1->LanguageGroup = 0;
193 return 0;
194 }
195
196 /* Fill in a newly built CharString-based font or FDArray entry. */
197 int
charstring_font_init(gs_font_type1 * pfont,const charstring_font_refs_t * pfr,const gs_type1_data * pdata1)198 charstring_font_init(gs_font_type1 *pfont, const charstring_font_refs_t *pfr,
199 const gs_type1_data *pdata1)
200 {
201 font_data *pdata;
202
203 pdata = pfont_data(pfont);
204 pfont->data = *pdata1;
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(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(&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
308 return (present == opresent &&
309 (present <= 0 || obj_eq(pvalue, povalue)));
310 }
311 private int
z1_same_font(const gs_font * font,const gs_font * ofont,int mask)312 z1_same_font(const gs_font *font, const gs_font *ofont, int mask)
313 {
314 if (ofont->FontType != font->FontType)
315 return 0;
316 while (font->base != font)
317 font = font->base;
318 while (ofont->base != ofont)
319 ofont = ofont->base;
320 if (ofont == font)
321 return mask;
322 {
323 int same = gs_base_same_font(font, ofont, mask);
324 int check = mask & ~same;
325 const gs_font_type1 *const pfont1 = (const gs_font_type1 *)font;
326 const font_data *const pdata = pfont_data(pfont1);
327 const gs_font_type1 *pofont1 = (const gs_font_type1 *)ofont;
328 const font_data *const podata = pfont_data(pofont1);
329
330 if ((check & (FONT_SAME_OUTLINES | FONT_SAME_METRICS)) &&
331 !memcmp(&pofont1->data.procs, &z1_data_procs, sizeof(z1_data_procs)) &&
332 obj_eq(&pdata->CharStrings, &podata->CharStrings) &&
333 /*
334 * We use same_font_dict for convenience: we know that
335 * both fonts do have Private dictionaries.
336 */
337 same_font_dict(pdata, podata, "Private")
338 )
339 same |= FONT_SAME_OUTLINES;
340
341 if ((check & FONT_SAME_METRICS) && (same & FONT_SAME_OUTLINES) &&
342 !memcmp(&pofont1->data.procs, &z1_data_procs, sizeof(z1_data_procs)) &&
343 /* Metrics may be affected by CDevProc, Metrics, Metrics2. */
344 same_font_dict(pdata, podata, "Metrics") &&
345 same_font_dict(pdata, podata, "Metrics2") &&
346 same_font_dict(pdata, podata, "CDevProc")
347 )
348 same |= FONT_SAME_METRICS;
349
350 if ((check & FONT_SAME_ENCODING) &&
351 pofont1->procs.same_font == z1_same_font &&
352 obj_eq(&pdata->Encoding, &podata->Encoding)
353 )
354 same |= FONT_SAME_ENCODING;
355
356 return same & mask;
357 }
358 }
359
360