2 |
- |
1 |
/* Copyright (C) 1997, 1998, 1999, 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: gxtype1.c,v 1.41 2004/11/19 04:39:11 ray Exp $ */
|
|
|
18 |
/* Adobe Type 1 font interpreter support */
|
|
|
19 |
#include "math_.h"
|
|
|
20 |
#include "memory_.h"
|
|
|
21 |
#include "gx.h"
|
|
|
22 |
#include "gserrors.h"
|
|
|
23 |
#include "gsccode.h"
|
|
|
24 |
#include "gsline.h"
|
|
|
25 |
#include "gsstruct.h"
|
|
|
26 |
#include "gxarith.h"
|
|
|
27 |
#include "gxchrout.h"
|
|
|
28 |
#include "gxfixed.h"
|
|
|
29 |
#include "gxistate.h"
|
|
|
30 |
#include "gxmatrix.h"
|
|
|
31 |
#include "gxcoord.h"
|
|
|
32 |
#include "gxfont.h"
|
|
|
33 |
#include "gxfont1.h"
|
|
|
34 |
#include "gxtype1.h"
|
|
|
35 |
#include "gzpath.h"
|
|
|
36 |
|
|
|
37 |
/*
|
|
|
38 |
* The routines in this file are used for both Type 1 and Type 2
|
|
|
39 |
* charstring interpreters.
|
|
|
40 |
*/
|
|
|
41 |
|
|
|
42 |
/*
|
|
|
43 |
* Define whether or not to force hints to "big pixel" boundaries
|
|
|
44 |
* when rasterizing at higher resolution. With the current algorithms,
|
|
|
45 |
* a value of 1 is better for devices without alpha capability,
|
|
|
46 |
* but 0 is better if alpha is available.
|
|
|
47 |
*/
|
|
|
48 |
#define FORCE_HINTS_TO_BIG_PIXELS 1
|
|
|
49 |
|
|
|
50 |
/* Structure descriptor */
|
|
|
51 |
public_st_gs_font_type1();
|
|
|
52 |
|
|
|
53 |
/* Define the structure type for a Type 1 interpreter state. */
|
|
|
54 |
public_st_gs_type1_state();
|
|
|
55 |
/* GC procedures */
|
|
|
56 |
private
|
|
|
57 |
ENUM_PTRS_WITH(gs_type1_state_enum_ptrs, gs_type1_state *pcis)
|
|
|
58 |
{
|
|
|
59 |
index -= 4;
|
|
|
60 |
if (index < pcis->ips_count * ST_GLYPH_DATA_NUM_PTRS)
|
|
|
61 |
return ENUM_USING(st_glyph_data,
|
|
|
62 |
&pcis->ipstack[index / ST_GLYPH_DATA_NUM_PTRS].cs_data,
|
|
|
63 |
sizeof(pcis->ipstack[0].cs_data),
|
|
|
64 |
index % ST_GLYPH_DATA_NUM_PTRS);
|
|
|
65 |
return 0;
|
|
|
66 |
}
|
|
|
67 |
ENUM_PTR3(0, gs_type1_state, pfont, pis, path);
|
|
|
68 |
ENUM_PTR(3, gs_type1_state, callback_data);
|
|
|
69 |
ENUM_PTRS_END
|
|
|
70 |
private RELOC_PTRS_WITH(gs_type1_state_reloc_ptrs, gs_type1_state *pcis)
|
|
|
71 |
{
|
|
|
72 |
int i;
|
|
|
73 |
|
|
|
74 |
RELOC_PTR(gs_type1_state, pfont);
|
|
|
75 |
RELOC_PTR(gs_type1_state, pis);
|
|
|
76 |
RELOC_PTR(gs_type1_state, path);
|
|
|
77 |
RELOC_PTR(gs_type1_state, callback_data);
|
|
|
78 |
for (i = 0; i < pcis->ips_count; i++) {
|
|
|
79 |
ip_state_t *ipsp = &pcis->ipstack[i];
|
|
|
80 |
int diff = ipsp->ip - ipsp->cs_data.bits.data;
|
|
|
81 |
|
|
|
82 |
RELOC_USING(st_glyph_data, &ipsp->cs_data, sizeof(ipsp->cs_data));
|
|
|
83 |
ipsp->ip = ipsp->cs_data.bits.data + diff;
|
|
|
84 |
}
|
|
|
85 |
} RELOC_PTRS_END
|
|
|
86 |
|
|
|
87 |
/* Define a string to interact with unique_name in lib/pdf_font.ps .
|
|
|
88 |
The string is used to resolve glyph name conflict while
|
|
|
89 |
converting PDF Widths into Metrics.
|
|
|
90 |
*/
|
|
|
91 |
const char gx_extendeg_glyph_name_separator[] = "~GS~";
|
|
|
92 |
|
|
|
93 |
|
|
|
94 |
/* ------ Interpreter services ------ */
|
|
|
95 |
|
|
|
96 |
#define s (*ps)
|
|
|
97 |
|
|
|
98 |
/* Initialize a Type 1 interpreter. */
|
|
|
99 |
/* The caller must supply a string to the first call of gs_type1_interpret. */
|
|
|
100 |
int
|
|
|
101 |
gs_type1_interp_init(register gs_type1_state * pcis, gs_imager_state * pis,
|
|
|
102 |
gx_path * ppath, const gs_log2_scale_point * pscale,
|
|
|
103 |
const gs_log2_scale_point * psubpixels, bool no_grid_fitting,
|
|
|
104 |
int paint_type, gs_font_type1 * pfont)
|
|
|
105 |
{
|
|
|
106 |
static const gs_log2_scale_point no_scale = {0, 0};
|
|
|
107 |
const gs_log2_scale_point *plog2_scale =
|
|
|
108 |
(FORCE_HINTS_TO_BIG_PIXELS && pscale != NULL ? pscale : &no_scale);
|
|
|
109 |
const gs_log2_scale_point *plog2_subpixels =
|
|
|
110 |
(FORCE_HINTS_TO_BIG_PIXELS ? (psubpixels != NULL ? psubpixels : plog2_scale) : &no_scale);
|
|
|
111 |
|
|
|
112 |
if_debug0('1', "[1]gs_type1_interp_init\n");
|
|
|
113 |
pcis->pfont = pfont;
|
|
|
114 |
pcis->pis = pis;
|
|
|
115 |
pcis->path = ppath;
|
|
|
116 |
pcis->callback_data = pfont; /* default callback data */
|
|
|
117 |
pcis->no_grid_fitting = no_grid_fitting;
|
|
|
118 |
pcis->paint_type = paint_type;
|
|
|
119 |
pcis->os_count = 0;
|
|
|
120 |
pcis->ips_count = 1;
|
|
|
121 |
pcis->ipstack[0].ip = 0;
|
|
|
122 |
gs_glyph_data_from_null(&pcis->ipstack[0].cs_data);
|
|
|
123 |
pcis->ignore_pops = 0;
|
|
|
124 |
pcis->init_done = -1;
|
|
|
125 |
pcis->sb_set = false;
|
|
|
126 |
pcis->width_set = false;
|
|
|
127 |
pcis->num_hints = 0;
|
|
|
128 |
pcis->seac_accent = -1;
|
|
|
129 |
pcis->log2_subpixels = *plog2_subpixels;
|
|
|
130 |
|
|
|
131 |
/* Set the sampling scale. */
|
|
|
132 |
set_pixel_scale(&pcis->scale.x, plog2_scale->x);
|
|
|
133 |
set_pixel_scale(&pcis->scale.y, plog2_scale->y);
|
|
|
134 |
|
|
|
135 |
return 0;
|
|
|
136 |
}
|
|
|
137 |
|
|
|
138 |
/* Set the push/pop callback data. */
|
|
|
139 |
void
|
|
|
140 |
gs_type1_set_callback_data(gs_type1_state *pcis, void *callback_data)
|
|
|
141 |
{
|
|
|
142 |
pcis->callback_data = callback_data;
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
|
|
|
146 |
/* Preset the left side bearing and/or width. */
|
|
|
147 |
void
|
|
|
148 |
gs_type1_set_lsb(gs_type1_state * pcis, const gs_point * psbpt)
|
|
|
149 |
{
|
|
|
150 |
pcis->lsb.x = float2fixed(psbpt->x);
|
|
|
151 |
pcis->lsb.y = float2fixed(psbpt->y);
|
|
|
152 |
pcis->sb_set = true;
|
|
|
153 |
}
|
|
|
154 |
void
|
|
|
155 |
gs_type1_set_width(gs_type1_state * pcis, const gs_point * pwpt)
|
|
|
156 |
{
|
|
|
157 |
pcis->width.x = float2fixed(pwpt->x);
|
|
|
158 |
pcis->width.y = float2fixed(pwpt->y);
|
|
|
159 |
pcis->width_set = true;
|
|
|
160 |
}
|
|
|
161 |
|
|
|
162 |
/* Finish initializing the interpreter if we are actually rasterizing */
|
|
|
163 |
/* the character, as opposed to just computing the side bearing and width. */
|
|
|
164 |
void
|
|
|
165 |
gs_type1_finish_init(gs_type1_state * pcis)
|
|
|
166 |
{
|
|
|
167 |
gs_imager_state *pis = pcis->pis;
|
|
|
168 |
const int max_coeff_bits = 11; /* max coefficient in char space */
|
|
|
169 |
|
|
|
170 |
/* Set up the fixed version of the transformation. */
|
|
|
171 |
gx_matrix_to_fixed_coeff(&ctm_only(pis), &pcis->fc, max_coeff_bits);
|
|
|
172 |
|
|
|
173 |
/* Set the current point of the path to the origin, */
|
|
|
174 |
pcis->origin.x = pcis->path->position.x;
|
|
|
175 |
pcis->origin.y = pcis->path->position.y;
|
|
|
176 |
|
|
|
177 |
/* Initialize hint-related scalars. */
|
|
|
178 |
pcis->asb_diff = pcis->adxy.x = pcis->adxy.y = 0;
|
|
|
179 |
pcis->flex_count = flex_max; /* not in Flex */
|
|
|
180 |
pcis->vs_offset.x = pcis->vs_offset.y = 0;
|
|
|
181 |
|
|
|
182 |
|
|
|
183 |
/* Compute the flatness needed for accurate rendering. */
|
|
|
184 |
pcis->flatness = gs_char_flatness(pis, 0.001);
|
|
|
185 |
|
|
|
186 |
pcis->init_done = 1;
|
|
|
187 |
}
|
|
|
188 |
|
|
|
189 |
|
|
|
190 |
#undef s
|
|
|
191 |
|
|
|
192 |
/* Record the side bearing and character width. */
|
|
|
193 |
int
|
|
|
194 |
gs_type1_sbw(gs_type1_state * pcis, fixed lsbx, fixed lsby, fixed wx, fixed wy)
|
|
|
195 |
{
|
|
|
196 |
if (!pcis->sb_set)
|
|
|
197 |
pcis->lsb.x = lsbx, pcis->lsb.y = lsby,
|
|
|
198 |
pcis->sb_set = true; /* needed for accented chars */
|
|
|
199 |
if (!pcis->width_set)
|
|
|
200 |
pcis->width.x = wx, pcis->width.y = wy,
|
|
|
201 |
pcis->width_set = true;
|
|
|
202 |
if_debug4('1', "[1]sb=(%g,%g) w=(%g,%g)\n",
|
|
|
203 |
fixed2float(pcis->lsb.x), fixed2float(pcis->lsb.y),
|
|
|
204 |
fixed2float(pcis->width.x), fixed2float(pcis->width.y));
|
|
|
205 |
return 0;
|
|
|
206 |
}
|
|
|
207 |
|
|
|
208 |
/* Blend values for a Multiple Master font instance. */
|
|
|
209 |
/* The stack holds values ... K*N othersubr#. */
|
|
|
210 |
int
|
|
|
211 |
gs_type1_blend(gs_type1_state *pcis, fixed *csp, int num_results)
|
|
|
212 |
{
|
|
|
213 |
gs_type1_data *pdata = &pcis->pfont->data;
|
|
|
214 |
int num_values = fixed2int_var(csp[-1]);
|
|
|
215 |
int k1 = num_values / num_results - 1;
|
|
|
216 |
int i, j;
|
|
|
217 |
fixed *base;
|
|
|
218 |
fixed *deltas;
|
|
|
219 |
|
|
|
220 |
if (num_values < num_results ||
|
|
|
221 |
num_values % num_results != 0
|
|
|
222 |
)
|
|
|
223 |
return_error(gs_error_invalidfont);
|
|
|
224 |
base = csp - 1 - num_values;
|
|
|
225 |
deltas = base + num_results - 1;
|
|
|
226 |
for (j = 0; j < num_results;
|
|
|
227 |
j++, base++, deltas += k1
|
|
|
228 |
)
|
|
|
229 |
for (i = 1; i <= k1; i++)
|
|
|
230 |
*base += (fixed)(deltas[i] *
|
|
|
231 |
pdata->WeightVector.values[i]);
|
|
|
232 |
pcis->ignore_pops = num_results;
|
|
|
233 |
return num_values - num_results + 2;
|
|
|
234 |
}
|
|
|
235 |
|
|
|
236 |
/*
|
|
|
237 |
* Handle a seac. Do the base character now; when it finishes (detected
|
|
|
238 |
* in endchar), do the accent. Note that we pass only 4 operands on the
|
|
|
239 |
* stack, and pass asb separately.
|
|
|
240 |
*/
|
|
|
241 |
int
|
|
|
242 |
gs_type1_seac(gs_type1_state * pcis, const fixed * cstack, fixed asb,
|
|
|
243 |
ip_state_t * ipsp)
|
|
|
244 |
{
|
|
|
245 |
gs_font_type1 *pfont = pcis->pfont;
|
|
|
246 |
gs_glyph_data_t bgdata;
|
|
|
247 |
gs_const_string gstr;
|
|
|
248 |
int code;
|
|
|
249 |
|
|
|
250 |
/* Save away all the operands. */
|
|
|
251 |
pcis->seac_accent = fixed2int_var(cstack[3]);
|
|
|
252 |
pcis->save_asb = asb;
|
|
|
253 |
pcis->save_lsb = pcis->lsb;
|
|
|
254 |
pcis->save_adxy.x = cstack[0];
|
|
|
255 |
pcis->save_adxy.y = cstack[1];
|
|
|
256 |
pcis->os_count = 0; /* clear */
|
|
|
257 |
/* Ask the caller to provide the base character's CharString. */
|
|
|
258 |
code = pfont->data.procs.seac_data
|
|
|
259 |
(pfont, fixed2int_var(cstack[2]), NULL, &gstr, &bgdata);
|
|
|
260 |
if (code < 0)
|
|
|
261 |
return code;
|
|
|
262 |
/* Continue with the supplied string. */
|
|
|
263 |
ipsp->cs_data = bgdata;
|
|
|
264 |
return 0;
|
|
|
265 |
}
|
|
|
266 |
|
|
|
267 |
/*
|
|
|
268 |
* Handle the end of a character. Return 0 if this is really the end of a
|
|
|
269 |
* character, or 1 if we still have to process the accent of a seac.
|
|
|
270 |
* In the latter case, the interpreter control stack has been set up to
|
|
|
271 |
* point to the start of the accent's CharString; the caller must
|
|
|
272 |
* also set ptx/y to pcis->position.x/y.
|
|
|
273 |
*/
|
|
|
274 |
int
|
|
|
275 |
gs_type1_endchar(gs_type1_state * pcis)
|
|
|
276 |
{
|
|
|
277 |
gs_imager_state *pis = pcis->pis;
|
|
|
278 |
|
|
|
279 |
if (pcis->seac_accent >= 0) { /* We just finished the base character of a seac. */
|
|
|
280 |
/* Do the accent. */
|
|
|
281 |
gs_font_type1 *pfont = pcis->pfont;
|
|
|
282 |
gs_glyph_data_t agdata;
|
|
|
283 |
int achar = pcis->seac_accent;
|
|
|
284 |
gs_const_string gstr;
|
|
|
285 |
int code;
|
|
|
286 |
|
|
|
287 |
agdata.memory = pfont->memory;
|
|
|
288 |
pcis->seac_accent = -1;
|
|
|
289 |
/* Reset the coordinate system origin */
|
|
|
290 |
pcis->asb_diff = pcis->save_asb - pcis->save_lsb.x;
|
|
|
291 |
pcis->adxy = pcis->save_adxy;
|
|
|
292 |
pcis->os_count = 0; /* clear */
|
|
|
293 |
/* Clear the ipstack, in case the base character */
|
|
|
294 |
/* ended inside a subroutine. */
|
|
|
295 |
pcis->ips_count = 1;
|
|
|
296 |
/* Ask the caller to provide the accent's CharString. */
|
|
|
297 |
code = pfont->data.procs.seac_data(pfont, achar, NULL, &gstr, &agdata);
|
|
|
298 |
if (code == gs_error_undefined) {
|
|
|
299 |
/*
|
|
|
300 |
* The font is missing the accent's CharString (due to
|
|
|
301 |
* bad subsetting). Just end drawing here without error.
|
|
|
302 |
* This is like Acrobat Reader behaves.
|
|
|
303 |
*/
|
|
|
304 |
char buf0[gs_font_name_max + 1], buf1[30];
|
|
|
305 |
int l0 = min(pcis->pfont->font_name.size, sizeof(buf0) - 1);
|
|
|
306 |
int l1 = min(gstr.size, sizeof(buf1) - 1);
|
|
|
307 |
|
|
|
308 |
memcpy(buf0, pcis->pfont->font_name.chars, l0);
|
|
|
309 |
buf0[l0] = 0;
|
|
|
310 |
memcpy(buf1, gstr.data, l1);
|
|
|
311 |
buf1[l1] = 0;
|
|
|
312 |
eprintf2("The font '%s' misses the glyph '%s' . Continue skipping the glyph.", buf0, buf1);
|
|
|
313 |
return 0;
|
|
|
314 |
}
|
|
|
315 |
if (code < 0)
|
|
|
316 |
return code;
|
|
|
317 |
/* Continue with the supplied string. */
|
|
|
318 |
pcis->ips_count = 1;
|
|
|
319 |
pcis->ipstack[0].cs_data = agdata;
|
|
|
320 |
return 1;
|
|
|
321 |
}
|
|
|
322 |
if (pcis->pfont->PaintType == 0)
|
|
|
323 |
pis->fill_adjust.x = pis->fill_adjust.y = -1;
|
|
|
324 |
/* Set the flatness for curve rendering. */
|
|
|
325 |
if (!pcis->no_grid_fitting)
|
|
|
326 |
gs_imager_setflat(pis, pcis->flatness);
|
|
|
327 |
return 0;
|
|
|
328 |
}
|
|
|
329 |
|
|
|
330 |
/* Get the metrics (l.s.b. and width) from the Type 1 interpreter. */
|
|
|
331 |
void
|
|
|
332 |
type1_cis_get_metrics(const gs_type1_state * pcis, double psbw[4])
|
|
|
333 |
{
|
|
|
334 |
psbw[0] = fixed2float(pcis->lsb.x);
|
|
|
335 |
psbw[1] = fixed2float(pcis->lsb.y);
|
|
|
336 |
psbw[2] = fixed2float(pcis->width.x);
|
|
|
337 |
psbw[3] = fixed2float(pcis->width.y);
|
|
|
338 |
}
|
|
|
339 |
|
|
|
340 |
/* ------ Font procedures ------ */
|
|
|
341 |
|
|
|
342 |
|
|
|
343 |
/*
|
|
|
344 |
* If a Type 1 character is defined with 'seac', store the character codes
|
|
|
345 |
* in chars[0] and chars[1] and return 1; otherwise, return 0 or <0.
|
|
|
346 |
* This is exported only for the benefit of font copying.
|
|
|
347 |
*/
|
|
|
348 |
int
|
|
|
349 |
gs_type1_piece_codes(/*const*/ gs_font_type1 *pfont,
|
|
|
350 |
const gs_glyph_data_t *pgd, gs_char *chars)
|
|
|
351 |
{
|
|
|
352 |
gs_type1_data *const pdata = &pfont->data;
|
|
|
353 |
/*
|
|
|
354 |
* Decode the CharString looking for seac. We have to process
|
|
|
355 |
* callsubr, callothersubr, and return operators, but if we see
|
|
|
356 |
* any other operators other than [h]sbw, pop, hint operators,
|
|
|
357 |
* or endchar, we can return immediately. We have to include
|
|
|
358 |
* endchar because it is an (undocumented) equivalent for seac
|
|
|
359 |
* in Type 2 CharStrings: see the cx_endchar case in
|
|
|
360 |
* gs_type2_interpret in gstype2.c.
|
|
|
361 |
*
|
|
|
362 |
* It's really unfortunate that we have to duplicate so much parsing
|
|
|
363 |
* code, but factoring out the parser from the interpreter would
|
|
|
364 |
* involve more restructuring than we're prepared to do right now.
|
|
|
365 |
*/
|
|
|
366 |
bool encrypted = pdata->lenIV >= 0;
|
|
|
367 |
fixed cstack[ostack_size];
|
|
|
368 |
fixed *csp;
|
|
|
369 |
ip_state_t ipstack[ipstack_size + 1];
|
|
|
370 |
ip_state_t *ipsp = &ipstack[0];
|
|
|
371 |
const byte *cip;
|
|
|
372 |
crypt_state state;
|
|
|
373 |
int c;
|
|
|
374 |
int code;
|
|
|
375 |
|
|
|
376 |
CLEAR_CSTACK(cstack, csp);
|
|
|
377 |
cip = pgd->bits.data;
|
|
|
378 |
call:
|
|
|
379 |
state = crypt_charstring_seed;
|
|
|
380 |
if (encrypted) {
|
|
|
381 |
int skip = pdata->lenIV;
|
|
|
382 |
|
|
|
383 |
/* Skip initial random bytes */
|
|
|
384 |
for (; skip > 0; ++cip, --skip)
|
|
|
385 |
decrypt_skip_next(*cip, state);
|
|
|
386 |
}
|
|
|
387 |
top:
|
|
|
388 |
for (;;) {
|
|
|
389 |
uint c0 = *cip++;
|
|
|
390 |
|
|
|
391 |
charstring_next(c0, state, c, encrypted);
|
|
|
392 |
if (c >= c_num1) {
|
|
|
393 |
/* This is a number, decode it and push it on the stack. */
|
|
|
394 |
if (c < c_pos2_0) { /* 1-byte number */
|
|
|
395 |
decode_push_num1(csp, cstack, c);
|
|
|
396 |
} else if (c < cx_num4) { /* 2-byte number */
|
|
|
397 |
decode_push_num2(csp, cstack, c, cip, state, encrypted);
|
|
|
398 |
} else if (c == cx_num4) { /* 4-byte number */
|
|
|
399 |
long lw;
|
|
|
400 |
|
|
|
401 |
decode_num4(lw, cip, state, encrypted);
|
|
|
402 |
CS_CHECK_PUSH(csp, cstack);
|
|
|
403 |
*++csp = int2fixed(lw);
|
|
|
404 |
} else /* not possible */
|
|
|
405 |
return_error(gs_error_invalidfont);
|
|
|
406 |
continue;
|
|
|
407 |
}
|
|
|
408 |
#define cnext CLEAR_CSTACK(cstack, csp); goto top
|
|
|
409 |
switch ((char_command) c) {
|
|
|
410 |
default:
|
|
|
411 |
goto out;
|
|
|
412 |
case c_callsubr:
|
|
|
413 |
c = fixed2int_var(*csp) + pdata->subroutineNumberBias;
|
|
|
414 |
code = pdata->procs.subr_data
|
|
|
415 |
(pfont, c, false, &ipsp[1].cs_data);
|
|
|
416 |
if (code < 0)
|
|
|
417 |
return_error(code);
|
|
|
418 |
--csp;
|
|
|
419 |
ipsp->ip = cip, ipsp->dstate = state;
|
|
|
420 |
++ipsp;
|
|
|
421 |
cip = ipsp->cs_data.bits.data;
|
|
|
422 |
goto call;
|
|
|
423 |
case c_return:
|
|
|
424 |
gs_glyph_data_free(&ipsp->cs_data, "gs_type1_piece_codes");
|
|
|
425 |
--ipsp;
|
|
|
426 |
cip = ipsp->ip, state = ipsp->dstate;
|
|
|
427 |
goto top;
|
|
|
428 |
case cx_hstem:
|
|
|
429 |
case cx_vstem:
|
|
|
430 |
case c1_hsbw:
|
|
|
431 |
cnext;
|
|
|
432 |
case cx_endchar:
|
|
|
433 |
if (csp < cstack + 3)
|
|
|
434 |
goto out; /* not seac */
|
|
|
435 |
do_seac:
|
|
|
436 |
/* This is the payoff for all this code! */
|
|
|
437 |
chars[0] = fixed2int(csp[-1]);
|
|
|
438 |
chars[1] = fixed2int(csp[0]);
|
|
|
439 |
return 1;
|
|
|
440 |
case cx_escape:
|
|
|
441 |
charstring_next(*cip, state, c, encrypted);
|
|
|
442 |
++cip;
|
|
|
443 |
switch ((char1_extended_command) c) {
|
|
|
444 |
default:
|
|
|
445 |
goto out;
|
|
|
446 |
case ce1_vstem3:
|
|
|
447 |
case ce1_hstem3:
|
|
|
448 |
case ce1_sbw:
|
|
|
449 |
cnext;
|
|
|
450 |
case ce1_pop:
|
|
|
451 |
/*
|
|
|
452 |
* pop must do nothing, since it is used after
|
|
|
453 |
* subr# 1 3 callothersubr.
|
|
|
454 |
*/
|
|
|
455 |
goto top;
|
|
|
456 |
case ce1_seac:
|
|
|
457 |
goto do_seac;
|
|
|
458 |
case ce1_callothersubr:
|
|
|
459 |
switch (fixed2int_var(*csp)) {
|
|
|
460 |
default:
|
|
|
461 |
goto out;
|
|
|
462 |
case 3:
|
|
|
463 |
csp -= 2;
|
|
|
464 |
goto top;
|
|
|
465 |
case 12:
|
|
|
466 |
case 13:
|
|
|
467 |
case 14:
|
|
|
468 |
case 15:
|
|
|
469 |
case 16:
|
|
|
470 |
case 17:
|
|
|
471 |
case 18:
|
|
|
472 |
cnext;
|
|
|
473 |
}
|
|
|
474 |
}
|
|
|
475 |
}
|
|
|
476 |
#undef cnext
|
|
|
477 |
}
|
|
|
478 |
out:
|
|
|
479 |
return 0;
|
|
|
480 |
}
|
|
|
481 |
|
|
|
482 |
/*
|
|
|
483 |
* Get PIECES and/or NUM_PIECES of a Type 1 glyph. Sets info->num_pieces
|
|
|
484 |
* and/or stores into info->pieces. Updates info->members. This is a
|
|
|
485 |
* single-use procedure broken out only for readability.
|
|
|
486 |
*/
|
|
|
487 |
private int
|
|
|
488 |
gs_type1_glyph_pieces(gs_font_type1 *pfont, const gs_glyph_data_t *pgd,
|
|
|
489 |
int members, gs_glyph_info_t *info)
|
|
|
490 |
{
|
|
|
491 |
gs_char chars[2];
|
|
|
492 |
gs_glyph glyphs[2];
|
|
|
493 |
int code = gs_type1_piece_codes(pfont, pgd, chars);
|
|
|
494 |
gs_type1_data *const pdata = &pfont->data;
|
|
|
495 |
gs_glyph *pieces =
|
|
|
496 |
(members & GLYPH_INFO_PIECES ? info->pieces : glyphs);
|
|
|
497 |
gs_const_string gstr;
|
|
|
498 |
int acode, bcode;
|
|
|
499 |
|
|
|
500 |
info->num_pieces = 0; /* default */
|
|
|
501 |
if (code <= 0) /* no seac, possibly error */
|
|
|
502 |
return code;
|
|
|
503 |
bcode = pdata->procs.seac_data(pfont, chars[0], &pieces[0], &gstr, NULL);
|
|
|
504 |
acode = pdata->procs.seac_data(pfont, chars[1], &pieces[1], &gstr, NULL);
|
|
|
505 |
code = (bcode < 0 ? bcode : acode);
|
|
|
506 |
info->num_pieces = 2;
|
|
|
507 |
return code;
|
|
|
508 |
}
|
|
|
509 |
|
|
|
510 |
int
|
|
|
511 |
gs_type1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat,
|
|
|
512 |
int members, gs_glyph_info_t *info)
|
|
|
513 |
{
|
|
|
514 |
gs_font_type1 *const pfont = (gs_font_type1 *)font;
|
|
|
515 |
gs_type1_data *const pdata = &pfont->data;
|
|
|
516 |
int wmode = ((members & GLYPH_INFO_WIDTH1) != 0);
|
|
|
517 |
int piece_members = members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES);
|
|
|
518 |
int width_members = (members & ((GLYPH_INFO_WIDTH0 << wmode) | (GLYPH_INFO_VVECTOR0 << wmode)));
|
|
|
519 |
int default_members = members & ~(piece_members | GLYPH_INFO_WIDTHS |
|
|
|
520 |
GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1 |
|
|
|
521 |
GLYPH_INFO_OUTLINE_WIDTHS);
|
|
|
522 |
int code = 0;
|
|
|
523 |
gs_glyph_data_t gdata;
|
|
|
524 |
|
|
|
525 |
if (default_members) {
|
|
|
526 |
code = gs_default_glyph_info(font, glyph, pmat, default_members, info);
|
|
|
527 |
|
|
|
528 |
if (code < 0)
|
|
|
529 |
return code;
|
|
|
530 |
} else
|
|
|
531 |
info->members = 0;
|
|
|
532 |
|
|
|
533 |
if (default_members == members)
|
|
|
534 |
return code; /* all done */
|
|
|
535 |
|
|
|
536 |
gdata.memory = pfont->memory;
|
|
|
537 |
if ((code = pdata->procs.glyph_data(pfont, glyph, &gdata)) < 0)
|
|
|
538 |
return code; /* non-existent glyph */
|
|
|
539 |
|
|
|
540 |
if (piece_members) {
|
|
|
541 |
code = gs_type1_glyph_pieces(pfont, &gdata, members, info);
|
|
|
542 |
if (code < 0)
|
|
|
543 |
return code;
|
|
|
544 |
info->members |= piece_members;
|
|
|
545 |
}
|
|
|
546 |
|
|
|
547 |
if (width_members) {
|
|
|
548 |
/*
|
|
|
549 |
* Interpret the CharString until we get to the [h]sbw.
|
|
|
550 |
*/
|
|
|
551 |
gs_imager_state gis;
|
|
|
552 |
gs_type1_state cis;
|
|
|
553 |
int value;
|
|
|
554 |
|
|
|
555 |
/* Initialize just enough of the imager state. */
|
|
|
556 |
if (pmat)
|
|
|
557 |
gs_matrix_fixed_from_matrix(&gis.ctm, pmat);
|
|
|
558 |
else {
|
|
|
559 |
gs_matrix imat;
|
|
|
560 |
|
|
|
561 |
gs_make_identity(&imat);
|
|
|
562 |
gs_matrix_fixed_from_matrix(&gis.ctm, &imat);
|
|
|
563 |
}
|
|
|
564 |
gis.flatness = 0;
|
|
|
565 |
code = gs_type1_interp_init(&cis, &gis, NULL /* no path needed */,
|
|
|
566 |
NULL, NULL, true, 0, pfont);
|
|
|
567 |
if (code < 0)
|
|
|
568 |
return code;
|
|
|
569 |
cis.no_grid_fitting = true;
|
|
|
570 |
code = pdata->interpret(&cis, &gdata, &value);
|
|
|
571 |
switch (code) {
|
|
|
572 |
case 0: /* done with no [h]sbw, error */
|
|
|
573 |
code = gs_note_error(gs_error_invalidfont);
|
|
|
574 |
default: /* code < 0, error */
|
|
|
575 |
return code;
|
|
|
576 |
case type1_result_callothersubr: /* unknown OtherSubr */
|
|
|
577 |
return_error(gs_error_rangecheck); /* can't handle it */
|
|
|
578 |
case type1_result_sbw:
|
|
|
579 |
info->width[wmode].x = fixed2float(cis.width.x);
|
|
|
580 |
info->width[wmode].y = fixed2float(cis.width.y);
|
|
|
581 |
info->v.x = fixed2float(cis.lsb.x);
|
|
|
582 |
info->v.y = fixed2float(cis.lsb.y);
|
|
|
583 |
break;
|
|
|
584 |
}
|
|
|
585 |
info->members |= width_members | (GLYPH_INFO_VVECTOR0 << wmode);
|
|
|
586 |
}
|
|
|
587 |
|
|
|
588 |
gs_glyph_data_free(&gdata, "gs_type1_glyph_info");
|
|
|
589 |
return code;
|
|
|
590 |
}
|
|
|
591 |
|
|
|
592 |
/* Get font parent (a Type 9 font). */
|
|
|
593 |
const gs_font_base *
|
|
|
594 |
gs_font_parent(const gs_font_base *pbfont)
|
|
|
595 |
{
|
|
|
596 |
if (pbfont->FontType == ft_encrypted || pbfont->FontType == ft_encrypted2) {
|
|
|
597 |
const gs_font_type1 *pfont1 = (const gs_font_type1 *)pbfont;
|
|
|
598 |
|
|
|
599 |
if (pfont1->data.parent != NULL)
|
|
|
600 |
return pfont1->data.parent;
|
|
|
601 |
}
|
|
|
602 |
return pbfont;
|
|
|
603 |
}
|