/src/libspectre/ghostscript/devices/vector/gdevpdtt.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2020 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Text processing for pdfwrite. */ |
18 | | #include "math_.h" |
19 | | #include "string_.h" |
20 | | #include <stdlib.h> /* abs() */ |
21 | | #include "gx.h" |
22 | | #include "gserrors.h" |
23 | | #include "gscencs.h" |
24 | | #include "gscedata.h" |
25 | | #include "gsmatrix.h" |
26 | | #include "gzstate.h" |
27 | | #include "gxfcache.h" /* for orig_fonts list */ |
28 | | #include "gxfont.h" |
29 | | #include "gxfont0.h" |
30 | | #include "gxfcid.h" |
31 | | #include "gxfcopy.h" |
32 | | #include "gxfcmap.h" |
33 | | #include "gxpath.h" /* for getting current point */ |
34 | | #include "gxchar.h" |
35 | | #include "gxstate.h" |
36 | | #include "gdevpdfx.h" |
37 | | #include "gdevpdfg.h" |
38 | | #include "gdevpdfo.h" |
39 | | #include "gdevpdtx.h" |
40 | | #include "gdevpdtd.h" |
41 | | #include "gdevpdtf.h" |
42 | | #include "gdevpdts.h" |
43 | | #include "gdevpdtt.h" |
44 | | #include "gdevpdti.h" |
45 | | #include "gxhldevc.h" |
46 | | #include "gzpath.h" |
47 | | |
48 | | /* ================ Text enumerator ================ */ |
49 | | |
50 | | /* GC descriptor */ |
51 | | private_st_pdf_text_enum(); |
52 | | |
53 | | /* Define the auxiliary procedures for text processing. */ |
54 | | static int |
55 | | pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom) |
56 | 0 | { |
57 | 0 | pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; |
58 | |
|
59 | 0 | if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY) |
60 | 0 | return_error(gs_error_rangecheck); |
61 | 0 | if (penum->pte_default) { |
62 | 0 | int code = gs_text_resync(penum->pte_default, pfrom); |
63 | |
|
64 | 0 | if (code < 0) |
65 | 0 | return code; |
66 | 0 | } |
67 | 0 | pte->text = pfrom->text; |
68 | 0 | gs_text_enum_copy_dynamic(pte, pfrom, false); |
69 | 0 | return 0; |
70 | 0 | } |
71 | | static bool |
72 | | pdf_text_is_width_only(const gs_text_enum_t *pte) |
73 | 0 | { |
74 | 0 | const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte; |
75 | |
|
76 | 0 | if (penum->pte_default) |
77 | 0 | return gs_text_is_width_only(penum->pte_default); |
78 | 0 | return false; |
79 | 0 | } |
80 | | static int |
81 | | pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth) |
82 | 0 | { |
83 | 0 | const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte; |
84 | |
|
85 | 0 | if (penum->pte_default) |
86 | 0 | return gs_text_current_width(penum->pte_default, pwidth); |
87 | 0 | return_error(gs_error_rangecheck); /* can't happen */ |
88 | 0 | } |
89 | | static int |
90 | | pdf_text_set_cache(gs_text_enum_t *pte, const double *pw, |
91 | | gs_text_cache_control_t control) |
92 | 0 | { |
93 | 0 | pdf_text_enum_t *penum; |
94 | 0 | gs_text_enum_t *pgste; |
95 | 0 | gx_device_pdf *pdev = (gx_device_pdf *)pte->dev; |
96 | 0 | gs_matrix m; |
97 | |
|
98 | 0 | if (pdev->pte != NULL) |
99 | 0 | penum = (pdf_text_enum_t *)pdev->pte; |
100 | 0 | else { |
101 | 0 | if (gs_object_type(pte->memory, pte) == &st_pdf_text_enum) |
102 | 0 | penum = (pdf_text_enum_t *)pte; |
103 | 0 | else |
104 | 0 | return_error(gs_error_typecheck); |
105 | 0 | } |
106 | | |
107 | 0 | if (pdev->type3charpath) |
108 | 0 | return gs_text_set_cache(penum->pte_default, pw, control); |
109 | | |
110 | 0 | switch (control) { |
111 | 0 | case TEXT_SET_CHAR_WIDTH: |
112 | 0 | case TEXT_SET_CACHE_DEVICE: |
113 | | /* See comments in pdf_text_process. We are using a 100x100 matrix |
114 | | * NOT the identity, but we want the cache device values to be in |
115 | | * font co-ordinate space, so we need to undo that scale here. |
116 | | */ |
117 | 0 | if (pdev->PS_accumulator){ |
118 | 0 | gs_matrix_scale(&ctm_only(pte->pgs), .01, .01, &m); |
119 | 0 | gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width); |
120 | 0 | } else { |
121 | 0 | pdev->char_width.x = pw[0]; |
122 | 0 | pdev->char_width.y = pw[1]; |
123 | 0 | } |
124 | 0 | break; |
125 | 0 | case TEXT_SET_CACHE_DEVICE2: |
126 | | /* |
127 | | * pdev->char_width is used with synthesized Type 3 fonts only. |
128 | | * Since they are simple fonts, we only need the horisontal |
129 | | * width for Widths array. Therefore we don't check |
130 | | * gs_rootfont(pgs)->WMode and don't use pw[6:7]. |
131 | | */ |
132 | | /* See comments in pdf_text_process. We are using a 100x100 matrix |
133 | | * NOT the identity, but we want the cache device values to be in |
134 | | * font co-ordinate space, so we need to undo that scale here. |
135 | | */ |
136 | 0 | if (pdev->PS_accumulator){ |
137 | 0 | gs_matrix_scale(&ctm_only(pte->pgs), .01, .01, &m); |
138 | 0 | gs_distance_transform(pw[0], pw[1], &m, &pdev->char_width); |
139 | 0 | } else { |
140 | 0 | pdev->char_width.x = pw[0]; |
141 | 0 | pdev->char_width.y = pw[1]; |
142 | 0 | } |
143 | 0 | if (penum->cdevproc_callout) { |
144 | 0 | memcpy(penum->cdevproc_result, pw, sizeof(penum->cdevproc_result)); |
145 | 0 | return 0; |
146 | 0 | } |
147 | 0 | break; |
148 | 0 | default: |
149 | 0 | return_error(gs_error_rangecheck); |
150 | 0 | } |
151 | 0 | if (!pdev->PS_accumulator) |
152 | 0 | pgste = (gs_text_enum_t *)penum; |
153 | 0 | else |
154 | 0 | pgste = penum->pte_default; |
155 | |
|
156 | 0 | if ((penum->current_font->FontType == ft_user_defined || |
157 | 0 | penum->current_font->FontType == ft_PDF_user_defined || |
158 | 0 | penum->current_font->FontType == ft_PCL_user_defined || |
159 | 0 | penum->current_font->FontType == ft_MicroType || |
160 | 0 | penum->current_font->FontType == ft_GL2_stick_user_defined || |
161 | 0 | penum->current_font->FontType == ft_GL2_531) && |
162 | 0 | penum->outer_CID == GS_NO_GLYPH && |
163 | 0 | !(pgste->text.operation & TEXT_DO_CHARWIDTH)) { |
164 | 0 | int code; |
165 | 0 | gs_glyph glyph; |
166 | |
|
167 | 0 | glyph = pte->returned.current_glyph; |
168 | 0 | if ((glyph != GS_NO_GLYPH && penum->output_char_code != GS_NO_CHAR) || !pdev->PS_accumulator) { |
169 | 0 | gs_show_enum *penum_s; |
170 | 0 | gs_fixed_rect clip_box; |
171 | 0 | double pw1[10]; |
172 | 0 | int narg = (control == TEXT_SET_CHAR_WIDTH ? 2 : |
173 | 0 | control == TEXT_SET_CACHE_DEVICE ? 6 : 10), i; |
174 | |
|
175 | 0 | penum_s = (gs_show_enum *)pgste; |
176 | | /* BuildChar could change the scale before calling setcachedevice (Bug 687290). |
177 | | We must scale the setcachedevice arguments because we assumed |
178 | | identity scale before entering the charproc. |
179 | | For now we only handle scaling matrices. |
180 | | */ |
181 | 0 | for (i = 0; i < narg; i += 2) { |
182 | 0 | gs_point p; |
183 | |
|
184 | 0 | gs_point_transform(pw[i], pw[i + 1], &ctm_only(penum_s->pgs), &p); |
185 | 0 | pw1[i] = p.x; |
186 | 0 | pw1[i + 1] = p.y; |
187 | 0 | } |
188 | 0 | if (control != TEXT_SET_CHAR_WIDTH) { |
189 | 0 | clip_box.p.x = float2fixed(pw1[2]); |
190 | 0 | clip_box.p.y = float2fixed(pw1[3]); |
191 | 0 | clip_box.q.x = float2fixed(pw1[4]); |
192 | 0 | clip_box.q.y = float2fixed(pw1[5]); |
193 | 0 | } else { |
194 | | /* |
195 | | * We have no character bbox, but we need one to install the clipping |
196 | | * to the graphic state of the PS interpreter. Since some fonts don't |
197 | | * provide a proper FontBBox (Bug 687239 supplies a zero one), |
198 | | * we set an "infinite" clipping here. |
199 | | * We also detected that min_int, max_int don't work here with |
200 | | * comparefiles/Bug687044.ps, therefore we divide them by 2. |
201 | | */ |
202 | 0 | clip_box.p.x = clip_box.p.y = min_int / 2; |
203 | 0 | clip_box.q.x = clip_box.q.y = max_int / 2; |
204 | 0 | } |
205 | 0 | code = gx_clip_to_rectangle(penum_s->pgs, &clip_box); |
206 | 0 | if (code < 0) |
207 | 0 | return code; |
208 | | |
209 | | /* See comments in pdf_text_process. We are using a 100x100 matrix |
210 | | * NOT the identity, but we want the cache device values to be in |
211 | | * font co-ordinate space, so we need to undo that scale here. We |
212 | | * can't do it above, where we take any scaling from the BuildChar |
213 | | * into account, because that would get the clip path wrong, that |
214 | | * needs to be in the 100x100 space so that it doesn't clip |
215 | | * out marking operations. |
216 | | */ |
217 | 0 | if (pdev->PS_accumulator) |
218 | 0 | gs_matrix_scale(&ctm_only(penum_s->pgs), .01, .01, &m); |
219 | 0 | else |
220 | 0 | m = ctm_only(penum_s->pgs); |
221 | 0 | for (i = 0; i < narg; i += 2) { |
222 | 0 | gs_point p; |
223 | |
|
224 | 0 | gs_point_transform(pw[i], pw[i + 1], &m, &p); |
225 | 0 | pw1[i] = p.x; |
226 | 0 | pw1[i + 1] = p.y; |
227 | 0 | } |
228 | 0 | if (!pdev->PS_accumulator) |
229 | 0 | code = pdf_set_charproc_attrs(pdev, pte->current_font, |
230 | 0 | pw1, narg, control, penum->returned.current_char, false); |
231 | 0 | else |
232 | 0 | code = pdf_set_charproc_attrs(pdev, pte->current_font, |
233 | 0 | pw1, narg, control, penum->output_char_code, true); |
234 | 0 | if (code < 0) |
235 | 0 | return code; |
236 | | /* Prevent writing the clipping path to charproc. |
237 | | See the comment above and bugs 687678, 688327. |
238 | | Note that the clipping in the graphic state will be used while |
239 | | fallbacks to default implementations of graphic objects. |
240 | | Hopely such fallbacks are rare. */ |
241 | 0 | pdev->clip_path_id = gx_get_clip_path_id(penum_s->pgs); |
242 | 0 | return code; |
243 | 0 | } else { |
244 | 0 | gs_matrix m; |
245 | 0 | pdf_resource_t *pres = pdev->accumulating_substream_resource; |
246 | | |
247 | | /* pdf_text_process started a charproc stream accumulation, |
248 | | but now we re-decided to go with the default implementation. |
249 | | Cancel the stream now. |
250 | | */ |
251 | 0 | code = pdf_exit_substream(pdev); |
252 | 0 | if (code < 0) |
253 | 0 | return code; |
254 | 0 | code = pdf_cancel_resource(pdev, pres, resourceCharProc); |
255 | 0 | if (code < 0) |
256 | 0 | return code; |
257 | 0 | pdf_forget_resource(pdev, pres, resourceCharProc); |
258 | | /* pdf_text_process had set an identity CTM for the |
259 | | charproc stream accumulation, but now we re-decided |
260 | | to go with the default implementation. |
261 | | Need to restore the correct CTM and add |
262 | | changes, which the charproc possibly did. */ |
263 | | /* See comments in pdf_text_process. We are using a 100x100 matrix |
264 | | * NOT the identity, so we need to undo that scale here. |
265 | | */ |
266 | 0 | gs_matrix_scale(&ctm_only(penum->pgs), .01, .01, (gs_matrix *)&ctm_only(penum->pgs)); |
267 | | /* We also scaled the page height and width. Because we |
268 | | * don't go through the accumulator 'close' in pdf_text_process |
269 | | * we must also undo that scale. |
270 | | */ |
271 | 0 | pdev->width /= 100; |
272 | 0 | pdev->height /= 100; |
273 | |
|
274 | 0 | gs_matrix_multiply((gs_matrix *)&pdev->charproc_ctm, (gs_matrix *)&penum->pgs->ctm, &m); |
275 | 0 | gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m); |
276 | 0 | penum->charproc_accum = false; |
277 | 0 | pdev->accumulating_charproc = false; |
278 | 0 | } |
279 | 0 | } |
280 | 0 | if (pdev->PS_accumulator && penum->pte_default) { |
281 | 0 | if (penum->pte_default->text.operation & TEXT_DO_CHARWIDTH /* See process_cmap_text.*/) |
282 | 0 | return gs_text_set_cache(penum->pte_default, pw, TEXT_SET_CHAR_WIDTH); |
283 | 0 | else |
284 | 0 | return gs_text_set_cache(penum->pte_default, pw, control); |
285 | 0 | } |
286 | 0 | return_error(gs_error_unregistered); /* can't happen */ |
287 | 0 | } |
288 | | |
289 | | static int |
290 | | pdf_text_retry(gs_text_enum_t *pte) |
291 | 0 | { |
292 | 0 | pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; |
293 | |
|
294 | 0 | if (penum->pte_default) |
295 | 0 | return gs_text_retry(penum->pte_default); |
296 | 0 | return_error(gs_error_rangecheck); /* can't happen */ |
297 | 0 | } |
298 | | static void |
299 | | pdf_text_release(gs_text_enum_t *pte, client_name_t cname) |
300 | 0 | { |
301 | 0 | pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; |
302 | |
|
303 | 0 | if (penum->pte_default) { |
304 | 0 | gs_text_release(penum->pte_default, cname); |
305 | 0 | penum->pte_default = 0; |
306 | 0 | } |
307 | 0 | pdf_text_release_cgp(penum); |
308 | 0 | gx_default_text_release(pte, cname); |
309 | 0 | } |
310 | | void |
311 | | pdf_text_release_cgp(pdf_text_enum_t *penum) |
312 | 0 | { |
313 | 0 | if (penum->cgp) { |
314 | 0 | gs_free_object(penum->memory, penum->cgp, "pdf_text_release"); |
315 | 0 | penum->cgp = 0; |
316 | 0 | } |
317 | 0 | } |
318 | | |
319 | | /* Begin processing text. */ |
320 | | static text_enum_proc_process(pdf_text_process); |
321 | | static const gs_text_enum_procs_t pdf_text_procs = { |
322 | | pdf_text_resync, pdf_text_process, |
323 | | pdf_text_is_width_only, pdf_text_current_width, |
324 | | pdf_text_set_cache, pdf_text_retry, |
325 | | pdf_text_release |
326 | | }; |
327 | | |
328 | | /* Ideally we would set the stroke and fill colours in pdf_prepare_text_drawing |
329 | | * but this is called from pdf_process_text, not pdf_begin_text. The problem is |
330 | | * that if we get a pattern colour we need to exit to the interpreter and run |
331 | | * the PaintProc, we do this by retunring e_ReampColor. But the 'process' routines |
332 | | * aren't set up to accept this, and just throw an error. Trying to rework the |
333 | | * interpreter routines began turning into a gigantic task, so I chose instead |
334 | | * to 'set' the colours here, which is called from text_begin, where the code |
335 | | * allows us to return_error(gs_error_RemapColor. Attempting to write the colour to the PDF file |
336 | | * in this routine as well caused trouble keeping the graphics states synchronised, |
337 | | * so this functionality was left in pdf_prepare_text_drawing. |
338 | | */ |
339 | | static int |
340 | | pdf_prepare_text_color(gx_device_pdf *const pdev, gs_gstate *pgs, const gs_text_params_t *text, gs_font *font) |
341 | 0 | { |
342 | 0 | int code=0; |
343 | 0 | if (text->operation & TEXT_DO_DRAW) { |
344 | 0 | if (!pdev->ForOPDFRead) { |
345 | 0 | if (pgs->text_rendering_mode != 3 && pgs->text_rendering_mode != 7) { |
346 | 0 | if (font->PaintType == 2) { |
347 | | /* Bit awkward, if the PaintType is 2 then we want to set the |
348 | | * current ie 'fill' colour, but as a stroke colour because we |
349 | | * will later change the text rendering mode to 1 (stroke). |
350 | | */ |
351 | 0 | code = gx_set_dev_color(pgs); |
352 | 0 | if (code != 0) |
353 | 0 | return code; |
354 | 0 | code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color, |
355 | 0 | &pdev->stroke_used_process_color, |
356 | 0 | &psdf_set_stroke_color_commands); |
357 | 0 | if (code < 0) |
358 | 0 | return code; |
359 | 0 | } else { |
360 | 0 | if ((pgs->text_rendering_mode == 0 || pgs->text_rendering_mode == 2 || |
361 | 0 | pgs->text_rendering_mode == 4 || pgs->text_rendering_mode == 6) && |
362 | 0 | !pdev->remap_stroke_color) { |
363 | 0 | code = gx_set_dev_color(pgs); |
364 | 0 | if (code != 0) |
365 | 0 | return code; |
366 | 0 | } |
367 | 0 | if (pgs->text_rendering_mode == 1 || pgs->text_rendering_mode == 2 || |
368 | 0 | pgs->text_rendering_mode == 5 || pgs->text_rendering_mode == 6) { |
369 | 0 | if (!pdev->remap_fill_color) { |
370 | 0 | if (pdev->remap_stroke_color) { |
371 | 0 | pdev->remap_stroke_color = false; |
372 | 0 | } else { |
373 | 0 | gs_swapcolors_quick(pgs); |
374 | 0 | code = gx_set_dev_color(pgs); |
375 | 0 | if (code == gs_error_Remap_Color) |
376 | 0 | pdev->remap_stroke_color = true; |
377 | 0 | if (code != 0) |
378 | 0 | return code; |
379 | 0 | } |
380 | 0 | } else |
381 | 0 | pdev->remap_fill_color = false; |
382 | 0 | gs_swapcolors_quick(pgs); |
383 | 0 | code = gx_set_dev_color(pgs); |
384 | 0 | if (code == gs_error_Remap_Color) |
385 | 0 | pdev->remap_fill_color = true; |
386 | 0 | if (code != 0) |
387 | 0 | return code; |
388 | 0 | } |
389 | 0 | } |
390 | 0 | } |
391 | 0 | } |
392 | 0 | } |
393 | 0 | return code; |
394 | 0 | } |
395 | | |
396 | | static int |
397 | | pdf_prepare_text_drawing(gx_device_pdf *const pdev, gs_text_enum_t *pte) |
398 | 0 | { |
399 | 0 | gs_gstate * pgs = pte->pgs; |
400 | 0 | const gx_clip_path * pcpath = pte->pcpath; |
401 | 0 | const gs_text_params_t *text = &pte->text; |
402 | 0 | bool new_clip = false; /* Quiet compiler. */ |
403 | 0 | int code; |
404 | 0 | gs_font *font = pte->current_font; |
405 | |
|
406 | 0 | if (!(text->operation & TEXT_DO_NONE) || pgs->text_rendering_mode == 3) { |
407 | 0 | code = pdf_check_soft_mask(pdev, pte->pgs); |
408 | 0 | if (code < 0) |
409 | 0 | return code; |
410 | 0 | new_clip = pdf_must_put_clip_path(pdev, pcpath); |
411 | 0 | if (new_clip) |
412 | 0 | code = pdf_unclip(pdev); |
413 | 0 | else if (pdev->context == PDF_IN_NONE) |
414 | 0 | code = pdf_open_page(pdev, PDF_IN_STREAM); |
415 | 0 | else |
416 | 0 | code = 0; |
417 | 0 | if (code < 0) |
418 | 0 | return code; |
419 | 0 | code = pdf_prepare_fill(pdev, pgs, true); |
420 | 0 | if (code < 0) |
421 | 0 | return code; |
422 | 0 | } |
423 | 0 | if (text->operation & TEXT_DO_DRAW) { |
424 | | /* |
425 | | * Set the clipping path and drawing color. We set both the fill |
426 | | * and stroke color, because we don't know whether the fonts will be |
427 | | * filled or stroked, and we can't set a color while we are in text |
428 | | * mode. (This is a consequence of the implementation, not a |
429 | | * limitation of PDF.) |
430 | | */ |
431 | |
|
432 | 0 | if (new_clip) { |
433 | 0 | code = pdf_put_clip_path(pdev, pcpath); |
434 | 0 | if (code < 0) |
435 | 0 | return code; |
436 | 0 | } |
437 | | |
438 | 0 | if (!pdev->ForOPDFRead) { |
439 | 0 | if (pgs->text_rendering_mode != 3 && pgs->text_rendering_mode != 7) { |
440 | 0 | if (font->PaintType == 2) { |
441 | | /* Bit awkward, if the PaintType is 2 then we want to set the |
442 | | * current ie 'fill' colour, but as a stroke colour because we |
443 | | * will later change the text rendering mode to 1 (stroke). |
444 | | */ |
445 | 0 | code = gx_set_dev_color(pgs); |
446 | 0 | if (code != 0) |
447 | 0 | return code; |
448 | 0 | code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color, |
449 | 0 | &pdev->stroke_used_process_color, |
450 | 0 | &psdf_set_stroke_color_commands); |
451 | 0 | if (code < 0) |
452 | 0 | return code; |
453 | 0 | } else { |
454 | 0 | if (pgs->text_rendering_mode == 0 || pgs->text_rendering_mode == 2 || |
455 | 0 | pgs->text_rendering_mode == 4 || pgs->text_rendering_mode == 6) { |
456 | 0 | code = gx_set_dev_color(pgs); |
457 | 0 | if (code != 0) |
458 | 0 | return code; |
459 | 0 | code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_fill_color, |
460 | 0 | &pdev->fill_used_process_color, |
461 | 0 | &psdf_set_fill_color_commands); |
462 | 0 | if (code < 0) |
463 | 0 | return code; |
464 | 0 | } |
465 | 0 | if (pgs->text_rendering_mode == 1 || pgs->text_rendering_mode == 2 || |
466 | 0 | pgs->text_rendering_mode == 5 || pgs->text_rendering_mode == 6) { |
467 | 0 | gs_swapcolors_quick(pgs); |
468 | 0 | code = gx_set_dev_color(pgs); |
469 | 0 | if (code != 0) |
470 | 0 | return code; |
471 | 0 | code = pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color, |
472 | 0 | &pdev->stroke_used_process_color, |
473 | 0 | &psdf_set_stroke_color_commands); |
474 | 0 | if (code < 0) |
475 | 0 | return code; |
476 | | |
477 | 0 | gs_swapcolors_quick(pgs); |
478 | 0 | } |
479 | 0 | } |
480 | 0 | } |
481 | 0 | } else { |
482 | 0 | code = gx_set_dev_color(pgs); |
483 | 0 | if (code != 0) |
484 | 0 | return code; |
485 | | |
486 | 0 | if ((code = |
487 | 0 | pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_stroke_color, |
488 | 0 | &pdev->stroke_used_process_color, |
489 | 0 | &psdf_set_stroke_color_commands)) < 0 || |
490 | 0 | (code = |
491 | 0 | pdf_set_drawing_color(pdev, pgs, pgs->color[0].dev_color, &pdev->saved_fill_color, |
492 | 0 | &pdev->fill_used_process_color, |
493 | 0 | &psdf_set_fill_color_commands)) < 0 |
494 | 0 | ) |
495 | 0 | return code; |
496 | 0 | } |
497 | 0 | } |
498 | 0 | return 0; |
499 | 0 | } |
500 | | |
501 | | int |
502 | | gdev_pdf_text_begin(gx_device * dev, gs_gstate * pgs, |
503 | | const gs_text_params_t *text, gs_font * font, |
504 | | gx_path * path0, const gx_device_color * pdcolor, |
505 | | const gx_clip_path * pcpath, |
506 | | gs_memory_t * mem, gs_text_enum_t ** ppte) |
507 | 0 | { |
508 | 0 | gx_device_pdf *const pdev = (gx_device_pdf *)dev; |
509 | 0 | gx_path *path = path0; |
510 | 0 | pdf_text_enum_t *penum; |
511 | 0 | int code, user_defined = 0; |
512 | | |
513 | | /* should we "flatten" the font to "normal" marking operations */ |
514 | 0 | if (pdev->FlattenFonts) { |
515 | 0 | font->dir->ccache.upper = 0; |
516 | 0 | return gx_default_text_begin(dev, pgs, text, font, path, pdcolor, |
517 | 0 | pcpath, mem, ppte); |
518 | 0 | } |
519 | | |
520 | | /* Track the dominant text rotation. */ |
521 | 0 | { |
522 | 0 | gs_matrix tmat; |
523 | 0 | gs_point p; |
524 | 0 | int i; |
525 | |
|
526 | 0 | gs_matrix_multiply(&font->FontMatrix, &ctm_only(pgs), &tmat); |
527 | 0 | gs_distance_transform(1, 0, &tmat, &p); |
528 | 0 | if (p.x > fabs(p.y)) |
529 | 0 | i = 0; |
530 | 0 | else if (p.x < -fabs(p.y)) |
531 | 0 | i = 2; |
532 | 0 | else if (p.y > fabs(p.x)) |
533 | 0 | i = 1; |
534 | 0 | else if (p.y < -fabs(p.x)) |
535 | 0 | i = 3; |
536 | 0 | else |
537 | 0 | i = 4; |
538 | 0 | pdf_current_page(pdev)->text_rotation.counts[i] += text->size; |
539 | 0 | } |
540 | |
|
541 | 0 | pdev->last_charpath_op = 0; |
542 | 0 | if ((text->operation & TEXT_DO_ANY_CHARPATH) && !path0->first_subpath) { |
543 | 0 | if (pdf_compare_text_state_for_charpath(pdev->text->text_state, pdev, pgs, font, text)) |
544 | 0 | pdev->last_charpath_op = text->operation & TEXT_DO_ANY_CHARPATH; |
545 | 0 | } |
546 | |
|
547 | 0 | if(font->FontType == ft_user_defined || |
548 | 0 | font->FontType == ft_PDF_user_defined || |
549 | 0 | font->FontType == ft_PCL_user_defined || |
550 | 0 | font->FontType == ft_MicroType || |
551 | 0 | font->FontType == ft_GL2_stick_user_defined || |
552 | 0 | font->FontType == ft_GL2_531) |
553 | 0 | user_defined = 1; |
554 | | |
555 | | /* We need to know whether any of the glyphs in a string using a composite font |
556 | | * use a descendant font which is a type 3 (user-defined) so that we can properly |
557 | | * skip the caching below. |
558 | | */ |
559 | 0 | if(font->FontType == ft_composite && ((gs_font_type0 *)font)->data.FMapType != fmap_CMap) { |
560 | 0 | int font_code; |
561 | 0 | gs_char chr; |
562 | 0 | gs_glyph glyph; |
563 | |
|
564 | 0 | rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem, |
565 | 0 | return_error(gs_error_VMerror), "gdev_pdf_text_begin"); |
566 | 0 | penum->rc.free = rc_free_text_enum; |
567 | 0 | penum->pte_default = 0; |
568 | 0 | penum->charproc_accum = false; |
569 | 0 | pdev->accumulating_charproc = false; |
570 | 0 | penum->cdevproc_callout = false; |
571 | 0 | penum->returned.total_width.x = penum->returned.total_width.y = 0; |
572 | 0 | penum->cgp = NULL; |
573 | 0 | penum->output_char_code = GS_NO_CHAR; |
574 | 0 | code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs, |
575 | 0 | dev, pgs, text, font, path, pdcolor, pcpath, mem); |
576 | 0 | if (code < 0) { |
577 | 0 | gs_free_object(mem, penum, "gdev_pdf_text_begin"); |
578 | 0 | return code; |
579 | 0 | } |
580 | 0 | do { |
581 | 0 | font_code = penum->orig_font->procs.next_char_glyph |
582 | 0 | ((gs_text_enum_t *)penum, &chr, &glyph); |
583 | 0 | if (font_code == 1){ |
584 | 0 | if (penum->fstack.items[penum->fstack.depth].font->FontType == 3) { |
585 | 0 | user_defined = 1; |
586 | 0 | break; |
587 | 0 | } |
588 | 0 | } |
589 | 0 | } while(font_code != 2 && font_code >= 0); |
590 | 0 | if (!user_defined) { |
591 | 0 | if (penum->fstack.items[penum->fstack.depth].font->FontType == 3) |
592 | 0 | user_defined = 1; |
593 | 0 | } |
594 | 0 | gs_text_release((gs_text_enum_t *)penum, "pdf_text_process"); |
595 | 0 | } |
596 | | |
597 | 0 | if (!user_defined || !(text->operation & TEXT_DO_ANY_CHARPATH)) { |
598 | 0 | if (user_defined && |
599 | 0 | (text->operation & TEXT_DO_NONE) && (text->operation & TEXT_RETURN_WIDTH) |
600 | 0 | && pgs->text_rendering_mode != 3) { |
601 | | /* This is stringwidth, see gx_default_text_begin. |
602 | | * We need to prevent writing characters to PS cache, |
603 | | * otherwise the font converts to bitmaps. |
604 | | * So pass through even with stringwidth. |
605 | | */ |
606 | 0 | code = gx_hld_stringwidth_begin(pgs, &path); |
607 | 0 | if (code < 0) |
608 | 0 | return code; |
609 | 0 | } else if ((!(text->operation & TEXT_DO_DRAW) && pgs->text_rendering_mode != 3) |
610 | 0 | || path == 0 || !path_position_valid(path) |
611 | 0 | || pdev->type3charpath) |
612 | 0 | return gx_default_text_begin(dev, pgs, text, font, path, pdcolor, |
613 | 0 | pcpath, mem, ppte); |
614 | 0 | else if (text->operation & TEXT_DO_ANY_CHARPATH) |
615 | 0 | return gx_default_text_begin(dev, pgs, text, font, path, pdcolor, |
616 | 0 | pcpath, mem, ppte); |
617 | 0 | } |
618 | | |
619 | 0 | if (!pdev->ForOPDFRead) { |
620 | 0 | code = pdf_prepare_text_color(pdev, pgs, text, font); |
621 | 0 | if (code != 0) |
622 | 0 | return code; |
623 | 0 | } |
624 | | |
625 | | /* Allocate and initialize the enumerator. */ |
626 | | |
627 | 0 | rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem, |
628 | 0 | return_error(gs_error_VMerror), "gdev_pdf_text_begin"); |
629 | 0 | penum->rc.free = rc_free_text_enum; |
630 | 0 | penum->pte_default = 0; |
631 | 0 | penum->charproc_accum = false; |
632 | 0 | pdev->accumulating_charproc = false; |
633 | 0 | penum->cdevproc_callout = false; |
634 | 0 | penum->returned.total_width.x = penum->returned.total_width.y = 0; |
635 | 0 | penum->cgp = NULL; |
636 | 0 | penum->output_char_code = GS_NO_CHAR; |
637 | 0 | code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs, |
638 | 0 | dev, pgs, text, font, path, pdcolor, pcpath, mem); |
639 | 0 | if (code < 0) { |
640 | 0 | gs_free_object(mem, penum, "gdev_pdf_text_begin"); |
641 | 0 | return code; |
642 | 0 | } |
643 | 0 | if (pdev->font3 != 0) { |
644 | | /* A text operation happens while accumulating a charproc. |
645 | | This is a case when source document uses a Type 3 font, |
646 | | which's charproc uses another font. |
647 | | Since the text operation is handled by the device, |
648 | | the font isn't converting to a raster (i.e. to a bitmap font). |
649 | | Disable the grid fitting for the convertion to get a proper outlines, |
650 | | because the viewer resolution is not known during the accumulation. |
651 | | Note we set identity CTM in pdf_text_set_cache for the accumilation, |
652 | | and therefore the font may look too small while the source charproc |
653 | | interpretation. The document tpc2.ps of the bug 687087 is an example. |
654 | | */ |
655 | 0 | penum->device_disabled_grid_fitting = true; |
656 | 0 | } |
657 | |
|
658 | 0 | *ppte = (gs_text_enum_t *)penum; |
659 | |
|
660 | 0 | return 0; |
661 | 0 | } |
662 | | |
663 | | /* ================ Font cache element ================ */ |
664 | | |
665 | | /* GC descriptor */ |
666 | | private_st_pdf_font_cache_elem(); |
667 | | |
668 | | /* |
669 | | * Compute id for a font cache element. |
670 | | */ |
671 | | static ulong |
672 | | pdf_font_cache_elem_id(gs_font *font) |
673 | 0 | { |
674 | 0 | return font->id; |
675 | 0 | } |
676 | | |
677 | | pdf_font_cache_elem_t ** |
678 | | pdf_locate_font_cache_elem(gx_device_pdf *pdev, gs_font *font) |
679 | 0 | { |
680 | 0 | pdf_font_cache_elem_t **e = &pdev->font_cache; |
681 | 0 | long id = pdf_font_cache_elem_id(font); |
682 | |
|
683 | 0 | for (; *e != 0; e = &(*e)->next) |
684 | 0 | if ((*e)->font_id == id) { |
685 | 0 | return e; |
686 | 0 | } |
687 | 0 | return 0; |
688 | 0 | } |
689 | | |
690 | | static void |
691 | | pdf_remove_font_cache_elem(gx_device_pdf *pdev, pdf_font_cache_elem_t *e0) |
692 | 0 | { |
693 | 0 | pdf_font_cache_elem_t **e = &pdev->font_cache; |
694 | |
|
695 | 0 | for (; *e != 0; e = &(*e)->next) |
696 | 0 | if (*e == e0) { |
697 | 0 | *e = e0->next; |
698 | 0 | gs_free_object(pdev->pdf_memory, e0->glyph_usage, |
699 | 0 | "pdf_remove_font_cache_elem"); |
700 | 0 | gs_free_object(pdev->pdf_memory, e0->real_widths, |
701 | 0 | "pdf_remove_font_cache_elem"); |
702 | | /* Clean pointers, because gs_free_object below may work idle |
703 | | when this function is called by a garbager notification. |
704 | | Leaving unclean pointers may cause |
705 | | a further heap validation to fail |
706 | | since the unfreed structure points to freed areas. |
707 | | For instance, e0->next may point to an element, |
708 | | which is really freed with a subsequent 'restore'. |
709 | | Bug 688837. */ |
710 | 0 | e0->next = 0; |
711 | 0 | e0->glyph_usage = 0; |
712 | 0 | e0->real_widths = 0; |
713 | 0 | gs_free_object(pdev->pdf_memory, e0, |
714 | 0 | "pdf_remove_font_cache_elem"); |
715 | 0 | return; |
716 | 0 | } |
717 | 0 | } |
718 | | |
719 | | static void |
720 | | font_cache_elem_array_sizes(gx_device_pdf *pdev, gs_font *font, |
721 | | int *num_widths, int *num_chars) |
722 | 0 | { |
723 | 0 | switch (font->FontType) { |
724 | 0 | case ft_composite: |
725 | 0 | *num_widths = 0; /* Unused for Type 0 */ |
726 | 0 | *num_chars = 65536; /* No chance to determine, use max. */ |
727 | 0 | break; |
728 | 0 | case ft_encrypted: |
729 | 0 | case ft_encrypted2: |
730 | 0 | case ft_user_defined: |
731 | 0 | case ft_PDF_user_defined: |
732 | 0 | case ft_GL2_stick_user_defined: |
733 | 0 | case ft_PCL_user_defined: |
734 | 0 | case ft_MicroType: |
735 | 0 | case ft_GL2_531: |
736 | 0 | case ft_disk_based: |
737 | 0 | case ft_Chameleon: |
738 | 0 | case ft_TrueType: |
739 | 0 | *num_widths = *num_chars = 256; /* Assuming access to glyph_usage by character codes */ |
740 | 0 | break; |
741 | 0 | case ft_CID_encrypted: |
742 | 0 | *num_widths = *num_chars = ((gs_font_cid0 *)font)->cidata.common.MaxCID + 1; |
743 | 0 | break; |
744 | 0 | case ft_CID_TrueType: |
745 | 0 | *num_widths = *num_chars = ((gs_font_cid2 *)font)->cidata.common.CIDCount; |
746 | 0 | break; |
747 | 0 | default: |
748 | 0 | *num_widths = *num_chars = 65536; /* No chance to determine, use max. */ |
749 | 0 | } |
750 | 0 | } |
751 | | |
752 | | static int |
753 | | alloc_font_cache_elem_arrays(gx_device_pdf *pdev, pdf_font_cache_elem_t *e, |
754 | | gs_font *font) |
755 | 0 | { |
756 | 0 | int num_widths, num_chars, len; |
757 | |
|
758 | 0 | font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars); |
759 | 0 | len = (num_chars + 7) / 8; |
760 | 0 | e->glyph_usage = gs_alloc_bytes(pdev->pdf_memory, |
761 | 0 | len, "alloc_font_cache_elem_arrays"); |
762 | |
|
763 | 0 | e->real_widths = (num_widths > 0 ? (double *)gs_alloc_bytes(pdev->pdf_memory, |
764 | 0 | num_widths * sizeof(*e->real_widths) * |
765 | 0 | ((font->FontType == ft_user_defined || |
766 | 0 | font->FontType == ft_PDF_user_defined || |
767 | 0 | font->FontType == ft_GL2_stick_user_defined || |
768 | 0 | font->FontType == ft_PCL_user_defined || |
769 | 0 | font->FontType == ft_MicroType || |
770 | 0 | font->FontType == ft_GL2_531) ? 2 : 1), |
771 | 0 | "alloc_font_cache_elem_arrays") : NULL); |
772 | 0 | if (e->glyph_usage == NULL || (num_widths !=0 && e->real_widths == NULL)) { |
773 | 0 | gs_free_object(pdev->pdf_memory, e->glyph_usage, |
774 | 0 | "pdf_attach_font_resource"); |
775 | 0 | gs_free_object(pdev->pdf_memory, e->real_widths, |
776 | 0 | "alloc_font_cache_elem_arrays"); |
777 | 0 | return_error(gs_error_VMerror); |
778 | 0 | } |
779 | 0 | e->num_chars = num_chars; |
780 | 0 | e->num_widths = num_widths; |
781 | 0 | memset(e->glyph_usage, 0, len); |
782 | 0 | if (e->real_widths != NULL) |
783 | 0 | memset(e->real_widths, 0, num_widths * sizeof(*e->real_widths)); |
784 | 0 | return 0; |
785 | 0 | } |
786 | | |
787 | | int |
788 | | pdf_free_font_cache(gx_device_pdf *pdev) |
789 | 0 | { |
790 | 0 | pdf_font_cache_elem_t *e = pdev->font_cache, *next; |
791 | | |
792 | | /* fixed! fixme : release elements. |
793 | | * We no longer track font_cache elements in the original font, which is where |
794 | | * the memory used to be released. So now we must release it ourselves. |
795 | | */ |
796 | |
|
797 | 0 | while (e != NULL) { |
798 | 0 | next = e->next; |
799 | 0 | pdf_remove_font_cache_elem(pdev, e); |
800 | 0 | e = next; |
801 | 0 | } |
802 | 0 | pdev->font_cache = NULL; |
803 | 0 | return 0; |
804 | 0 | } |
805 | | |
806 | | /* |
807 | | * Retrive font resource attached to a font, |
808 | | * allocating glyph_usage and real_widths on request. |
809 | | */ |
810 | | int |
811 | | pdf_attached_font_resource(gx_device_pdf *pdev, gs_font *font, |
812 | | pdf_font_resource_t **pdfont, byte **glyph_usage, |
813 | | double **real_widths, int *num_chars, int *num_widths) |
814 | 0 | { |
815 | 0 | pdf_font_cache_elem_t **e = pdf_locate_font_cache_elem(pdev, font); |
816 | |
|
817 | 0 | if (e != NULL && (((*e)->glyph_usage == NULL && glyph_usage !=NULL) || |
818 | 0 | ((*e)->real_widths == NULL && real_widths !=NULL))) { |
819 | 0 | int code = alloc_font_cache_elem_arrays(pdev, *e, font); |
820 | |
|
821 | 0 | if (code < 0) |
822 | 0 | return code; |
823 | 0 | } |
824 | 0 | *pdfont = (e == NULL ? NULL : (*e)->pdfont); |
825 | 0 | if (glyph_usage != NULL) |
826 | 0 | *glyph_usage = (e == NULL ? NULL : (*e)->glyph_usage); |
827 | 0 | if (real_widths != NULL) |
828 | 0 | *real_widths = (e == NULL ? NULL : (*e)->real_widths); |
829 | 0 | if (num_chars != NULL) |
830 | 0 | *num_chars = (e == NULL ? 0 : (*e)->num_chars); |
831 | 0 | if (num_widths != NULL) |
832 | 0 | *num_widths = (e == NULL ? 0 : (*e)->num_widths); |
833 | 0 | return 0; |
834 | 0 | } |
835 | | |
836 | | /* |
837 | | * Attach font resource to a font. |
838 | | */ |
839 | | int |
840 | | pdf_attach_font_resource(gx_device_pdf *pdev, gs_font *font, |
841 | | pdf_font_resource_t *pdfont) |
842 | 0 | { |
843 | 0 | int num_chars, num_widths, len; |
844 | 0 | pdf_font_cache_elem_t *e, **pe = pdf_locate_font_cache_elem(pdev, font); |
845 | | |
846 | | /* Allow the HPGL2 stick font to be attached to a type 3 font, it *is* a |
847 | | * type 3 font, its just identified differently so that we can choose not |
848 | | * to capture it elsewhere. Same for PCL bitmap fonts. |
849 | | */ |
850 | 0 | if (pdfont->FontType != font->FontType && |
851 | 0 | (pdfont->FontType != ft_user_defined || |
852 | 0 | (font->FontType != ft_PCL_user_defined && |
853 | 0 | font->FontType != ft_PDF_user_defined && |
854 | 0 | font->FontType != ft_MicroType && |
855 | 0 | font->FontType != ft_GL2_stick_user_defined && |
856 | 0 | font->FontType != ft_GL2_531))) |
857 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
858 | 0 | font_cache_elem_array_sizes(pdev, font, &num_widths, &num_chars); |
859 | 0 | len = (num_chars + 7) / 8; |
860 | 0 | if (pe != NULL) { |
861 | 0 | e = *pe; |
862 | 0 | if (e->pdfont == pdfont) |
863 | 0 | return 0; |
864 | 0 | e->pdfont = pdfont; |
865 | | /* Reset glyph cache because e->pdfont had changed. */ |
866 | 0 | memset(e->glyph_usage, 0, len); |
867 | 0 | memset(e->real_widths, 0, num_widths * sizeof(*e->real_widths)); |
868 | 0 | } else { |
869 | 0 | e = (pdf_font_cache_elem_t *)gs_alloc_struct(pdev->pdf_memory, |
870 | 0 | pdf_font_cache_elem_t, &st_pdf_font_cache_elem, |
871 | 0 | "pdf_attach_font_resource"); |
872 | 0 | if (e == NULL) |
873 | 0 | return_error(gs_error_VMerror); |
874 | 0 | e->pdfont = pdfont; |
875 | 0 | e->font_id = pdf_font_cache_elem_id(font); |
876 | 0 | e->num_chars = 0; |
877 | 0 | e->glyph_usage = NULL; |
878 | 0 | e->real_widths = NULL; |
879 | 0 | e->next = pdev->font_cache; |
880 | 0 | pdev->font_cache = e; |
881 | 0 | return 0; |
882 | 0 | } |
883 | 0 | return 0; |
884 | 0 | } |
885 | | |
886 | | /* ================ Process text ================ */ |
887 | | |
888 | | /* ---------------- Internal utilities ---------------- */ |
889 | | |
890 | | /* |
891 | | * Compute and return the orig_matrix of a font. |
892 | | */ |
893 | | int |
894 | | pdf_font_orig_matrix(const gs_font *font, gs_matrix *pmat) |
895 | 0 | { |
896 | 0 | switch (font->FontType) { |
897 | 0 | case ft_composite: /* subfonts have their own FontMatrix */ |
898 | 0 | case ft_TrueType: |
899 | 0 | case ft_CID_TrueType: |
900 | | /* The TrueType FontMatrix is 1 unit per em, which is what we want. */ |
901 | 0 | gs_make_identity(pmat); |
902 | 0 | return 0; |
903 | 0 | case ft_encrypted: |
904 | 0 | case ft_encrypted2: |
905 | 0 | case ft_CID_encrypted: |
906 | 0 | case ft_user_defined: |
907 | 0 | case ft_PCL_user_defined: |
908 | 0 | case ft_PDF_user_defined: |
909 | 0 | case ft_MicroType: |
910 | 0 | case ft_GL2_stick_user_defined: |
911 | 0 | case ft_GL2_531: |
912 | | /* |
913 | | * Type 1 fonts are supposed to use a standard FontMatrix of |
914 | | * [0.001 0 0 0.001 0 0], with a 1000-unit cell. However, |
915 | | * Windows NT 4.0 creates Type 1 fonts, apparently derived from |
916 | | * TrueType fonts, that use a 2048-unit cell and corresponding |
917 | | * FontMatrix. Also, some PS programs perform font scaling by |
918 | | * replacing FontMatrix like this : |
919 | | * |
920 | | * /f12 /Times-Roman findfont |
921 | | * copyfont % (remove FID) |
922 | | * dup /FontMatrix [0.012 0 0 0.012 0 0] put |
923 | | * definefont |
924 | | * /f12 1 selectfont |
925 | | * |
926 | | * Such fonts are their own "base font", but the orig_matrix |
927 | | * must still be set to 0.001, not 0.012 . |
928 | | * |
929 | | * The old code used a heuristic to detect and correct for this here. |
930 | | * Unfortunately it doesn't work properly when it meets a font |
931 | | * with FontMatrix like this : |
932 | | * |
933 | | * /FontMatrix [1 2288 div 0 0 1 2288 div 0 0 ] def |
934 | | * |
935 | | * (the bug 686970). Also comparefiles\455690.pdf appears to |
936 | | * have similar problem. Therefore we added a support to lib/gs_fonts.ps, |
937 | | * src/zbfont.c, src/gsfont.c that provides an acces to the original |
938 | | * font via a special key OrigFont added to the font dictionary while definefont. |
939 | | * Now we work through this access with PS interpreter, |
940 | | * but keep the old heuristic for other clients. |
941 | | */ |
942 | 0 | { |
943 | 0 | const gs_font *base_font = font; |
944 | |
|
945 | 0 | while (base_font->base != base_font) |
946 | 0 | base_font = base_font->base; |
947 | 0 | if (font->FontType == ft_user_defined || |
948 | 0 | font->FontType == ft_PDF_user_defined || |
949 | 0 | font->FontType == ft_PCL_user_defined || |
950 | 0 | font->FontType == ft_MicroType || |
951 | 0 | font->FontType == ft_GL2_stick_user_defined || |
952 | 0 | font->FontType == ft_GL2_531) |
953 | 0 | *pmat = base_font->FontMatrix; |
954 | 0 | else if (base_font->orig_FontMatrix.xx != 0 || base_font->orig_FontMatrix.xy != 0 || |
955 | 0 | base_font->orig_FontMatrix.yx != 0 || base_font->orig_FontMatrix.yy != 0) |
956 | 0 | *pmat = base_font->orig_FontMatrix; |
957 | 0 | else { |
958 | | /* Must not happen with PS interpreter. |
959 | | Provide a hewuristic for other clients. |
960 | | */ |
961 | 0 | if (base_font->FontMatrix.xx == 1.0/2048 && |
962 | 0 | base_font->FontMatrix.xy == 0 && |
963 | 0 | base_font->FontMatrix.yx == 0 && |
964 | 0 | any_abs(base_font->FontMatrix.yy) == 1.0/2048 |
965 | 0 | ) |
966 | 0 | *pmat = base_font->FontMatrix; |
967 | 0 | else |
968 | 0 | gs_make_scaling(0.001, 0.001, pmat); |
969 | 0 | } |
970 | 0 | } |
971 | 0 | return 0; |
972 | 0 | default: |
973 | 0 | return_error(gs_error_rangecheck); |
974 | 0 | } |
975 | 0 | } |
976 | | |
977 | | /* |
978 | | * Special version of pdf_font_orig_matrix(), that cares FDArray font's FontMatrix too. |
979 | | * Called only by pdf_glyph_width(). |
980 | | * 'cid' is only consulted if 'font' is a CIDFontType 0 CID font. |
981 | | */ |
982 | | static int |
983 | | glyph_orig_matrix(const gs_font *font, gs_glyph cid, gs_matrix *pmat) |
984 | 0 | { |
985 | 0 | int code = pdf_font_orig_matrix(font, pmat); |
986 | 0 | if (code >= 0) { |
987 | 0 | if (font->FontType == ft_CID_encrypted) { |
988 | 0 | int fidx; |
989 | |
|
990 | 0 | if (cid < GS_MIN_CID_GLYPH) |
991 | 0 | cid = GS_MIN_CID_GLYPH; |
992 | 0 | code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font, |
993 | 0 | cid, NULL, &fidx); |
994 | 0 | if (code < 0) { |
995 | 0 | code = ((gs_font_cid0 *)font)->cidata.glyph_data((gs_font_base *)font, |
996 | 0 | (gs_glyph)GS_MIN_CID_GLYPH, NULL, &fidx); |
997 | 0 | } |
998 | 0 | if (code >= 0) { |
999 | 0 | gs_matrix_multiply(&(gs_cid0_indexed_font(font, fidx)->FontMatrix), |
1000 | 0 | pmat, pmat); |
1001 | 0 | } |
1002 | 0 | } |
1003 | 0 | } |
1004 | 0 | return code; |
1005 | 0 | } |
1006 | | |
1007 | | /* |
1008 | | * Check the Encoding compatibility |
1009 | | */ |
1010 | | bool |
1011 | | pdf_check_encoding_compatibility(const pdf_font_resource_t *pdfont, |
1012 | | const pdf_char_glyph_pair_t *pairs, int num_chars) |
1013 | 0 | { |
1014 | 0 | int i; |
1015 | |
|
1016 | 0 | for (i = 0; i < num_chars; ++i) { |
1017 | 0 | gs_char ch = pairs[i].chr; |
1018 | 0 | pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; |
1019 | |
|
1020 | 0 | if (pairs[i].glyph == pet->glyph) |
1021 | 0 | continue; |
1022 | 0 | if (pet->glyph != GS_NO_GLYPH) /* encoding conflict */ |
1023 | 0 | return false; |
1024 | 0 | } |
1025 | 0 | return true; |
1026 | 0 | } |
1027 | | |
1028 | | /* |
1029 | | * Check whether the Encoding has listed glyphs. |
1030 | | */ |
1031 | | static bool |
1032 | | pdf_check_encoding_has_glyphs(const pdf_font_resource_t *pdfont, |
1033 | | const pdf_char_glyph_pair_t *pairs, int num_chars) |
1034 | 0 | { |
1035 | | /* This function is pretty slow, but we can't find a better algorithm. |
1036 | | It works for the case of glyphshow with no proper encoding, |
1037 | | which we believe comes from poorly designed documents. |
1038 | | */ |
1039 | 0 | int i, ch; |
1040 | |
|
1041 | 0 | for (i = 0; i < num_chars; ++i) { |
1042 | 0 | for (ch = 0; ch < 256; ch++) { |
1043 | 0 | pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; |
1044 | |
|
1045 | 0 | if (pairs[i].glyph == pet->glyph) |
1046 | 0 | return true; |
1047 | 0 | } |
1048 | 0 | } |
1049 | 0 | return false; |
1050 | 0 | } |
1051 | | |
1052 | | /* |
1053 | | * Check font resource for encoding compatibility. |
1054 | | */ |
1055 | | static bool |
1056 | | pdf_is_compatible_encoding(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, |
1057 | | gs_font *font, const pdf_char_glyph_pair_t *pairs, int num_chars) |
1058 | 0 | { |
1059 | | /* |
1060 | | * This crude version of the code ignores |
1061 | | * the possibility of re-encoding characters. |
1062 | | */ |
1063 | 0 | switch (pdfont->FontType) { |
1064 | 0 | case ft_composite: |
1065 | 0 | { /* |
1066 | | * We assume that source document don't redefine CMap |
1067 | | * resources and that incremental CMaps do not exist. |
1068 | | * Therefore we don't maintain stable CMap copies, |
1069 | | * but just compare CMap names for equality. |
1070 | | * A better implementation should compare the chars->glyphs |
1071 | | * translation against the stable copy of CMap, |
1072 | | * which to be handled with PDF CMap resource. |
1073 | | */ |
1074 | 0 | gs_font_type0 *pfont = (gs_font_type0 *)font; |
1075 | |
|
1076 | 0 | if (pfont->data.FMapType == fmap_CMap) { |
1077 | 0 | const gs_cmap_t *pcmap = pfont->data.CMap; |
1078 | 0 | const gs_const_string *s0 = &pdfont->u.type0.CMapName; |
1079 | 0 | const gs_const_string *s1 = &pcmap->CMapName; |
1080 | |
|
1081 | 0 | return (s0->size == s1->size && |
1082 | 0 | !memcmp(s0->data, s1->data, s0->size)); |
1083 | 0 | } |
1084 | 0 | } |
1085 | 0 | return false; |
1086 | 0 | case ft_user_defined: |
1087 | 0 | case ft_PDF_user_defined: |
1088 | 0 | case ft_PCL_user_defined: |
1089 | 0 | case ft_MicroType: |
1090 | 0 | case ft_GL2_stick_user_defined: |
1091 | 0 | case ft_GL2_531: |
1092 | 0 | if (pdfont->u.simple.Encoding == NULL) |
1093 | 0 | return false; /* Not sure. Happens with 020-01.ps . */ |
1094 | | /* fall through */ |
1095 | 0 | case ft_encrypted: |
1096 | 0 | case ft_encrypted2: |
1097 | 0 | case ft_TrueType: |
1098 | 0 | return pdf_check_encoding_compatibility(pdfont, pairs, num_chars); |
1099 | 0 | case ft_CID_encrypted: |
1100 | 0 | case ft_CID_TrueType: |
1101 | 0 | { |
1102 | 0 | gs_font *font1 = (gs_font *)pdf_font_resource_font(pdfont, false); |
1103 | |
|
1104 | 0 | return gs_is_CIDSystemInfo_compatible( |
1105 | 0 | gs_font_cid_system_info(font), |
1106 | 0 | gs_font_cid_system_info(font1)); |
1107 | 0 | } |
1108 | 0 | default: |
1109 | 0 | return false; |
1110 | 0 | } |
1111 | 0 | } |
1112 | | |
1113 | | /* |
1114 | | * Check whethet the font resource has glyphs. |
1115 | | */ |
1116 | | static bool |
1117 | | pdf_font_has_glyphs(gx_device_pdf *pdev, pdf_font_resource_t *pdfont, |
1118 | | gs_font *font, const pdf_char_glyph_pair_t *pairs, int num_chars) |
1119 | 0 | { |
1120 | | /* |
1121 | | * This crude version of the code ignores |
1122 | | * the possibility of re-encoding characters. |
1123 | | */ |
1124 | 0 | switch (pdfont->FontType) { |
1125 | 0 | case ft_composite: |
1126 | 0 | case ft_user_defined: |
1127 | 0 | case ft_PDF_user_defined: |
1128 | 0 | case ft_PCL_user_defined: |
1129 | 0 | case ft_MicroType: |
1130 | 0 | case ft_GL2_stick_user_defined: |
1131 | 0 | case ft_GL2_531: |
1132 | | /* Unused case. */ |
1133 | 0 | return false; |
1134 | 0 | case ft_encrypted: |
1135 | 0 | case ft_encrypted2: |
1136 | 0 | case ft_TrueType: |
1137 | 0 | return pdf_check_encoding_has_glyphs(pdfont, pairs, num_chars); |
1138 | 0 | case ft_CID_encrypted: |
1139 | 0 | case ft_CID_TrueType: |
1140 | | /* Unused case. */ |
1141 | 0 | return false; |
1142 | 0 | default: |
1143 | 0 | return false; |
1144 | 0 | } |
1145 | 0 | } |
1146 | | |
1147 | | /* |
1148 | | * Find a font resource compatible with a given font. |
1149 | | */ |
1150 | | static int |
1151 | | pdf_find_font_resource(gx_device_pdf *pdev, gs_font *font, |
1152 | | pdf_resource_type_t type, |
1153 | | pdf_font_resource_t **ppdfont, |
1154 | | pdf_char_glyph_pairs_t *cgp, |
1155 | | bool compatible_encoding) |
1156 | 0 | { |
1157 | 0 | pdf_resource_t **pchain = pdev->resources[type].chains; |
1158 | 0 | pdf_resource_t *pres; |
1159 | 0 | int i; |
1160 | |
|
1161 | 0 | for (i = 0; i < NUM_RESOURCE_CHAINS; i++) { |
1162 | 0 | for (pres = pchain[i]; pres != 0; pres = pres->next) { |
1163 | 0 | pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres; |
1164 | 0 | const gs_font_base *cfont; |
1165 | 0 | gs_font *ofont = font; |
1166 | 0 | int code; |
1167 | |
|
1168 | 0 | cfont = (gs_font_base *)font; |
1169 | 0 | if (uid_is_XUID(&cfont->UID)){ |
1170 | 0 | int size = uid_XUID_size(&cfont->UID); |
1171 | 0 | long *xvalues = uid_XUID_values(&cfont->UID); |
1172 | 0 | if (xvalues && size >= 2 && xvalues[0] == 1000000) { |
1173 | 0 | if (xvalues[size - 1] != pdfont->XUID) |
1174 | 0 | continue; |
1175 | 0 | } |
1176 | 0 | } |
1177 | | |
1178 | 0 | if (font->FontType != pdfont->FontType) |
1179 | 0 | continue; |
1180 | 0 | if (pdfont->FontType == ft_composite) { |
1181 | 0 | gs_font_type0 *font0 = (gs_font_type0 *)font; |
1182 | |
|
1183 | 0 | ofont = font0->data.FDepVector[0]; /* See pdf_make_font_resource. */ |
1184 | 0 | cfont = pdf_font_resource_font(pdfont->u.type0.DescendantFont, false); |
1185 | 0 | if (font0->data.CMap->WMode != pdfont->u.type0.WMode) |
1186 | 0 | continue; |
1187 | 0 | } else |
1188 | 0 | cfont = pdf_font_resource_font(pdfont, false); |
1189 | 0 | if (!pdf_is_CID_font(ofont) && |
1190 | 0 | (compatible_encoding |
1191 | 0 | ? !pdf_is_compatible_encoding(pdev, pdfont, font, cgp->s, cgp->num_all_chars) |
1192 | 0 | : !pdf_font_has_glyphs(pdev, pdfont, font, cgp->s, cgp->num_all_chars))) |
1193 | 0 | continue; |
1194 | 0 | if (cfont == 0) |
1195 | 0 | continue; |
1196 | 0 | code = gs_copied_can_copy_glyphs((const gs_font *)cfont, ofont, |
1197 | 0 | &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars, |
1198 | 0 | sizeof(pdf_char_glyph_pair_t), true); |
1199 | 0 | if (code == gs_error_unregistered) /* Debug purpose only. */ |
1200 | 0 | return code; |
1201 | 0 | if(code > 0) { |
1202 | 0 | *ppdfont = pdfont; |
1203 | 0 | return 1; |
1204 | 0 | } |
1205 | 0 | } |
1206 | 0 | } |
1207 | 0 | return 0; |
1208 | 0 | } |
1209 | | |
1210 | | /* |
1211 | | * Find a type0 font resource for a gived descendent name and CMap name. |
1212 | | */ |
1213 | | static int |
1214 | | pdf_find_type0_font_resource(gx_device_pdf *pdev, const pdf_font_resource_t *pdsubf, |
1215 | | const gs_const_string *CMapName, uint font_index, pdf_font_resource_t **ppdfont) |
1216 | 0 | { |
1217 | 0 | pdf_resource_t **pchain = pdev->resources[resourceFont].chains; |
1218 | 0 | pdf_resource_t *pres; |
1219 | 0 | int i; |
1220 | |
|
1221 | 0 | for (i = 0; i < NUM_RESOURCE_CHAINS; i++) { |
1222 | 0 | for (pres = pchain[i]; pres != 0; pres = pres->next) { |
1223 | 0 | pdf_font_resource_t *pdfont = (pdf_font_resource_t *)pres; |
1224 | |
|
1225 | 0 | if (pdfont->FontType != ft_composite) |
1226 | 0 | continue; |
1227 | 0 | if (pdfont->u.type0.DescendantFont != pdsubf) |
1228 | 0 | continue; |
1229 | 0 | if (pdfont->u.type0.font_index != font_index) |
1230 | 0 | continue; |
1231 | | |
1232 | | /* Check to see if the PDF font name is of the form FontName-CMapName |
1233 | | * If it is, check the name and cmap against the BaseFont Name and CMap |
1234 | | * I'm not certain this is *ever* true. |
1235 | | */ |
1236 | 0 | if (pdfont->BaseFont.size == pdsubf->BaseFont.size + CMapName->size + 1) { |
1237 | 0 | if (memcmp(pdfont->BaseFont.data + pdsubf->BaseFont.size + 1, |
1238 | 0 | CMapName->data, CMapName->size)) |
1239 | 0 | continue; |
1240 | 0 | } else { |
1241 | | /* Otherwise, check the PDF font name against the subfont name, and the |
1242 | | * CMap used with the PDF font against the requested CMap. If either differs |
1243 | | * then this PDF font is not usable. |
1244 | | */ |
1245 | 0 | if (pdfont->BaseFont.size != pdsubf->BaseFont.size) |
1246 | 0 | continue; |
1247 | 0 | if (pdfont->u.type0.CMapName.size != CMapName->size) |
1248 | 0 | continue; |
1249 | 0 | if (memcmp(pdfont->u.type0.CMapName.data, CMapName->data, CMapName->size)) |
1250 | 0 | continue; |
1251 | 0 | } |
1252 | | |
1253 | 0 | *ppdfont = pdfont; |
1254 | 0 | return 1; |
1255 | 0 | } |
1256 | 0 | } |
1257 | 0 | return 0; |
1258 | 0 | } |
1259 | | |
1260 | | static int pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font, |
1261 | | pdf_font_resource_t **ppdfont, |
1262 | | pdf_char_glyph_pairs_t *cgp); |
1263 | | |
1264 | | /* |
1265 | | * Create or find a CID font resource object for a glyph set. |
1266 | | */ |
1267 | | int |
1268 | | pdf_obtain_cidfont_resource(gx_device_pdf *pdev, gs_font *subfont, |
1269 | | pdf_font_resource_t **ppdsubf, |
1270 | | pdf_char_glyph_pairs_t *cgp) |
1271 | 0 | { |
1272 | 0 | int code = 0; |
1273 | |
|
1274 | 0 | code = pdf_attached_font_resource(pdev, subfont, ppdsubf, NULL, NULL, NULL, NULL); |
1275 | 0 | if (code < 0) |
1276 | 0 | return code; |
1277 | 0 | if (*ppdsubf != NULL) { |
1278 | 0 | const gs_font_base *cfont = pdf_font_resource_font(*ppdsubf, false); |
1279 | |
|
1280 | 0 | code = gs_copied_can_copy_glyphs((const gs_font *)cfont, subfont, |
1281 | 0 | &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars, |
1282 | 0 | sizeof(pdf_char_glyph_pair_t), true); |
1283 | 0 | if (code > 0) |
1284 | 0 | return 0; |
1285 | 0 | if (code < 0) |
1286 | 0 | return code; |
1287 | 0 | *ppdsubf = NULL; |
1288 | 0 | } |
1289 | 0 | code = pdf_find_font_resource(pdev, subfont, |
1290 | 0 | resourceCIDFont, ppdsubf, cgp, true); |
1291 | 0 | if (code < 0) |
1292 | 0 | return code; |
1293 | 0 | if (*ppdsubf == NULL) { |
1294 | 0 | code = pdf_make_font_resource(pdev, subfont, ppdsubf, cgp); |
1295 | 0 | if (code < 0) |
1296 | 0 | return code; |
1297 | 0 | } |
1298 | 0 | return pdf_attach_font_resource(pdev, subfont, *ppdsubf); |
1299 | 0 | } |
1300 | | |
1301 | | /* |
1302 | | * Refine index of BaseEncoding. |
1303 | | */ |
1304 | | static int |
1305 | | pdf_refine_encoding_index(const gx_device_pdf *pdev, int index, bool is_standard) |
1306 | 0 | { |
1307 | 0 | if (pdev->ForOPDFRead) { |
1308 | | /* |
1309 | | * Allow Postscript encodings only. |
1310 | | * No, also allow MacRoman because if we have a TT font, and subset it, then opdfread |
1311 | | * will prefer thte MacRoman CMAP from the subset TT font. |
1312 | | */ |
1313 | 0 | switch (index) { |
1314 | | |
1315 | 0 | case ENCODING_INDEX_STANDARD: return index; |
1316 | 0 | case ENCODING_INDEX_MACROMAN: return index; |
1317 | 0 | case ENCODING_INDEX_ISOLATIN1: return index; |
1318 | 0 | default: |
1319 | 0 | return ENCODING_INDEX_STANDARD; |
1320 | 0 | } |
1321 | 0 | } |
1322 | | /* |
1323 | | * Per the PDF 1.3 documentation, there are only 3 BaseEncoding |
1324 | | * values allowed for non-embedded fonts. Pick one here. |
1325 | | */ |
1326 | 0 | switch (index) { |
1327 | 0 | case ENCODING_INDEX_WINANSI: |
1328 | 0 | case ENCODING_INDEX_MACROMAN: |
1329 | 0 | case ENCODING_INDEX_MACEXPERT: |
1330 | 0 | return index; |
1331 | 0 | case ENCODING_INDEX_STANDARD: |
1332 | 0 | if (is_standard) |
1333 | 0 | return index; |
1334 | | /* Falls through. */ |
1335 | 0 | default: |
1336 | 0 | return ENCODING_INDEX_WINANSI; |
1337 | 0 | } |
1338 | 0 | } |
1339 | | |
1340 | | /* |
1341 | | * Create a font resource object for a gs_font of Type 3. |
1342 | | */ |
1343 | | int |
1344 | | pdf_make_font3_resource(gx_device_pdf *pdev, gs_font *font, |
1345 | | pdf_font_resource_t **ppdfont) |
1346 | 0 | { |
1347 | 0 | const gs_font_base *bfont = (const gs_font_base *)font; |
1348 | 0 | pdf_font_resource_t *pdfont; |
1349 | 0 | byte *cached; |
1350 | 0 | int code; |
1351 | |
|
1352 | 0 | cached = gs_alloc_bytes(pdev->pdf_memory, 256/8, "pdf_make_font3_resource"); |
1353 | 0 | if (cached == NULL) |
1354 | 0 | return_error(gs_error_VMerror); |
1355 | 0 | code = font_resource_encoded_alloc(pdev, &pdfont, bfont->id, |
1356 | 0 | ft_user_defined, pdf_write_contents_bitmap); |
1357 | 0 | if (code < 0) { |
1358 | 0 | gs_free_object(pdev->pdf_memory, cached, "pdf_make_font3_resource"); |
1359 | 0 | return code; |
1360 | 0 | } |
1361 | 0 | memset(cached, 0, 256 / 8); |
1362 | 0 | pdfont->mark_glyph = font->dir->ccache.mark_glyph; /* For pdf_font_resource_enum_ptrs. */ |
1363 | 0 | pdfont->u.simple.s.type3.bitmap_font = false; |
1364 | 0 | pdfont->u.simple.BaseEncoding = pdf_refine_encoding_index(pdev, |
1365 | 0 | bfont->nearest_encoding_index, true); |
1366 | 0 | pdfont->u.simple.s.type3.char_procs = NULL; |
1367 | 0 | pdfont->u.simple.s.type3.cached = cached; |
1368 | 0 | if ((pdfont->FontType == ft_user_defined || pdfont->FontType == ft_PDF_user_defined) && bfont->FontBBox.p.x == 0.0 && |
1369 | 0 | bfont->FontBBox.p.y == 0.00 && bfont->FontBBox.q.x == 0.00 && |
1370 | 0 | bfont->FontBBox.q.y == 0.0) { |
1371 | | /* I think this can only happen with a type 3 (bitmap) font from PCL. |
1372 | | * If we leave the BBox as 0 then we end up putting a 0 0 1000 1000 in |
1373 | | * the PDF. This causes Acrobat to be unable to search or highlight |
1374 | | * the search results. I think that we will always get a consistent |
1375 | | * type of font from the PCL interpreter, and if so the correct BBox |
1376 | | * sould always is 0 0 1 -1. |
1377 | | */ |
1378 | 0 | pdfont->u.simple.s.type3.FontBBox.p.x = 0; |
1379 | 0 | pdfont->u.simple.s.type3.FontBBox.p.y = 0; |
1380 | 0 | pdfont->u.simple.s.type3.FontBBox.q.x = 1; |
1381 | 0 | pdfont->u.simple.s.type3.FontBBox.q.y = -1; |
1382 | 0 | } else { |
1383 | 0 | pdfont->u.simple.s.type3.FontBBox.p.x = bfont->FontBBox.p.x; |
1384 | 0 | pdfont->u.simple.s.type3.FontBBox.p.y = bfont->FontBBox.p.y; |
1385 | 0 | pdfont->u.simple.s.type3.FontBBox.q.x = bfont->FontBBox.q.x; |
1386 | 0 | pdfont->u.simple.s.type3.FontBBox.q.y = bfont->FontBBox.q.y; |
1387 | 0 | } |
1388 | 0 | pdfont->u.simple.s.type3.FontMatrix = bfont->FontMatrix; |
1389 | 0 | pdfont->u.simple.s.type3.Resources = cos_dict_alloc(pdev, "pdf_make_font3_resource"); |
1390 | 0 | if (pdfont->u.simple.s.type3.Resources == NULL) |
1391 | 0 | return_error(gs_error_VMerror); |
1392 | | /* Adobe viewers have a precision problem with small font matrices : */ |
1393 | | /* Don't perform this test if all entries are 0, leads to infinite loop! */ |
1394 | 0 | if (pdfont->u.simple.s.type3.FontMatrix.xx != 0.0 || |
1395 | 0 | pdfont->u.simple.s.type3.FontMatrix.xy != 0.0 || |
1396 | 0 | pdfont->u.simple.s.type3.FontMatrix.yx != 0.0 || |
1397 | 0 | pdfont->u.simple.s.type3.FontMatrix.yy != 0.0) { |
1398 | 0 | while (any_abs(pdfont->u.simple.s.type3.FontMatrix.xx) < 0.001 && |
1399 | 0 | any_abs(pdfont->u.simple.s.type3.FontMatrix.xy) < 0.001 && |
1400 | 0 | any_abs(pdfont->u.simple.s.type3.FontMatrix.yx) < 0.001 && |
1401 | 0 | any_abs(pdfont->u.simple.s.type3.FontMatrix.yy) < 0.001) { |
1402 | 0 | pdfont->u.simple.s.type3.FontMatrix.xx *= 10; |
1403 | 0 | pdfont->u.simple.s.type3.FontMatrix.xy *= 10; |
1404 | 0 | pdfont->u.simple.s.type3.FontMatrix.yx *= 10; |
1405 | 0 | pdfont->u.simple.s.type3.FontMatrix.yy *= 10; |
1406 | 0 | } |
1407 | 0 | } |
1408 | 0 | *ppdfont = pdfont; |
1409 | 0 | return 0; |
1410 | 0 | } |
1411 | | |
1412 | | /* |
1413 | | * Create a font resource object for a gs_font. Return 1 iff the |
1414 | | * font was newly created (it's a roudiment, keeping reverse compatibility). |
1415 | | * This procedure is only intended to be called |
1416 | | * from a few places in the text code. |
1417 | | */ |
1418 | | static int |
1419 | | pdf_make_font_resource(gx_device_pdf *pdev, gs_font *font, |
1420 | | pdf_font_resource_t **ppdfont, |
1421 | | pdf_char_glyph_pairs_t *cgp) |
1422 | 0 | { |
1423 | 0 | int index = -1; |
1424 | 0 | int BaseEncoding = ENCODING_INDEX_UNKNOWN; |
1425 | 0 | pdf_font_embed_t embed; |
1426 | 0 | pdf_font_descriptor_t *pfd = 0; |
1427 | 0 | int (*font_alloc)(gx_device_pdf *, pdf_font_resource_t **, |
1428 | 0 | gs_id, pdf_font_descriptor_t *); |
1429 | 0 | gs_font *base_font = font; /* A roudiment from old code. Keep it for a while. */ |
1430 | 0 | pdf_font_resource_t *pdfont; |
1431 | 0 | pdf_standard_font_t *const psfa = |
1432 | 0 | pdev->text->outline_fonts->standard_fonts; |
1433 | 0 | int code = 0; |
1434 | 0 | long XUID = 0; |
1435 | 0 | gs_font_base *bfont = (gs_font_base *)font; |
1436 | |
|
1437 | 0 | if (pdev->version < psdf_version_level2_with_TT) { |
1438 | 0 | switch(font->FontType) { |
1439 | 0 | case ft_TrueType: |
1440 | 0 | case ft_CID_TrueType: |
1441 | 0 | return_error(gs_error_undefined); |
1442 | 0 | default: |
1443 | 0 | break; |
1444 | 0 | } |
1445 | 0 | } |
1446 | 0 | if (pdev->ForOPDFRead && !pdev->HaveCIDSystem) { |
1447 | 0 | switch(font->FontType) { |
1448 | 0 | case ft_CID_encrypted: |
1449 | 0 | case ft_CID_TrueType: |
1450 | 0 | return_error(gs_error_undefined); |
1451 | 0 | default: |
1452 | 0 | break; |
1453 | 0 | } |
1454 | 0 | } |
1455 | 0 | if (!pdev->HaveCFF) { |
1456 | 0 | if (font->FontType == ft_encrypted2) |
1457 | 0 | return_error(gs_error_undefined); |
1458 | 0 | } |
1459 | 0 | embed = pdf_font_embed_status(pdev, base_font, &index, cgp->s, cgp->num_all_chars); |
1460 | 0 | if (pdev->CompatibilityLevel < 1.3) |
1461 | 0 | if (embed != FONT_EMBED_NO && font->FontType == ft_CID_TrueType) |
1462 | 0 | return_error(gs_error_rangecheck); |
1463 | 0 | if (embed == FONT_EMBED_STANDARD && pdev->CompatibilityLevel < 2.0) { |
1464 | 0 | pdf_standard_font_t *psf = &psfa[index]; |
1465 | |
|
1466 | 0 | if (psf->pdfont == NULL || |
1467 | 0 | !pdf_is_compatible_encoding(pdev, psf->pdfont, font, |
1468 | 0 | cgp->s, cgp->num_all_chars)) { |
1469 | 0 | code = pdf_font_std_alloc(pdev, ppdfont, (psf->pdfont == NULL), base_font->id, |
1470 | 0 | (gs_font_base *)base_font, index); |
1471 | 0 | if (code < 0) |
1472 | 0 | return code; |
1473 | 0 | if (psf->pdfont == NULL) |
1474 | 0 | psf->pdfont = *ppdfont; |
1475 | 0 | (*ppdfont)->u.simple.BaseEncoding = pdf_refine_encoding_index(pdev, |
1476 | 0 | ((const gs_font_base *)base_font)->nearest_encoding_index, true); |
1477 | 0 | code = 1; |
1478 | 0 | } else |
1479 | 0 | *ppdfont = psf->pdfont; |
1480 | 0 | return code; |
1481 | 0 | } |
1482 | | |
1483 | 0 | if (uid_is_XUID(&bfont->UID)){ |
1484 | 0 | int size = uid_XUID_size(&bfont->UID); |
1485 | 0 | long *xvalues = uid_XUID_values(&bfont->UID); |
1486 | 0 | if (xvalues && size >= 2 && xvalues[0] == 1000000) { |
1487 | 0 | XUID = xvalues[size - 1]; |
1488 | 0 | } |
1489 | 0 | } |
1490 | |
|
1491 | 0 | switch (font->FontType) { |
1492 | 0 | case ft_CID_encrypted: |
1493 | 0 | case ft_CID_TrueType: |
1494 | 0 | font_alloc = pdf_font_cidfont_alloc; |
1495 | 0 | break; |
1496 | 0 | case ft_encrypted: |
1497 | 0 | case ft_encrypted2: |
1498 | 0 | case ft_TrueType: |
1499 | 0 | font_alloc = pdf_font_simple_alloc; |
1500 | 0 | break; |
1501 | 0 | case ft_user_defined: |
1502 | 0 | case ft_PDF_user_defined: |
1503 | 0 | case ft_PCL_user_defined: |
1504 | 0 | case ft_MicroType: |
1505 | 0 | case ft_GL2_stick_user_defined: |
1506 | 0 | case ft_GL2_531: |
1507 | 0 | code = pdf_make_font3_resource(pdev, font, ppdfont); |
1508 | 0 | if (code < 0) |
1509 | 0 | return code; |
1510 | 0 | (*ppdfont)->XUID = XUID; |
1511 | 0 | return 1; |
1512 | 0 | default: |
1513 | 0 | return_error(gs_error_invalidfont); |
1514 | 0 | } |
1515 | | |
1516 | | /* Create an appropriate font resource and descriptor. */ |
1517 | 0 | if (embed == FONT_EMBED_YES) { |
1518 | | /* |
1519 | | * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4 |
1520 | | * and 6 not work in embedded TrueType fonts. Consequently, it |
1521 | | * can only handle embedded TrueType fonts if all the glyphs |
1522 | | * referenced by the Encoding have numbers 0-255. Check for |
1523 | | * this now. |
1524 | | */ |
1525 | 0 | if (font->FontType == ft_TrueType && |
1526 | 0 | pdev->CompatibilityLevel <= 1.2 && !pdev->ForOPDFRead |
1527 | 0 | ) { |
1528 | 0 | int i; |
1529 | |
|
1530 | 0 | for (i = 0; i <= 0xff; ++i) { |
1531 | 0 | gs_glyph glyph = |
1532 | 0 | font->procs.encode_char(font, (gs_char)i, |
1533 | 0 | GLYPH_SPACE_INDEX); |
1534 | |
|
1535 | 0 | if (glyph == GS_NO_GLYPH || |
1536 | 0 | (glyph >= GS_MIN_GLYPH_INDEX && |
1537 | 0 | glyph <= GS_MIN_GLYPH_INDEX + 0xff) |
1538 | 0 | ) |
1539 | 0 | continue; |
1540 | | /* Can't embed, punt. */ |
1541 | 0 | return_error(gs_error_rangecheck); |
1542 | 0 | } |
1543 | 0 | } |
1544 | 0 | } |
1545 | 0 | if ((code = pdf_font_descriptor_alloc(pdev, &pfd, |
1546 | 0 | (gs_font_base *)base_font, |
1547 | 0 | embed == FONT_EMBED_YES)) < 0 || |
1548 | 0 | (code = font_alloc(pdev, &pdfont, base_font->id, pfd)) < 0 |
1549 | 0 | ) |
1550 | 0 | return code; |
1551 | | |
1552 | 0 | pdfont->XUID = XUID; |
1553 | 0 | pdf_do_subset_font(pdev, pfd->base_font, -1); |
1554 | | |
1555 | | /* If we have a TrueType font to embed, and we're producing an (E)PS output |
1556 | | * file, and we are subsetting the font, then the font we produce will *NOT* |
1557 | | * have the CMAP from the original TrueType font, we will generate a Windows 3,1 |
1558 | | * and a MacRoman 1,0 CMAP, and the opdfread.ps code will prefer to use the |
1559 | | * MacRoman one. So, in this case, use MacRoman otherwise we will end up |
1560 | | * with erroneous encodings. Of course, when we are not subssetting the font |
1561 | | * we do want ot use the original fonts encoding. |
1562 | | */ |
1563 | 0 | if ((font->FontType == ft_TrueType && pdev->ForOPDFRead)) { |
1564 | 0 | if (pfd->base_font->do_subset == DO_SUBSET_YES) |
1565 | 0 | BaseEncoding = pdf_refine_encoding_index(pdev, |
1566 | 0 | ENCODING_INDEX_MACROMAN, false); |
1567 | 0 | else |
1568 | 0 | BaseEncoding = pdf_refine_encoding_index(pdev, |
1569 | 0 | ((const gs_font_base *)base_font)->nearest_encoding_index, false); |
1570 | 0 | } |
1571 | 0 | if (font->FontType == ft_encrypted || font->FontType == ft_encrypted2 |
1572 | 0 | || (font->FontType == ft_TrueType && ((const gs_font_base *)base_font)->nearest_encoding_index != ENCODING_INDEX_UNKNOWN && pfd->base_font->do_subset == DO_SUBSET_NO)) { |
1573 | | /* Yet more crazy heuristics. If we embed a TrueType font and don't subset it, then |
1574 | | * we preserve the CMAP subtable(s) rather than generatng new ones. The problem is |
1575 | | * that if we ake the font symbolic, Acrobat uses the 1,0 CMAP, whereas if we don't |
1576 | | * It uses the 3,1 CMAP (and the Encoding). If these two are not compatible, then |
1577 | | * the result will be different. So, if we are not subsetting the font, and the original |
1578 | | * font wasn't symbolic (it has an Encoding) then we will create a new Encoding, and |
1579 | | * in pdf_write_font_descriptor we wil take back off the symbolic flag. |
1580 | | */ |
1581 | | /* Removed the addition of Encodings to TrueType fonts as we always write |
1582 | | * these with the Symbolic flag set. The comment below explains why we |
1583 | | * previously wrote these, but as the comment notes this was incorrect. |
1584 | | * Removed as it is causing preflight problems, and is specifically |
1585 | | * disallowed with PDF/A output. |
1586 | | */ |
1587 | | /* |
1588 | | * We write True Types with Symbolic flag set. |
1589 | | * PDF spec says that "symbolic font should not specify Encoding entry" |
1590 | | * (see section 5.5, the article "Encodings for True Type fonts", paragraph 3). |
1591 | | * However Acrobat Reader 4,5,6 fail when TT font with no Encoding |
1592 | | * appears in a document together with a CID font with a non-standard CMap |
1593 | | * (AR 4 and 5 claim "The encoding (CMap) specified by a font is corrupted." |
1594 | | * (we read it as "The encoding or CMap specified by a font is corrupted.", |
1595 | | * and apply the 1st alternative)). We believe that AR is buggy, |
1596 | | * and therefore we write an Encoding with non-CID True Type fonts. |
1597 | | * Hopely other viewers can ignore Encoding in such case. Actually in this case |
1598 | | * an Encoding doesn't add an useful information. |
1599 | | */ |
1600 | 0 | BaseEncoding = pdf_refine_encoding_index(pdev, |
1601 | 0 | ((const gs_font_base *)base_font)->nearest_encoding_index, false); |
1602 | 0 | } |
1603 | 0 | if (!pdf_is_CID_font(font)) { |
1604 | 0 | pdfont->u.simple.BaseEncoding = BaseEncoding; |
1605 | 0 | pdfont->mark_glyph = font->dir->ccache.mark_glyph; |
1606 | 0 | } |
1607 | |
|
1608 | 0 | if (pdev->PDFA != 0 && font->FontType == ft_TrueType) { |
1609 | | /* The Adobe preflight tool for PDF/A |
1610 | | checks whether Width or W include elements |
1611 | | for all characters in the True Type font. |
1612 | | Due to that we need to provide a width |
1613 | | for .notdef glyph. |
1614 | | (It's a part of the bug 688790). |
1615 | | */ |
1616 | 0 | gs_font_base *cfont = pdf_font_descriptor_font(pfd, false/*any*/); |
1617 | 0 | gs_glyph notdef_glyph = copied_get_notdef((const gs_font *)cfont); |
1618 | 0 | pdf_glyph_widths_t widths; |
1619 | 0 | double cdevproc_result[10] = {0,0,0,0,0, 0,0,0,0,0}; |
1620 | 0 | double *w, *v, *w0; |
1621 | |
|
1622 | 0 | if (notdef_glyph != GS_NO_GLYPH) { |
1623 | 0 | code = pdf_obtain_cidfont_widths_arrays(pdev, pdfont, font->WMode, &w, &w0, &v); |
1624 | 0 | if (code < 0) |
1625 | 0 | return code; |
1626 | 0 | widths.Width.w = 0; |
1627 | 0 | code = pdf_glyph_widths(pdfont, font->WMode, notdef_glyph, |
1628 | 0 | font, &widths, cdevproc_result); |
1629 | 0 | if (code < 0) |
1630 | 0 | return code; |
1631 | 0 | w[0] = widths.Width.w; |
1632 | 0 | pdfont->used[0] |= 0x80; |
1633 | 0 | } |
1634 | 0 | } |
1635 | 0 | *ppdfont = pdfont; |
1636 | 0 | return 1; |
1637 | 0 | } |
1638 | | |
1639 | | /* |
1640 | | * Check for simple font. |
1641 | | */ |
1642 | | bool |
1643 | | pdf_is_simple_font(gs_font *font) |
1644 | 0 | { |
1645 | 0 | return (font->FontType == ft_encrypted || |
1646 | 0 | font->FontType == ft_encrypted2 || |
1647 | 0 | font->FontType == ft_TrueType || |
1648 | 0 | font->FontType == ft_user_defined || |
1649 | 0 | font->FontType == ft_PDF_user_defined || |
1650 | 0 | font->FontType == ft_PCL_user_defined || |
1651 | 0 | font->FontType == ft_MicroType || |
1652 | 0 | font->FontType == ft_GL2_stick_user_defined || |
1653 | 0 | font->FontType == ft_GL2_531); |
1654 | 0 | } |
1655 | | |
1656 | | /* |
1657 | | * Check for CID font. |
1658 | | */ |
1659 | | bool |
1660 | | pdf_is_CID_font(gs_font *font) |
1661 | 0 | { |
1662 | 0 | return (font->FontType == ft_CID_encrypted || |
1663 | 0 | font->FontType == ft_CID_TrueType); |
1664 | 0 | } |
1665 | | |
1666 | | /* |
1667 | | * Enumerate glyphs for a text. |
1668 | | */ |
1669 | | static int |
1670 | | pdf_next_char_glyph(gs_text_enum_t *penum, const gs_string *pstr, |
1671 | | /* const */ gs_font *font, bool font_is_simple, |
1672 | | gs_char *char_code, gs_char *cid, gs_glyph *glyph) |
1673 | 0 | { |
1674 | 0 | int code = font->procs.next_char_glyph(penum, char_code, glyph); |
1675 | |
|
1676 | 0 | if (code == 2) /* end of string */ |
1677 | 0 | return code; |
1678 | 0 | if (code < 0) |
1679 | 0 | return code; |
1680 | 0 | if (font_is_simple) { |
1681 | 0 | *cid = *char_code; |
1682 | 0 | *glyph = font->procs.encode_char(font, *char_code, GLYPH_SPACE_NAME); |
1683 | 0 | if (*glyph == GS_NO_GLYPH) |
1684 | 0 | return 3; |
1685 | 0 | } else { |
1686 | 0 | if (*glyph < GS_MIN_CID_GLYPH) |
1687 | 0 | return 3; /* Not sure why, copied from scan_cmap_text. */ |
1688 | 0 | *cid = *glyph - GS_MIN_CID_GLYPH; /* CID */ |
1689 | 0 | } |
1690 | 0 | return 0; |
1691 | 0 | } |
1692 | | |
1693 | | static void |
1694 | | store_glyphs(pdf_char_glyph_pairs_t *cgp, |
1695 | | byte *glyph_usage, int char_cache_size, |
1696 | | gs_char char_code, gs_char cid, gs_glyph glyph) |
1697 | 0 | { |
1698 | 0 | int j; |
1699 | |
|
1700 | 0 | for (j = 0; j < cgp->num_all_chars; j++) |
1701 | 0 | if (cgp->s[j].chr == cid) |
1702 | 0 | break; |
1703 | 0 | if (j < cgp->num_all_chars) |
1704 | 0 | return; |
1705 | 0 | cgp->s[cgp->num_all_chars].glyph = glyph; |
1706 | 0 | cgp->s[cgp->num_all_chars].chr = char_code; |
1707 | 0 | cgp->num_all_chars++; |
1708 | 0 | if (glyph_usage == 0 || !(glyph_usage[cid / 8] & (0x80 >> (cid & 7)))) { |
1709 | 0 | cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph; |
1710 | 0 | cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = char_code; |
1711 | 0 | cgp->num_unused_chars++; |
1712 | 0 | } |
1713 | | /* We are disliked that gs_copied_can_copy_glyphs can get redundant |
1714 | | * glyphs, if Encoding specifies several codes for same glyph. |
1715 | | * But we need the positional correspondence |
1716 | | * of glyphs to codes for pdf_is_compatible_encoding. |
1717 | | * Redundant glyphs isn't a big payment for it |
1718 | | * because they happen seldom. |
1719 | | */ |
1720 | 0 | } |
1721 | | |
1722 | | static gs_char |
1723 | | pdf_new_char_code_in_pdfont(pdf_char_glyph_pairs_t *cgp, gs_glyph glyph, int *last_reserved_char) |
1724 | 0 | { /* Returns 256 if encoding overflows. */ |
1725 | 0 | int j, ch; |
1726 | |
|
1727 | 0 | for (j = 0; j < cgp->num_all_chars; j++) |
1728 | 0 | if (cgp->s[j].glyph == glyph) |
1729 | 0 | break; |
1730 | 0 | if (j < cgp->num_all_chars) |
1731 | 0 | return cgp->s[j].chr; |
1732 | 0 | ch = ++*last_reserved_char; |
1733 | 0 | cgp->s[cgp->num_all_chars].glyph = glyph; |
1734 | 0 | cgp->s[cgp->num_all_chars].chr = ch; |
1735 | 0 | cgp->num_all_chars++; |
1736 | 0 | cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph; |
1737 | 0 | cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = ch; |
1738 | 0 | cgp->num_unused_chars++; |
1739 | 0 | return ch; |
1740 | 0 | } |
1741 | | |
1742 | | static gs_char |
1743 | | pdf_reserve_char_code_in_pdfont(pdf_font_resource_t *pdfont, pdf_char_glyph_pairs_t *cgp, gs_glyph glyph, |
1744 | | int *last_reserved_char) |
1745 | 0 | { /* Returns 256 if encoding overflows. */ |
1746 | | /* This function is pretty slow, but we can't find a better algorithm. |
1747 | | It works for the case of glyphshow with no proper encoding, |
1748 | | which we believe comes from poorly designed documents. |
1749 | | */ |
1750 | 0 | int j, ch; |
1751 | |
|
1752 | 0 | for (j = 0; j < cgp->num_all_chars; j++) |
1753 | 0 | if (cgp->s[j].glyph == glyph) |
1754 | 0 | break; |
1755 | 0 | if (j < cgp->num_all_chars) |
1756 | 0 | return cgp->s[j].chr; |
1757 | | |
1758 | 0 | for (ch = 0; ch < 256; ch++) { |
1759 | 0 | pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; |
1760 | |
|
1761 | 0 | if (glyph == pet->glyph) |
1762 | 0 | return ch; |
1763 | 0 | } |
1764 | | /* If the font has a known encoding, prefer .notdef codes. */ |
1765 | 0 | if (pdfont->u.simple.preferred_encoding_index != -1) { |
1766 | 0 | const ushort *enc = gs_c_known_encodings[pdfont->u.simple.preferred_encoding_index]; |
1767 | |
|
1768 | 0 | for (ch = *last_reserved_char + 1; ch < 256; ch++) { |
1769 | 0 | pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; |
1770 | |
|
1771 | 0 | if (pet->glyph == GS_NO_GLYPH && enc[ch] == pdfont->u.simple.standard_glyph_code_for_notdef) { |
1772 | 0 | *last_reserved_char = ch; |
1773 | 0 | break; |
1774 | 0 | } |
1775 | 0 | } |
1776 | 0 | } |
1777 | | /* Otherwise use any code unused in the font. */ |
1778 | 0 | if (ch > 255) { |
1779 | 0 | ch = *last_reserved_char + 1; |
1780 | 0 | for (; ch < 255; ch++) { |
1781 | 0 | pdf_encoding_element_t *pet = &pdfont->u.simple.Encoding[ch]; |
1782 | |
|
1783 | 0 | if (pet->glyph == GS_NO_GLYPH) |
1784 | 0 | break; |
1785 | 0 | } |
1786 | 0 | *last_reserved_char = ch; |
1787 | 0 | } |
1788 | 0 | cgp->s[cgp->num_all_chars].glyph = glyph; |
1789 | 0 | cgp->s[cgp->num_all_chars].chr = ch; |
1790 | 0 | cgp->num_all_chars++; |
1791 | 0 | cgp->s[cgp->unused_offset + cgp->num_unused_chars].glyph = glyph; |
1792 | 0 | cgp->s[cgp->unused_offset + cgp->num_unused_chars].chr = ch; |
1793 | 0 | cgp->num_unused_chars++; |
1794 | 0 | return ch; |
1795 | 0 | } |
1796 | | |
1797 | | /* Allocate storage for the glyph set of the text. */ |
1798 | | static int |
1799 | | pdf_alloc_text_glyphs_table(gx_device_pdf *pdev, pdf_text_enum_t *penum, const gs_string *pstr) |
1800 | 0 | { |
1801 | 0 | const int go = (pstr != NULL ? pstr->size : penum->text.size); |
1802 | 0 | const int struct_size = sizeof(pdf_char_glyph_pairs_t) + |
1803 | 0 | sizeof(pdf_char_glyph_pair_t) * (2 * go - 1); |
1804 | 0 | pdf_char_glyph_pairs_t *cgp = (pdf_char_glyph_pairs_t *)gs_alloc_bytes(penum->memory, |
1805 | 0 | struct_size, "pdf_alloc_text_glyphs_table"); |
1806 | 0 | if (cgp == NULL) |
1807 | 0 | return_error(gs_error_VMerror); |
1808 | 0 | penum->cgp = cgp; |
1809 | 0 | cgp->unused_offset = go; |
1810 | 0 | cgp->num_all_chars = 0; |
1811 | 0 | cgp->num_unused_chars = 0; |
1812 | 0 | return 0; |
1813 | 0 | } |
1814 | | |
1815 | | /* Build the glyph set of the text. */ |
1816 | | static int |
1817 | | pdf_make_text_glyphs_table(pdf_text_enum_t *penum, const gs_string *pstr, |
1818 | | byte *glyph_usage, int char_cache_size) |
1819 | 0 | { |
1820 | 0 | gs_text_enum_t scan = *(gs_text_enum_t *)penum; |
1821 | 0 | gs_font *font = (gs_font *)penum->current_font; |
1822 | 0 | bool font_is_simple = pdf_is_simple_font(font); |
1823 | 0 | pdf_char_glyph_pairs_t *cgp = penum->cgp; |
1824 | 0 | gs_char char_code, cid; |
1825 | 0 | gs_glyph glyph; |
1826 | 0 | int code; |
1827 | |
|
1828 | 0 | cgp->num_unused_chars = 0; |
1829 | 0 | cgp->num_all_chars = 0; |
1830 | 0 | if (pstr != NULL) { |
1831 | 0 | scan.text.data.bytes = pstr->data; |
1832 | 0 | scan.text.size = pstr->size; |
1833 | 0 | scan.index = 0; |
1834 | | /* if TEXT_FROM_CHARS the data was converted to bytes earlier */ |
1835 | 0 | if ( scan.text.operation & TEXT_FROM_CHARS ) |
1836 | 0 | scan.text.operation = ((scan.text.operation & ~TEXT_FROM_CHARS) | TEXT_FROM_STRING); |
1837 | 0 | } |
1838 | 0 | for (;;) { |
1839 | 0 | code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple, |
1840 | 0 | &char_code, &cid, &glyph); |
1841 | 0 | if (code == 2) /* end of string */ |
1842 | 0 | break; |
1843 | 0 | if (code == 3) /* no glyph */ |
1844 | 0 | continue; |
1845 | 0 | if (code < 0) |
1846 | 0 | return code; |
1847 | 0 | if (cgp->num_all_chars > cgp->unused_offset) |
1848 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
1849 | 0 | if (glyph_usage != 0 && cid > char_cache_size) |
1850 | 0 | continue; |
1851 | 0 | store_glyphs(cgp, glyph_usage, char_cache_size, |
1852 | 0 | char_code, cid, glyph); |
1853 | 0 | } |
1854 | 0 | return 0; |
1855 | 0 | } |
1856 | | |
1857 | | /* Build the glyph set of the glyphshow text, and re_encode the text. */ |
1858 | | static int |
1859 | | pdf_make_text_glyphs_table_unencoded(gx_device_pdf *pdev, pdf_char_glyph_pairs_t *cgp, |
1860 | | gs_font *font, const gs_string *pstr, const gs_glyph *gdata, |
1861 | | int *ps_encoding_index) |
1862 | 0 | { |
1863 | 0 | int i, j, code; |
1864 | 0 | gs_char ch; |
1865 | 0 | gs_const_string gname; |
1866 | 0 | gs_glyph *gid = (gs_glyph *)pstr->data; /* pdf_text_process allocs enough space. */ |
1867 | 0 | gs_font_base *bfont; |
1868 | 0 | bool unknown = false; |
1869 | 0 | pdf_font_resource_t *pdfont; |
1870 | 0 | int ei, start_ei = -1; |
1871 | |
|
1872 | 0 | code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL); |
1873 | 0 | if (code < 0) |
1874 | 0 | return code; |
1875 | | /* Translate glyph name indices into gscencs.c indices. */ |
1876 | 0 | for (i = 0; i < pstr->size; i++) { |
1877 | 0 | int code = font->procs.glyph_name(font, gdata[i], &gname); |
1878 | |
|
1879 | 0 | if (code < 0) |
1880 | 0 | return code; |
1881 | 0 | gid[i] = gs_c_name_glyph(gname.data, gname.size); |
1882 | 0 | if (gid[i] == GS_NO_GLYPH) { |
1883 | | /* Use global glyph name. */ |
1884 | | /* Assuming this can't fail in a middle of a text, |
1885 | | because TEXT_FROM_GLYPHS never works for Postscript. */ |
1886 | 0 | gid[i] = gdata[i]; |
1887 | 0 | unknown = true; |
1888 | 0 | } |
1889 | 0 | } |
1890 | 0 | do_unknown: |
1891 | 0 | if (unknown) { |
1892 | 0 | int last_reserved_char = -1; |
1893 | | /* Using global glyph names. */ |
1894 | | |
1895 | | /* Try to find an existing font resource, which has necessary glyphs. |
1896 | | Doing so to prevent creating multiple font copies. |
1897 | | */ |
1898 | 0 | cgp->num_unused_chars = 0; |
1899 | 0 | cgp->num_all_chars = 0; |
1900 | 0 | for (i = 0; i < pstr->size; i++) { |
1901 | | /* Temporary stub gid instead cid and char_code : */ |
1902 | 0 | store_glyphs(cgp, NULL, 0, gdata[i], gdata[i], gdata[i]); |
1903 | 0 | } |
1904 | 0 | code = pdf_find_font_resource(pdev, font, resourceFont, &pdfont, cgp, false); |
1905 | 0 | if (code < 0) |
1906 | 0 | return code; |
1907 | 0 | if (code) { |
1908 | | /* Found one - make it be current. */ |
1909 | 0 | code = pdf_attach_font_resource(pdev, font, pdfont); |
1910 | 0 | if (code < 0) |
1911 | 0 | return code; |
1912 | 0 | } |
1913 | | /* Try to add glyphs to the current font resource. . */ |
1914 | 0 | cgp->num_unused_chars = 0; |
1915 | 0 | cgp->num_all_chars = 0; |
1916 | |
|
1917 | 0 | if(pdfont != NULL) |
1918 | 0 | last_reserved_char = pdfont->u.simple.last_reserved_char; |
1919 | |
|
1920 | 0 | for (i = 0; i < pstr->size; i++) { |
1921 | |
|
1922 | 0 | if (pdfont == NULL) |
1923 | 0 | ch = 256; /* Force new encoding. */ |
1924 | 0 | else |
1925 | 0 | ch = pdf_reserve_char_code_in_pdfont(pdfont, cgp, gdata[i], &last_reserved_char); |
1926 | 0 | if (ch > 255) { |
1927 | 0 | if(pdfont != NULL) |
1928 | 0 | last_reserved_char = pdfont->u.simple.last_reserved_char; |
1929 | | /* Start a new font/encoding. */ |
1930 | 0 | last_reserved_char = -1; |
1931 | |
|
1932 | 0 | cgp->num_unused_chars = 0; |
1933 | 0 | cgp->num_all_chars = 0; |
1934 | 0 | for (i = 0; i < pstr->size; i++) { |
1935 | 0 | ch = pdf_new_char_code_in_pdfont(cgp, gdata[i], &last_reserved_char); |
1936 | 0 | if (ch > 255) { |
1937 | | /* More than 255 unknown characters in a text. |
1938 | | It must not happen because TEXT_FROM_GLYPHS |
1939 | | never works for Postscript. */ |
1940 | 0 | return_error(gs_error_unregistered); |
1941 | 0 | } |
1942 | 0 | } |
1943 | 0 | } |
1944 | 0 | } |
1945 | 0 | if (pdfont != NULL) |
1946 | 0 | pdfont->u.simple.last_reserved_char = last_reserved_char; |
1947 | | /* Change glyphs to char codes in the text : */ |
1948 | 0 | for (i = 0; i < pstr->size; i++) { |
1949 | | /* Picked up by Coverity, if pdfont is NULL then the call might dereference it */ |
1950 | 0 | if (pdfont != NULL) { |
1951 | | /* A trick : pdf_reserve_char_code_in_pdfont here simply encodes with cgp. */ |
1952 | 0 | ch = pdf_reserve_char_code_in_pdfont(pdfont, cgp, gdata[i], &pdfont->u.simple.last_reserved_char); |
1953 | 0 | pstr->data[i] = ch; |
1954 | 0 | } else { |
1955 | | /* So if pdffont is NULL, do the 'trick' code mentioned above. |
1956 | | * If that fails (I believe it shouod not), then return an error. |
1957 | | */ |
1958 | 0 | int j; |
1959 | |
|
1960 | 0 | for (j = 0; j < cgp->num_all_chars; j++) |
1961 | 0 | if (cgp->s[j].glyph == gdata[i]) |
1962 | 0 | break; |
1963 | 0 | if (j < cgp->num_all_chars) |
1964 | 0 | pstr->data[i] = cgp->s[j].chr; |
1965 | 0 | else |
1966 | 0 | return_error(gs_error_unregistered); |
1967 | 0 | } |
1968 | 0 | } |
1969 | 0 | return 0; |
1970 | 0 | } |
1971 | | /* Now we know it's a base font, bcause it has glyph names. */ |
1972 | 0 | bfont = (gs_font_base *)font; |
1973 | 0 | if (start_ei < 0) |
1974 | 0 | start_ei = bfont->nearest_encoding_index; |
1975 | 0 | if (start_ei < 0) |
1976 | 0 | start_ei = 0; |
1977 | | /* Find an acceptable encodng, starting from start_ei. |
1978 | | We need a conservative search to minimize the probability |
1979 | | of encoding conflicts. |
1980 | | */ |
1981 | 0 | for (j = 0, ei = start_ei; gs_c_known_encodings[j]; j++, ei++) { |
1982 | 0 | if (!gs_c_known_encodings[ei]) |
1983 | 0 | ei = 0; |
1984 | | /* Restrict with PDF encodings, because others give frequent conflicts. */ |
1985 | 0 | if (ei > 5) /* Hack : gscedata.c must provide a constant. */ |
1986 | 0 | continue; |
1987 | 0 | cgp->num_unused_chars = 0; |
1988 | 0 | cgp->num_all_chars = 0; |
1989 | 0 | for (i = 0; i < pstr->size; i++) { |
1990 | 0 | ch = gs_c_decode(gid[i], ei); |
1991 | 0 | if (ch == GS_NO_CHAR) |
1992 | 0 | break; |
1993 | 0 | if (ch > 255) |
1994 | 0 | break; /* MacGlyphEncoding defines extra glyphs. */ |
1995 | | /* pstr->data[i] = (byte)ch; Can't do because pstr->data and gid |
1996 | | are same pointer. Will do in a separate pass below. */ |
1997 | 0 | store_glyphs(cgp, NULL, 0, ch, ch, gdata[i]); |
1998 | 0 | } |
1999 | 0 | *ps_encoding_index = ei; |
2000 | 0 | if (i == pstr->size) { |
2001 | | /* Change glyphs to char codes in the text : */ |
2002 | 0 | for (i = 0; i < pstr->size; i++) |
2003 | 0 | pstr->data[i] = (byte)gs_c_decode(gid[i], ei); |
2004 | 0 | return 0; |
2005 | 0 | } |
2006 | 0 | } |
2007 | 0 | unknown = true; |
2008 | 0 | goto do_unknown; |
2009 | 0 | } |
2010 | | |
2011 | | /* Get/make font resource for the font with a known encoding. */ |
2012 | | static int |
2013 | | pdf_obtain_font_resource_encoded(gx_device_pdf *pdev, gs_font *font, |
2014 | | pdf_font_resource_t **ppdfont, pdf_char_glyph_pairs_t *cgp) |
2015 | 0 | { |
2016 | 0 | int code; |
2017 | 0 | pdf_font_resource_t *pdfont_not_allowed = NULL; |
2018 | |
|
2019 | 0 | if (*ppdfont != 0) { |
2020 | 0 | gs_font_base *cfont = pdf_font_resource_font(*ppdfont, false); |
2021 | |
|
2022 | 0 | if (font->FontType != ft_user_defined && |
2023 | 0 | font->FontType != ft_PDF_user_defined && |
2024 | 0 | font->FontType != ft_PCL_user_defined && |
2025 | 0 | font->FontType != ft_MicroType && |
2026 | 0 | font->FontType != ft_GL2_stick_user_defined && |
2027 | 0 | font->FontType != ft_GL2_531) { |
2028 | 0 | code = gs_copied_can_copy_glyphs((gs_font *)cfont, font, |
2029 | 0 | &cgp->s[cgp->unused_offset].glyph, cgp->num_unused_chars, |
2030 | 0 | sizeof(pdf_char_glyph_pair_t), true); |
2031 | 0 | if (code < 0) |
2032 | 0 | code = 1; |
2033 | 0 | } else |
2034 | 0 | code = 1; |
2035 | 0 | if (code == 0) { |
2036 | 0 | pdfont_not_allowed = *ppdfont; |
2037 | 0 | *ppdfont = 0; |
2038 | 0 | } else if(!pdf_is_compatible_encoding(pdev, *ppdfont, font, |
2039 | 0 | cgp->s, cgp->num_all_chars)) { |
2040 | 0 | pdfont_not_allowed = *ppdfont; |
2041 | 0 | *ppdfont = 0; |
2042 | 0 | } |
2043 | 0 | } |
2044 | 0 | if (*ppdfont == 0) { |
2045 | 0 | gs_font *base_font = font; |
2046 | 0 | gs_font *below; |
2047 | 0 | bool same_encoding = true; |
2048 | | |
2049 | | /* |
2050 | | * Find the "lowest" base font that has the same outlines. |
2051 | | * We use its FontName for font resource. |
2052 | | */ |
2053 | 0 | while ((below = base_font->base) != base_font && |
2054 | 0 | base_font->procs.same_font(base_font, below, FONT_SAME_OUTLINES)) |
2055 | 0 | base_font = below; |
2056 | 0 | if (base_font != font) |
2057 | 0 | same_encoding = ((base_font->procs.same_font(base_font, font, |
2058 | 0 | FONT_SAME_ENCODING) & FONT_SAME_ENCODING) != 0); |
2059 | | /* Find or make font resource. */ |
2060 | 0 | code = pdf_attached_font_resource(pdev, base_font, ppdfont, NULL, NULL, NULL, NULL); |
2061 | 0 | if (code < 0) |
2062 | 0 | return code; |
2063 | 0 | if (base_font != font) { |
2064 | 0 | if (pdfont_not_allowed == *ppdfont) |
2065 | 0 | *ppdfont = NULL; |
2066 | 0 | } |
2067 | 0 | if(*ppdfont != NULL && !pdf_is_compatible_encoding(pdev, *ppdfont, |
2068 | 0 | base_font, cgp->s, cgp->num_all_chars)) |
2069 | 0 | *ppdfont = NULL; |
2070 | 0 | if (*ppdfont == NULL || *ppdfont == pdfont_not_allowed) { |
2071 | 0 | pdf_resource_type_t type = |
2072 | 0 | (pdf_is_CID_font(base_font) ? resourceCIDFont |
2073 | 0 | : resourceFont); |
2074 | 0 | *ppdfont = NULL; |
2075 | 0 | code = pdf_find_font_resource(pdev, base_font, type, ppdfont, cgp, true); |
2076 | 0 | if (code < 0) |
2077 | 0 | return code; |
2078 | 0 | if (*ppdfont == NULL) { |
2079 | 0 | code = pdf_make_font_resource(pdev, base_font, ppdfont, cgp); |
2080 | 0 | if (code < 0) |
2081 | 0 | return code; |
2082 | 0 | } |
2083 | 0 | if (base_font != font && same_encoding) { |
2084 | 0 | code = pdf_attach_font_resource(pdev, base_font, *ppdfont); |
2085 | 0 | if (code < 0) |
2086 | 0 | return code; |
2087 | 0 | } |
2088 | 0 | } |
2089 | 0 | code = pdf_attach_font_resource(pdev, font, *ppdfont); |
2090 | 0 | if (code < 0) |
2091 | 0 | return code; |
2092 | 0 | } |
2093 | 0 | return 0; |
2094 | 0 | } |
2095 | | |
2096 | | /* Mark glyphs used in the text with the font resource. */ |
2097 | | static int |
2098 | | pdf_mark_text_glyphs(const gs_text_enum_t *penum, const gs_string *pstr, |
2099 | | byte *glyph_usage, int char_cache_size) |
2100 | 0 | { |
2101 | 0 | gs_text_enum_t scan = *penum; |
2102 | 0 | gs_font *font = (gs_font *)penum->current_font; |
2103 | 0 | bool font_is_simple = pdf_is_simple_font(font); |
2104 | 0 | gs_char char_code, cid; |
2105 | 0 | gs_glyph glyph; |
2106 | |
|
2107 | 0 | if (glyph_usage == NULL) |
2108 | 0 | return 0; |
2109 | | |
2110 | 0 | if (pstr != NULL) { |
2111 | 0 | scan.text.data.bytes = pstr->data; |
2112 | 0 | scan.text.size = pstr->size; |
2113 | 0 | scan.index = 0; |
2114 | | /* if TEXT_FROM_CHARS the data was converted to bytes earlier */ |
2115 | 0 | if ( scan.text.operation & TEXT_FROM_CHARS ) |
2116 | 0 | scan.text.operation = |
2117 | 0 | ((scan.text.operation & ~TEXT_FROM_CHARS) | TEXT_FROM_STRING); |
2118 | 0 | } |
2119 | 0 | for (;;) { |
2120 | 0 | int code = pdf_next_char_glyph(&scan, pstr, font, font_is_simple, |
2121 | 0 | &char_code, &cid, &glyph); |
2122 | |
|
2123 | 0 | if (code == 2) /* end of string */ |
2124 | 0 | break; |
2125 | 0 | if (code == 3) /* no glyph */ |
2126 | 0 | continue; |
2127 | 0 | if (code < 0) |
2128 | 0 | return code; |
2129 | 0 | if (cid >= char_cache_size) |
2130 | 0 | continue; |
2131 | 0 | glyph_usage[cid / 8] |= 0x80 >> (cid & 7); |
2132 | 0 | } |
2133 | 0 | return 0; |
2134 | 0 | } |
2135 | | |
2136 | | /* Mark glyphs used in the glyphshow text with the font resource. */ |
2137 | | static int |
2138 | | pdf_mark_text_glyphs_unencoded(const gs_text_enum_t *penum, const gs_string *pstr, |
2139 | | byte *glyph_usage, int char_cache_size) |
2140 | 0 | { |
2141 | 0 | int i; |
2142 | |
|
2143 | 0 | for(i = 0; i < pstr->size; i++) { |
2144 | 0 | byte ch = pstr->data[i]; |
2145 | |
|
2146 | 0 | if (ch >= char_cache_size) |
2147 | 0 | return_error(gs_error_rangecheck); |
2148 | 0 | glyph_usage[ch / 8] |= 0x80 >> (ch & 7); |
2149 | 0 | } |
2150 | 0 | return 0; |
2151 | 0 | } |
2152 | | |
2153 | | /* |
2154 | | * Create or find a font resource object for a text. |
2155 | | */ |
2156 | | int |
2157 | | pdf_obtain_font_resource(pdf_text_enum_t *penum, |
2158 | | const gs_string *pstr, pdf_font_resource_t **ppdfont) |
2159 | 0 | { |
2160 | 0 | gx_device_pdf *pdev = (gx_device_pdf *)penum->dev; |
2161 | 0 | gs_font *font = (gs_font *)penum->current_font; |
2162 | 0 | byte *glyph_usage = 0; |
2163 | 0 | double *real_widths; |
2164 | 0 | int char_cache_size, width_cache_size; |
2165 | 0 | int code; |
2166 | |
|
2167 | 0 | if (font->FontType == ft_composite) { |
2168 | | /* Must not happen, because we always split composite fonts into descendents. */ |
2169 | 0 | return_error(gs_error_unregistered); |
2170 | 0 | } |
2171 | 0 | code = pdf_attached_font_resource(pdev, font, ppdfont, |
2172 | 0 | &glyph_usage, &real_widths, &char_cache_size, &width_cache_size); |
2173 | | /* *ppdfont is NULL if no resource attached. */ |
2174 | 0 | if (code < 0) |
2175 | 0 | return code; |
2176 | 0 | if (penum->cgp == NULL) { |
2177 | 0 | code = pdf_alloc_text_glyphs_table(pdev, penum, pstr); |
2178 | 0 | if (code < 0) |
2179 | 0 | return code; |
2180 | 0 | code = pdf_make_text_glyphs_table(penum, pstr, |
2181 | 0 | glyph_usage, char_cache_size); |
2182 | 0 | if (code < 0) |
2183 | 0 | return code; |
2184 | 0 | } |
2185 | 0 | code = pdf_obtain_font_resource_encoded(pdev, font, ppdfont, penum->cgp); |
2186 | 0 | if (code < 0) |
2187 | 0 | return code; |
2188 | 0 | code = pdf_attached_font_resource(pdev, font, ppdfont, |
2189 | 0 | &glyph_usage, &real_widths, &char_cache_size, &width_cache_size); |
2190 | 0 | if (code < 0) |
2191 | 0 | return code; |
2192 | 0 | return pdf_mark_text_glyphs((const gs_text_enum_t *)penum, pstr, glyph_usage, char_cache_size); |
2193 | 0 | } |
2194 | | |
2195 | | /* |
2196 | | * Create or find a font resource object for a glyphshow text. |
2197 | | */ |
2198 | | int |
2199 | | pdf_obtain_font_resource_unencoded(pdf_text_enum_t *penum, |
2200 | | const gs_string *pstr, pdf_font_resource_t **ppdfont, const gs_glyph *gdata) |
2201 | 0 | { |
2202 | 0 | gx_device_pdf *pdev = (gx_device_pdf *)penum->dev; |
2203 | 0 | gs_font *font = (gs_font *)penum->current_font; |
2204 | 0 | byte *glyph_usage = 0; |
2205 | 0 | double *real_widths = 0; |
2206 | 0 | int char_cache_size = 0, width_cache_size = 0; |
2207 | 0 | int code, ps_encoding_index = -1; |
2208 | |
|
2209 | 0 | if (font->FontType == ft_composite) { |
2210 | | /* Must not happen, because we always split composite fonts into descendents. */ |
2211 | 0 | return_error(gs_error_unregistered); |
2212 | 0 | } |
2213 | 0 | code = pdf_attached_font_resource(pdev, font, ppdfont, |
2214 | 0 | &glyph_usage, &real_widths, &char_cache_size, &width_cache_size); |
2215 | 0 | if (code < 0) |
2216 | 0 | return code; |
2217 | | /* *ppdfont is NULL if no resource attached. */ |
2218 | 0 | if (*ppdfont != NULL) |
2219 | 0 | ps_encoding_index = (*ppdfont)->u.simple.preferred_encoding_index; |
2220 | 0 | if (penum->cgp == NULL) { |
2221 | 0 | code = pdf_alloc_text_glyphs_table(pdev, penum, pstr); |
2222 | 0 | if (code < 0) |
2223 | 0 | return code; |
2224 | 0 | code = pdf_make_text_glyphs_table_unencoded(pdev, penum->cgp, font, pstr, gdata, &ps_encoding_index); |
2225 | 0 | if (code < 0) |
2226 | 0 | return code; |
2227 | 0 | } |
2228 | 0 | code = pdf_obtain_font_resource_encoded(pdev, font, ppdfont, penum->cgp); |
2229 | 0 | if (code < 0) |
2230 | 0 | return code; |
2231 | 0 | code = pdf_attached_font_resource(pdev, font, ppdfont, |
2232 | 0 | &glyph_usage, &real_widths, &char_cache_size, &width_cache_size); |
2233 | 0 | if (code < 0) |
2234 | 0 | return code; |
2235 | 0 | (*ppdfont)->u.simple.preferred_encoding_index = ps_encoding_index; |
2236 | 0 | return pdf_mark_text_glyphs_unencoded((const gs_text_enum_t *)penum, |
2237 | 0 | pstr, glyph_usage, char_cache_size); |
2238 | 0 | } |
2239 | | |
2240 | | static inline bool |
2241 | | strings_equal(const gs_const_string *s1, const gs_const_string *s2) |
2242 | 0 | { |
2243 | 0 | return s1->size == s2->size && |
2244 | 0 | !memcmp(s1->data, s2->data, s1->size); |
2245 | 0 | } |
2246 | | |
2247 | | /* |
2248 | | * Create or find a parent Type 0 font resource object for a CID font resource. |
2249 | | */ |
2250 | | int |
2251 | | pdf_obtain_parent_type0_font_resource(gx_device_pdf *pdev, pdf_font_resource_t *pdsubf, |
2252 | | uint font_index, const gs_const_string *CMapName, pdf_font_resource_t **pdfont) |
2253 | 0 | { |
2254 | 0 | if (pdsubf->u.cidfont.parent != 0 && |
2255 | 0 | font_index == pdsubf->u.cidfont.parent->u.type0.font_index && |
2256 | 0 | strings_equal(CMapName, &pdsubf->u.cidfont.parent->u.type0.CMapName)) |
2257 | 0 | *pdfont = pdsubf->u.cidfont.parent; |
2258 | 0 | else { |
2259 | | /* |
2260 | | * PDF spec 1.4 section 5.6 "Composite Fonts" says : |
2261 | | * |
2262 | | * PDF 1.2 introduces a general architecture for composite fonts that theoretically |
2263 | | * allows a Type 0 font to have multiple descendants,which might themselves be |
2264 | | * Type 0 fonts.However,in versions up to and including PDF 1.4,only a single |
2265 | | * descendant is allowed,which must be a CIDFont (not a font).This restriction |
2266 | | * may be relaxed in a future PDF version. |
2267 | | */ |
2268 | |
|
2269 | 0 | if (pdsubf->u.cidfont.parent == NULL || |
2270 | 0 | pdf_find_type0_font_resource(pdev, pdsubf, CMapName, font_index, pdfont) <= 0) { |
2271 | 0 | int code = pdf_font_type0_alloc(pdev, pdfont, gs_no_id, pdsubf, CMapName); |
2272 | |
|
2273 | 0 | if (code < 0) |
2274 | 0 | return code; |
2275 | 0 | (*pdfont)->u.type0.font_index = font_index; |
2276 | 0 | } |
2277 | 0 | pdsubf->u.cidfont.parent = *pdfont; |
2278 | 0 | } |
2279 | 0 | return 0; |
2280 | 0 | } |
2281 | | |
2282 | | gs_char |
2283 | | pdf_find_glyph(pdf_font_resource_t *pdfont, gs_glyph glyph) |
2284 | 0 | { |
2285 | 0 | if (pdfont->FontType != ft_user_defined && |
2286 | 0 | pdfont->FontType != ft_PDF_user_defined && |
2287 | 0 | pdfont->FontType != ft_PCL_user_defined && |
2288 | 0 | pdfont->FontType != ft_MicroType && |
2289 | 0 | pdfont->FontType != ft_GL2_stick_user_defined && |
2290 | 0 | pdfont->FontType != ft_GL2_531) |
2291 | 0 | return GS_NO_CHAR; |
2292 | 0 | else { |
2293 | 0 | pdf_encoding_element_t *pet = pdfont->u.simple.Encoding; |
2294 | 0 | int i, i0 = -1; |
2295 | |
|
2296 | 0 | if (pdfont->u.simple.FirstChar > pdfont->u.simple.LastChar) |
2297 | 0 | return (gs_char)0; |
2298 | 0 | for (i = pdfont->u.simple.FirstChar; i <= pdfont->u.simple.LastChar; i++, pet++) { |
2299 | 0 | if (pet->glyph == glyph) |
2300 | 0 | return (gs_char)i; |
2301 | 0 | if (i0 == -1 && pet->glyph == GS_NO_GLYPH) |
2302 | 0 | i0 = i; |
2303 | 0 | } |
2304 | 0 | if (i0 != -1) |
2305 | 0 | return (gs_char)i0; |
2306 | 0 | if (i < 256) |
2307 | 0 | return (gs_char)i; |
2308 | 0 | return GS_NO_CHAR; |
2309 | 0 | } |
2310 | 0 | } |
2311 | | |
2312 | | /* |
2313 | | * Compute the cached values in the text processing state from the text |
2314 | | * parameters, current_font, and pgs->ctm. Return either an error code (< |
2315 | | * 0) or a mask of operation attributes that the caller must emulate. |
2316 | | * Currently the only such attributes are TEXT_ADD_TO_ALL_WIDTHS and |
2317 | | * TEXT_ADD_TO_SPACE_WIDTH. Note that this procedure fills in all the |
2318 | | * values in ppts->values, not just the ones that need to be set now. |
2319 | | */ |
2320 | | static int |
2321 | | transform_delta_inverse(const gs_point *pdelta, const gs_matrix *pmat, |
2322 | | gs_point *ppt) |
2323 | 0 | { |
2324 | 0 | int code = gs_distance_transform_inverse(pdelta->x, pdelta->y, pmat, ppt); |
2325 | 0 | gs_point delta; |
2326 | |
|
2327 | 0 | if (code < 0) |
2328 | 0 | return code; |
2329 | 0 | if (ppt->y == 0) |
2330 | 0 | return 0; |
2331 | | /* Check for numerical fuzz. */ |
2332 | 0 | code = gs_distance_transform(ppt->x, 0.0, pmat, &delta); |
2333 | 0 | if (code < 0) |
2334 | 0 | return 0; /* punt */ |
2335 | 0 | if (fabs(delta.x - pdelta->x) < 0.01 && fabs(delta.y - pdelta->y) < 0.01) { |
2336 | | /* Close enough to y == 0: device space error < 0.01 pixel. */ |
2337 | 0 | ppt->y = 0; |
2338 | 0 | } |
2339 | 0 | return 0; |
2340 | 0 | } |
2341 | | |
2342 | | float pdf_calculate_text_size(gs_gstate *pgs, pdf_font_resource_t *pdfont, |
2343 | | const gs_matrix *pfmat, gs_matrix *smat, gs_matrix *tmat, |
2344 | | gs_font *font, gx_device_pdf *pdev) |
2345 | 0 | { |
2346 | 0 | gs_matrix orig_matrix; |
2347 | 0 | double |
2348 | 0 | sx = pdev->HWResolution[0] / 72.0, |
2349 | 0 | sy = pdev->HWResolution[1] / 72.0; |
2350 | 0 | float size; |
2351 | | |
2352 | | /* Get the original matrix of the base font. */ |
2353 | |
|
2354 | 0 | { |
2355 | 0 | gs_font_base *cfont = pdf_font_resource_font(pdfont, false); |
2356 | |
|
2357 | 0 | if (pdfont->FontType == ft_user_defined || |
2358 | 0 | pdfont->FontType == ft_PDF_user_defined || |
2359 | 0 | pdfont->FontType == ft_PCL_user_defined || |
2360 | 0 | pdfont->FontType == ft_MicroType || |
2361 | 0 | pdfont->FontType == ft_GL2_stick_user_defined || |
2362 | 0 | pdfont->FontType == ft_GL2_531) |
2363 | 0 | orig_matrix = pdfont->u.simple.s.type3.FontMatrix; |
2364 | 0 | else if (cfont != 0) { |
2365 | | /* |
2366 | | * The text matrix to be computed relatively to the |
2367 | | * embedded font matrix. |
2368 | | */ |
2369 | 0 | orig_matrix = cfont->FontMatrix; |
2370 | 0 | } else { |
2371 | | /* |
2372 | | * We don't embed the font. |
2373 | | * The text matrix to be computed relatively to |
2374 | | * standard font matrix. |
2375 | | */ |
2376 | 0 | pdf_font_orig_matrix(font, &orig_matrix); |
2377 | 0 | } |
2378 | 0 | } |
2379 | | |
2380 | | /* Compute the scaling matrix and combined matrix. */ |
2381 | |
|
2382 | 0 | if (gs_matrix_invert(&orig_matrix, smat) < 0) { |
2383 | 0 | gs_make_identity(smat); |
2384 | 0 | gs_make_identity(tmat); |
2385 | 0 | return 1; /* Arbitrary */ |
2386 | 0 | } |
2387 | 0 | gs_matrix_multiply(smat, pfmat, smat); |
2388 | 0 | *tmat = ctm_only(pgs); |
2389 | 0 | tmat->tx = tmat->ty = 0; |
2390 | 0 | gs_matrix_multiply(smat, tmat, tmat); |
2391 | | |
2392 | | /* Try to find a reasonable size value. This isn't necessary, */ |
2393 | | /* but it's worth a little effort. */ |
2394 | |
|
2395 | 0 | size = hypot(tmat->yx, tmat->yy) / sy; |
2396 | 0 | if (size < 0.01) |
2397 | 0 | size = hypot(tmat->xx, tmat->xy) / sx; |
2398 | 0 | if (size < 0.01) |
2399 | 0 | size = 1; |
2400 | |
|
2401 | 0 | return(size); |
2402 | 0 | } |
2403 | | |
2404 | | int |
2405 | | pdf_update_text_state(pdf_text_process_state_t *ppts, |
2406 | | const pdf_text_enum_t *penum, |
2407 | | pdf_font_resource_t *pdfont, const gs_matrix *pfmat) |
2408 | 0 | { |
2409 | 0 | gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev; |
2410 | 0 | gs_font *font = penum->current_font; |
2411 | 0 | gs_fixed_point cpt; |
2412 | 0 | gs_matrix smat, tmat; |
2413 | 0 | float size; |
2414 | 0 | float c_s = 0, w_s = 0; |
2415 | 0 | int mask = 0; |
2416 | 0 | int code = gx_path_current_point(penum->path, &cpt); |
2417 | |
|
2418 | 0 | if (code < 0) |
2419 | 0 | return code; |
2420 | | |
2421 | 0 | size = pdf_calculate_text_size(penum->pgs, pdfont, pfmat, &smat, &tmat, penum->current_font, pdev); |
2422 | | /* Check for spacing parameters we can handle, and transform them. */ |
2423 | |
|
2424 | 0 | if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) { |
2425 | 0 | if (penum->current_font->WMode == 0) { |
2426 | 0 | gs_point pt; |
2427 | |
|
2428 | 0 | code = transform_delta_inverse(&penum->text.delta_all, &smat, &pt); |
2429 | 0 | if (code >= 0 && pt.y == 0) |
2430 | 0 | c_s = pt.x * size; |
2431 | 0 | else |
2432 | 0 | mask |= TEXT_ADD_TO_ALL_WIDTHS; |
2433 | 0 | } |
2434 | 0 | else |
2435 | 0 | mask |= TEXT_ADD_TO_ALL_WIDTHS; |
2436 | 0 | } |
2437 | |
|
2438 | 0 | if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) { |
2439 | 0 | gs_point pt; |
2440 | |
|
2441 | 0 | code = transform_delta_inverse(&penum->text.delta_space, &smat, &pt); |
2442 | 0 | if (code >= 0 && pt.y == 0 && penum->text.space.s_char == 32) |
2443 | 0 | w_s = pt.x * size; |
2444 | 0 | else |
2445 | 0 | mask |= TEXT_ADD_TO_SPACE_WIDTH; |
2446 | 0 | } |
2447 | | /* Store the updated values. */ |
2448 | |
|
2449 | 0 | tmat.xx /= size; |
2450 | 0 | tmat.xy /= size; |
2451 | 0 | tmat.yx /= size; |
2452 | 0 | tmat.yy /= size; |
2453 | 0 | tmat.tx += fixed2float(cpt.x); |
2454 | 0 | tmat.ty += fixed2float(cpt.y); |
2455 | |
|
2456 | 0 | ppts->values.character_spacing = c_s; |
2457 | 0 | ppts->values.pdfont = pdfont; |
2458 | 0 | ppts->values.size = size; |
2459 | 0 | ppts->values.matrix = tmat; |
2460 | 0 | ppts->values.render_mode = penum->pgs->text_rendering_mode; |
2461 | 0 | ppts->values.word_spacing = w_s; |
2462 | 0 | ppts->font = font; |
2463 | |
|
2464 | 0 | if (font->PaintType == 2 && penum->pgs->text_rendering_mode == 0) |
2465 | 0 | { |
2466 | 0 | gs_gstate *pgs = penum->pgs; |
2467 | 0 | gs_font *font = penum->current_font; |
2468 | 0 | double scaled_width = font->StrokeWidth != 0 ? font->StrokeWidth : 0.001; |
2469 | 0 | double saved_width = pgs->line_params.half_width; |
2470 | | /* |
2471 | | * See stream_to_text in gdevpdfu.c re the computation of |
2472 | | * the scaling value. |
2473 | | */ |
2474 | 0 | double scale = 72.0 / pdev->HWResolution[1]; |
2475 | |
|
2476 | 0 | if (font->FontMatrix.yy != 0) |
2477 | 0 | scaled_width *= fabs(font->orig_FontMatrix.yy) * size * scale; |
2478 | 0 | else |
2479 | 0 | scaled_width *= fabs(font->orig_FontMatrix.xy) * size * scale; |
2480 | |
|
2481 | 0 | if (tmat.yy != 0) |
2482 | 0 | scaled_width *= tmat.yy; |
2483 | 0 | else |
2484 | 0 | scaled_width *= tmat.xy; |
2485 | |
|
2486 | 0 | ppts->values.render_mode = 1; |
2487 | | |
2488 | | /* Sort out any pending glyphs */ |
2489 | 0 | code = pdf_set_PaintType0_params(pdev, pgs, size, scaled_width, &ppts->values); |
2490 | 0 | if (code < 0) |
2491 | 0 | return code; |
2492 | | |
2493 | 0 | pgs->line_params.half_width = scaled_width / 2; |
2494 | 0 | code = pdf_set_text_process_state(pdev, (const gs_text_enum_t *)penum, |
2495 | 0 | ppts); |
2496 | 0 | if (code < 0) |
2497 | 0 | return code; |
2498 | | |
2499 | 0 | pgs->line_params.half_width = saved_width; |
2500 | 0 | } else { |
2501 | 0 | code = pdf_set_text_process_state(pdev, (const gs_text_enum_t *)penum, |
2502 | 0 | ppts); |
2503 | 0 | } |
2504 | 0 | return (code < 0 ? code : mask); |
2505 | 0 | } |
2506 | | |
2507 | | /* |
2508 | | * Set up commands to make the output state match the processing state. |
2509 | | * General graphics state commands are written now; text state commands |
2510 | | * are written later. |
2511 | | */ |
2512 | | int |
2513 | | pdf_set_text_process_state(gx_device_pdf *pdev, |
2514 | | const gs_text_enum_t *pte, /* for pdcolor, pgs */ |
2515 | | pdf_text_process_state_t *ppts) |
2516 | 0 | { |
2517 | | /* |
2518 | | * Setting the stroke parameters may exit text mode, causing the |
2519 | | * settings of the text parameters to be lost. Therefore, we set the |
2520 | | * stroke parameters first. |
2521 | | */ |
2522 | 0 | if (pdf_render_mode_uses_stroke(pdev, &ppts->values)) { |
2523 | | /* Write all the parameters for stroking. */ |
2524 | 0 | gs_gstate *pgs = pte->pgs; |
2525 | 0 | float save_width = pgs->line_params.half_width; |
2526 | 0 | int code; |
2527 | |
|
2528 | 0 | if (pdev->context == PDF_IN_STRING) { |
2529 | 0 | code = sync_text_state(pdev); |
2530 | 0 | if (code < 0) |
2531 | 0 | return code; |
2532 | 0 | } |
2533 | | |
2534 | 0 | code = pdf_open_contents(pdev, PDF_IN_STREAM); |
2535 | 0 | if (code < 0) |
2536 | 0 | return code; |
2537 | | |
2538 | 0 | code = pdf_prepare_stroke(pdev, pgs, true); |
2539 | 0 | if (code >= 0) { |
2540 | 0 | code = gdev_vector_prepare_stroke((gx_device_vector *)pdev, |
2541 | 0 | pgs, NULL, NULL, 1); |
2542 | 0 | if (code < 0) |
2543 | 0 | return code; |
2544 | 0 | } |
2545 | | |
2546 | 0 | code = pdf_open_contents(pdev, PDF_IN_STRING); |
2547 | 0 | if (code < 0) |
2548 | 0 | return code; |
2549 | | |
2550 | 0 | pgs->line_params.half_width = save_width; |
2551 | 0 | } |
2552 | | |
2553 | | /* Now set all the other parameters. */ |
2554 | | |
2555 | 0 | return pdf_set_text_state_values(pdev, &ppts->values); |
2556 | 0 | } |
2557 | | |
2558 | | static int |
2559 | | store_glyph_width(pdf_glyph_width_t *pwidth, int wmode, const gs_matrix *scale, |
2560 | | const gs_glyph_info_t *pinfo) |
2561 | 0 | { |
2562 | 0 | double w, v; |
2563 | |
|
2564 | 0 | gs_distance_transform(pinfo->width[wmode].x, pinfo->width[wmode].y, scale, &pwidth->xy); |
2565 | 0 | if (wmode) |
2566 | 0 | w = pwidth->xy.y, v = pwidth->xy.x; |
2567 | 0 | else |
2568 | 0 | w = pwidth->xy.x, v = pwidth->xy.y; |
2569 | 0 | pwidth->w = w; |
2570 | 0 | if (v != 0) |
2571 | 0 | return 1; |
2572 | 0 | gs_distance_transform(pinfo->v.x, pinfo->v.y, scale, &pwidth->v); |
2573 | 0 | return 0; |
2574 | 0 | } |
2575 | | |
2576 | | static int |
2577 | | get_missing_width(gs_font_base *cfont, int wmode, const gs_matrix *scale_c, |
2578 | | pdf_glyph_widths_t *pwidths) |
2579 | 0 | { |
2580 | 0 | gs_font_info_t finfo; |
2581 | 0 | int code; |
2582 | |
|
2583 | 0 | code = cfont->procs.font_info((gs_font *)cfont, NULL, |
2584 | 0 | FONT_INFO_MISSING_WIDTH, &finfo); |
2585 | 0 | if (code < 0) |
2586 | 0 | return code; |
2587 | 0 | if (wmode) { |
2588 | 0 | gs_distance_transform(0.0, -finfo.MissingWidth, scale_c, &pwidths->real_width.xy); |
2589 | 0 | pwidths->Width.xy.x = 0; |
2590 | 0 | pwidths->Width.xy.y = pwidths->real_width.xy.y; |
2591 | 0 | pwidths->Width.w = pwidths->real_width.w = |
2592 | 0 | pwidths->Width.xy.y; |
2593 | 0 | pwidths->Width.v.x = - pwidths->Width.xy.y / 2; |
2594 | 0 | pwidths->Width.v.y = - pwidths->Width.xy.y; |
2595 | 0 | } else { |
2596 | 0 | gs_distance_transform(finfo.MissingWidth, 0.0, scale_c, &pwidths->real_width.xy); |
2597 | 0 | pwidths->Width.xy.x = pwidths->real_width.xy.x; |
2598 | 0 | pwidths->Width.xy.y = 0; |
2599 | 0 | pwidths->Width.w = pwidths->real_width.w = |
2600 | 0 | pwidths->Width.xy.x; |
2601 | 0 | pwidths->Width.v.x = pwidths->Width.v.y = 0; |
2602 | 0 | } |
2603 | | /* |
2604 | | * Don't mark the width as known, just in case this is an |
2605 | | * incrementally defined font. |
2606 | | */ |
2607 | 0 | return 1; |
2608 | 0 | } |
2609 | | |
2610 | | /* |
2611 | | * Get the widths (unmodified from the copied font, |
2612 | | * and possibly modified from the original font) of a given glyph. |
2613 | | * Return 1 if the width was defaulted to MissingWidth. |
2614 | | * Return TEXT_PROCESS_CDEVPROC if a CDevProc callout is needed. |
2615 | | * cdevproc_result != NULL if we restart after a CDevProc callout. |
2616 | | */ |
2617 | | int |
2618 | | pdf_glyph_widths(pdf_font_resource_t *pdfont, int wmode, gs_glyph glyph, |
2619 | | gs_font *orig_font, pdf_glyph_widths_t *pwidths, |
2620 | | const double cdevproc_result[10]) |
2621 | 0 | { |
2622 | 0 | gs_font_base *cfont = pdf_font_resource_font(pdfont, false); |
2623 | 0 | gs_font *ofont = orig_font; |
2624 | 0 | gs_glyph_info_t info; |
2625 | 0 | gs_matrix scale_c, scale_o; |
2626 | 0 | int code, rcode = 0; |
2627 | 0 | gs_point v; |
2628 | 0 | int allow_cdevproc_callout = (orig_font->FontType == ft_CID_TrueType |
2629 | 0 | || orig_font->FontType == ft_CID_encrypted |
2630 | 0 | ? GLYPH_INFO_CDEVPROC : 0); /* fixme : allow more font types. */ |
2631 | |
|
2632 | 0 | if (ofont->FontType == ft_composite) |
2633 | 0 | return_error(gs_error_unregistered); /* Must not happen. */ |
2634 | 0 | code = glyph_orig_matrix((const gs_font *)cfont, glyph, &scale_c); |
2635 | 0 | if (code < 0) |
2636 | 0 | return code; |
2637 | 0 | code = glyph_orig_matrix(ofont, glyph, &scale_o); |
2638 | 0 | if (code < 0) |
2639 | 0 | return code; |
2640 | 0 | gs_matrix_scale(&scale_c, 1000.0, 1000.0, &scale_c); |
2641 | 0 | gs_matrix_scale(&scale_o, 1000.0, 1000.0, &scale_o); |
2642 | 0 | pwidths->Width.v.x = pwidths->Width.v.y = 0; |
2643 | 0 | pwidths->real_width.v.x = pwidths->real_width.v.y = 0; |
2644 | 0 | pwidths->real_width.w = pwidths->real_width.xy.x = pwidths->real_width.xy.y = 0; |
2645 | 0 | pwidths->replaced_v = false; |
2646 | 0 | pwidths->ignore_wmode = false; |
2647 | 0 | if (glyph == GS_NO_GLYPH) |
2648 | 0 | return get_missing_width(cfont, wmode, &scale_c, pwidths); |
2649 | 0 | code = cfont->procs.glyph_info((gs_font *)cfont, glyph, NULL, |
2650 | 0 | GLYPH_INFO_WIDTH0 | |
2651 | 0 | (GLYPH_INFO_WIDTH0 << wmode) | |
2652 | 0 | GLYPH_INFO_OUTLINE_WIDTHS | |
2653 | 0 | (GLYPH_INFO_VVECTOR0 << wmode), |
2654 | 0 | &info); |
2655 | | /* For CID fonts the PDF spec requires the x-component of v-vector |
2656 | | to be equal to half glyph width, and AR5 takes it from W, DW. |
2657 | | So make a compatibe data here. |
2658 | | */ |
2659 | 0 | if ((code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode)))) { |
2660 | | /* If we got an undefined error, and its a type 1/CFF font, try to |
2661 | | * find the /.notdef glyph and use its width instead (as this is the |
2662 | | * glyph which will be rendered). We don't do this for other font types |
2663 | | * as it seems Acrobat/Distiller may not do so either. |
2664 | | */ |
2665 | 0 | if (code == gs_error_undefined && (ofont->FontType == ft_encrypted || ofont->FontType == ft_encrypted2)) { |
2666 | 0 | int index; |
2667 | 0 | gs_glyph notdef_glyph; |
2668 | |
|
2669 | 0 | v.x = v.y = 0; |
2670 | |
|
2671 | 0 | for (index = 0; |
2672 | 0 | (ofont->procs.enumerate_glyph((gs_font *)ofont, &index, |
2673 | 0 | (GLYPH_SPACE_NAME), ¬def_glyph)) >= 0 && |
2674 | 0 | index != 0;) { |
2675 | 0 | if (gs_font_glyph_is_notdef((gs_font_base *)ofont, notdef_glyph)) { |
2676 | 0 | code = ofont->procs.glyph_info((gs_font *)ofont, notdef_glyph, NULL, |
2677 | 0 | GLYPH_INFO_WIDTH0 << wmode, |
2678 | 0 | &info); |
2679 | |
|
2680 | 0 | if (code < 0) |
2681 | 0 | return code; |
2682 | 0 | code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info); |
2683 | 0 | if (code < 0) |
2684 | 0 | return code; |
2685 | 0 | rcode |= code; |
2686 | 0 | if (info.members & (GLYPH_INFO_VVECTOR0 << wmode)) |
2687 | 0 | gs_distance_transform(info.v.x, info.v.y, &scale_c, &v); |
2688 | 0 | else |
2689 | 0 | v.x = v.y = 0; |
2690 | 0 | break; |
2691 | 0 | } |
2692 | 0 | } |
2693 | 0 | } else { |
2694 | 0 | code = get_missing_width(cfont, wmode, &scale_c, pwidths); |
2695 | 0 | if (code < 0) |
2696 | 0 | v.y = 0; |
2697 | 0 | else |
2698 | 0 | v.y = pwidths->Width.v.y; |
2699 | 0 | if (wmode) { |
2700 | 0 | pdf_glyph_widths_t widths1; |
2701 | |
|
2702 | 0 | if (get_missing_width(cfont, 0, &scale_c, &widths1) < 0) |
2703 | 0 | v.x = 0; |
2704 | 0 | else |
2705 | 0 | v.x = widths1.Width.w / 2; |
2706 | 0 | } else |
2707 | 0 | v.x = pwidths->Width.v.x; |
2708 | 0 | } |
2709 | 0 | } else if (code < 0) |
2710 | 0 | return code; |
2711 | 0 | else { |
2712 | 0 | code = store_glyph_width(&pwidths->Width, wmode, &scale_c, &info); |
2713 | 0 | if (code < 0) |
2714 | 0 | return code; |
2715 | 0 | rcode |= code; |
2716 | 0 | if (info.members & (GLYPH_INFO_VVECTOR0 << wmode)) |
2717 | 0 | gs_distance_transform(info.v.x, info.v.y, &scale_c, &v); |
2718 | 0 | else |
2719 | 0 | v.x = v.y = 0; |
2720 | 0 | if (wmode && pdf_is_CID_font(ofont)) { |
2721 | 0 | if (info.members & (GLYPH_INFO_WIDTH0 << wmode)) { |
2722 | 0 | gs_point xy; |
2723 | |
|
2724 | 0 | gs_distance_transform(info.width[0].x, info.width[0].y, &scale_c, &xy); |
2725 | 0 | v.x = xy.x / 2; |
2726 | 0 | } else { |
2727 | 0 | pdf_glyph_widths_t widths1; |
2728 | |
|
2729 | 0 | if (get_missing_width(cfont, 0, &scale_c, &widths1) < 0) |
2730 | 0 | v.x = 0; |
2731 | 0 | else |
2732 | 0 | v.x = widths1.Width.w / 2; |
2733 | 0 | } |
2734 | 0 | } |
2735 | 0 | } |
2736 | 0 | pwidths->Width.v = v; |
2737 | 0 | if (code > 0 && !pdf_is_CID_font(ofont)) |
2738 | 0 | pwidths->Width.xy.x = pwidths->Width.xy.y = pwidths->Width.w = 0; |
2739 | 0 | if (cdevproc_result == NULL) { |
2740 | 0 | info.members = 0; |
2741 | 0 | code = ofont->procs.glyph_info(ofont, glyph, NULL, |
2742 | 0 | (GLYPH_INFO_WIDTH0 << wmode) | |
2743 | 0 | (GLYPH_INFO_VVECTOR0 << wmode) | |
2744 | 0 | allow_cdevproc_callout, |
2745 | 0 | &info); |
2746 | | /* fixme : Move this call before cfont->procs.glyph_info. */ |
2747 | 0 | if (info.members & GLYPH_INFO_CDEVPROC) { |
2748 | 0 | if (allow_cdevproc_callout) |
2749 | 0 | return TEXT_PROCESS_CDEVPROC; |
2750 | 0 | else |
2751 | 0 | return_error(gs_error_rangecheck); |
2752 | 0 | } |
2753 | 0 | } else { |
2754 | 0 | info.width[0].x = cdevproc_result[0]; |
2755 | 0 | info.width[0].y = cdevproc_result[1]; |
2756 | 0 | info.width[1].x = cdevproc_result[6]; |
2757 | 0 | info.width[1].y = cdevproc_result[7]; |
2758 | 0 | info.v.x = (wmode ? cdevproc_result[8] : 0); |
2759 | 0 | info.v.y = (wmode ? cdevproc_result[9] : 0); |
2760 | 0 | info.members = (GLYPH_INFO_WIDTH0 << wmode) | |
2761 | 0 | (wmode ? GLYPH_INFO_VVECTOR1 : 0); |
2762 | 0 | code = 0; |
2763 | 0 | } |
2764 | 0 | if (code == gs_error_undefined || !(info.members & (GLYPH_INFO_WIDTH0 << wmode))) |
2765 | 0 | pwidths->real_width = pwidths->Width; |
2766 | 0 | else if (code < 0) |
2767 | 0 | return code; |
2768 | 0 | else { |
2769 | 0 | if ((info.members & (GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1)) != 0) { |
2770 | 0 | pwidths->replaced_v = true; |
2771 | 0 | if ((info.members & GLYPH_INFO_VVECTOR1) == 0 && wmode == 1) |
2772 | 0 | pwidths->ignore_wmode = true; |
2773 | 0 | } |
2774 | 0 | else |
2775 | 0 | info.v.x = info.v.y = 0; |
2776 | 0 | code = store_glyph_width(&pwidths->real_width, wmode, &scale_o, &info); |
2777 | 0 | if (code < 0) |
2778 | 0 | return code; |
2779 | 0 | rcode |= code; |
2780 | 0 | gs_distance_transform(info.v.x, info.v.y, &scale_o, &pwidths->real_width.v); |
2781 | 0 | } |
2782 | 0 | return rcode; |
2783 | 0 | } |
2784 | | |
2785 | | static int |
2786 | | pdf_choose_output_char_code(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_char *pch) |
2787 | 0 | { |
2788 | 0 | gs_char ch; |
2789 | 0 | gs_font *font = penum->current_font; |
2790 | |
|
2791 | 0 | if (penum->text.operation & TEXT_FROM_SINGLE_GLYPH) { |
2792 | 0 | byte buf[1]; |
2793 | 0 | int char_code_length; |
2794 | 0 | gs_glyph glyph = penum->text.data.d_glyph; |
2795 | 0 | int code = pdf_encode_glyph((gs_font_base *)font, glyph, |
2796 | 0 | buf, sizeof(buf), &char_code_length); |
2797 | |
|
2798 | 0 | if (code < 0) { |
2799 | | /* Must not happen, becuse pdf_encode_glyph was passed in process_plain_text.*/ |
2800 | 0 | ch = GS_NO_CHAR; |
2801 | 0 | } else if (char_code_length != 1) { |
2802 | | /* Must not happen with type 3 fonts.*/ |
2803 | 0 | ch = GS_NO_CHAR; |
2804 | 0 | } else |
2805 | 0 | ch = buf[0]; |
2806 | 0 | } else if (penum->orig_font->FontType == ft_composite) { |
2807 | 0 | gs_font_type0 *font0 = (gs_font_type0 *)penum->orig_font; |
2808 | 0 | gs_glyph glyph = penum->returned.current_glyph; |
2809 | |
|
2810 | 0 | if (font0->data.FMapType == fmap_CMap) { |
2811 | 0 | pdf_font_resource_t *pdfont; |
2812 | 0 | int code = pdf_attached_font_resource(pdev, font, &pdfont, NULL, NULL, NULL, NULL); |
2813 | |
|
2814 | 0 | if (code < 0) |
2815 | 0 | return code; |
2816 | 0 | ch = pdf_find_glyph(pdfont, glyph); |
2817 | 0 | } else |
2818 | 0 | ch = penum->returned.current_char; |
2819 | 0 | } else { |
2820 | 0 | ch = penum->returned.current_char; |
2821 | | /* Keep for records : glyph = font->procs.encode_char(font, ch, GLYPH_SPACE_NAME); */ |
2822 | | /* |
2823 | | * If glyph == GS_NO_GLYPH, we should replace it with |
2824 | | * a notdef glyph, but we don't know how to do with Type 3 fonts. |
2825 | | */ |
2826 | 0 | } |
2827 | 0 | *pch = ch; |
2828 | 0 | return 0; |
2829 | 0 | } |
2830 | | |
2831 | | static int |
2832 | | pdf_choose_output_glyph_name(gx_device_pdf *pdev, pdf_text_enum_t *penum, gs_const_string *gnstr, gs_glyph glyph) |
2833 | 0 | { |
2834 | 0 | if (penum->orig_font->FontType == ft_composite || penum->orig_font->procs.glyph_name(penum->orig_font, glyph, gnstr) < 0 |
2835 | 0 | || (penum->orig_font->FontType > 42 && gnstr->size == 7 && strcmp((const char *)gnstr->data, ".notdef")== 0)) { |
2836 | | /* If we're capturing a PCL bitmap, and the glyph comes back with a name of '/.notdef' then |
2837 | | * generate a name instead. There's nothing wrong technically with using /.notdef, but Acrobat does |
2838 | | * 'special stuff' with that name, and messes up the display. See bug #699102. |
2839 | | */ |
2840 | | /* couldn't find a glyph name, so make one up! This can happen if we are handling PCL and the glyph |
2841 | | * (character code) is less than 29, the PCL glyph names start with /.notdef at 29. We also need to |
2842 | | * do this for composite fonts. |
2843 | | */ |
2844 | 0 | char buf[6]; |
2845 | 0 | byte *p; |
2846 | |
|
2847 | 0 | gnstr->size = 5; |
2848 | 0 | p = (byte *)gs_alloc_string(pdev->pdf_memory, gnstr->size, "pdf_text_set_cache"); |
2849 | 0 | if (p == NULL) |
2850 | 0 | return_error(gs_error_VMerror); |
2851 | 0 | gs_sprintf(buf, "g%04x", (unsigned int)(glyph & 0xFFFF)); |
2852 | 0 | memcpy(p, buf, 5); |
2853 | 0 | gnstr->data = p; |
2854 | 0 | } |
2855 | 0 | return 0; |
2856 | 0 | } |
2857 | | |
2858 | | /* ---------------- Main entry ---------------- */ |
2859 | | |
2860 | | /* |
2861 | | * Fall back to the default text processing code when needed. |
2862 | | */ |
2863 | | int |
2864 | | pdf_default_text_begin(gs_text_enum_t *pte, const gs_text_params_t *text, |
2865 | | gs_text_enum_t **ppte) |
2866 | 0 | { |
2867 | 0 | gs_text_params_t text1 = *text; |
2868 | |
|
2869 | 0 | if(pte->current_font->FontType == 3 && (text1.operation & TEXT_DO_NONE)) { |
2870 | | /* We need a real drawing to accumulate charproc. */ |
2871 | 0 | text1.operation &= ~TEXT_DO_NONE; |
2872 | 0 | text1.operation |= TEXT_DO_DRAW; |
2873 | 0 | } |
2874 | 0 | return gx_default_text_begin(pte->dev, pte->pgs, &text1, pte->current_font, |
2875 | 0 | pte->path, pte->pdcolor, pte->pcpath, |
2876 | 0 | pte->memory, ppte); |
2877 | 0 | } |
2878 | | |
2879 | | static int install_PS_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte, |
2880 | | gs_text_enum_t *pte_default, pdf_text_enum_t *const penum) |
2881 | 0 | { |
2882 | 0 | int code; |
2883 | |
|
2884 | 0 | penum->returned.current_char = pte_default->returned.current_char; |
2885 | 0 | penum->returned.current_glyph = pte_default->returned.current_glyph; |
2886 | 0 | pdev->charproc_ctm = penum->pgs->ctm; |
2887 | 0 | if ((penum->current_font->FontType == ft_user_defined || penum->current_font->FontType == ft_PDF_user_defined)&& |
2888 | 0 | penum->outer_CID == GS_NO_GLYPH && |
2889 | 0 | !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) { |
2890 | | /* The condition above must be consistent with one in pdf_text_set_cache, |
2891 | | which decides to apply pdf_set_charproc_attrs. */ |
2892 | 0 | gs_matrix m; |
2893 | 0 | pdf_font_resource_t *pdfont; |
2894 | |
|
2895 | 0 | code = pdf_start_charproc_accum(pdev); |
2896 | 0 | if (code < 0) |
2897 | 0 | return code; |
2898 | | |
2899 | | /* We need to give FreeType some room for accuracy when |
2900 | | * retrieving the outline. We will use a scale factor of 100 |
2901 | | * (see below). Because this appears to the regular path |
2902 | | * handling code as if it were at the page level, the co-ords |
2903 | | * would be clipped frequently, so we temporarily hack the |
2904 | | * width and height of the device here to ensure it doesn't. |
2905 | | * Note that this requires some careful manipulation of the |
2906 | | * CTM in various places, which want numbers in the font |
2907 | | * co-ordinate space, not the scaled user space. |
2908 | | */ |
2909 | 0 | pdev->width *= 100; |
2910 | 0 | pdev->height *= 100; |
2911 | |
|
2912 | 0 | pdf_viewer_state_from_gs_gstate(pdev, pte->pgs, pte->pdcolor); |
2913 | | /* Set line params to unallowed values so that |
2914 | | they'll synchronize with writing them out on the first use. |
2915 | | Doing so because PDF viewer inherits them from the |
2916 | | contents stream when executing the charproc, |
2917 | | but at this moment we don't know in what contexts |
2918 | | it will be used. */ |
2919 | 0 | pdev->state.line_params.half_width = -1; |
2920 | 0 | pdev->state.line_params.start_cap = gs_cap_unknown; |
2921 | 0 | pdev->state.line_params.end_cap = gs_cap_unknown; |
2922 | 0 | pdev->state.line_params.dash_cap = gs_cap_unknown; |
2923 | 0 | pdev->state.line_params.join = gs_join_unknown; |
2924 | 0 | pdev->state.line_params.miter_limit = -1; |
2925 | 0 | pdev->state.line_params.dash.pattern_size = -1; |
2926 | | /* Must set an identity CTM for the charproc accumulation. |
2927 | | The function show_proceed (called from gs_text_process above) |
2928 | | executed gsave, so we are safe to change CTM now. |
2929 | | Note that BuildChar may change CTM before calling setcachedevice. */ |
2930 | 0 | gs_make_identity(&m); |
2931 | | /* See comment above, we actually want to use a scale factor |
2932 | | * of 100 in order to give FreeType some room in the fixed |
2933 | | * precision calculations when retrieing the outline. So in |
2934 | | * fact we don't use the identity CTM, but a 100x100 matrix |
2935 | | * Originally tried 1000, but that was too likely to cause |
2936 | | * clipping or arithmetic overflow. |
2937 | | */ |
2938 | 0 | gs_matrix_scale(&m, 100, 100, &m); |
2939 | 0 | gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m); |
2940 | | |
2941 | | /* Choose a character code to use with the charproc. */ |
2942 | 0 | code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code); |
2943 | 0 | if (code < 0) |
2944 | 0 | return code; |
2945 | 0 | code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL); |
2946 | 0 | if (code < 0) |
2947 | 0 | return code; |
2948 | 0 | pdev->font3 = (pdf_resource_t *)pdfont; |
2949 | 0 | pdev->substream_Resources = pdfont->u.simple.s.type3.Resources; |
2950 | 0 | penum->charproc_accum = true; |
2951 | 0 | pdev->accumulating_charproc = true; |
2952 | 0 | pdev->charproc_BBox.p.x = 10000; |
2953 | 0 | pdev->charproc_BBox.p.y = 10000; |
2954 | 0 | pdev->charproc_BBox.q.x = 0; |
2955 | 0 | pdev->charproc_BBox.q.y = 0; |
2956 | 0 | return TEXT_PROCESS_RENDER; |
2957 | 0 | } |
2958 | 0 | return 0; |
2959 | 0 | } |
2960 | | |
2961 | | static int install_charproc_accumulator(gx_device_pdf *pdev, gs_text_enum_t *pte, |
2962 | | gs_text_enum_t *pte_default, pdf_text_enum_t *const penum) |
2963 | 0 | { |
2964 | 0 | int code; |
2965 | |
|
2966 | 0 | pdev->charproc_ctm = penum->pgs->ctm; |
2967 | 0 | if ((penum->current_font->FontType == ft_user_defined || |
2968 | 0 | penum->current_font->FontType == ft_PDF_user_defined || |
2969 | 0 | penum->current_font->FontType == ft_PCL_user_defined || |
2970 | 0 | penum->current_font->FontType == ft_MicroType || |
2971 | 0 | penum->current_font->FontType == ft_GL2_stick_user_defined || |
2972 | 0 | penum->current_font->FontType == ft_GL2_531) && |
2973 | 0 | penum->outer_CID == GS_NO_GLYPH && |
2974 | 0 | !(penum->pte_default->text.operation & TEXT_DO_CHARWIDTH)) { |
2975 | | /* The condition above must be consistent with one in pdf_text_set_cache, |
2976 | | which decides to apply pdf_set_charproc_attrs. */ |
2977 | 0 | gs_matrix m; |
2978 | 0 | pdf_font_resource_t *pdfont; |
2979 | |
|
2980 | 0 | pdev->PS_accumulator = false; |
2981 | 0 | code = pdf_start_charproc_accum(pdev); |
2982 | 0 | if (code < 0) |
2983 | 0 | return code; |
2984 | | |
2985 | 0 | pdf_viewer_state_from_gs_gstate(pdev, pte->pgs, pte->pdcolor); |
2986 | | /* Set line params to unallowed values so that |
2987 | | they'll synchronize with writing them out on the first use. |
2988 | | Doing so because PDF viewer inherits them from the |
2989 | | contents stream when executing the charproc, |
2990 | | but at this moment we don't know in what contexts |
2991 | | it will be used. */ |
2992 | 0 | pdev->state.line_params.half_width = -1; |
2993 | 0 | pdev->state.line_params.start_cap = gs_cap_unknown; |
2994 | 0 | pdev->state.line_params.end_cap = gs_cap_unknown; |
2995 | 0 | pdev->state.line_params.dash_cap = gs_cap_unknown; |
2996 | 0 | pdev->state.line_params.join = gs_join_unknown; |
2997 | 0 | pdev->state.line_params.miter_limit = -1; |
2998 | 0 | pdev->state.line_params.dash.pattern_size = -1; |
2999 | | /* Must set an identity CTM for the charproc accumulation. |
3000 | | The function show_proceed (called from gs_text_process above) |
3001 | | executed gsave, so we are safe to change CTM now. |
3002 | | Note that BuildChar may change CTM before calling setcachedevice. */ |
3003 | 0 | gs_make_identity(&m); |
3004 | 0 | gs_matrix_fixed_from_matrix(&penum->pgs->ctm, &m); |
3005 | | |
3006 | | /* Choose a character code to use with the charproc. */ |
3007 | 0 | code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code); |
3008 | 0 | if (code < 0) { |
3009 | 0 | (void)pdf_exit_substream(pdev); |
3010 | 0 | return code; |
3011 | 0 | } |
3012 | 0 | code = pdf_attached_font_resource(pdev, penum->current_font, &pdfont, NULL, NULL, NULL, NULL); |
3013 | 0 | if (code < 0) { |
3014 | 0 | (void)pdf_exit_substream(pdev); |
3015 | 0 | return code; |
3016 | 0 | } |
3017 | 0 | pdev->font3 = (pdf_resource_t *)pdfont; |
3018 | 0 | if (pdfont == 0L) { |
3019 | 0 | (void)pdf_exit_substream(pdev); |
3020 | 0 | return gs_note_error(gs_error_invalidfont); |
3021 | 0 | } |
3022 | | |
3023 | 0 | pdev->substream_Resources = pdfont->u.simple.s.type3.Resources; |
3024 | 0 | penum->charproc_accum = true; |
3025 | 0 | pdev->accumulating_charproc = true; |
3026 | 0 | return TEXT_PROCESS_RENDER; |
3027 | 0 | } |
3028 | 0 | return 0; |
3029 | 0 | } |
3030 | | |
3031 | | static int complete_charproc(gx_device_pdf *pdev, gs_text_enum_t *pte, |
3032 | | gs_text_enum_t *pte_default, pdf_text_enum_t *const penum, |
3033 | | bool was_PS_type3) |
3034 | 0 | { |
3035 | 0 | gs_const_string gnstr; |
3036 | 0 | int code; |
3037 | |
|
3038 | 0 | if (pte_default->returned.current_glyph == GS_NO_GLYPH) |
3039 | 0 | return_error(gs_error_undefined); |
3040 | 0 | code = pdf_choose_output_glyph_name(pdev, penum, &gnstr, pte_default->returned.current_glyph); |
3041 | 0 | if (code < 0) { |
3042 | 0 | return code; |
3043 | 0 | } |
3044 | | |
3045 | 0 | if ((penum->current_font->FontType == ft_user_defined || |
3046 | 0 | penum->current_font->FontType == ft_PDF_user_defined || |
3047 | 0 | penum->current_font->FontType == ft_PCL_user_defined || |
3048 | 0 | penum->current_font->FontType == ft_MicroType || |
3049 | 0 | penum->current_font->FontType == ft_GL2_stick_user_defined || |
3050 | 0 | penum->current_font->FontType == ft_GL2_531) && |
3051 | 0 | stell(pdev->strm) == 0) |
3052 | 0 | { |
3053 | 0 | char glyph[256], FontName[gs_font_name_max + 1], KeyName[256]; |
3054 | 0 | int len; |
3055 | |
|
3056 | 0 | len = min(gs_font_name_max, gnstr.size); |
3057 | 0 | memcpy(glyph, gnstr.data, len); |
3058 | 0 | glyph[len] = 0x00; |
3059 | 0 | len = min(gs_font_name_max, penum->current_font->font_name.size); |
3060 | 0 | memcpy(FontName, penum->current_font->font_name.chars, len); |
3061 | 0 | FontName[len] = 0x00; |
3062 | 0 | len = min(gs_font_name_max, penum->current_font->key_name.size); |
3063 | 0 | memcpy(KeyName, penum->current_font->key_name.chars, len); |
3064 | 0 | KeyName[len] = 0x00; |
3065 | |
|
3066 | 0 | emprintf4(pdev->memory, |
3067 | 0 | "ERROR: Page %d used undefined glyph '%s' from type 3 font '%s', key '%s'\n", |
3068 | 0 | pdev->next_page, glyph, FontName, KeyName); |
3069 | 0 | stream_puts(pdev->strm, "0 0 0 0 0 0 d1\n"); |
3070 | 0 | } |
3071 | |
|
3072 | 0 | if (was_PS_type3) { |
3073 | | /* See below, we scaled the device height and width to prevent |
3074 | | * clipping of the CharProc operations, now we need to undo that. |
3075 | | */ |
3076 | 0 | pdev->width /= 100; |
3077 | 0 | pdev->height /= 100; |
3078 | 0 | } |
3079 | 0 | code = pdf_end_charproc_accum(pdev, penum->current_font, penum->cgp, |
3080 | 0 | pte_default->returned.current_glyph, penum->output_char_code, &gnstr); |
3081 | 0 | if (code < 0) |
3082 | 0 | return code; |
3083 | 0 | pdev->accumulating_charproc = false; |
3084 | 0 | penum->charproc_accum = false; |
3085 | 0 | code = gx_default_text_restore_state(pte_default); |
3086 | 0 | if (code < 0) |
3087 | 0 | return code; |
3088 | 0 | gs_text_release(pte_default, "pdf_text_process"); |
3089 | 0 | penum->pte_default = 0; |
3090 | |
|
3091 | 0 | return 0; |
3092 | 0 | } |
3093 | | |
3094 | | /* Nasty hackery. The PCL 'stick font' is drawn by constructing a path, and then stroking it. |
3095 | | * The stroke width is calculated under the influence of the device default matrix, which |
3096 | | * ensures it is the same, no matter what size the font is drawn at. Of course we are |
3097 | | * capturing the glyph under an identity matrix, so using the device matrix blows it up. |
3098 | | * What we do is replace the get_initial_matrix method for the course of the charproc |
3099 | | * accumulation *only*, and return a more sensible 'device' matrix. |
3100 | | * We know that the Charproc CTM is a combination of the font point size, and the default device |
3101 | | * matrix, so we just take off the default matrix, and invert the font scaling. |
3102 | | * This will scale the linewidth nicely for us. It does mean that if we use the |
3103 | | * same font at a different size, then the width will not be 'correct', but I |
3104 | | * think this is good enough. |
3105 | | */ |
3106 | | static void pdf_type3_get_initial_matrix(gx_device * dev, gs_matrix * pmat) |
3107 | 0 | { |
3108 | 0 | gx_device_pdf *pdev = (gx_device_pdf *)dev; |
3109 | |
|
3110 | 0 | pmat->xx = pdev->charproc_ctm.xx; |
3111 | 0 | pmat->xy = pdev->charproc_ctm.xy; |
3112 | 0 | pmat->yx = pdev->charproc_ctm.yx; |
3113 | 0 | pmat->yy = pdev->charproc_ctm.yy; |
3114 | 0 | pmat->tx = 0; |
3115 | 0 | pmat->ty = 0; |
3116 | | /* FIXME: Handle error here? Or is the charproc_ctm guaranteed to be invertible? */ |
3117 | 0 | (void)gs_matrix_invert(pmat, pmat); |
3118 | 0 | gs_matrix_scale(pmat, pdev->HWResolution[0] / 72.0, pdev->HWResolution[0] / 72.0, pmat); |
3119 | 0 | } |
3120 | | |
3121 | | static int pdf_query_purge_cached_char(const gs_memory_t *mem, cached_char *cc, void *data) |
3122 | 0 | { |
3123 | 0 | cached_char *to_purge = (cached_char *)data; |
3124 | | |
3125 | |
|
3126 | 0 | if (cc->code == to_purge->code && cc_pair(cc) == cc_pair(to_purge) && |
3127 | 0 | cc->subpix_origin.x == to_purge->subpix_origin.x && |
3128 | 0 | cc->subpix_origin.y == to_purge->subpix_origin.y && |
3129 | 0 | cc->wmode == to_purge->wmode && cc_depth(cc) == cc_depth(to_purge) |
3130 | 0 | ) |
3131 | 0 | return 1; |
3132 | 0 | return 0; |
3133 | 0 | } |
3134 | | |
3135 | | /* |
3136 | | * Continue processing text. This is the 'process' procedure in the text |
3137 | | * enumerator. Per the check in pdf_text_begin, we know the operation is |
3138 | | * not a charpath, but it could be anything else. |
3139 | | */ |
3140 | | int |
3141 | | pdf_text_process(gs_text_enum_t *pte) |
3142 | 0 | { |
3143 | 0 | pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte; |
3144 | 0 | uint operation = pte->text.operation; |
3145 | 0 | uint size = pte->text.size - pte->index; |
3146 | 0 | gs_text_enum_t *pte_default; |
3147 | 0 | PROCESS_TEXT_PROC((*process)); |
3148 | 0 | int code = 0, early_accumulator = 0; |
3149 | 0 | gx_device_pdf *pdev = (gx_device_pdf *)penum->dev; |
3150 | 0 | uint captured_pte_index = 0xFFFFFFFF; |
3151 | 0 | #define BUF_SIZE 100 /* arbitrary > 0 */ |
3152 | | /* Use a union to ensure alignment. */ |
3153 | 0 | union bu_ { |
3154 | 0 | byte bytes[BUF_SIZE]; |
3155 | 0 | gs_char chars[BUF_SIZE / sizeof(gs_char)]; |
3156 | 0 | gs_glyph glyphs[BUF_SIZE / sizeof(gs_glyph)]; |
3157 | 0 | } buf; |
3158 | |
|
3159 | 0 | if (!penum->pte_default) { |
3160 | | /* Don't need to sync before exiting charproc. */ |
3161 | 0 | code = pdf_prepare_text_drawing(pdev, pte); |
3162 | 0 | if (code == gs_error_rangecheck) { |
3163 | | /* Fallback to the default implermentation for handling |
3164 | | a transparency with CompatibilityLevel<=1.3 . */ |
3165 | 0 | goto default_impl; |
3166 | 0 | } |
3167 | 0 | if (code < 0) |
3168 | 0 | return code; |
3169 | 0 | } |
3170 | 0 | if (!penum->pte_default) { |
3171 | 0 | pdev->charproc_just_accumulated = false; |
3172 | 0 | if (penum->cdevproc_callout) { |
3173 | | /* Restore after TEXT_PROCESS_CDEVPROC in scan_cmap_text. */ |
3174 | 0 | penum->current_font = penum->orig_font; |
3175 | 0 | } |
3176 | 0 | } |
3177 | 0 | if ((penum->current_font->FontType == ft_user_defined || |
3178 | 0 | penum->current_font->FontType == ft_PCL_user_defined || |
3179 | 0 | penum->current_font->FontType == ft_PDF_user_defined || |
3180 | 0 | penum->current_font->FontType == ft_MicroType || |
3181 | 0 | penum->current_font->FontType == ft_GL2_stick_user_defined || |
3182 | 0 | penum->current_font->FontType == ft_GL2_531) && |
3183 | 0 | (penum->text.operation & TEXT_DO_ANY_CHARPATH) |
3184 | 0 | && !pdev->type3charpath) { |
3185 | 0 | pdev->type3charpath = true; |
3186 | 0 | if (!penum->charproc_accum) |
3187 | 0 | goto default_impl; |
3188 | 0 | } |
3189 | | |
3190 | 0 | code = -1; /* to force default implementation */ |
3191 | | |
3192 | | /* |
3193 | | * If we fell back to the default implementation, continue using it. |
3194 | | */ |
3195 | 0 | top: |
3196 | 0 | pte_default = penum->pte_default; |
3197 | | /* pte_default is a signal that we can't handle the glyph in the current |
3198 | | * font 'natively'. This means either a type 3 font (for PostScript we |
3199 | | * need to return to the PS interpreter to run the BuildChar), or a font |
3200 | | * type we can't or don't support in PDF. In the latter case we have the |
3201 | | * BuildChar render the glyph and store it in the cache, spot the usage |
3202 | | * in the pdfwrite image routine and we store the resluting bitmap in a |
3203 | | * Type 3 font. NB if the glyph is uncached then it just ends up in the |
3204 | | * output as a bitmap image. |
3205 | | */ |
3206 | 0 | if (pte_default) { |
3207 | 0 | gs_char *cdata; |
3208 | |
|
3209 | 0 | cdata = (gs_char *)pte->text.data.chars; |
3210 | 0 | if (penum->charproc_accum) { |
3211 | | /* We've been accumulating a Type 3 CharProc, so now we need to |
3212 | | * finish off and store it in the font. |
3213 | | */ |
3214 | 0 | code = complete_charproc(pdev, pte, pte_default, penum, true); |
3215 | 0 | if (code < 0) |
3216 | 0 | return code; |
3217 | | /* Record the current index of the text, this is the index for which we captured |
3218 | | * this charproc. We use this below to determine whether an error return is an |
3219 | | * error after we've already captured a CharProc. If it is, then we must not |
3220 | | * attempt to capture it again, this wil lead to an infinite loop. |
3221 | | */ |
3222 | 0 | captured_pte_index = pte->index; |
3223 | 0 | if (!pdev->type3charpath) |
3224 | 0 | goto top; |
3225 | 0 | else |
3226 | 0 | goto default_impl; |
3227 | 0 | } |
3228 | | |
3229 | 0 | if ((penum->current_font->FontType == ft_GL2_stick_user_defined || |
3230 | 0 | penum->current_font->FontType == ft_GL2_531 || penum->current_font->FontType == ft_MicroType) |
3231 | 0 | && operation & TEXT_FROM_CHARS && !pdev->type3charpath) { |
3232 | | /* Check for anamorphic sacling, we msut not cache stick font |
3233 | | * in this case, as the stroke width will vary with the scaling. |
3234 | | */ |
3235 | | |
3236 | | /* To test the scaling we'll map two unit vectors, calculate the |
3237 | | * length of the transformed vectors and see if they are the same |
3238 | | * x' = ax + cy + Tx |
3239 | | * y' = bx + dy + Ty |
3240 | | * We set Tx and Ty to zero (we only care about scale not translation) |
3241 | | * We then test 0,0->0,1 and 0,0 -> 1,0. Because one term is always 0 |
3242 | | * this means we can simplify the math. |
3243 | | */ |
3244 | | /* Vector 0,0 -> 0,1 x is always 0, Tx and Ty are 0 => |
3245 | | * x' = cy = c |
3246 | | * y' = dy = d |
3247 | | */ |
3248 | | /* Vector 0,0 -> 1,0 y is always 0, Tx and Ty are 0 => |
3249 | | * x' = ax = a |
3250 | | * y' = bx = b |
3251 | | */ |
3252 | | /* Length of hypotenuse squared = sum of squares We don't care |
3253 | | * about the length's actual magnitude, so we can compare the |
3254 | | * squared length |
3255 | | */ |
3256 | 0 | float x0y1, x1y0; |
3257 | |
|
3258 | 0 | x0y1 = (penum->pgs->ctm.yx * penum->pgs->ctm.yx) + |
3259 | 0 | (penum->pgs->ctm.yy * penum->pgs->ctm.yy); |
3260 | 0 | x1y0 = (penum->pgs->ctm.xx * penum->pgs->ctm.xx) + |
3261 | 0 | (penum->pgs->ctm.xy * penum->pgs->ctm.xy); |
3262 | |
|
3263 | 0 | if (x0y1 == x1y0) |
3264 | 0 | early_accumulator = 1; |
3265 | 0 | } |
3266 | 0 | if (penum->current_font->FontType == ft_PDF_user_defined) { |
3267 | 0 | early_accumulator = 1; |
3268 | 0 | } |
3269 | 0 | if (early_accumulator) { |
3270 | 0 | if (pte->text.operation & TEXT_FROM_BYTES || pte->text.operation & TEXT_FROM_STRING || (pte->text.operation & TEXT_FROM_CHARS && cdata[pte->index] <= 255)) { |
3271 | | /* The enumerator is created in pdf_default_text_begin and *is* |
3272 | | * a show enumerator, so this is safe. We need to update the |
3273 | | * graphics state pointer below which is why we need this. |
3274 | | */ |
3275 | 0 | gs_show_enum psenum = *(gs_show_enum *)pte_default; |
3276 | 0 | gs_gstate *pgs = (gs_gstate *)penum->pgs; |
3277 | 0 | gs_text_enum_procs_t special_procs = *pte_default->procs; |
3278 | 0 | void (*save_proc)(gx_device *, gs_matrix *) = pdev->procs.get_initial_matrix; |
3279 | 0 | gs_matrix m, savem; |
3280 | |
|
3281 | 0 | special_procs.set_cache = pdf_text_set_cache; |
3282 | 0 | pte_default->procs = &special_procs; |
3283 | |
|
3284 | 0 | { |
3285 | | /* We should not come here if we already have a cached character (except for the special case |
3286 | | * of redefined characters in PCL downloaded fonts). If we do, it means that we are doing |
3287 | | * 'page bursting', ie each page is going to a separate file, and the cache has an entry |
3288 | | * from previous pages, but the PDF font resource doesn't. So empty the cached character |
3289 | | * from the cache, to ensure the character description gets executed. |
3290 | | */ |
3291 | 0 | gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font); |
3292 | 0 | gs_font *pfont = (pte->fstack.depth < 0 ? pte->current_font : |
3293 | 0 | pte->fstack.items[pte->fstack.depth].font); |
3294 | 0 | int wmode = rfont->WMode; |
3295 | 0 | gs_log2_scale_point log2_scale = {0,0}; |
3296 | 0 | gs_fixed_point subpix_origin = {0,0}; |
3297 | 0 | cached_fm_pair *pair; |
3298 | 0 | cached_char *cc; |
3299 | |
|
3300 | 0 | code = gx_lookup_fm_pair(pfont, &ctm_only(pte->pgs), &log2_scale, false, &pair); |
3301 | 0 | if (code < 0) |
3302 | 0 | return code; |
3303 | 0 | cc = gx_lookup_cached_char(pfont, pair, pte_default->text.data.chars[pte_default->index], wmode, 1, &subpix_origin); |
3304 | 0 | if (cc != 0) { |
3305 | 0 | gx_purge_selected_cached_chars(pfont->dir, pdf_query_purge_cached_char, (void *)cc); |
3306 | 0 | } |
3307 | 0 | } |
3308 | | /* charproc completion will restore a gstate */ |
3309 | 0 | gs_gsave(pgs); |
3310 | | /* Assigning the gs_gstate pointer to the graphics state pointer |
3311 | | * makes sure that when we make the CTM into the identity it |
3312 | | * affects both. |
3313 | | */ |
3314 | 0 | psenum.pgs = (gs_gstate *)psenum.pgs; |
3315 | | /* Save the current FontMatrix */ |
3316 | 0 | savem = pgs->font->FontMatrix; |
3317 | | /* Make the FontMatrix the identity otherwise we will apply |
3318 | | * it twice, once in the glyph description and again in the |
3319 | | * text matrix. |
3320 | | */ |
3321 | 0 | gs_make_identity(&m); |
3322 | 0 | pgs->font->FontMatrix = m; |
3323 | |
|
3324 | 0 | pgs->char_tm_valid = 0; |
3325 | 0 | pgs->char_tm.txy_fixed_valid = 0; |
3326 | 0 | pgs->current_point.x = pgs->current_point.y = 0; |
3327 | 0 | pgs->char_tm.txy_fixed_valid = 0; |
3328 | |
|
3329 | 0 | if (pte->text.operation & TEXT_FROM_CHARS) |
3330 | 0 | pte_default->returned.current_char = penum->returned.current_char = |
3331 | 0 | pte->text.data.chars[pte->index]; |
3332 | 0 | else |
3333 | 0 | pte_default->returned.current_char = penum->returned.current_char = |
3334 | 0 | pte->text.data.bytes[pte->index]; |
3335 | |
|
3336 | 0 | code = install_charproc_accumulator(pdev, pte, pte_default, penum); |
3337 | 0 | if (code < 0) { |
3338 | 0 | gs_grestore(pgs); |
3339 | 0 | pgs->font->FontMatrix = savem; |
3340 | 0 | return code; |
3341 | 0 | } |
3342 | | |
3343 | | /* We can't capture more than one glyph at a time, so amek this one |
3344 | | * otherwise the gs_text_process would try to render all the glyphs |
3345 | | * in the string. |
3346 | | */ |
3347 | 0 | if (pte->text.size != 1) |
3348 | 0 | pte_default->text.size = pte->index + 1; |
3349 | | /* We need a special 'initial matrix' method for stick fonts, |
3350 | | * See pdf_type3_get_initial_matrix above. |
3351 | | */ |
3352 | 0 | pdev->procs.get_initial_matrix = pdf_type3_get_initial_matrix; |
3353 | |
|
3354 | 0 | pdev->pte = (gs_text_enum_t *)penum; /* CAUTION: See comment in gdevpdfx.h . */ |
3355 | 0 | code = gs_text_process(pte_default); |
3356 | 0 | if (code < 0) { |
3357 | 0 | (void)complete_charproc(pdev, pte, pte_default, penum, false); |
3358 | 0 | gs_grestore(pgs); |
3359 | 0 | return code; |
3360 | 0 | } |
3361 | 0 | pdev->pte = NULL; /* CAUTION: See comment in gdevpdfx.h . */ |
3362 | 0 | pdev->charproc_just_accumulated = false; |
3363 | | |
3364 | | /* Restore the saved FontMatrix, so that it gets applied |
3365 | | * as part of the text matrix |
3366 | | */ |
3367 | 0 | pgs->font->FontMatrix = savem; |
3368 | | /* Restore the default 'initial matrix' mathod. */ |
3369 | 0 | pdev->procs.get_initial_matrix = save_proc; |
3370 | 0 | penum->returned.current_char = pte_default->returned.current_char; |
3371 | 0 | penum->returned.current_glyph = pte_default->returned.current_glyph; |
3372 | 0 | code = pdf_choose_output_char_code(pdev, penum, &penum->output_char_code); |
3373 | 0 | if (code < 0) { |
3374 | 0 | (void)complete_charproc(pdev, pte, pte_default, penum, false); |
3375 | 0 | gs_grestore(pgs); |
3376 | 0 | return code; |
3377 | 0 | } |
3378 | | |
3379 | | /* complete_charproc will release the text enumerator 'pte_default', we assume |
3380 | | * that we are holding the only reference to it. Note that complete_charproc |
3381 | | * also sets penum->pte_default to 0, so that we don't re-entre this section of |
3382 | | * code but process the text normally, now that we have captured the glyph description. |
3383 | | */ |
3384 | 0 | code = complete_charproc(pdev, pte, pte_default, penum, false); |
3385 | 0 | if (penum->current_font->FontType == ft_PCL_user_defined) |
3386 | 0 | { |
3387 | | /* PCL bitmap fonts can have glyphs 'reused'. We can't handle |
3388 | | * handle this in a single PDF font, so we need to know when |
3389 | | * it has happened and fall back to the 'default' implementation. |
3390 | | * In order to do this, we create a cached character representation |
3391 | | * and add it to the cache. If the glyph is reused then the |
3392 | | * act of redefining it will remove this entry from the cache. |
3393 | | * We check if the glyph is in the cache in process_text_return_width |
3394 | | * and come back into this code. In the test above for PCL bitmap |
3395 | | * fonts we also check to see if the PDF font already has a |
3396 | | *'used' entry. If it does we know that its a redefinition, and |
3397 | | * we don't try to capture the glyph. |
3398 | | */ |
3399 | 0 | cached_char *cc; |
3400 | 0 | cached_fm_pair *pair; |
3401 | 0 | gs_log2_scale_point log2_scale = {0,0}; |
3402 | 0 | gs_font *rfont = (pte->fstack.depth < 0 ? pte->current_font : pte->fstack.items[0].font); |
3403 | 0 | int wmode = rfont->WMode; |
3404 | 0 | pdf_font_resource_t *pdfont; |
3405 | | |
3406 | | /* This code copied from show_cache_setup */ |
3407 | 0 | gs_memory_t *mem = penum->memory; |
3408 | 0 | gx_device_memory *dev = |
3409 | 0 | gs_alloc_struct(mem, gx_device_memory, &st_device_memory, |
3410 | 0 | "show_cache_setup(dev_cache)"); |
3411 | |
|
3412 | 0 | if (dev == 0) { |
3413 | 0 | gs_free_object(mem, dev, "show_cache_setup(dev_cache)"); |
3414 | 0 | return_error(gs_error_VMerror); |
3415 | 0 | } |
3416 | 0 | gs_make_mem_mono_device(dev, mem, penum->dev); |
3417 | 0 | dev->HWResolution[0] = pgs->device->HWResolution[0]; |
3418 | 0 | dev->HWResolution[1] = pgs->device->HWResolution[1]; |
3419 | | /* Retain these devices. */ |
3420 | 0 | gx_device_retain((gx_device *)dev, true); |
3421 | | /* end of code copied from show_cache_setup */ |
3422 | | |
3423 | | /* This copied from set_cache */ |
3424 | 0 | code = gx_alloc_char_bits(pte->current_font->dir, dev, NULL, |
3425 | 0 | 0, 0, &log2_scale, 1, &cc); |
3426 | 0 | if (code < 0) |
3427 | 0 | return code; |
3428 | | |
3429 | | /* The following code is copied from show_update, case sws_cache */ |
3430 | 0 | code = gx_lookup_fm_pair(pte->current_font, &ctm_only(pte->pgs), |
3431 | 0 | &log2_scale, false, &pair); |
3432 | 0 | if (code < 0) |
3433 | 0 | return code; |
3434 | | |
3435 | | /* These members of the cached character are required |
3436 | | * in order to find the cache entry later |
3437 | | */ |
3438 | 0 | cc->code = penum->returned.current_char; |
3439 | 0 | cc->wmode = wmode; |
3440 | 0 | cc->subpix_origin.x = cc->subpix_origin.y = 0; |
3441 | 0 | log2_scale.x = log2_scale.y = 0; |
3442 | 0 | code = gx_add_cached_char(pte->current_font->dir, dev, |
3443 | 0 | cc, pair, &log2_scale); |
3444 | 0 | if (code < 0) |
3445 | 0 | return code; |
3446 | | /* End of code from show_update */ |
3447 | | |
3448 | | /* Finally, dispose of the device, which we don't actually need */ |
3449 | 0 | gx_device_retain((gx_device *)dev, false); |
3450 | | |
3451 | | /* Its possible for a bitmapped PCL font to not execute setcachedevice (invalid empty glyph) |
3452 | | * which means that the pdfwrite override doesn't see it, and we don't note that the |
3453 | | * glyph is 'cached' in the PDF font resource, but the 'used' flag does get set. |
3454 | | * This causes our detection some problems, so mark it 'cached' here to make sure. |
3455 | | */ |
3456 | 0 | code = pdf_attached_font_resource(pdev, (gs_font *)penum->current_font, &pdfont, NULL, NULL, NULL, NULL); |
3457 | 0 | if (code < 0) |
3458 | 0 | return code; |
3459 | | |
3460 | 0 | pdfont->u.simple.s.type3.cached[cdata[pte->index] >> 3] |= 0x80 >> (cdata[pte->index] & 7); |
3461 | 0 | } |
3462 | 0 | size = pte->text.size - pte->index; |
3463 | 0 | if (code < 0) |
3464 | 0 | return code; |
3465 | 0 | if (!pdev->type3charpath) |
3466 | 0 | goto top; |
3467 | 0 | else |
3468 | 0 | goto default_impl; |
3469 | 0 | } |
3470 | 0 | } |
3471 | | |
3472 | | /* Now we run the default text procedure to see what happens. |
3473 | | * PCL bitmap fonts and the HP/GL-2 stick font are handled above. |
3474 | | * If its a PostScript type 3 font (and some other kinds) |
3475 | | * then it will return TEXT_PROCESS_RENDER and we need to exit |
3476 | | * to the interpreter to run the glyph description. Otherwise we just |
3477 | | * run the BuildChar, and later capture the cached bitmap for incorporation |
3478 | | * into a type 3 font. Note that sometimes we will handle PCL or HP/GL-2 |
3479 | | * fonts by not capturing them above, and they will come through here. |
3480 | | * The stick font will not be captured as a font at all, just vectors |
3481 | | * stored into the content stream (for osme kinds of scale/shear), |
3482 | | * bitmap fonts will be captured in the pdfwrite image routine. These |
3483 | | * are added to a type 3 font in the same way as glyphs which need to |
3484 | | * be rendered. |
3485 | | */ |
3486 | 0 | { |
3487 | 0 | gs_show_enum *penum = (gs_show_enum *)pte_default; |
3488 | 0 | int save_can_cache = penum->can_cache; |
3489 | 0 | const gs_color_space *pcs; |
3490 | 0 | const gs_client_color *pcc; |
3491 | 0 | gs_gstate * pgs = pte->pgs; |
3492 | | |
3493 | | /* If we are using a high level pattern, we must not use the cached character, as the |
3494 | | * cache hasn't seen the pattern. So set can_cache to < 0, which prevents us consulting |
3495 | | * the cache, or storing the result in it. |
3496 | | * We actually don't want to use the cache for any Type 3 font where we're trying to |
3497 | | * capture the charproc - if we want to have a chance of capturing the charproc, we |
3498 | | * need it to execute, and not use a cache entry. |
3499 | | */ |
3500 | 0 | if (gx_hld_get_color_space_and_ccolor(pgs, (const gx_drawing_color *)pgs->color[0].dev_color, &pcs, &pcc) == pattern_color_space) |
3501 | 0 | penum->can_cache = -1; |
3502 | 0 | pdev->pte = pte_default; /* CAUTION: See comment in gdevpdfx.h . */ |
3503 | 0 | code = gs_text_process(pte_default); |
3504 | 0 | if (code < 0) |
3505 | 0 | return code; |
3506 | | |
3507 | 0 | penum->can_cache = save_can_cache; |
3508 | |
|
3509 | 0 | pdev->pte = NULL; /* CAUTION: See comment in gdevpdfx.h . */ |
3510 | 0 | pdev->charproc_just_accumulated = false; |
3511 | 0 | } |
3512 | | |
3513 | | /* If the BuildChar returned TEXT_PROCESS_RENDER then we want to try and |
3514 | | * capture this as a type 3 font, so start the accumulator now. Note |
3515 | | * that the setcachedevice handling can still abort this later. In which |
3516 | | * case we get the rendered bitmap, just as for non type 3 fonts. |
3517 | | */ |
3518 | 0 | if (code == TEXT_PROCESS_RENDER && !pdev->type3charpath) { |
3519 | 0 | int code1; |
3520 | |
|
3521 | 0 | code1 = install_PS_charproc_accumulator(pdev, pte, pte_default, penum); |
3522 | 0 | if (code1 != 0) |
3523 | 0 | return code1; |
3524 | 0 | } |
3525 | | |
3526 | 0 | gs_text_enum_copy_dynamic(pte, pte_default, true); |
3527 | 0 | if (code) |
3528 | 0 | return code; |
3529 | 0 | gs_text_release(pte_default, "pdf_text_process"); |
3530 | 0 | penum->pte_default = 0; |
3531 | 0 | if (pdev->type3charpath) |
3532 | 0 | pdev->type3charpath = false; |
3533 | 0 | return 0; |
3534 | 0 | } |
3535 | 0 | { |
3536 | 0 | gs_font *font = pte->orig_font; /* Not sure. Changed for CDevProc callout. Was pte->current_font */ |
3537 | |
|
3538 | 0 | switch (font->FontType) { |
3539 | 0 | case ft_CID_encrypted: |
3540 | 0 | case ft_CID_TrueType: |
3541 | 0 | process = process_cid_text; |
3542 | 0 | break; |
3543 | 0 | case ft_encrypted: |
3544 | 0 | case ft_encrypted2: |
3545 | 0 | case ft_TrueType: |
3546 | 0 | case ft_user_defined: |
3547 | 0 | case ft_PDF_user_defined: |
3548 | 0 | case ft_PCL_user_defined: |
3549 | 0 | case ft_MicroType: |
3550 | 0 | case ft_GL2_stick_user_defined: |
3551 | 0 | case ft_GL2_531: |
3552 | | /* The data may be either glyphs or characters. */ |
3553 | 0 | process = process_plain_text; |
3554 | 0 | break; |
3555 | 0 | case ft_composite: |
3556 | 0 | process = |
3557 | 0 | (((gs_font_type0 *)font)->data.FMapType == fmap_CMap ? |
3558 | 0 | process_cmap_text : |
3559 | 0 | process_composite_text); |
3560 | 0 | break; |
3561 | 0 | default: |
3562 | 0 | goto skip; |
3563 | 0 | } |
3564 | 0 | } |
3565 | | |
3566 | | /* |
3567 | | * We want to process the entire string in a single call, but we may |
3568 | | * need to modify it. Copy it to a buffer. Note that it may consist |
3569 | | * of bytes, gs_chars, or gs_glyphs. |
3570 | | */ |
3571 | | |
3572 | 0 | if (operation & (TEXT_FROM_STRING | TEXT_FROM_BYTES)) { |
3573 | 0 | if (size < sizeof(gs_glyph)) |
3574 | 0 | size = sizeof(gs_glyph); /* for process_cid_text */ |
3575 | 0 | } else if (operation & TEXT_FROM_CHARS) |
3576 | 0 | size *= sizeof(gs_char); |
3577 | 0 | else if (operation & TEXT_FROM_SINGLE_CHAR) |
3578 | 0 | size = sizeof(gs_char); |
3579 | 0 | else if (operation & TEXT_FROM_GLYPHS) |
3580 | 0 | size *= sizeof(gs_glyph); |
3581 | 0 | else if (operation & TEXT_FROM_SINGLE_GLYPH) |
3582 | 0 | size = sizeof(gs_glyph); |
3583 | 0 | else |
3584 | 0 | goto skip; |
3585 | | |
3586 | | /* Now that we are using the working buffer for text in composite fonts, we must make sure |
3587 | | * it is large enough. Each input character code may be promoted to a gs_glyph, in scan_cmap_text |
3588 | | * when processing a Type 0 font with a type 1 descendant font. This routine uses |
3589 | | * pdf_make_text_glyphs_table_unencoded (called from pdf_obtain_font_resource_unencoded) which |
3590 | | * also may require an identically sized buffer, so we need: |
3591 | | * num__input_characters * sizeof(gs_glyph) * 2. |
3592 | | */ |
3593 | 0 | if (pte->orig_font->FontType == ft_composite) { |
3594 | 0 | if (size < (pte->text.size - pte->index) * sizeof(gs_glyph) * 2) |
3595 | 0 | size = (pte->text.size - pte->index) * sizeof(gs_glyph) * 2; |
3596 | 0 | } |
3597 | |
|
3598 | 0 | if (size <= sizeof(buf)) { |
3599 | 0 | code = process(pte, buf.bytes, size); |
3600 | 0 | } else { |
3601 | 0 | byte *buf = gs_alloc_string(pte->memory, size, "pdf_text_process"); |
3602 | |
|
3603 | 0 | if (buf == 0) |
3604 | 0 | return_error(gs_error_VMerror); |
3605 | 0 | code = process(pte, buf, size); |
3606 | 0 | gs_free_string(pte->memory, buf, size, "pdf_text_process"); |
3607 | 0 | } |
3608 | 0 | skip: |
3609 | 0 | if (code < 0 || |
3610 | 0 | ((pte->current_font->FontType == ft_user_defined || |
3611 | 0 | pte->current_font->FontType == ft_PCL_user_defined || |
3612 | 0 | pte->current_font->FontType == ft_PDF_user_defined || |
3613 | 0 | pte->current_font->FontType == ft_MicroType || |
3614 | 0 | pte->current_font->FontType == ft_GL2_stick_user_defined || |
3615 | 0 | pte->current_font->FontType == ft_GL2_531 || |
3616 | 0 | pte->current_font->FontType == ft_TrueType) && |
3617 | 0 | code != TEXT_PROCESS_INTERVENE && |
3618 | 0 | penum->index < penum->text.size)) { |
3619 | 0 | if (code == gs_error_unregistered) /* Debug purpose only. */ |
3620 | 0 | return code; |
3621 | 0 | if (code == gs_error_VMerror) |
3622 | 0 | return code; |
3623 | 0 | if (code == gs_error_invalidfont) /* Bug 688370. */ |
3624 | 0 | return code; |
3625 | 0 | default_impl: |
3626 | | /* If we have captured a CharProc, and the current index into the |
3627 | | * text is unchanged, then the capturing a CharProc for this text still |
3628 | | * resulted in a text error. So don't try to fix it by capturing the |
3629 | | * CharProc again, this causes an endless loop. |
3630 | | */ |
3631 | 0 | if (captured_pte_index == pte->index) |
3632 | 0 | return code; |
3633 | | /* Fall back to the default implementation. */ |
3634 | 0 | code = pdf_default_text_begin(pte, &pte->text, &pte_default); |
3635 | 0 | if (code < 0) |
3636 | 0 | return code; |
3637 | 0 | penum->pte_default = pte_default; |
3638 | 0 | gs_text_enum_copy_dynamic(pte_default, pte, false); |
3639 | 0 | } |
3640 | | /* The 'process' procedure might also have set pte_default itself. */ |
3641 | 0 | if (penum->pte_default && !code) |
3642 | 0 | goto top; |
3643 | 0 | return code; |
3644 | | /* |
3645 | | * This function uses an unobvious algorithm while handling type 3 fonts. |
3646 | | * It runs 'process' to copy text until a glyph, which was not copied to |
3647 | | * output font. Then it installs pte_default and falls back to default |
3648 | | * implementation with PS interpreter callout. The callout executes |
3649 | | * BuildChar/BuildGlyph with setcachedevice. The latter calls |
3650 | | * pdf_set_charproc_attrs, which sets up an accumulator |
3651 | | * of graphic objects to a pdf_begin_resource stream. |
3652 | | * When the callout completes, pdf_text_process calls pdf_end_charproc_accum |
3653 | | * and later resumes the normal (non-default) text enumeration, repeating the |
3654 | | * the "callouted" glyph AT SECOND TIME. We can't do without the second pass |
3655 | | * becauase in the first pass the glyph widths is unknown. |
3656 | | */ |
3657 | | /* |
3658 | | * Another unobvious thing is a CDevProc callout. |
3659 | | * If 'process' returns with TEXT_PROCESS_CDEVPROC, |
3660 | | * an interpreter callout will happen, and the function will be called again |
3661 | | * with pte->cdevproc_result_valid = true. Then it restatrs with taking |
3662 | | * glyph metrics from pte->cdevproc_result instead obtaining them with |
3663 | | * font->procs.glyph_info . |
3664 | | */ |
3665 | 0 | } |