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