/src/ghostpdl/pdf/pdf_fontTT.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2019-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 | | /* code for TrueType font handling */ |
17 | | |
18 | | #include "pdf_int.h" |
19 | | #include "pdf_font.h" |
20 | | #include "pdf_fontTT.h" |
21 | | #include "pdf_font1C.h" /* OTTO support */ |
22 | | #include "pdf_font_types.h" |
23 | | #include "pdf_stack.h" |
24 | | #include "pdf_file.h" |
25 | | #include "pdf_dict.h" |
26 | | #include "pdf_array.h" |
27 | | #include "pdf_deref.h" |
28 | | #include "gxfont42.h" |
29 | | #include "gscencs.h" |
30 | | #include "gsagl.h" |
31 | | #include "gsutil.h" /* For gs_next_ids() */ |
32 | | |
33 | | enum { |
34 | | CMAP_TABLE_NONE = 0, |
35 | | CMAP_TABLE_10_PRESENT = 1, |
36 | | CMAP_TABLE_30_PRESENT = 2, |
37 | | CMAP_TABLE_31_PRESENT = 4, |
38 | | CMAP_TABLE_310_PRESENT = 8 |
39 | | }; |
40 | | |
41 | | static int |
42 | | pdfi_ttf_string_proc(gs_font_type42 * pfont, ulong offset, uint length, const byte ** pdata) |
43 | 145M | { |
44 | 145M | pdf_font_truetype *ttfont = (pdf_font_truetype *)pfont->client_data; |
45 | 145M | int code = 0; |
46 | | |
47 | 145M | if ((uint64_t)offset + length > ttfont->sfnt->length) { |
48 | 4.26M | *pdata = NULL; |
49 | 4.26M | code = gs_note_error(gs_error_invalidfont); |
50 | 4.26M | } |
51 | 141M | else { |
52 | 141M | *pdata = ttfont->sfnt->data + offset; |
53 | 141M | } |
54 | 145M | return code; |
55 | 145M | } |
56 | | |
57 | | static gs_glyph pdfi_ttf_encode_char(gs_font *pfont, gs_char chr, gs_glyph_space_t sp) |
58 | 6.99M | { |
59 | 6.99M | pdf_font_truetype *ttfont = (pdf_font_truetype *)pfont->client_data; |
60 | 6.99M | gs_glyph g = GS_NO_GLYPH; |
61 | 6.99M | uint ID; |
62 | 6.99M | int code; |
63 | | |
64 | 6.99M | if ((ttfont->descflags & 4) != 0 || sp == GLYPH_SPACE_INDEX) { |
65 | 491k | int code = pdfi_fapi_check_cmap_for_GID(pfont, (uint)chr, &ID); |
66 | 491k | if (code < 0 || ID == 0) |
67 | 173k | code = pdfi_fapi_check_cmap_for_GID(pfont, (uint)(chr | 0xf0 << 8), &ID); |
68 | 491k | g = (gs_glyph)ID; |
69 | 491k | } |
70 | 6.50M | else { |
71 | 6.50M | pdf_context *ctx = (pdf_context *)ttfont->ctx; |
72 | | |
73 | 6.50M | if (ttfont->Encoding != NULL) { /* safety */ |
74 | 6.50M | pdf_name *GlyphName = NULL; |
75 | 6.50M | code = pdfi_array_get(ctx, ttfont->Encoding, (uint64_t)chr, (pdf_obj **)&GlyphName); |
76 | 6.50M | if (code >= 0) { |
77 | 6.49M | code = (*ctx->get_glyph_index)(pfont, (byte *)GlyphName->data, GlyphName->length, &ID); |
78 | 6.49M | pdfi_countdown(GlyphName); |
79 | 6.49M | if (code >= 0) |
80 | 6.49M | g = (gs_glyph)ID; |
81 | 6.49M | } |
82 | 6.50M | } |
83 | 6.50M | } |
84 | | |
85 | 6.99M | return g; |
86 | 6.99M | } |
87 | | |
88 | | extern single_glyph_list_t SingleGlyphList[]; |
89 | | |
90 | | static uint pdfi_type42_get_glyph_index(gs_font_type42 *pfont, gs_glyph glyph) |
91 | 4.65M | { |
92 | 4.65M | pdf_font_truetype *ttfont = (pdf_font_truetype *)pfont->client_data; |
93 | 4.65M | uint gind = 0; |
94 | 4.65M | uint cc = 0; |
95 | 4.65M | int i, code = 0; |
96 | | |
97 | 4.65M | if ((ttfont->descflags & 4) != 0 || glyph >= GS_MIN_GLYPH_INDEX) { |
98 | 152k | gind = (uint)glyph < GS_MIN_GLYPH_INDEX ? glyph : glyph - GS_MIN_GLYPH_INDEX; |
99 | 152k | } |
100 | 4.50M | else { |
101 | 4.50M | pdf_context *ctx = (pdf_context *)ttfont->ctx; |
102 | 4.50M | gs_const_string gname; |
103 | | |
104 | 4.50M | code = (*ctx->get_glyph_name)((gs_font *)pfont, glyph, &gname); |
105 | 4.50M | if (code < 0 || gname.data == NULL) { |
106 | 0 | return (uint)glyph; |
107 | 0 | } |
108 | 4.50M | if (gname.size == 7 && gname.data[0] == '.' && strncmp((char *)gname.data, ".notdef", 7) == 0) { |
109 | 456k | return 0; /* .notdef is GID 0, so short cut the rest of the function */ |
110 | 456k | } |
111 | | |
112 | 4.05M | if (ttfont->cmap == pdfi_truetype_cmap_10) { |
113 | 343k | gs_string postname = {0}; |
114 | 343k | gs_glyph g; |
115 | | |
116 | 343k | g = gs_c_name_glyph((const byte *)gname.data, gname.size); |
117 | 343k | if (g != GS_NO_GLYPH) { |
118 | 343k | g = (gs_glyph)gs_c_decode(g, ENCODING_INDEX_MACROMAN); |
119 | 343k | } |
120 | 0 | else { |
121 | 0 | g = GS_NO_CHAR; |
122 | 0 | } |
123 | | |
124 | 343k | if (g != GS_NO_CHAR) { |
125 | 342k | code = pdfi_fapi_check_cmap_for_GID((gs_font *)pfont, (uint)g, &cc); |
126 | 342k | } |
127 | | |
128 | 343k | if (code < 0 || cc == 0) { |
129 | | /* This is a very slow implementation, we may benefit from creating a |
130 | | * a reverse post table upfront */ |
131 | 28.7M | for (i = 0; i < pfont->data.numGlyphs; i++) { |
132 | 28.4M | code = gs_type42_find_post_name(pfont, (gs_glyph)i, &postname); |
133 | 28.4M | if (code >= 0) { |
134 | 2.23M | if (gname.data[0] == postname.data[0] |
135 | 2.23M | && gname.size == postname.size |
136 | 2.23M | && !strncmp((char *)gname.data, (char *)postname.data, postname.size)) |
137 | 4.62k | { |
138 | 4.62k | cc = i; |
139 | 4.62k | break; |
140 | 4.62k | } |
141 | 2.23M | } |
142 | 28.4M | } |
143 | 260k | } |
144 | 343k | } |
145 | 3.70M | else { |
146 | | /* In theory, this should be 3,1 cmap, but we have examples that use 0,1 or other |
147 | | Unicode "platform" cmap tables, so "hail mary" just try it |
148 | | */ |
149 | 3.70M | single_glyph_list_t *sgl = (single_glyph_list_t *)&(SingleGlyphList); |
150 | | /* Not to spec, but... if we get a "uni..." formatted name, use |
151 | | the hex value from that. |
152 | | */ |
153 | 3.70M | if (gname.size > 5 && !strncmp((char *)gname.data, "uni", 3)) { |
154 | 8.37k | char gnbuf[64]; |
155 | 8.37k | int l = (gname.size - 3) > 63 ? 63 : gname.size - 3; |
156 | | |
157 | 8.37k | memcpy(gnbuf, gname.data + 3, l); |
158 | 8.37k | gnbuf[l] = '\0'; |
159 | 8.37k | l = sscanf(gnbuf, "%x", &gind); |
160 | 8.37k | if (l > 0) |
161 | 8.37k | (void)pdfi_fapi_check_cmap_for_GID((gs_font *)pfont, (uint)gind, &cc); |
162 | 0 | else |
163 | 0 | cc = 0; |
164 | 8.37k | } |
165 | 3.69M | else { |
166 | | /* Slow linear search */ |
167 | 6.83G | for (i = 0; sgl->Glyph != 0x00; i++) { |
168 | 6.83G | if (sgl->Glyph[0] == gname.data[0] |
169 | 6.83G | && strlen(sgl->Glyph) == gname.size |
170 | 6.83G | && !strncmp((char *)sgl->Glyph, (char *)gname.data, gname.size)) |
171 | 3.69M | break; |
172 | 6.83G | sgl++; |
173 | 6.83G | } |
174 | 3.69M | if (sgl->Glyph != NULL) { |
175 | 3.69M | code = pdfi_fapi_check_cmap_for_GID((gs_font *)pfont, (uint)sgl->Unicode, &cc); |
176 | 3.69M | if (code < 0 || cc == 0) |
177 | 2.19M | cc = 0; |
178 | 3.69M | } |
179 | 12 | else |
180 | 12 | cc = 0; |
181 | | |
182 | 3.69M | if (cc == 0) { |
183 | 2.19M | gs_string postname = {0}; |
184 | | |
185 | | /* This is a very slow implementation, we may benefit from creating a |
186 | | * a reverse post table upfront */ |
187 | 3.33G | for (i = 0; i < pfont->data.numGlyphs; i++) { |
188 | 3.33G | code = gs_type42_find_post_name(pfont, (gs_glyph)i, &postname); |
189 | 3.33G | if (code >= 0) { |
190 | 185k | if (postname.data[0] == gname.data[0] |
191 | 185k | && postname.size == gname.size |
192 | 185k | && !strncmp((char *)postname.data, (char *)gname.data, gname.size)) |
193 | 825 | { |
194 | 825 | cc = i; |
195 | 825 | break; |
196 | 825 | } |
197 | 185k | } |
198 | 3.33G | } |
199 | 2.19M | } |
200 | 3.69M | } |
201 | 3.70M | } |
202 | 4.05M | gind = cc; |
203 | 4.05M | } |
204 | 4.20M | return gind; |
205 | 4.65M | } |
206 | | |
207 | | static int |
208 | | pdfi_ttf_enumerate_glyph(gs_font *font, int *pindex, gs_glyph_space_t glyph_space, gs_glyph *pglyph) |
209 | 3.17M | { |
210 | 3.17M | if (glyph_space == GLYPH_SPACE_INDEX) { |
211 | 106k | return gs_type42_enumerate_glyph(font, pindex, glyph_space, pglyph); |
212 | 106k | } |
213 | 3.06M | else if (glyph_space == GLYPH_SPACE_NAME) { |
214 | 3.06M | pdf_font_truetype *ttfont = (pdf_font_truetype *)font->client_data; |
215 | | |
216 | 3.06M | if ((ttfont->descflags & 4) == 0) { |
217 | 3.06M | if (*pindex <= 0) { |
218 | 23.7k | *pindex = 0; |
219 | 23.7k | } |
220 | 3.06M | *pglyph = (*font->procs.encode_char)(font, (gs_char)*pindex, glyph_space); |
221 | 3.06M | if (*pglyph == GS_NO_GLYPH) |
222 | 11.5k | *pindex = 0; |
223 | 3.05M | else |
224 | 3.05M | (*pindex)++; |
225 | 3.06M | } |
226 | 3.06M | } |
227 | 0 | else |
228 | 0 | *pindex = 0; |
229 | 3.06M | return 0; |
230 | 3.17M | } |
231 | | |
232 | | static int pdfi_ttf_glyph_name(gs_font *pfont, gs_glyph glyph, gs_const_string * pstr) |
233 | 787k | { |
234 | 787k | pdf_font_truetype *ttfont = (pdf_font_truetype *)pfont->client_data; |
235 | 787k | pdf_context *ctx = (pdf_context *)ttfont->ctx; |
236 | 787k | uint ID = 0; |
237 | 787k | int code = -1; |
238 | | |
239 | 787k | if (glyph >= GS_MIN_GLYPH_INDEX) |
240 | 320 | glyph -= GS_MIN_GLYPH_INDEX; |
241 | | |
242 | 787k | if ((ttfont->descflags & 4) != 0) { |
243 | 6.01k | code = gs_type42_find_post_name((gs_font_type42 *)pfont, glyph, (gs_string *)pstr); |
244 | 6.01k | if (code < 0) { |
245 | 5.87k | char buf[64]; |
246 | 5.87k | int l; |
247 | 5.87k | l = gs_snprintf(buf, sizeof(buf), "~gs~gName~%04x", (uint)glyph); |
248 | 5.87k | code = (*ctx->get_glyph_index)(pfont, (byte *)buf, l, &ID); |
249 | 5.87k | } |
250 | 139 | else { |
251 | 139 | code = (*ctx->get_glyph_index)(pfont, (byte *)pstr->data, pstr->size, &ID); |
252 | 139 | } |
253 | 6.01k | if (code < 0) |
254 | 0 | return -1; /* No name, trigger pdfwrite Type 3 fallback */ |
255 | | |
256 | 6.01k | code = (*ctx->get_glyph_name)(pfont, (gs_glyph)ID, pstr); |
257 | 6.01k | if (code < 0) |
258 | 0 | return -1; /* No name, trigger pdfwrite Type 3 fallback */ |
259 | 6.01k | } |
260 | 781k | else { |
261 | 781k | code = (*ctx->get_glyph_name)(pfont, glyph, pstr); |
262 | 781k | if (code < 0) |
263 | 0 | return -1; /* No name, trigger pdfwrite Type 3 fallback */ |
264 | 781k | } |
265 | 787k | return code; |
266 | | |
267 | 787k | } |
268 | | |
269 | | static int |
270 | | pdfi_alloc_tt_font(pdf_context *ctx, pdf_font_truetype **font, bool is_cid) |
271 | 16.8k | { |
272 | 16.8k | pdf_font_truetype *ttfont = NULL; |
273 | 16.8k | gs_font_type42 *pfont = NULL; |
274 | | |
275 | 16.8k | ttfont = (pdf_font_truetype *)gs_alloc_bytes(ctx->memory, sizeof(pdf_font_truetype), "pdfi (truetype pdf_font)"); |
276 | 16.8k | if (ttfont == NULL) |
277 | 0 | return_error(gs_error_VMerror); |
278 | | |
279 | 16.8k | memset(ttfont, 0x00, sizeof(pdf_font_truetype)); |
280 | 16.8k | ttfont->type = PDF_FONT; |
281 | 16.8k | ttfont->ctx = ctx; |
282 | 16.8k | ttfont->pdfi_font_type = e_pdf_font_truetype; |
283 | | |
284 | | #if REFCNT_DEBUG |
285 | | ttfont->UID = ctx->UID++; |
286 | | dmprintf2(ctx->memory, "Allocated object of type %c with UID %"PRIi64"\n", ttfont->type, ttfont->UID); |
287 | | #endif |
288 | | |
289 | 16.8k | pdfi_countup(ttfont); |
290 | | |
291 | 16.8k | pfont = (gs_font_type42 *)gs_alloc_struct(ctx->memory, gs_font_type42, &st_gs_font_type42, |
292 | 16.8k | "pdfi (truetype pfont)"); |
293 | 16.8k | if (pfont == NULL) { |
294 | 0 | pdfi_countdown(ttfont); |
295 | 0 | return_error(gs_error_VMerror); |
296 | 0 | } |
297 | 16.8k | memset(pfont, 0x00, sizeof(gs_font_type42)); |
298 | | |
299 | 16.8k | ttfont->pfont = (gs_font_base *)pfont; |
300 | | |
301 | 16.8k | gs_make_identity(&pfont->orig_FontMatrix); |
302 | 16.8k | gs_make_identity(&pfont->FontMatrix); |
303 | 16.8k | pfont->next = pfont->prev = 0; |
304 | 16.8k | pfont->memory = ctx->memory; |
305 | 16.8k | pfont->dir = ctx->font_dir; |
306 | 16.8k | pfont->is_resource = false; |
307 | 16.8k | gs_notify_init(&pfont->notify_list, ctx->memory); |
308 | 16.8k | pfont->base = (gs_font *) ttfont->pfont; |
309 | 16.8k | pfont->client_data = ttfont; |
310 | 16.8k | pfont->WMode = 0; |
311 | 16.8k | pfont->PaintType = 0; |
312 | 16.8k | pfont->StrokeWidth = 0; |
313 | 16.8k | pfont->is_cached = 0; |
314 | 16.8k | pfont->FAPI = NULL; |
315 | 16.8k | pfont->FAPI_font_data = NULL; |
316 | 16.8k | pfont->procs.init_fstack = gs_default_init_fstack; |
317 | 16.8k | pfont->procs.next_char_glyph = gs_default_next_char_glyph; |
318 | 16.8k | pfont->FontType = ft_TrueType; |
319 | 16.8k | pfont->ExactSize = fbit_use_outlines; |
320 | 16.8k | pfont->InBetweenSize = fbit_use_outlines; |
321 | 16.8k | pfont->TransformedChar = fbit_use_outlines; |
322 | | /* We may want to do something clever with an XUID here */ |
323 | 16.8k | pfont->id = gs_next_ids(ctx->memory, 1); |
324 | 16.8k | uid_set_UniqueID(&pfont->UID, pfont->id); |
325 | | /* The buildchar proc will be filled in by FAPI - |
326 | | we won't worry about working without FAPI */ |
327 | 16.8k | pfont->procs.encode_char = pdfi_ttf_encode_char; |
328 | 16.8k | pfont->data.string_proc = pdfi_ttf_string_proc; |
329 | 16.8k | pfont->procs.glyph_name = pdfi_ttf_glyph_name; |
330 | 16.8k | pfont->procs.decode_glyph = pdfi_decode_glyph; |
331 | 16.8k | pfont->procs.define_font = gs_no_define_font; |
332 | 16.8k | pfont->procs.make_font = gs_no_make_font; |
333 | 16.8k | pfont->procs.font_info = gs_default_font_info; |
334 | 16.8k | pfont->procs.glyph_info = gs_default_glyph_info; |
335 | 16.8k | pfont->procs.glyph_outline = gs_no_glyph_outline; |
336 | 16.8k | pfont->procs.build_char = NULL; |
337 | 16.8k | pfont->procs.same_font = gs_default_same_font; |
338 | 16.8k | pfont->procs.enumerate_glyph = gs_no_enumerate_glyph; |
339 | | |
340 | 16.8k | pfont->encoding_index = -1; /****** WRONG ******/ |
341 | 16.8k | pfont->nearest_encoding_index = -1; /****** WRONG ******/ |
342 | | |
343 | 16.8k | pfont->client_data = (void *)ttfont; |
344 | | |
345 | 16.8k | *font = ttfont; |
346 | 16.8k | return 0; |
347 | 16.8k | } |
348 | | |
349 | | static int pdfi_set_type42_data_procs(gs_font_type42 *pfont) |
350 | 13.5k | { |
351 | 13.5k | pfont->data.get_glyph_index = pdfi_type42_get_glyph_index; |
352 | 13.5k | pfont->procs.enumerate_glyph = pdfi_ttf_enumerate_glyph; |
353 | 13.5k | return 0; |
354 | 13.5k | } |
355 | | |
356 | | int pdfi_read_truetype_font(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *stream_dict, pdf_dict *page_dict, byte *buf, int64_t buflen, int findex, pdf_font **ppdffont) |
357 | 16.8k | { |
358 | 16.8k | pdf_font_truetype *font = NULL; |
359 | 16.8k | int code = 0, i; |
360 | 16.8k | pdf_obj *fontdesc = NULL; |
361 | 16.8k | pdf_obj *obj = NULL; |
362 | 16.8k | pdf_obj *basefont = NULL; |
363 | 16.8k | int64_t descflags; |
364 | 16.8k | bool encoding_known = false; |
365 | 16.8k | bool forced_symbolic = false; |
366 | 16.8k | pdf_obj *tounicode = NULL; |
367 | | |
368 | 16.8k | if (ppdffont == NULL) |
369 | 0 | return_error(gs_error_invalidaccess); |
370 | | |
371 | 16.8k | *ppdffont = NULL; |
372 | | |
373 | 16.8k | if (font_dict != NULL) |
374 | 16.8k | (void)pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, &fontdesc); |
375 | | |
376 | 16.8k | if ((code = pdfi_alloc_tt_font(ctx, &font, false)) < 0) { |
377 | 0 | code = gs_note_error(gs_error_invalidfont); |
378 | 0 | goto error; |
379 | 0 | } |
380 | 16.8k | if (font_dict != NULL) { |
381 | 16.8k | font->object_num = font_dict->object_num; |
382 | 16.8k | font->generation_num = font_dict->generation_num; |
383 | 16.8k | font->indirect_num = font_dict->indirect_num; |
384 | 16.8k | font->indirect_gen = font_dict->indirect_gen; |
385 | 16.8k | } |
386 | | |
387 | 16.8k | font->FontDescriptor = (pdf_dict *)fontdesc; |
388 | 16.8k | fontdesc = NULL; |
389 | | |
390 | 16.8k | pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)font); |
391 | | |
392 | 16.8k | code = pdfi_object_alloc(ctx, PDF_BUFFER, 0, (pdf_obj **)&font->sfnt); |
393 | 16.8k | if (code < 0) { |
394 | 0 | goto error; |
395 | 0 | } |
396 | 16.8k | pdfi_countup(font->sfnt); |
397 | 16.8k | code = pdfi_buffer_set_data((pdf_obj *)font->sfnt, buf, buflen); |
398 | 16.8k | if (code < 0) { |
399 | 0 | goto error; |
400 | 0 | } |
401 | 16.8k | buf = NULL; |
402 | | |
403 | | /* Strictly speaking BaseFont is required, but we can continue without one */ |
404 | 16.8k | if (font_dict != NULL) { |
405 | 16.8k | code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, (pdf_obj **)&basefont); |
406 | 16.8k | if (code > 0) { |
407 | 16.7k | pdf_name *nobj = (pdf_name *)basefont; |
408 | 16.7k | int nlen = nobj->length > gs_font_name_max ? gs_font_name_max : nobj->length; |
409 | | |
410 | 16.7k | memcpy(font->pfont->key_name.chars, nobj->data, nlen); |
411 | 16.7k | font->pfont->key_name.chars[nlen] = 0; |
412 | 16.7k | font->pfont->key_name.size = nlen; |
413 | 16.7k | memcpy(font->pfont->font_name.chars, nobj->data, nlen); |
414 | 16.7k | font->pfont->font_name.chars[nlen] = 0; |
415 | 16.7k | font->pfont->font_name.size = nlen; |
416 | 16.7k | pdfi_countdown(obj); |
417 | 16.7k | obj = NULL; |
418 | 16.7k | } |
419 | 16.8k | } |
420 | 16.8k | font->BaseFont = basefont; |
421 | 16.8k | basefont = NULL; |
422 | 16.8k | font->PDF_font = font_dict; |
423 | 16.8k | pdfi_countup(font_dict); |
424 | | |
425 | | /* ignore errors with widths... for now */ |
426 | 16.8k | if (font_dict != NULL) |
427 | 16.8k | (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)font, 0.001); |
428 | | |
429 | 16.8k | if (ctx->args.ignoretounicode != true && font_dict != NULL) { |
430 | 16.8k | code = pdfi_dict_get(ctx, font_dict, "ToUnicode", (pdf_obj **)&tounicode); |
431 | 16.8k | if (code >= 0 && pdfi_type_of(tounicode) == PDF_STREAM) { |
432 | 3.78k | pdf_cmap *tu = NULL; |
433 | 3.78k | code = pdfi_read_cmap(ctx, tounicode, &tu); |
434 | 3.78k | pdfi_countdown(tounicode); |
435 | 3.78k | tounicode = (pdf_obj *)tu; |
436 | 3.78k | } |
437 | 16.8k | if (code < 0 || (tounicode != NULL && pdfi_type_of(tounicode) != PDF_CMAP)) { |
438 | 13.1k | pdfi_countdown(tounicode); |
439 | 13.1k | tounicode = NULL; |
440 | 13.1k | code = 0; |
441 | 13.1k | } |
442 | 16.8k | } |
443 | 0 | else { |
444 | 0 | tounicode = NULL; |
445 | 0 | } |
446 | 16.8k | font->ToUnicode = tounicode; |
447 | 16.8k | tounicode = NULL; |
448 | | |
449 | 16.8k | if (font->FontDescriptor != NULL) { |
450 | 16.8k | code = pdfi_dict_get_int(ctx, font->FontDescriptor, "Flags", &descflags); |
451 | 16.8k | if (code < 0) |
452 | 4 | descflags = 0; |
453 | 16.8k | } |
454 | 0 | else { |
455 | 0 | descflags = 0; |
456 | 0 | } |
457 | | |
458 | 16.8k | if (font_dict != NULL) |
459 | 16.8k | code = pdfi_dict_get(ctx, font_dict, "Encoding", &obj); |
460 | 0 | else |
461 | 0 | code = gs_error_undefined; |
462 | | |
463 | 16.8k | if (code < 0) { |
464 | 1.26k | static const char encstr[] = "WinAnsiEncoding"; |
465 | 1.26k | code = pdfi_name_alloc(ctx, (byte *)encstr, strlen(encstr), (pdf_obj **)&obj); |
466 | 1.26k | if (code >= 0) |
467 | 1.26k | pdfi_countup(obj); |
468 | 0 | else |
469 | 0 | goto error; |
470 | 1.26k | } |
471 | 15.6k | else { |
472 | 15.6k | encoding_known = true; |
473 | | /* If we have and encoding, and both the symbolic and non-symbolic flag are set, |
474 | | believe that latter. |
475 | | */ |
476 | 15.6k | if ((descflags & 32) != 0) |
477 | 15.4k | descflags = (descflags & ~4); |
478 | 15.6k | } |
479 | | |
480 | 16.8k | if ((forced_symbolic = pdfi_font_known_symbolic(font->BaseFont)) == true) { |
481 | 0 | descflags |= 4; |
482 | 0 | } |
483 | | |
484 | 16.8k | code = pdfi_create_Encoding(ctx, obj, NULL, (pdf_obj **)&font->Encoding); |
485 | | /* If we get an error, and the font is non-symbolic, return the error */ |
486 | 16.8k | if (code < 0 && (descflags & 4) == 0) |
487 | 24 | goto error; |
488 | | /* If we get an error, and the font is symbolic, pretend we never saw an /Encoding */ |
489 | 16.8k | if (code < 0) |
490 | 4 | encoding_known = false; |
491 | 16.8k | pdfi_countdown(obj); |
492 | 16.8k | obj = NULL; |
493 | | |
494 | 16.8k | code = gs_type42_font_init((gs_font_type42 *)font->pfont, 0); |
495 | 16.8k | if (code < 0) { |
496 | 3.34k | goto error; |
497 | 3.34k | } |
498 | | |
499 | 13.5k | code = pdfi_set_type42_data_procs((gs_font_type42 *)font->pfont); |
500 | 13.5k | if (code < 0) { |
501 | 0 | goto error; |
502 | 0 | } |
503 | | |
504 | | /* We're probably dead in the water without cmap tables, but make sure, for safety */ |
505 | | /* This is a horrendous morass of guesses at what Acrobat does with files that contravene |
506 | | what the spec says about symbolic fonts, cmap tables and encodings. |
507 | | */ |
508 | 13.5k | if (forced_symbolic != true && (descflags & 4) != 0 && ((gs_font_type42 *)font->pfont)->data.cmap != 0) { |
509 | 1.06k | gs_font_type42 *t42f = (gs_font_type42 *)font->pfont; |
510 | 1.06k | int numcmaps; |
511 | 1.06k | int cmaps_available = CMAP_TABLE_NONE; |
512 | 1.06k | const byte *d; |
513 | 1.06k | code = (*t42f->data.string_proc)(t42f, t42f->data.cmap + 2, 2, &d); |
514 | 1.06k | if (code < 0) |
515 | 1 | goto error; |
516 | 1.06k | numcmaps = d[1] | d[0] << 8; |
517 | 18.2k | for (i = 0; i < numcmaps; i++) { |
518 | 17.1k | code = (*t42f->data.string_proc)(t42f, t42f->data.cmap + 4 + i * 8, 4, &d); |
519 | 17.1k | if (code < 0) |
520 | 19 | goto error; |
521 | 18.4k | #define CMAP_PLAT_ENC_ID(a,b,c,d) (a << 24 | b << 16 | c << 8 | d) |
522 | 17.1k | switch(CMAP_PLAT_ENC_ID(d[0], d[1], d[2], d[3])) { |
523 | 1.00k | case CMAP_PLAT_ENC_ID(0, 1, 0, 0): |
524 | 1.00k | cmaps_available |= CMAP_TABLE_10_PRESENT; |
525 | 1.00k | break; |
526 | 256 | case CMAP_PLAT_ENC_ID(0, 3, 0, 0): |
527 | 256 | cmaps_available |= CMAP_TABLE_30_PRESENT; |
528 | 256 | break; |
529 | 18 | case CMAP_PLAT_ENC_ID(0, 3, 0, 1): |
530 | 18 | cmaps_available |= CMAP_TABLE_31_PRESENT; |
531 | 18 | break; |
532 | 0 | case CMAP_PLAT_ENC_ID(0, 3, 1, 0): |
533 | 0 | cmaps_available |= CMAP_TABLE_310_PRESENT; |
534 | 0 | break; |
535 | 15.8k | default: /* Not one we're interested in */ |
536 | 15.8k | break; |
537 | 17.1k | } |
538 | 17.1k | } |
539 | 1.04k | #undef CMAP_PLAT_ENC_ID |
540 | 1.04k | if ((cmaps_available & CMAP_TABLE_30_PRESENT) == CMAP_TABLE_30_PRESENT) { |
541 | 256 | font->descflags = descflags; |
542 | 256 | } |
543 | 791 | else if (encoding_known == true) { |
544 | 8 | static const char mrencstr[] = "MacRomanEncoding"; |
545 | 8 | static const char waencstr[] = "WinAnsiEncoding"; |
546 | 8 | const char *encstr = ((cmaps_available & CMAP_TABLE_31_PRESENT) == CMAP_TABLE_31_PRESENT) ? waencstr : mrencstr; |
547 | 8 | font->descflags = descflags & ~4; |
548 | 8 | code = pdfi_name_alloc(ctx, (byte *)encstr, strlen(encstr), (pdf_obj **)&obj); |
549 | 8 | if (code >= 0) |
550 | 8 | pdfi_countup(obj); |
551 | 0 | else |
552 | 0 | goto error; |
553 | 8 | pdfi_countdown(font->Encoding); |
554 | 8 | code = pdfi_create_Encoding(ctx, obj, NULL, (pdf_obj **)&font->Encoding); |
555 | 8 | if (code < 0) |
556 | 0 | goto error; |
557 | 8 | pdfi_countdown(obj); |
558 | 8 | obj = NULL; |
559 | 8 | } |
560 | 783 | else |
561 | 783 | font->descflags = descflags; |
562 | 1.04k | } |
563 | 12.4k | else { |
564 | 12.4k | font->descflags = descflags; |
565 | 12.4k | } |
566 | | |
567 | 13.5k | if (uid_is_XUID(&font->pfont->UID)) |
568 | 13.5k | uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); |
569 | 13.5k | uid_set_invalid(&font->pfont->UID); |
570 | | |
571 | 13.5k | code = pdfi_font_generate_pseudo_XUID(ctx, font_dict, font->pfont); |
572 | 13.5k | if (code < 0) { |
573 | 0 | goto error; |
574 | 0 | } |
575 | | |
576 | 13.5k | if ((font->descflags & 4) == 0) { |
577 | | /* Horrid hacky solution */ |
578 | | /* We don't want to draw the TTF notdef */ |
579 | 12.4k | gs_font_type42 *gst42 = ((gs_font_type42 *)font->pfont); |
580 | 12.4k | if (gst42->data.len_glyphs != NULL && gst42->data.len_glyphs[0] > 10) { |
581 | 10.3k | gst42->data.len_glyphs[0] = 0; |
582 | 10.3k | } |
583 | 12.4k | } |
584 | | |
585 | 13.5k | code = gs_definefont(ctx->font_dir, (gs_font *)font->pfont); |
586 | 13.5k | if (code < 0) { |
587 | 0 | goto error; |
588 | 0 | } |
589 | | |
590 | 13.5k | code = pdfi_fapi_passfont((pdf_font *)font, 0, NULL, NULL, font->sfnt->data, font->sfnt->length); |
591 | 13.5k | if (code < 0) { |
592 | 1.16k | goto error; |
593 | 1.16k | } |
594 | | |
595 | | /* object_num can be zero if the dictionary was defined inline */ |
596 | 12.3k | if (font->object_num != 0) { |
597 | 11.8k | (void)replace_cache_entry(ctx, (pdf_obj *)font); |
598 | 11.8k | } |
599 | | |
600 | 12.3k | *ppdffont = (pdf_font *)font; |
601 | 12.3k | return code; |
602 | 4.55k | error: |
603 | 4.55k | if (buf != NULL) |
604 | 0 | gs_free_object(ctx->memory, buf, "pdfi_read_truetype_font(buf)"); |
605 | 4.55k | pdfi_countdown(fontdesc); |
606 | 4.55k | pdfi_countdown(basefont); |
607 | 4.55k | pdfi_countdown(obj); |
608 | 4.55k | pdfi_countdown(font); |
609 | 4.55k | return code; |
610 | 13.5k | } |
611 | | |
612 | | int |
613 | | pdfi_copy_truetype_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont) |
614 | 0 | { |
615 | 0 | int code = 0; |
616 | 0 | pdf_font_truetype *font = NULL; |
617 | 0 | gs_font_type42 *spfont1 = (gs_font_type42 *) spdffont->pfont; |
618 | 0 | gs_font_type42 *dpfont42; |
619 | 0 | gs_id t_id; |
620 | 0 | pdf_obj *tmp; |
621 | |
|
622 | 0 | if (font_dict == NULL) |
623 | 0 | return_error(gs_error_invalidfont); |
624 | | |
625 | 0 | code = pdfi_alloc_tt_font(ctx, &font, font_dict->object_num); |
626 | 0 | if (code < 0) |
627 | 0 | return code; |
628 | 0 | dpfont42 = (gs_font_type42 *) font->pfont; |
629 | |
|
630 | 0 | t_id = dpfont42->id; |
631 | 0 | memcpy(dpfont42, spfont1, sizeof(gs_font_type42)); |
632 | 0 | dpfont42->id = t_id; |
633 | 0 | dpfont42->FAPI = NULL; |
634 | 0 | dpfont42->FAPI_font_data = NULL; |
635 | 0 | dpfont42->notify_list.memory = NULL; |
636 | 0 | dpfont42->notify_list.first = NULL; |
637 | 0 | gs_notify_init(&dpfont42->notify_list, dpfont42->memory); |
638 | |
|
639 | 0 | memcpy(font, spdffont, sizeof(pdf_font_truetype)); |
640 | 0 | font->refcnt = 1; |
641 | 0 | font->filename = NULL; |
642 | |
|
643 | 0 | font->pfont = (gs_font_base *)dpfont42; |
644 | 0 | dpfont42->client_data = (void *)font; |
645 | |
|
646 | 0 | font->PDF_font = font_dict; |
647 | 0 | font->object_num = font_dict->object_num; |
648 | 0 | font->generation_num = font_dict->generation_num; |
649 | 0 | pdfi_countup(font->PDF_font); |
650 | | |
651 | | /* We want basefont and descriptor, but we can live without them */ |
652 | 0 | font->BaseFont = NULL; |
653 | 0 | (void)pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &font->BaseFont); |
654 | 0 | font->FontDescriptor = NULL; |
655 | 0 | (void)pdfi_dict_knownget_type(ctx, font_dict, "FontDescriptor", PDF_DICT, (pdf_obj **)&font->FontDescriptor); |
656 | |
|
657 | 0 | pdfi_countup(font->sfnt); |
658 | |
|
659 | 0 | if (font->BaseFont != NULL && ((pdf_name *)font->BaseFont)->length <= gs_font_name_max) { |
660 | 0 | memcpy(dpfont42->key_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); |
661 | 0 | dpfont42->key_name.size = ((pdf_name *)font->BaseFont)->length; |
662 | 0 | memcpy(dpfont42->font_name.chars, ((pdf_name *)font->BaseFont)->data, ((pdf_name *)font->BaseFont)->length); |
663 | 0 | dpfont42->font_name.size = ((pdf_name *)font->BaseFont)->length; |
664 | 0 | } |
665 | |
|
666 | 0 | font->Encoding = NULL; |
667 | 0 | font->ToUnicode = NULL; |
668 | 0 | font->Widths = NULL; |
669 | |
|
670 | 0 | pdfi_font_set_first_last_char(ctx, font_dict, (pdf_font *)font); |
671 | 0 | (void)pdfi_font_create_widths(ctx, font_dict, (pdf_font*)font, (double)0.001); |
672 | |
|
673 | 0 | font->descflags = 0; |
674 | 0 | if (font->FontDescriptor != NULL) { |
675 | 0 | code = pdfi_dict_get_int(ctx, font->FontDescriptor, "Flags", &font->descflags); |
676 | 0 | if (code >= 0) { |
677 | | /* If both the symbolic and non-symbolic flag are set, |
678 | | believe that latter. |
679 | | */ |
680 | 0 | if ((font->descflags & 32) != 0) |
681 | 0 | font->descflags = (font->descflags & ~4); |
682 | 0 | } |
683 | 0 | } |
684 | |
|
685 | 0 | tmp = NULL; |
686 | 0 | code = pdfi_dict_knownget(ctx, font_dict, "Encoding", &tmp); |
687 | 0 | if (code == 1) { |
688 | 0 | if ((pdfi_type_of(tmp) == PDF_NAME || pdfi_type_of(tmp) == PDF_DICT) && (font->descflags & 4) == 0) { |
689 | 0 | code = pdfi_create_Encoding(ctx, tmp, NULL, (pdf_obj **) & font->Encoding); |
690 | 0 | } |
691 | 0 | else if (pdfi_type_of(tmp) == PDF_DICT && (font->descflags & 4) != 0) { |
692 | 0 | code = pdfi_create_Encoding(ctx, tmp, (pdf_obj *)spdffont->Encoding, (pdf_obj **) &font->Encoding); |
693 | 0 | } |
694 | 0 | else { |
695 | 0 | code = gs_error_undefined; |
696 | 0 | } |
697 | 0 | pdfi_countdown(tmp); |
698 | 0 | tmp = NULL; |
699 | 0 | } |
700 | 0 | else { |
701 | 0 | pdfi_countdown(tmp); |
702 | 0 | tmp = NULL; |
703 | 0 | code = gs_error_undefined; |
704 | 0 | } |
705 | |
|
706 | 0 | if (code < 0) { |
707 | 0 | font->Encoding = spdffont->Encoding; |
708 | 0 | pdfi_countup(font->Encoding); |
709 | 0 | } |
710 | | |
711 | | /* Since various aspects of the font may differ (widths, encoding, etc) |
712 | | we cannot reliably use the UniqueID/XUID for copied fonts. |
713 | | */ |
714 | 0 | if (uid_is_XUID(&font->pfont->UID)) |
715 | 0 | uid_free(&font->pfont->UID, font->pfont->memory, "pdfi_read_type1_font"); |
716 | 0 | uid_set_invalid(&font->pfont->UID); |
717 | |
|
718 | 0 | code = pdfi_font_generate_pseudo_XUID(ctx, font_dict, font->pfont); |
719 | 0 | if (code < 0) { |
720 | 0 | goto error; |
721 | 0 | } |
722 | | |
723 | 0 | if (ctx->args.ignoretounicode != true) { |
724 | 0 | code = pdfi_dict_get(ctx, font_dict, "ToUnicode", (pdf_obj **)&tmp); |
725 | 0 | if (code >= 0 && pdfi_type_of(tmp) == PDF_STREAM) { |
726 | 0 | pdf_cmap *tu = NULL; |
727 | 0 | code = pdfi_read_cmap(ctx, tmp, &tu); |
728 | 0 | pdfi_countdown(tmp); |
729 | 0 | tmp = (pdf_obj *)tu; |
730 | 0 | } |
731 | 0 | if (code < 0 || (tmp != NULL && pdfi_type_of(tmp) != PDF_CMAP)) { |
732 | 0 | pdfi_countdown(tmp); |
733 | 0 | tmp = NULL; |
734 | 0 | code = 0; |
735 | 0 | } |
736 | 0 | } |
737 | 0 | else { |
738 | 0 | tmp = NULL; |
739 | 0 | } |
740 | 0 | font->ToUnicode = tmp; |
741 | 0 | code = gs_definefont(ctx->font_dir, (gs_font *) font->pfont); |
742 | 0 | if (code < 0) { |
743 | 0 | goto error; |
744 | 0 | } |
745 | | |
746 | 0 | code = pdfi_fapi_passfont((pdf_font *) font, 0, NULL, NULL, NULL, 0); |
747 | 0 | if (code < 0) { |
748 | 0 | goto error; |
749 | 0 | } |
750 | | /* object_num can be zero if the dictionary was defined inline */ |
751 | 0 | if (font->object_num != 0) { |
752 | 0 | (void)replace_cache_entry(ctx, (pdf_obj *) font); |
753 | 0 | } |
754 | |
|
755 | 0 | *tpdffont = (pdf_font *)font; |
756 | |
|
757 | 0 | error: |
758 | 0 | if (code < 0) |
759 | 0 | pdfi_countdown(font); |
760 | 0 | return code; |
761 | 0 | } |
762 | | |
763 | | int pdfi_free_font_truetype(pdf_obj *font) |
764 | 16.8k | { |
765 | 16.8k | pdf_font_truetype *ttfont = (pdf_font_truetype *)font; |
766 | | |
767 | 16.8k | if (ttfont->pfont) |
768 | 16.8k | gs_free_object(OBJ_MEMORY(ttfont), ttfont->pfont, "Free TrueType gs_font"); |
769 | | |
770 | 16.8k | if (ttfont->Widths) |
771 | 16.5k | gs_free_object(OBJ_MEMORY(ttfont), ttfont->Widths, "Free TrueType font Widths array"); |
772 | | |
773 | 16.8k | pdfi_countdown(ttfont->sfnt); |
774 | 16.8k | pdfi_countdown(ttfont->FontDescriptor); |
775 | 16.8k | pdfi_countdown(ttfont->Encoding); |
776 | 16.8k | pdfi_countdown(ttfont->BaseFont); |
777 | 16.8k | pdfi_countdown(ttfont->PDF_font); |
778 | 16.8k | pdfi_countdown(ttfont->ToUnicode); |
779 | 16.8k | pdfi_countdown(ttfont->filename); |
780 | | |
781 | 16.8k | gs_free_object(OBJ_MEMORY(ttfont), ttfont, "Free TrueType font"); |
782 | | |
783 | 16.8k | return 0; |
784 | 16.8k | } |