/src/ghostpdl/pdf/pdf_font.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2018-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 | | /* Font operations for the PDF interpreter */ |
17 | | |
18 | | #include "pdf_int.h" |
19 | | #include "pdf_font_types.h" |
20 | | #include "pdf_gstate.h" |
21 | | #include "pdf_file.h" |
22 | | #include "pdf_dict.h" |
23 | | #include "pdf_loop_detect.h" |
24 | | #include "pdf_array.h" |
25 | | #include "pdf_font.h" |
26 | | #include "pdf_stack.h" |
27 | | #include "pdf_misc.h" |
28 | | #include "pdf_doc.h" |
29 | | #include "pdf_font0.h" |
30 | | #include "pdf_font1.h" |
31 | | #include "pdf_font1C.h" |
32 | | #include "pdf_font3.h" |
33 | | #include "pdf_fontTT.h" |
34 | | #include "pdf_font0.h" |
35 | | #include "pdf_fmap.h" |
36 | | #include "gscencs.h" /* For gs_c_known_encode and gs_c_glyph_name */ |
37 | | #include "gsagl.h" |
38 | | |
39 | | #include "strmio.h" |
40 | | #include "stream.h" |
41 | | #include "gsstate.h" /* For gs_setPDFfontsize() */ |
42 | | |
43 | | extern single_glyph_list_t SingleGlyphList[]; |
44 | | |
45 | | static int pdfi_gs_setfont(pdf_context *ctx, gs_font *pfont) |
46 | 428k | { |
47 | 428k | int code = 0; |
48 | 428k | pdfi_int_gstate *igs = (pdfi_int_gstate *)ctx->pgs->client_data; |
49 | 428k | pdf_font *old_font = igs->current_font; |
50 | | |
51 | 428k | code = gs_setfont(ctx->pgs, pfont); |
52 | 428k | if (code >= 0) { |
53 | 428k | igs->current_font = (pdf_font *)pfont->client_data; |
54 | 428k | pdfi_countup(igs->current_font); |
55 | 428k | pdfi_countdown(old_font); |
56 | 428k | } |
57 | 428k | return code; |
58 | 428k | } |
59 | | |
60 | | /* These are fonts for which we have to ignore "named" encodings */ |
61 | | typedef struct known_symbolic_font_name_s |
62 | | { |
63 | | const char *name; |
64 | | const int namelen; |
65 | | } known_symbolic_font_name_t; |
66 | | |
67 | | #define DEFINE_NAME_LEN(s) #s, sizeof(#s) - 1 |
68 | | static const known_symbolic_font_name_t known_symbolic_font_names[] = |
69 | | { |
70 | | {DEFINE_NAME_LEN(Symbol)}, |
71 | | {DEFINE_NAME_LEN(Wingdings2)}, |
72 | | {DEFINE_NAME_LEN(Wingdings)}, |
73 | | {DEFINE_NAME_LEN(ZapfDingbats)}, |
74 | | {NULL , 0} |
75 | | }; |
76 | | #undef DEFINE_NAME_LEN |
77 | | |
78 | | bool pdfi_font_known_symbolic(pdf_obj *basefont) |
79 | 208k | { |
80 | 208k | bool ignore = false; |
81 | 208k | int i; |
82 | 208k | pdf_name *nm = (pdf_name *)basefont; |
83 | | |
84 | 208k | if (basefont != NULL && pdfi_type_of(basefont) == PDF_NAME) { |
85 | 935k | for (i = 0; known_symbolic_font_names[i].name != NULL; i++) { |
86 | 749k | if (nm->length == known_symbolic_font_names[i].namelen |
87 | 749k | && !strncmp((char *)nm->data, known_symbolic_font_names[i].name, nm->length)) { |
88 | 2.03k | ignore = true; |
89 | 2.03k | break; |
90 | 2.03k | } |
91 | 749k | } |
92 | 187k | } |
93 | 208k | return ignore; |
94 | 208k | } |
95 | | |
96 | | static int |
97 | | pdfi_font_match_glyph_widths(pdf_font *pdfont) |
98 | 151k | { |
99 | 151k | int code = 0; |
100 | 151k | int i; |
101 | 151k | int sindex, lindex; |
102 | 151k | gs_font_base *pbfont = pdfont->pfont; |
103 | 151k | double fw = 0.0, ww = 0.0; |
104 | | |
105 | 151k | if (pdfont->LastChar < pdfont->FirstChar || pdfont->Widths == NULL) |
106 | 142k | return 0; /* Technically invalid - carry on, hope for the best */ |
107 | | |
108 | | /* For "best" results, restrict to what we *hope* are A-Z,a-z */ |
109 | 8.70k | sindex = pdfont->FirstChar < 96 ? 96 : pdfont->FirstChar; |
110 | 8.70k | lindex = pdfont->LastChar > 122 ? 123 : pdfont->LastChar + 1; |
111 | | |
112 | 192k | for (i = sindex; i < lindex; i++) { |
113 | 184k | gs_glyph_info_t ginfo = {0}; |
114 | 184k | gs_glyph g; |
115 | 184k | g = pbfont->procs.encode_char((gs_font *)pbfont, i, GLYPH_SPACE_NAME); |
116 | | |
117 | | /* We're only interested in non-zero Widths entries for glyphs that actually exist in the font */ |
118 | 184k | if (g != GS_NO_GLYPH && pdfont->Widths[i - pdfont->FirstChar] != 0.0 |
119 | 184k | && (*pbfont->procs.glyph_info)((gs_font *)pbfont, g, NULL, GLYPH_INFO_WIDTH0, &ginfo) >= 0) { |
120 | 119k | fw += hypot(ginfo.width[0].x, ginfo.width[0].y); |
121 | 119k | ww += pdfont->Widths[i - pdfont->FirstChar]; |
122 | 119k | } |
123 | 184k | } |
124 | | /* Only reduce font width, don't expand */ |
125 | 8.70k | if (ww != 0.0 && fw != 0.0 && ww / fw < 1.0) { |
126 | 4.99k | gs_matrix nmat, smat = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; |
127 | 4.99k | double wscale; |
128 | 4.99k | smat.xx = smat.yy = ww/fw; |
129 | 4.99k | wscale = 1.0 / smat.xx; |
130 | | |
131 | 4.99k | gs_matrix_multiply(&pbfont->FontMatrix, &smat, &nmat); |
132 | 4.99k | memcpy(&pbfont->FontMatrix, &nmat, sizeof(pbfont->FontMatrix)); |
133 | | |
134 | 572k | for (i = pdfont->FirstChar; i <= pdfont->LastChar; i++) { |
135 | 567k | pdfont->Widths[i - pdfont->FirstChar] *= wscale; |
136 | 567k | } |
137 | | |
138 | | /* Purging a font can be expensive, but in this case, we know |
139 | | we have no scaled instances (pdfi doesn't work that way) |
140 | | and we know we have no fm pairs, nor glyphs to purge (we |
141 | | *just* created the font!). |
142 | | So "purging" the font is really just removing it from the |
143 | | doubly linked list of font objects in the font directory |
144 | | */ |
145 | 4.99k | code = gs_purge_font((gs_font *)pbfont); |
146 | 4.99k | if (code >= 0) |
147 | 4.99k | code = gs_definefont(pbfont->dir, (gs_font *)pbfont); |
148 | 4.99k | if (code >= 0) |
149 | 4.99k | code = pdfi_fapi_passfont((pdf_font *)pdfont, 0, NULL, NULL, NULL, 0); |
150 | 4.99k | } |
151 | | |
152 | 8.70k | return code; |
153 | 151k | } |
154 | | |
155 | | /* Print a name object to stdout */ |
156 | | static void pdfi_print_font_name(pdf_context *ctx, pdf_name *n) |
157 | 167k | { |
158 | 167k | if (ctx->args.QUIET != true) |
159 | 0 | (void)outwrite(ctx->memory, (const char *)n->data, n->length); |
160 | 167k | } |
161 | | |
162 | | static void pdfi_print_font_string(pdf_context *ctx, pdf_string *s) |
163 | 165k | { |
164 | 165k | if (ctx->args.QUIET != true) |
165 | 0 | (void)outwrite(ctx->memory, (const char *)s->data, s->length); |
166 | 165k | } |
167 | | |
168 | | /* Print a null terminated string to stdout */ |
169 | | static void pdfi_print_cstring(pdf_context *ctx, const char *str) |
170 | 527k | { |
171 | 527k | if (ctx->args.QUIET != true) |
172 | 0 | (void)outwrite(ctx->memory, str, strlen(str)); |
173 | 527k | } |
174 | | |
175 | | /* Call with a CIDFont name to try to find the CIDFont on disk |
176 | | call if with ffname NULL to load the default fallback CIDFont |
177 | | substitue |
178 | | Currently only loads subsitute - DroidSansFallback |
179 | | */ |
180 | | static int |
181 | | pdfi_open_CIDFont_substitute_file(pdf_context *ctx, pdf_dict *font_dict, pdf_dict *fontdesc, bool fallback, byte ** buf, int64_t * buflen, int *findex) |
182 | 5.09k | { |
183 | 5.09k | int code = 0; |
184 | 5.09k | char fontfname[gp_file_name_sizeof]; |
185 | 5.09k | stream *s; |
186 | 5.09k | pdf_name *cidname = NULL; |
187 | 5.09k | gs_const_string fname; |
188 | | |
189 | 5.09k | (void)pdfi_dict_get(ctx, font_dict, "BaseFont", (pdf_obj **)&cidname); |
190 | | |
191 | 5.09k | if (fallback == true) { |
192 | 2.54k | pdf_string *mname = NULL; |
193 | 2.54k | pdf_dict *csi = NULL; |
194 | | |
195 | 2.54k | code = pdfi_dict_get(ctx, font_dict, "CIDSystemInfo", (pdf_obj **)&csi); |
196 | 2.54k | if (code >= 0 && pdfi_type_of(csi) == PDF_DICT) { |
197 | 2.39k | pdf_string *csi_reg = NULL, *csi_ord = NULL; |
198 | | |
199 | 2.39k | if (pdfi_dict_get(ctx, csi, "Registry", (pdf_obj **)&csi_reg) >= 0 |
200 | 2.39k | && pdfi_dict_get(ctx, csi, "Ordering", (pdf_obj **)&csi_ord) >= 0 |
201 | 2.39k | && pdfi_type_of(csi_reg) == PDF_STRING && pdfi_type_of(csi_ord) == PDF_STRING |
202 | 2.39k | && csi_reg->length + csi_ord->length + 1 < gp_file_name_sizeof - 1) { |
203 | 2.38k | pdf_name *reg_ord; |
204 | 2.38k | memcpy(fontfname, csi_reg->data, csi_reg->length); |
205 | 2.38k | memcpy(fontfname + csi_reg->length, "-", 1); |
206 | 2.38k | memcpy(fontfname + csi_reg->length + 1, csi_ord->data, csi_ord->length); |
207 | 2.38k | fontfname[csi_reg->length + csi_ord->length + 1] = '\0'; |
208 | | |
209 | 2.38k | code = pdfi_name_alloc(ctx, (byte *)fontfname, strlen(fontfname), (pdf_obj **) ®_ord); |
210 | 2.38k | if (code >= 0) { |
211 | 2.38k | pdfi_countup(reg_ord); |
212 | 2.38k | code = pdf_fontmap_lookup_cidfont(ctx, font_dict, reg_ord, (pdf_obj **)&mname, findex); |
213 | 2.38k | pdfi_countdown(reg_ord); |
214 | 2.38k | } |
215 | 2.38k | } |
216 | 2.39k | pdfi_countdown(csi_reg); |
217 | 2.39k | pdfi_countdown(csi_ord); |
218 | 2.39k | } |
219 | 2.54k | pdfi_countdown(csi); |
220 | | |
221 | 2.54k | if (mname == NULL || pdfi_type_of(mname) != PDF_STRING) |
222 | 2.54k | code = pdf_fontmap_lookup_cidfont(ctx, font_dict, NULL, (pdf_obj **)&mname, findex); |
223 | | |
224 | 2.54k | if (code < 0 || pdfi_type_of(mname) != PDF_STRING) { |
225 | 2.54k | const char *fsprefix = "CIDFSubst/"; |
226 | 2.54k | int fsprefixlen = strlen(fsprefix); |
227 | 2.54k | const char *defcidfallack = "DroidSansFallback.ttf"; |
228 | 2.54k | int defcidfallacklen = strlen(defcidfallack); |
229 | | |
230 | 2.54k | pdfi_countdown(mname); |
231 | | |
232 | 2.54k | if (ctx->args.nocidfallback == true) { |
233 | 0 | code = gs_note_error(gs_error_invalidfont); |
234 | 0 | } |
235 | 2.54k | else { |
236 | 2.54k | if (ctx->args.cidfsubstpath.data == NULL) { |
237 | 2.54k | memcpy(fontfname, fsprefix, fsprefixlen); |
238 | 2.54k | } |
239 | 0 | else { |
240 | 0 | memcpy(fontfname, ctx->args.cidfsubstpath.data, ctx->args.cidfsubstpath.size); |
241 | 0 | fsprefixlen = ctx->args.cidfsubstpath.size; |
242 | 0 | } |
243 | | |
244 | 2.54k | if (ctx->args.cidfsubstfont.data == NULL) { |
245 | 2.54k | int len = 0; |
246 | 2.54k | if (gp_getenv("CIDFSUBSTFONT", (char *)0, &len) < 0 && len + fsprefixlen + 1 < gp_file_name_sizeof) { |
247 | 0 | (void)gp_getenv("CIDFSUBSTFONT", (char *)(fontfname + fsprefixlen), &defcidfallacklen); |
248 | 0 | } |
249 | 2.54k | else { |
250 | 2.54k | memcpy(fontfname + fsprefixlen, defcidfallack, defcidfallacklen); |
251 | 2.54k | } |
252 | 2.54k | } |
253 | 0 | else { |
254 | 0 | memcpy(fontfname, ctx->args.cidfsubstfont.data, ctx->args.cidfsubstfont.size); |
255 | 0 | defcidfallacklen = ctx->args.cidfsubstfont.size; |
256 | 0 | } |
257 | 2.54k | fontfname[fsprefixlen + defcidfallacklen] = '\0'; |
258 | | |
259 | 2.54k | code = pdfi_open_resource_file(ctx, fontfname, strlen(fontfname), &s); |
260 | 2.54k | if (code < 0) { |
261 | 0 | code = gs_note_error(gs_error_invalidfont); |
262 | 0 | } |
263 | 2.54k | else { |
264 | 2.54k | if (cidname) { |
265 | 2.54k | pdfi_print_cstring(ctx, "Loading CIDFont "); |
266 | 2.54k | pdfi_print_font_name(ctx, (pdf_name *)cidname); |
267 | 2.54k | pdfi_print_cstring(ctx, " substitute from "); |
268 | 2.54k | } |
269 | 6 | else { |
270 | 6 | pdfi_print_cstring(ctx, "Loading nameless CIDFont from "); |
271 | 6 | } |
272 | 2.54k | sfilename(s, &fname); |
273 | 2.54k | if (fname.size < gp_file_name_sizeof) { |
274 | 2.54k | memcpy(fontfname, fname.data, fname.size); |
275 | 2.54k | fontfname[fname.size] = '\0'; |
276 | 2.54k | } |
277 | 0 | else { |
278 | 0 | strcpy(fontfname, "unnamed file"); |
279 | 0 | } |
280 | 2.54k | pdfi_print_cstring(ctx, fontfname); |
281 | 2.54k | pdfi_print_cstring(ctx, "\n"); |
282 | | |
283 | | |
284 | 2.54k | sfseek(s, 0, SEEK_END); |
285 | 2.54k | *buflen = sftell(s); |
286 | 2.54k | sfseek(s, 0, SEEK_SET); |
287 | 2.54k | *buf = gs_alloc_bytes(ctx->memory, *buflen, "pdfi_open_CIDFont_file(buf)"); |
288 | 2.54k | if (*buf != NULL) { |
289 | 2.53k | sfread(*buf, 1, *buflen, s); |
290 | 2.53k | } |
291 | 13 | else { |
292 | 13 | code = gs_note_error(gs_error_VMerror); |
293 | 13 | } |
294 | 2.54k | sfclose(s); |
295 | 2.54k | } |
296 | 2.54k | } |
297 | 2.54k | } |
298 | 0 | else { |
299 | 0 | if (mname->length + 1 > gp_file_name_sizeof) { |
300 | 0 | pdfi_countdown(mname); |
301 | 0 | return_error(gs_error_invalidfont); |
302 | 0 | } |
303 | 0 | memcpy(fontfname, mname->data, mname->length); |
304 | 0 | fontfname[mname->length] = '\0'; |
305 | 0 | code = pdfi_open_resource_file(ctx, (const char *)fontfname, mname->length, &s); |
306 | 0 | pdfi_countdown(mname); |
307 | 0 | if (code < 0) { |
308 | 0 | code = gs_note_error(gs_error_invalidfont); |
309 | 0 | } |
310 | 0 | else { |
311 | 0 | if (cidname) { |
312 | 0 | pdfi_print_cstring(ctx, "Loading CIDFont "); |
313 | 0 | pdfi_print_font_name(ctx, (pdf_name *)cidname); |
314 | 0 | pdfi_print_cstring(ctx, " (or substitute) from "); |
315 | 0 | } |
316 | 0 | else { |
317 | 0 | pdfi_print_cstring(ctx, "Loading nameless CIDFont from "); |
318 | 0 | } |
319 | 0 | sfilename(s, &fname); |
320 | 0 | if (fname.size < gp_file_name_sizeof) { |
321 | 0 | memcpy(fontfname, fname.data, fname.size); |
322 | 0 | fontfname[fname.size] = '\0'; |
323 | 0 | } |
324 | 0 | else { |
325 | 0 | strcpy(fontfname, "unnamed file"); |
326 | 0 | } |
327 | 0 | pdfi_print_cstring(ctx, fontfname); |
328 | 0 | pdfi_print_cstring(ctx, "\n"); |
329 | 0 | sfseek(s, 0, SEEK_END); |
330 | 0 | *buflen = sftell(s); |
331 | 0 | sfseek(s, 0, SEEK_SET); |
332 | 0 | *buf = gs_alloc_bytes(ctx->memory, *buflen, "pdfi_open_CIDFont_file(buf)"); |
333 | 0 | if (*buf != NULL) { |
334 | 0 | sfread(*buf, 1, *buflen, s); |
335 | 0 | } |
336 | 0 | else { |
337 | 0 | code = gs_note_error(gs_error_VMerror); |
338 | 0 | } |
339 | 0 | sfclose(s); |
340 | 0 | } |
341 | 0 | } |
342 | 2.54k | } |
343 | 2.54k | else { |
344 | 2.54k | const char *fsprefix = "CIDFont/"; |
345 | 2.54k | const int fsprefixlen = strlen(fsprefix); |
346 | | |
347 | 2.54k | if (cidname == NULL || pdfi_type_of(cidname) != PDF_NAME |
348 | 2.54k | || fsprefixlen + cidname->length >= gp_file_name_sizeof) { |
349 | 8 | code = gs_note_error(gs_error_invalidfont); |
350 | 8 | goto exit; |
351 | 8 | } |
352 | | |
353 | 2.53k | memcpy(fontfname, fsprefix, fsprefixlen); |
354 | 2.53k | memcpy(fontfname + fsprefixlen, cidname->data, cidname->length); |
355 | 2.53k | fontfname[fsprefixlen + cidname->length] = '\0'; |
356 | | |
357 | 2.53k | code = pdfi_open_resource_file(ctx, fontfname, strlen(fontfname), &s); |
358 | 2.53k | if (code < 0) { |
359 | 2.53k | code = gs_note_error(gs_error_invalidfont); |
360 | 2.53k | } |
361 | 0 | else { |
362 | 0 | sfseek(s, 0, SEEK_END); |
363 | 0 | *buflen = sftell(s); |
364 | 0 | sfseek(s, 0, SEEK_SET); |
365 | 0 | *buf = gs_alloc_bytes(ctx->memory, *buflen, "pdfi_open_CIDFont_file(buf)"); |
366 | 0 | if (*buf != NULL) { |
367 | 0 | sfread(*buf, 1, *buflen, s); |
368 | 0 | } |
369 | 0 | else { |
370 | 0 | code = gs_note_error(gs_error_invalidfont); |
371 | 0 | } |
372 | 0 | sfclose(s); |
373 | 0 | } |
374 | 2.53k | } |
375 | | |
376 | 5.09k | exit: |
377 | 5.09k | if (cidname != NULL) |
378 | 5.08k | pdfi_countdown(cidname); |
379 | | |
380 | 5.09k | return code; |
381 | 5.09k | } |
382 | | |
383 | | enum |
384 | | { |
385 | | pdfi_font_flag_none = 0x00000, |
386 | | pdfi_font_flag_fixed = 0x00001, |
387 | | pdfi_font_flag_serif = 0x00002, |
388 | | pdfi_font_flag_symbolic = 0x00004, |
389 | | pdfi_font_flag_script = 0x00008, |
390 | | pdfi_font_flag_nonsymbolic = 0x00020, |
391 | | pdfi_font_flag_italic = 0x00040, |
392 | | pdfi_font_flag_allcap = 0x10000, |
393 | | pdfi_font_flag_smallcap = 0x20000, |
394 | | pdfi_font_flag_forcebold = 0x40000 |
395 | | }; |
396 | | |
397 | | /* Barefaced theft from mupdf! */ |
398 | | static const char *pdfi_base_font_names[][10] = |
399 | | { |
400 | | { "Courier", "CourierNew", "CourierNewPSMT", "CourierStd", NULL }, |
401 | | { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", "CourierNewPS-BoldMT", "CourierNew-Bold", NULL }, |
402 | | { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", "CourierNewPS-ItalicMT", "CourierNew-Italic", NULL }, |
403 | | { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", NULL }, |
404 | | { "Helvetica", "ArialMT", "Arial", NULL }, |
405 | | { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", "Helvetica,Bold", NULL }, |
406 | | { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", "Helvetica,Italic", "Helvetica-Italic", NULL }, |
407 | | { "Helvetica-BoldOblique", "Arial-BoldItalicMT", "Arial,BoldItalic", "Arial-BoldItalic", "Helvetica,BoldItalic", "Helvetica-BoldItalic", NULL }, |
408 | | { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", "TimesNewRomanPS", NULL }, |
409 | | { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", NULL }, |
410 | | { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", NULL }, |
411 | | { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", "TimesNewRoman-BoldItalic", NULL }, |
412 | | { "Symbol", "Symbol,Italic", "Symbol,Bold", "Symbol,BoldItalic", "SymbolMT", "SymbolMT,Italic", "SymbolMT,Bold", "SymbolMT,BoldItalic", NULL }, |
413 | | { "ZapfDingbats", NULL } |
414 | | }; |
415 | | |
416 | | static int strncmp_ignore_space(const char *a, const char *b) |
417 | 19.7M | { |
418 | 23.9M | while (1) |
419 | 23.9M | { |
420 | 23.9M | while (*a == ' ') |
421 | 0 | a++; |
422 | 23.9M | while (*b == ' ') |
423 | 1.54k | b++; |
424 | 23.9M | if (*a != *b) |
425 | 19.7M | return 1; |
426 | 4.14M | if (*a == 0) |
427 | 5.40k | return *a != *b; |
428 | 4.14M | if (*b == 0) |
429 | 0 | return *a != *b; |
430 | 4.14M | a++; |
431 | 4.14M | b++; |
432 | 4.14M | } |
433 | 0 | return 0; /* Shouldn't happen */ |
434 | 19.7M | } |
435 | | |
436 | | static const char *pdfi_clean_font_name(const char *fontname) |
437 | 298k | { |
438 | 298k | int i, k; |
439 | 4.42M | for (i = 0; i < (sizeof(pdfi_base_font_names)/sizeof(pdfi_base_font_names[0])); i++) { |
440 | 23.9M | for (k = 0; pdfi_base_font_names[i][k]; k++) { |
441 | 19.7M | if (!strncmp_ignore_space(pdfi_base_font_names[i][k], (const char *)fontname)) |
442 | 5.40k | return pdfi_base_font_names[i][0]; |
443 | 19.7M | } |
444 | 4.13M | } |
445 | 293k | return NULL; |
446 | 298k | } |
447 | | |
448 | | static int pdfi_font_substitute_by_flags(pdf_context *ctx, unsigned int flags, char **name, int *namelen) |
449 | 152k | { |
450 | 152k | bool fixed = ((flags & pdfi_font_flag_fixed) != 0); |
451 | 152k | bool serif = ((flags & pdfi_font_flag_serif) != 0); |
452 | 152k | bool italic = ((flags & pdfi_font_flag_italic) != 0); |
453 | 152k | bool bold = ((flags & pdfi_font_flag_forcebold) != 0); |
454 | 152k | int code = 0; |
455 | | |
456 | 152k | if (ctx->args.defaultfont_is_name == true && ctx->args.defaultfont.size == 4 |
457 | 152k | && !memcmp(ctx->args.defaultfont.data, "None", 4)) { |
458 | 0 | *name = NULL; |
459 | 0 | *namelen = 0; |
460 | 0 | code = gs_error_invalidfont; |
461 | 0 | } |
462 | 152k | else if (ctx->args.defaultfont.data != NULL && ctx->args.defaultfont.size > 0) { |
463 | 0 | *name = (char *)ctx->args.defaultfont.data; |
464 | 0 | *namelen = ctx->args.defaultfont.size; |
465 | 0 | } |
466 | 152k | else if (fixed) { |
467 | 43 | if (bold) { |
468 | 1 | if (italic) { |
469 | 1 | *name = (char *)pdfi_base_font_names[3][0]; |
470 | 1 | *namelen = strlen(*name); |
471 | 1 | } |
472 | 0 | else { |
473 | 0 | *name = (char *)pdfi_base_font_names[1][0]; |
474 | 0 | *namelen = strlen(*name); |
475 | 0 | } |
476 | 1 | } |
477 | 42 | else { |
478 | 42 | if (italic) { |
479 | 0 | *name = (char *)pdfi_base_font_names[2][0]; |
480 | 0 | *namelen = strlen(*name); |
481 | 0 | } |
482 | 42 | else { |
483 | 42 | *name = (char *)pdfi_base_font_names[0][0]; |
484 | 42 | *namelen = strlen(*name); |
485 | 42 | } |
486 | 42 | } |
487 | 43 | } |
488 | 152k | else if (serif) { |
489 | 1.23k | if (bold) { |
490 | 1 | if (italic) { |
491 | 0 | *name = (char *)pdfi_base_font_names[11][0]; |
492 | 0 | *namelen = strlen(*name); |
493 | 0 | } |
494 | 1 | else { |
495 | 1 | *name = (char *)pdfi_base_font_names[9][0]; |
496 | 1 | *namelen = strlen(*name); |
497 | 1 | } |
498 | 1 | } |
499 | 1.23k | else { |
500 | 1.23k | if (italic) { |
501 | 64 | *name = (char *)pdfi_base_font_names[10][0]; |
502 | 64 | *namelen = strlen(*name); |
503 | 64 | } |
504 | 1.17k | else { |
505 | 1.17k | *name = (char *)pdfi_base_font_names[8][0]; |
506 | 1.17k | *namelen = strlen(*name); |
507 | 1.17k | } |
508 | 1.23k | } |
509 | 150k | } else { |
510 | 150k | if (bold) { |
511 | 35 | if (italic) { |
512 | 0 | *name = (char *)pdfi_base_font_names[7][0]; |
513 | 0 | *namelen = strlen(*name); |
514 | 0 | } |
515 | 35 | else { |
516 | 35 | *name = (char *)pdfi_base_font_names[5][0]; |
517 | 35 | *namelen = strlen(*name); |
518 | 35 | } |
519 | 35 | } |
520 | 150k | else { |
521 | 150k | if (italic) { |
522 | 502 | *name = (char *)pdfi_base_font_names[6][0]; |
523 | 502 | *namelen = strlen(*name); |
524 | 502 | } |
525 | 150k | else { |
526 | 150k | *name = (char *)pdfi_base_font_names[4][0]; |
527 | 150k | *namelen = strlen(*name); |
528 | 150k | } |
529 | 150k | } |
530 | 150k | } |
531 | 152k | return code; |
532 | 152k | } |
533 | | |
534 | | enum { |
535 | | no_type_font = -1, |
536 | | type0_font = 0, |
537 | | type1_font = 1, |
538 | | cff_font = 2, |
539 | | type3_font = 3, |
540 | | tt_font = 42 |
541 | | }; |
542 | | |
543 | | static int pdfi_fonttype_picker(byte *buf, int64_t buflen) |
544 | 49.8k | { |
545 | 438k | #define MAKEMAGIC(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) |
546 | | |
547 | 49.8k | if (buflen >= 4) { |
548 | 49.8k | if (MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC(0, 1, 0, 0) |
549 | 49.8k | || MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('t', 'r', 'u', 'e') |
550 | 49.8k | || MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('t', 't', 'c', 'f')) { |
551 | 21.4k | return tt_font; |
552 | 21.4k | } |
553 | 28.3k | else if (MAKEMAGIC(buf[0], buf[1], buf[2], buf[3]) == MAKEMAGIC('O', 'T', 'T', 'O')) { |
554 | 157 | return cff_font; /* OTTO will end up as CFF */ |
555 | 157 | } |
556 | 28.1k | else if (MAKEMAGIC(buf[0], buf[1], buf[2], 0) == MAKEMAGIC('%', '!', 'P', 0)) { |
557 | 24.8k | return type1_font; /* pfa */ |
558 | 24.8k | } |
559 | 3.34k | else if (MAKEMAGIC(buf[0], buf[1], buf[2], 0) == MAKEMAGIC(1, 0, 4, 0)) { |
560 | 3.10k | return cff_font; /* 1C/CFF */ |
561 | 3.10k | } |
562 | 237 | else if (MAKEMAGIC(buf[0], buf[1], 0, 0) == MAKEMAGIC(128, 1, 0, 0)) { |
563 | 25 | return type1_font; /* pfb */ |
564 | 25 | } |
565 | 49.8k | } |
566 | 222 | return no_type_font; |
567 | 49.8k | #undef MAKEMAGIC |
568 | 49.8k | } |
569 | | |
570 | | static int pdfi_copy_font(pdf_context *ctx, pdf_font *spdffont, pdf_dict *font_dict, pdf_font **tpdffont) |
571 | 165k | { |
572 | 165k | int code; |
573 | 165k | if (pdfi_type_of(spdffont) != PDF_FONT) |
574 | 0 | return_error(gs_error_typecheck); |
575 | | |
576 | 165k | switch(spdffont->pdfi_font_type) { |
577 | 165k | case e_pdf_font_type1: |
578 | 165k | code = pdfi_copy_type1_font(ctx, spdffont, font_dict, tpdffont); |
579 | 165k | break; |
580 | 0 | case e_pdf_font_cff: |
581 | 0 | code = pdfi_copy_cff_font(ctx, spdffont, font_dict, tpdffont); |
582 | 0 | break; |
583 | 0 | case e_pdf_font_truetype: |
584 | 0 | code = pdfi_copy_truetype_font(ctx, spdffont, font_dict, tpdffont); |
585 | 0 | break; |
586 | 0 | default: |
587 | 0 | return_error(gs_error_invalidfont); |
588 | 165k | } |
589 | 165k | return code; |
590 | 165k | } |
591 | | |
592 | | enum { |
593 | | font_embedded = 0, |
594 | | font_from_file = 1, |
595 | | font_substitute = 2 |
596 | | }; |
597 | | |
598 | | static int pdfi_load_font_buffer(pdf_context *ctx, byte *fbuf, int fbuflen, int fftype, pdf_name *Subtype, int findex, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, pdf_font **ppdffont, bool cidfont) |
599 | 49.8k | { |
600 | 49.8k | int code = gs_error_invalidfont; |
601 | 49.8k | if (fbuf != NULL) { |
602 | | /* First, see if we can glean the type from the magic number */ |
603 | 49.8k | int sftype = pdfi_fonttype_picker(fbuf, fbuflen); |
604 | 49.8k | if (sftype == no_type_font) { |
605 | 222 | if (fftype != no_type_font) |
606 | 216 | sftype = fftype; |
607 | 6 | else { |
608 | | /* If we don't have a Subtype, can't work it out, try Type 1 */ |
609 | 6 | if (Subtype == NULL || pdfi_name_is(Subtype, "Type1") || pdfi_name_is(Subtype, "MMType1")) |
610 | 6 | sftype = type1_font; |
611 | 0 | else if (pdfi_name_is(Subtype, "Type1C")) |
612 | 0 | sftype = cff_font; |
613 | 0 | else if (pdfi_name_is(Subtype, "TrueType")) |
614 | 0 | sftype = tt_font; |
615 | 6 | } |
616 | 222 | } |
617 | | /* fbuf ownership passes to the font loader */ |
618 | 49.8k | switch (sftype) { |
619 | 25.0k | case type1_font: |
620 | 25.0k | code = pdfi_read_type1_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, fbuf, fbuflen, ppdffont); |
621 | 25.0k | fbuf = NULL; |
622 | 25.0k | break; |
623 | 3.27k | case cff_font: |
624 | 3.27k | code = pdfi_read_cff_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, fbuf, fbuflen, cidfont, ppdffont); |
625 | 3.27k | fbuf = NULL; |
626 | 3.27k | break; |
627 | 21.5k | case tt_font: |
628 | 21.5k | { |
629 | 21.5k | if (cidfont) |
630 | 4.61k | code = pdfi_read_cidtype2_font(ctx, font_dict, stream_dict, page_dict, fbuf, fbuflen, findex, ppdffont); |
631 | 16.8k | else |
632 | 16.8k | code = pdfi_read_truetype_font(ctx, font_dict, stream_dict, page_dict, fbuf, fbuflen, findex, ppdffont); |
633 | 21.5k | fbuf = NULL; |
634 | 21.5k | } |
635 | 21.5k | break; |
636 | 0 | default: |
637 | 0 | gs_free_object(ctx->memory, fbuf, "pdfi_load_font_buffer(fbuf)"); |
638 | 0 | code = gs_note_error(gs_error_invalidfont); |
639 | 49.8k | } |
640 | 49.8k | } |
641 | 49.8k | return code; |
642 | 49.8k | } |
643 | | |
644 | | static int pdfi_load_font_file(pdf_context *ctx, int fftype, pdf_name *Subtype, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, pdf_dict *fontdesc, bool substitute, pdf_font **ppdffont) |
645 | 317k | { |
646 | 317k | int code; |
647 | 317k | char fontfname[gp_file_name_sizeof]; |
648 | 317k | pdf_obj *basefont = NULL, *mapname = NULL; |
649 | 317k | pdf_obj *fontname = NULL; |
650 | 317k | stream *s; |
651 | 317k | const char *fn; |
652 | 317k | int findex = 0; |
653 | 317k | byte *buf; |
654 | 317k | int buflen; |
655 | 317k | pdf_font *pdffont = NULL; |
656 | 317k | pdf_font *substpdffont = NULL; |
657 | 317k | bool f_retry = true; |
658 | | |
659 | 317k | code = pdfi_dict_knownget_type(ctx, font_dict, "BaseFont", PDF_NAME, &basefont); |
660 | 317k | if (substitute == false && (code < 0 || basefont == NULL || ((pdf_name *)basefont)->length == 0)) { |
661 | 5.40k | pdfi_countdown(basefont); |
662 | 5.40k | return_error(gs_error_invalidfont); |
663 | 5.40k | } |
664 | | |
665 | 312k | if (substitute == true) { |
666 | 152k | char *fbname; |
667 | 152k | int fbnamelen; |
668 | 152k | int64_t flags = 0; |
669 | 152k | if (fontdesc != NULL) { |
670 | 8.58k | (void)pdfi_dict_get_int(ctx, fontdesc, "Flags", &flags); |
671 | 8.58k | } |
672 | 152k | code = pdfi_font_substitute_by_flags(ctx, (int)flags, &fbname, &fbnamelen); |
673 | 152k | if (code < 0) |
674 | 0 | return code; |
675 | | |
676 | 152k | code = pdfi_name_alloc(ctx, (byte *)fbname, strlen(fbname), (pdf_obj **) &fontname); |
677 | 152k | if (code < 0) |
678 | 0 | return code; |
679 | 152k | pdfi_countup(fontname); |
680 | 152k | } |
681 | 160k | else { |
682 | 160k | fontname = basefont; |
683 | 160k | pdfi_countup(fontname); |
684 | 160k | } |
685 | | |
686 | 312k | if (((pdf_name *)fontname)->length < gp_file_name_sizeof) { |
687 | 312k | memcpy(fontfname, ((pdf_name *)fontname)->data, ((pdf_name *)fontname)->length); |
688 | 312k | fontfname[((pdf_name *)fontname)->length] = '\0'; |
689 | 312k | pdfi_countdown(fontname); |
690 | | |
691 | 312k | code = pdfi_name_alloc(ctx, (byte *)fontfname, strlen(fontfname), (pdf_obj **) &fontname); |
692 | 312k | if (code < 0) |
693 | 0 | return code; |
694 | 312k | pdfi_countup(fontname); |
695 | 312k | } |
696 | | |
697 | 461k | do { |
698 | 461k | code = pdf_fontmap_lookup_font(ctx, (pdf_name *) fontname, &mapname, &findex); |
699 | 461k | if (code < 0) { |
700 | 298k | if (((pdf_name *)fontname)->length < gp_file_name_sizeof) { |
701 | 298k | memcpy(fontfname, ((pdf_name *)fontname)->data, ((pdf_name *)fontname)->length); |
702 | 298k | fontfname[((pdf_name *)fontname)->length] = '\0'; |
703 | 298k | fn = pdfi_clean_font_name(fontfname); |
704 | 298k | if (fn != NULL) { |
705 | 5.40k | pdfi_countdown(fontname); |
706 | | |
707 | 5.40k | code = pdfi_name_alloc(ctx, (byte *)fn, strlen(fn), (pdf_obj **) &fontname); |
708 | 5.40k | if (code < 0) |
709 | 0 | return code; |
710 | 5.40k | pdfi_countup(fontname); |
711 | 5.40k | } |
712 | 298k | } |
713 | 298k | code = pdf_fontmap_lookup_font(ctx, (pdf_name *) fontname, &mapname, &findex); |
714 | 298k | if (code < 0) { |
715 | 293k | mapname = fontname; |
716 | 293k | pdfi_countup(mapname); |
717 | 293k | code = 0; |
718 | 293k | } |
719 | 298k | } |
720 | 461k | if (pdfi_type_of(mapname) == PDF_NAME || pdfi_type_of(mapname) == PDF_STRING) { |
721 | 461k | pdf_name *mname = (pdf_name *) mapname; |
722 | 461k | if (mname->length + 1 < gp_file_name_sizeof) { |
723 | 461k | memcpy(fontfname, mname->data, mname->length); |
724 | 461k | fontfname[mname->length] = '\0'; |
725 | 461k | } |
726 | 0 | else { |
727 | 0 | pdfi_countdown(mapname); |
728 | 0 | pdfi_countdown(fontname); |
729 | 0 | return_error(gs_error_invalidfileaccess); |
730 | 0 | } |
731 | 461k | } |
732 | 0 | else { |
733 | 0 | pdfi_countdown(mapname); |
734 | 0 | pdfi_countdown(fontname); |
735 | 0 | return_error(gs_error_invalidfileaccess); |
736 | 0 | } |
737 | | |
738 | 461k | if (ctx->pdf_substitute_fonts != NULL) { |
739 | 422k | code = pdfi_dict_knownget_type(ctx, ctx->pdf_substitute_fonts, fontfname, PDF_FONT, (pdf_obj **)&pdffont); |
740 | 422k | if (code == 1 && pdffont->filename == NULL) { |
741 | 0 | pdfi_countdown(pdffont); |
742 | 0 | pdffont = NULL; |
743 | 0 | code = 0; |
744 | 0 | } |
745 | 422k | } |
746 | 38.5k | else |
747 | 38.5k | code = 0; |
748 | | |
749 | 461k | if (code != 1) { |
750 | 316k | code = pdfi_open_font_file(ctx, fontfname, strlen(fontfname), &s); |
751 | 316k | if (code < 0 && f_retry && pdfi_type_of(mapname) == PDF_NAME) { |
752 | 149k | pdfi_countdown(fontname); |
753 | 149k | fontname = mapname; |
754 | 149k | mapname = NULL; |
755 | 149k | f_retry = false; |
756 | 149k | continue; |
757 | 149k | } |
758 | 167k | if (code >= 0) { |
759 | 20.4k | gs_const_string fname; |
760 | | |
761 | 20.4k | sfilename(s, &fname); |
762 | 20.4k | if (fname.size < gp_file_name_sizeof) { |
763 | 20.4k | memcpy(fontfname, fname.data, fname.size); |
764 | 20.4k | fontfname[fname.size] = '\0'; |
765 | 20.4k | } |
766 | 0 | else { |
767 | 0 | strcpy(fontfname, "unnamed file"); |
768 | 0 | } |
769 | 20.4k | sfseek(s, 0, SEEK_END); |
770 | 20.4k | buflen = sftell(s); |
771 | 20.4k | sfseek(s, 0, SEEK_SET); |
772 | 20.4k | buf = gs_alloc_bytes(ctx->memory, buflen, "pdfi_open_t1_font_file(buf)"); |
773 | 20.4k | if (buf != NULL) { |
774 | 20.3k | sfread(buf, 1, buflen, s); |
775 | 20.3k | } |
776 | 75 | else { |
777 | 75 | code = gs_note_error(gs_error_VMerror); |
778 | 75 | } |
779 | 20.4k | sfclose(s); |
780 | | /* On success, the buffer owership moves to the font object */ |
781 | 20.4k | code = pdfi_load_font_buffer(ctx, buf, buflen, no_type_font, NULL, findex, stream_dict, page_dict, NULL, &pdffont, false); |
782 | 20.4k | if (code < 0) { |
783 | 75 | gs_free_object(ctx->memory, buf, "pdfi_load_font_file"); |
784 | 75 | } |
785 | 20.3k | else { |
786 | 20.3k | pdffont->filename = NULL; |
787 | 20.3k | code = pdfi_object_alloc(ctx, PDF_STRING, strlen(fontfname) , (pdf_obj **)&pdffont->filename); |
788 | 20.3k | if (code >= 0) { |
789 | 20.3k | pdfi_countup(pdffont->filename); |
790 | 20.3k | memcpy(pdffont->filename->data, fontfname, strlen(fontfname)); |
791 | 20.3k | pdffont->filename->length = strlen(fontfname); |
792 | 20.3k | } |
793 | | |
794 | 20.3k | if (ctx->pdf_substitute_fonts == NULL) { |
795 | 14.8k | code = pdfi_dict_alloc(ctx, 16, &ctx->pdf_substitute_fonts); |
796 | 14.8k | if (code >= 0) |
797 | 14.8k | pdfi_countup(ctx->pdf_substitute_fonts); |
798 | 14.8k | } |
799 | 20.3k | if (ctx->pdf_substitute_fonts != NULL) { |
800 | 20.3k | if (pdfi_type_of(mapname) == PDF_STRING) { |
801 | 0 | pdf_name *n = NULL; |
802 | 0 | pdf_string *mn = (pdf_string *)mapname; |
803 | |
|
804 | 0 | code = pdfi_name_alloc(ctx, mn->data, mn->length, (pdf_obj **)&n); |
805 | 0 | if (code >= 0) { |
806 | 0 | pdfi_countdown(mapname); |
807 | 0 | mapname = (pdf_obj *)n; |
808 | 0 | pdfi_countup(mapname); |
809 | 0 | code = 0; |
810 | 0 | } |
811 | 0 | } |
812 | 20.3k | else |
813 | 20.3k | code = 0; |
814 | | |
815 | 20.3k | if (code == 0) |
816 | 20.3k | (void)pdfi_dict_put_obj(ctx, ctx->pdf_substitute_fonts, mapname, (pdf_obj *)pdffont, true); |
817 | 20.3k | code = 0; |
818 | 20.3k | } |
819 | 20.3k | } |
820 | 20.4k | } |
821 | 167k | } |
822 | 312k | break; |
823 | 461k | } while (1); |
824 | | |
825 | 312k | if (code >= 0) { |
826 | 165k | if (basefont) { |
827 | 165k | pdfi_print_cstring(ctx, "Loading font "); |
828 | 165k | pdfi_print_font_name(ctx, (pdf_name *)basefont); |
829 | 165k | pdfi_print_cstring(ctx, " (or substitute) from "); |
830 | 165k | } |
831 | 142 | else { |
832 | 142 | pdfi_print_cstring(ctx, "Loading nameless font from "); |
833 | 142 | } |
834 | 165k | pdfi_print_font_string(ctx, pdffont->filename); |
835 | 165k | pdfi_print_cstring(ctx, "\n"); |
836 | | |
837 | 165k | code = pdfi_copy_font(ctx, pdffont, font_dict, &substpdffont); |
838 | 165k | pdfi_countdown(pdffont); |
839 | 165k | } |
840 | | |
841 | 312k | *ppdffont = substpdffont; |
842 | | |
843 | 312k | pdfi_countdown(basefont); |
844 | 312k | pdfi_countdown(mapname); |
845 | 312k | pdfi_countdown(fontname); |
846 | 312k | return code; |
847 | 312k | } |
848 | | |
849 | | int pdfi_load_font(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, gs_font **ppfont, bool cidfont) |
850 | 197k | { |
851 | 197k | int code; |
852 | 197k | pdf_font *ppdffont = NULL; |
853 | 197k | pdf_name *Type = NULL; |
854 | 197k | pdf_name *Subtype = NULL; |
855 | 197k | pdf_dict *fontdesc = NULL; |
856 | 197k | pdf_stream *fontfile = NULL; |
857 | 197k | pdf_name *ffsubtype = NULL; |
858 | 197k | int fftype = no_type_font; |
859 | 197k | byte *fbuf = NULL; |
860 | 197k | int64_t fbuflen = 0; |
861 | 197k | int substitute = font_embedded; |
862 | 197k | int findex = -1; |
863 | | |
864 | 197k | code = pdfi_dict_get_type(ctx, font_dict, "Type", PDF_NAME, (pdf_obj **)&Type); |
865 | 197k | if (code < 0) { |
866 | 68 | pdfi_set_error(ctx, 0, NULL, E_PDF_MISSINGTYPE, "pdfi_load_font", NULL); |
867 | 68 | } |
868 | 197k | else { |
869 | 197k | if (!pdfi_name_is(Type, "Font")){ |
870 | 1.57k | code = gs_note_error(gs_error_typecheck); |
871 | 1.57k | goto exit; |
872 | 1.57k | } |
873 | 197k | } |
874 | 195k | code = pdfi_dict_get_type(ctx, font_dict, "Subtype", PDF_NAME, (pdf_obj **)&Subtype); |
875 | 195k | if (code < 0) { |
876 | 143k | pdfi_set_error(ctx, 0, NULL, E_PDF_NO_SUBTYPE, "pdfi_load_font", NULL); |
877 | 143k | } |
878 | | |
879 | | /* Beyond Type 0 and Type 3, there is no point trusting the Subtype key */ |
880 | 195k | if (code >= 0 && pdfi_name_is(Subtype, "Type0")) { |
881 | 6.85k | if (cidfont == true) { |
882 | 3 | code = gs_note_error(gs_error_invalidfont); |
883 | 3 | } |
884 | 6.85k | else { |
885 | 6.85k | code = pdfi_read_type0_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, &ppdffont); |
886 | 6.85k | } |
887 | 6.85k | } |
888 | 188k | else if (code >= 0 && pdfi_name_is(Subtype, "Type3")) { |
889 | 622 | code = pdfi_read_type3_font(ctx, (pdf_dict *)font_dict, stream_dict, page_dict, &ppdffont); |
890 | 622 | if (code < 0) |
891 | 91 | goto exit; |
892 | 622 | } |
893 | 188k | else { |
894 | | /* We should always have a font descriptor here, but we have to carry on |
895 | | even if we don't |
896 | | */ |
897 | 188k | code = pdfi_dict_get_type(ctx, font_dict, "FontDescriptor", PDF_DICT, (pdf_obj**)&fontdesc); |
898 | 188k | if (fontdesc != NULL && pdfi_type_of(fontdesc) == PDF_DICT) { |
899 | 35.1k | code = pdfi_dict_get_type(ctx, (pdf_dict *) fontdesc, "FontFile", PDF_STREAM, (pdf_obj**)&fontfile); |
900 | 35.1k | if (code >= 0) |
901 | 4.71k | fftype = type1_font; |
902 | 30.4k | else { |
903 | 30.4k | code = pdfi_dict_get_type(ctx, (pdf_dict *) fontdesc, "FontFile2", PDF_STREAM, (pdf_obj**)&fontfile); |
904 | 30.4k | fftype = tt_font; |
905 | 30.4k | } |
906 | 35.1k | if (code < 0) { |
907 | 11.2k | code = pdfi_dict_get_type(ctx, (pdf_dict *) fontdesc, "FontFile3", PDF_STREAM, (pdf_obj**)&fontfile); |
908 | 11.2k | if (code >= 0 && fontfile != NULL) { |
909 | 3.31k | code = pdfi_dict_get_type(ctx, fontfile->stream_dict, "Subtype", PDF_NAME, (pdf_obj **)&ffsubtype); |
910 | 3.31k | if (code >= 0) { |
911 | 3.31k | if (pdfi_name_is(ffsubtype, "Type1")) |
912 | 0 | fftype = type1_font; |
913 | 3.31k | else if (pdfi_name_is(ffsubtype, "Type1C")) |
914 | 2.63k | fftype = cff_font; |
915 | 676 | else if (pdfi_name_is(ffsubtype, "OpenType")) |
916 | 96 | fftype = cff_font; |
917 | 580 | else if (pdfi_name_is(ffsubtype, "CIDFontType0C")) |
918 | 538 | fftype = cff_font; |
919 | 42 | else if (pdfi_name_is(ffsubtype, "TrueType")) |
920 | 0 | fftype = tt_font; |
921 | 42 | else |
922 | 42 | fftype = no_type_font; |
923 | 3.31k | } |
924 | 3.31k | } |
925 | 11.2k | } |
926 | 35.1k | } |
927 | | |
928 | 188k | if (fontfile != NULL) { |
929 | 27.2k | code = pdfi_stream_to_buffer(ctx, (pdf_stream *) fontfile, &fbuf, &fbuflen); |
930 | 27.2k | pdfi_countdown(fontfile); |
931 | 27.2k | if (fbuflen == 0) { |
932 | 314 | gs_free_object(ctx->memory, fbuf, "pdfi_load_font(fbuf)"); |
933 | 314 | fbuf = NULL; |
934 | 314 | code = gs_note_error(gs_error_invalidfont); |
935 | 314 | } |
936 | 27.2k | } |
937 | | |
938 | 190k | while (1) { |
939 | 190k | if (fbuf != NULL) { |
940 | | /* fbuf overship passes to pdfi_load_font_buffer() */ |
941 | 29.4k | code = pdfi_load_font_buffer(ctx, fbuf, fbuflen, fftype, Subtype, findex, stream_dict, page_dict, font_dict, &ppdffont, cidfont); |
942 | | |
943 | 29.4k | if (code < 0 && substitute == font_embedded) { |
944 | 6.99k | if (ctx->args.pdfstoponerror == true) { |
945 | 0 | goto exit; |
946 | 0 | } |
947 | 6.99k | else { |
948 | 6.99k | char obj[129]; |
949 | 6.99k | pdfi_print_cstring(ctx, "**** Warning: cannot process embedded stream for font object "); |
950 | 6.99k | gs_snprintf(obj, 128, "%d %d\n", (int)font_dict->object_num, (int)font_dict->generation_num); |
951 | 6.99k | pdfi_print_cstring(ctx, obj); |
952 | 6.99k | pdfi_print_cstring(ctx, "**** Attempting to load a substitute font.\n"); |
953 | 6.99k | } |
954 | 6.99k | } |
955 | 29.4k | } |
956 | 161k | else { |
957 | 161k | code = gs_error_invalidfont; |
958 | 161k | } |
959 | | |
960 | 190k | if (code < 0 && code != gs_error_VMerror && substitute == font_embedded) { |
961 | 168k | substitute = font_from_file; |
962 | | |
963 | 168k | if (cidfont == true) { |
964 | 2.54k | code = pdfi_open_CIDFont_substitute_file(ctx, font_dict, fontdesc, false, &fbuf, &fbuflen, &findex); |
965 | 2.54k | if (code < 0) { |
966 | 2.54k | code = pdfi_open_CIDFont_substitute_file(ctx, font_dict, fontdesc, true, &fbuf, &fbuflen, &findex); |
967 | 2.54k | substitute |= font_substitute; |
968 | 2.54k | } |
969 | | |
970 | 2.54k | if (code < 0) |
971 | 13 | goto exit; |
972 | 2.54k | } |
973 | 165k | else { |
974 | 165k | code = pdfi_load_font_file(ctx, no_type_font, Subtype, stream_dict, page_dict, font_dict, fontdesc, false, &ppdffont); |
975 | 165k | if (code < 0) { |
976 | 152k | code = pdfi_load_font_file(ctx, no_type_font, Subtype, stream_dict, page_dict, font_dict, fontdesc, true, &ppdffont); |
977 | 152k | substitute |= font_substitute; |
978 | 152k | } |
979 | 165k | break; |
980 | 165k | } |
981 | 2.53k | continue; |
982 | 168k | } |
983 | 22.7k | break; |
984 | 190k | } |
985 | 188k | } |
986 | | |
987 | 195k | if (ppdffont == NULL || code < 0) { |
988 | 4.81k | *ppfont = NULL; |
989 | 4.81k | code = gs_note_error(gs_error_invalidfont); |
990 | 4.81k | } |
991 | 190k | else { |
992 | 190k | if (cidfont) { |
993 | 3.46k | ((pdf_cidfont_t *)ppdffont)->substitute = (substitute != font_embedded); |
994 | 3.46k | } |
995 | 187k | else { |
996 | 187k | if ((substitute & font_substitute) == font_substitute) |
997 | 151k | code = pdfi_font_match_glyph_widths(ppdffont); |
998 | 187k | } |
999 | 190k | *ppfont = (gs_font *)ppdffont->pfont; |
1000 | 190k | } |
1001 | | |
1002 | 197k | exit: |
1003 | 197k | pdfi_countdown(fontdesc); |
1004 | 197k | pdfi_countdown(Type); |
1005 | 197k | pdfi_countdown(Subtype); |
1006 | 197k | pdfi_countdown(ffsubtype); |
1007 | 197k | return code; |
1008 | 195k | } |
1009 | | |
1010 | | int pdfi_load_dict_font(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_dict *font_dict, double point_size) |
1011 | 360k | { |
1012 | 360k | int code; |
1013 | 360k | gs_font *pfont; |
1014 | 360k | pdf_font *pdfif; |
1015 | | |
1016 | 360k | switch (pdfi_type_of(font_dict)) { |
1017 | 304k | case PDF_FONT: |
1018 | 304k | pdfi_countup(font_dict); |
1019 | 304k | pfont = (gs_font *)((pdf_font *)font_dict)->pfont; |
1020 | 304k | code = 0; |
1021 | 304k | break; |
1022 | 49.4k | case PDF_DICT: |
1023 | 49.4k | code = pdfi_load_font(ctx, stream_dict, page_dict, font_dict, &pfont, false); |
1024 | 49.4k | break; |
1025 | 5.96k | default: |
1026 | 5.96k | code = gs_note_error(gs_error_typecheck); |
1027 | 5.96k | goto exit; |
1028 | 360k | } |
1029 | 354k | if (code < 0) |
1030 | 4.85k | goto exit; |
1031 | | |
1032 | | /* Everything looks good, set the font, unless it's the current font */ |
1033 | 349k | if (pfont != ctx->pgs->font) { |
1034 | 286k | code = pdfi_gs_setfont(ctx, pfont); |
1035 | 286k | } |
1036 | 349k | pdfif = (pdf_font *)pfont->client_data; |
1037 | 349k | pdfi_countdown(pdfif); |
1038 | | |
1039 | 349k | if (code < 0) |
1040 | 0 | goto exit; |
1041 | | |
1042 | 349k | code = gs_setPDFfontsize(ctx->pgs, point_size); |
1043 | 360k | exit: |
1044 | 360k | return code; |
1045 | 349k | } |
1046 | | |
1047 | | static int pdfi_load_resource_font(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict, pdf_name *fontname, double point_size) |
1048 | 492k | { |
1049 | 492k | int code; |
1050 | 492k | pdf_dict *font_dict = NULL; |
1051 | | |
1052 | 492k | if (pdfi_type_of(fontname) != PDF_NAME) { |
1053 | | /* Passing empty string here should fall back to a default font */ |
1054 | 4.73k | return pdfi_font_set_internal_string(ctx, "", point_size); |
1055 | 4.73k | } |
1056 | | |
1057 | | /* Look fontname up in the resources */ |
1058 | 487k | code = pdfi_loop_detector_mark(ctx); |
1059 | 487k | if (code < 0) |
1060 | 0 | goto exit; |
1061 | 487k | code = pdfi_find_resource(ctx, (unsigned char *)"Font", fontname, stream_dict, page_dict, (pdf_obj **)&font_dict); |
1062 | 487k | (void)pdfi_loop_detector_cleartomark(ctx); |
1063 | 487k | if (code < 0) |
1064 | 127k | goto exit; |
1065 | 360k | code = pdfi_load_dict_font(ctx, stream_dict, page_dict, font_dict, point_size); |
1066 | | |
1067 | 487k | exit: |
1068 | 487k | pdfi_countdown(font_dict); |
1069 | 487k | return code; |
1070 | 360k | } |
1071 | | |
1072 | | int pdfi_get_cidfont_glyph_metrics(gs_font *pfont, gs_glyph cid, double *widths, bool vertical) |
1073 | 437k | { |
1074 | 437k | pdf_font *pdffont = (pdf_font *)pfont->client_data; |
1075 | 437k | int i, code = 0; |
1076 | 437k | pdf_num *c = NULL, *c2 = NULL; |
1077 | 437k | pdf_obj *o = NULL; |
1078 | 437k | pdf_array *W = NULL, *W2 = NULL, *DW2 = NULL; |
1079 | 437k | double DW; |
1080 | | |
1081 | 437k | if (pdffont->pdfi_font_type == e_pdf_cidfont_type0) { |
1082 | 11.0k | pdf_cidfont_type0 *cidfont = (pdf_cidfont_type0 *)pdffont; |
1083 | 11.0k | DW = (double)cidfont->DW; |
1084 | 11.0k | DW2 = cidfont->DW2; |
1085 | 11.0k | W = cidfont->W; |
1086 | 11.0k | W2 = cidfont->W2; |
1087 | 11.0k | } |
1088 | 426k | else if (pdffont->pdfi_font_type == e_pdf_cidfont_type2) { |
1089 | 426k | pdf_cidfont_type2 *cidfont = (pdf_cidfont_type2 *)pdffont; |
1090 | 426k | DW = (double)cidfont->DW; |
1091 | 426k | DW2 = cidfont->DW2; |
1092 | 426k | W = cidfont->W; |
1093 | 426k | W2 = cidfont->W2; |
1094 | 426k | } |
1095 | 0 | else { |
1096 | 0 | return_error(gs_error_invalidfont); |
1097 | 0 | } |
1098 | | |
1099 | 437k | widths[GLYPH_W0_WIDTH_INDEX] = DW; |
1100 | 437k | widths[GLYPH_W0_HEIGHT_INDEX] = 0; |
1101 | 437k | if (W != NULL) { |
1102 | 421k | i = 0; |
1103 | | |
1104 | 6.37M | while(1) { |
1105 | 6.37M | pdf_obj_type type; |
1106 | | |
1107 | 6.37M | if (i + 1>= W->size) break; |
1108 | 6.33M | code = pdfi_array_get_type(pdffont->ctx, W, i, PDF_INT, (pdf_obj **)&c); |
1109 | 6.33M | if (code < 0) goto cleanup; |
1110 | | |
1111 | 6.33M | code = pdfi_array_get(pdffont->ctx, W, i + 1, &o); |
1112 | 6.33M | if (code < 0) goto cleanup; |
1113 | | |
1114 | 6.33M | type = pdfi_type_of(o); |
1115 | 6.33M | if (type == PDF_INT) { |
1116 | 1.02M | double d; |
1117 | 1.02M | c2 = (pdf_num *)o; |
1118 | 1.02M | o = NULL; |
1119 | 1.02M | if (i + 2 >= W->size){ |
1120 | | /* We countdown and NULL c, c2 and o after exit from the loop |
1121 | | * in order to avoid doing so in the break statements |
1122 | | */ |
1123 | 83 | break; |
1124 | 83 | } |
1125 | | |
1126 | 1.02M | code = pdfi_array_get_number(pdffont->ctx, W, i + 2, &d); |
1127 | 1.02M | if (code < 0) goto cleanup; |
1128 | 1.02M | if (cid >= c->value.i && cid <= c2->value.i) { |
1129 | 67.0k | widths[GLYPH_W0_WIDTH_INDEX] = d; |
1130 | 67.0k | widths[GLYPH_W0_HEIGHT_INDEX] = 0.0; |
1131 | | /* We countdown and NULL c, c2 and o after exit from the loop |
1132 | | * in order to avoid doing so in the break statements |
1133 | | */ |
1134 | 67.0k | break; |
1135 | 67.0k | } |
1136 | 961k | else { |
1137 | 961k | i += 3; |
1138 | 961k | pdfi_countdown(c2); |
1139 | 961k | pdfi_countdown(c); |
1140 | 961k | c = c2 = NULL; |
1141 | 961k | continue; |
1142 | 961k | } |
1143 | 1.02M | } |
1144 | 5.30M | else if (type == PDF_ARRAY) { |
1145 | 5.30M | pdf_array *a = (pdf_array *)o; |
1146 | 5.30M | o = NULL; |
1147 | 5.30M | if (cid >= c->value.i && cid < c->value.i + a->size) { |
1148 | 311k | code = pdfi_array_get_number(pdffont->ctx, a, cid - c->value.i, &widths[GLYPH_W0_WIDTH_INDEX]); |
1149 | 311k | if (code >= 0) { |
1150 | 311k | pdfi_countdown(a); |
1151 | 311k | widths[GLYPH_W0_HEIGHT_INDEX] = 0.0; |
1152 | | /* We countdown and NULL c, c2 and o on exit from the loop |
1153 | | * in order to avoid doing so in the break statements |
1154 | | */ |
1155 | 311k | break; |
1156 | 311k | } |
1157 | 311k | } |
1158 | 4.99M | pdfi_countdown(a); |
1159 | 4.99M | pdfi_countdown(c); |
1160 | 4.99M | c = NULL; |
1161 | 4.99M | i += 2; |
1162 | 4.99M | continue; |
1163 | 5.30M | } |
1164 | 45 | else { |
1165 | 45 | code = gs_note_error(gs_error_typecheck); |
1166 | 45 | goto cleanup; |
1167 | 45 | } |
1168 | 6.33M | } |
1169 | 420k | pdfi_countdown(c2); |
1170 | 420k | pdfi_countdown(c); |
1171 | 420k | pdfi_countdown(o); |
1172 | 420k | c = c2 = NULL; |
1173 | 420k | o = NULL; |
1174 | 420k | } |
1175 | | |
1176 | 437k | if (vertical) { |
1177 | | /* Default default <sigh>! */ |
1178 | 437k | widths[GLYPH_W1_WIDTH_INDEX] = 0; |
1179 | 437k | widths[GLYPH_W1_HEIGHT_INDEX] = -1000.0; |
1180 | 437k | widths[GLYPH_W1_V_X_INDEX] = (widths[GLYPH_W0_WIDTH_INDEX] / 2.0); |
1181 | 437k | widths[GLYPH_W1_V_Y_INDEX] = 880.0; |
1182 | | |
1183 | 437k | if (DW2 != NULL && pdfi_type_of(DW2) == PDF_ARRAY |
1184 | 437k | && DW2->size >= 2) { |
1185 | 860 | code = pdfi_array_get_number(pdffont->ctx, (pdf_array *)DW2, 0, &widths[GLYPH_W1_V_Y_INDEX]); |
1186 | 860 | if (code >= 0) |
1187 | 860 | code = pdfi_array_get_number(pdffont->ctx, (pdf_array *)DW2, 1, &widths[GLYPH_W1_HEIGHT_INDEX]); |
1188 | 860 | if (code >= 0) { |
1189 | 860 | widths[GLYPH_W1_V_X_INDEX] = widths[GLYPH_W0_WIDTH_INDEX] / 2.0; |
1190 | 860 | widths[GLYPH_W1_WIDTH_INDEX] = 0.0; |
1191 | 860 | } |
1192 | 860 | } |
1193 | 437k | if (W2 != NULL && pdfi_type_of(W2) == PDF_ARRAY) { |
1194 | 0 | i = 0; |
1195 | 0 | while(1) { |
1196 | 0 | pdf_obj_type type; |
1197 | 0 | if (i + 1 >= W2->size) break; |
1198 | 0 | (void)pdfi_array_get(pdffont->ctx, W2, i, (pdf_obj **)&c); |
1199 | 0 | if (pdfi_type_of(c) != PDF_INT) { |
1200 | 0 | code = gs_note_error(gs_error_typecheck); |
1201 | 0 | goto cleanup; |
1202 | 0 | } |
1203 | 0 | code = pdfi_array_get(pdffont->ctx, W2, i + 1, (pdf_obj **)&o); |
1204 | 0 | if (code < 0) goto cleanup; |
1205 | 0 | type = pdfi_type_of(o); |
1206 | 0 | if (type == PDF_INT) { |
1207 | 0 | if (cid >= c->value.i && cid <= ((pdf_num *)o)->value.i) { |
1208 | 0 | if (i + 4 >= W2->size) { |
1209 | | /* We countdown and NULL c, and o on exit from the function |
1210 | | * so we don't need to do so in the break statements |
1211 | | */ |
1212 | 0 | break; |
1213 | 0 | } |
1214 | 0 | code = pdfi_array_get_number(pdffont->ctx, W2, i + 1, &widths[GLYPH_W1_HEIGHT_INDEX]); |
1215 | 0 | if (code < 0) goto cleanup; |
1216 | 0 | code = pdfi_array_get_number(pdffont->ctx, W2, i + 1, &widths[GLYPH_W1_V_X_INDEX]); |
1217 | 0 | if (code < 0) goto cleanup; |
1218 | 0 | code = pdfi_array_get_number(pdffont->ctx, W2, i + 1, &widths[GLYPH_W1_V_Y_INDEX]); |
1219 | 0 | if (code < 0) goto cleanup; |
1220 | | /* We countdown and NULL c, and o on exit from the function |
1221 | | * so we don't need to do so in the break statements |
1222 | | */ |
1223 | 0 | break; |
1224 | 0 | } |
1225 | 0 | i += 5; |
1226 | 0 | } |
1227 | 0 | else if (type == PDF_ARRAY) { |
1228 | 0 | pdf_array *a = (pdf_array *)o; |
1229 | 0 | int l = a->size - (a->size % 3); |
1230 | 0 | o = NULL; |
1231 | 0 | if (cid >= c->value.i && cid < c->value.i + (l / 3)) { |
1232 | 0 | int index = (cid - c->value.i) * 3; |
1233 | 0 | code = pdfi_array_get_number(pdffont->ctx, a, index, &widths[GLYPH_W1_HEIGHT_INDEX]); |
1234 | 0 | if (code < 0) { |
1235 | 0 | pdfi_countdown(a); |
1236 | 0 | goto cleanup; |
1237 | 0 | } |
1238 | 0 | code = pdfi_array_get_number(pdffont->ctx, a, index + 1, &widths[GLYPH_W1_V_X_INDEX]); |
1239 | 0 | if (code < 0) { |
1240 | 0 | pdfi_countdown(a); |
1241 | 0 | goto cleanup; |
1242 | 0 | } |
1243 | 0 | code = pdfi_array_get_number(pdffont->ctx, a, index + 2, &widths[GLYPH_W1_V_Y_INDEX]); |
1244 | 0 | pdfi_countdown(a); |
1245 | 0 | if (code < 0) goto cleanup; |
1246 | | |
1247 | | /* We countdown and NULL c, and o on exit from the function |
1248 | | * so we don't need to do so in the break statements |
1249 | | */ |
1250 | 0 | break; |
1251 | 0 | } else |
1252 | 0 | pdfi_countdown(a); |
1253 | 0 | i += 2; |
1254 | 0 | } |
1255 | 0 | else { |
1256 | 0 | code = gs_note_error(gs_error_typecheck); |
1257 | 0 | goto cleanup; |
1258 | 0 | } |
1259 | 0 | pdfi_countdown(o); |
1260 | 0 | pdfi_countdown(c); |
1261 | 0 | o = NULL; |
1262 | 0 | c = NULL; |
1263 | 0 | } |
1264 | 0 | } |
1265 | 437k | } |
1266 | | |
1267 | 437k | cleanup: |
1268 | 437k | pdfi_countdown(c2); |
1269 | 437k | pdfi_countdown(c); |
1270 | 437k | pdfi_countdown(o); |
1271 | | |
1272 | 437k | return code; |
1273 | 437k | } |
1274 | | |
1275 | | int pdfi_d0(pdf_context *ctx) |
1276 | 207 | { |
1277 | 207 | int code = 0, gsave_level = 0; |
1278 | 207 | double width[2]; |
1279 | | |
1280 | 207 | if (ctx->text.inside_CharProc == false) |
1281 | 147 | pdfi_set_warning(ctx, 0, NULL, W_PDF_NOTINCHARPROC, "pdfi_d0", NULL); |
1282 | | |
1283 | 207 | ctx->text.CharProc_d_type = pdf_type3_d0; |
1284 | | |
1285 | 207 | if (pdfi_count_stack(ctx) < 2) { |
1286 | 61 | code = gs_note_error(gs_error_stackunderflow); |
1287 | 61 | goto d0_error; |
1288 | 61 | } |
1289 | | |
1290 | 146 | if (pdfi_type_of(ctx->stack_top[-1]) != PDF_INT && pdfi_type_of(ctx->stack_top[-1]) != PDF_REAL) { |
1291 | 4 | code = gs_note_error(gs_error_typecheck); |
1292 | 4 | goto d0_error; |
1293 | 4 | } |
1294 | 142 | if (pdfi_type_of(ctx->stack_top[-2]) != PDF_INT && pdfi_type_of(ctx->stack_top[-2]) != PDF_REAL) { |
1295 | 28 | code = gs_note_error(gs_error_typecheck); |
1296 | 28 | goto d0_error; |
1297 | 28 | } |
1298 | 114 | if(ctx->text.current_enum == NULL) { |
1299 | 54 | code = gs_note_error(gs_error_undefined); |
1300 | 54 | goto d0_error; |
1301 | 54 | } |
1302 | | |
1303 | 60 | if (pdfi_type_of(ctx->stack_top[-1]) == PDF_INT) |
1304 | 60 | width[0] = (double)((pdf_num *)ctx->stack_top[-1])->value.i; |
1305 | 0 | else |
1306 | 0 | width[0] = ((pdf_num *)ctx->stack_top[-1])->value.d; |
1307 | 60 | if (pdfi_type_of(ctx->stack_top[-2]) == PDF_INT) |
1308 | 60 | width[1] = (double)((pdf_num *)ctx->stack_top[-1])->value.i; |
1309 | 0 | else |
1310 | 0 | width[1] = ((pdf_num *)ctx->stack_top[-1])->value.d; |
1311 | | |
1312 | 60 | gsave_level = ctx->pgs->level; |
1313 | | |
1314 | | /* |
1315 | | * We don't intend to retain this, instead we will use (effectively) xyshow to apply |
1316 | | * width overrides at the text level. |
1317 | | if (font && font->Widths && ctx->current_chr >= font->FirstChar && ctx->current_chr <= font->LastChar) |
1318 | | width[0] = font->Widths[font->ctx->current_chr - font->FirstChar]; |
1319 | | */ |
1320 | | |
1321 | 60 | if (ctx->text.current_enum == NULL) { |
1322 | 0 | code = gs_note_error(gs_error_unknownerror); |
1323 | 0 | goto d0_error; |
1324 | 0 | } |
1325 | | |
1326 | 60 | code = gs_text_setcharwidth(ctx->text.current_enum, width); |
1327 | | |
1328 | | /* Nasty hackery. setcachedevice potentially pushes a new device into the graphics state |
1329 | | * and there's no way to remove that device again without grestore'ing back to a point |
1330 | | * before the device was loaded. To facilitate this, setcachedevice will do a gs_gsave() |
1331 | | * before changing the device. Note, the grestore for this is done back in show_update() |
1332 | | * which is not reached until after the CharProc has been executed. |
1333 | | * |
1334 | | * This is a problem for us when running a PDF content stream, because after running the |
1335 | | * stream we check the gsave level and, if its not the same as it was when we started |
1336 | | * the stream, we pdfi_grestore() back until it is. This mismatch of the gsave levels |
1337 | | * causes all sorts of trouble with the font and we can end up counting the pdf_font |
1338 | | * object down and discarding the font we're tryign to use. |
1339 | | * |
1340 | | * The solution (ugly though it is) is to patch up the saved gsave_level in the |
1341 | | * context to expect that we have one more gsave level on exit. That wasy we won't |
1342 | | * try and pdf_grestore() back to an earlier point. |
1343 | | */ |
1344 | 60 | if (ctx->pgs->level > gsave_level) |
1345 | 0 | ctx->current_stream_save.gsave_level += ctx->pgs->level - gsave_level; |
1346 | | |
1347 | 60 | if (code < 0) |
1348 | 0 | goto d0_error; |
1349 | 60 | pdfi_pop(ctx, 2); |
1350 | 60 | return 0; |
1351 | | |
1352 | 147 | d0_error: |
1353 | 147 | pdfi_clearstack(ctx); |
1354 | 147 | return code; |
1355 | 60 | } |
1356 | | |
1357 | | int pdfi_d1(pdf_context *ctx) |
1358 | 7.10k | { |
1359 | 7.10k | int code = 0, gsave_level; |
1360 | 7.10k | double wbox[6]; |
1361 | | |
1362 | 7.10k | if (ctx->text.inside_CharProc == false) |
1363 | 52 | pdfi_set_warning(ctx, 0, NULL, W_PDF_NOTINCHARPROC, "pdfi_d1", NULL); |
1364 | | |
1365 | 7.10k | ctx->text.CharProc_d_type = pdf_type3_d1; |
1366 | | |
1367 | 7.10k | code = pdfi_destack_reals(ctx, wbox, 6); |
1368 | 7.10k | if (code < 0) |
1369 | 61 | goto d1_error; |
1370 | | |
1371 | | /* |
1372 | | * We don't intend to retain this, instead we will use (effectively) xyshow to apply |
1373 | | * width overrides at the text level. |
1374 | | if (font && font->Widths && ctx->current_chr >= font->FirstChar && ctx->current_chr <= font->LastChar) |
1375 | | wbox[0] = font->Widths[font->ctx->current_chr - font->FirstChar]; |
1376 | | */ |
1377 | | |
1378 | 7.03k | gsave_level = ctx->pgs->level; |
1379 | | |
1380 | 7.03k | if (ctx->text.current_enum == NULL) { |
1381 | 16 | code = gs_note_error(gs_error_unknownerror); |
1382 | 16 | goto d1_error; |
1383 | 16 | } |
1384 | | |
1385 | 7.02k | code = gs_text_setcachedevice(ctx->text.current_enum, wbox); |
1386 | | |
1387 | | /* See the comment immediately after gs_text_setcachedvice() in pdfi_d0 above */ |
1388 | 7.02k | if (ctx->pgs->level > gsave_level) |
1389 | 6.15k | ctx->current_stream_save.gsave_level += ctx->pgs->level - gsave_level; |
1390 | | |
1391 | 7.02k | if (code < 0) |
1392 | 0 | goto d1_error; |
1393 | 7.02k | return 0; |
1394 | | |
1395 | 77 | d1_error: |
1396 | 77 | pdfi_clearstack(ctx); |
1397 | 77 | return code; |
1398 | 7.02k | } |
1399 | | |
1400 | | int pdfi_Tf(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) |
1401 | 498k | { |
1402 | 498k | double point_size = 0; |
1403 | 498k | pdf_obj *point_arg = NULL; |
1404 | 498k | int code = 0; |
1405 | 498k | pdf_name *fontname = NULL; |
1406 | | |
1407 | 498k | if (pdfi_count_stack(ctx) < 2) { |
1408 | 5.28k | pdfi_clearstack(ctx); |
1409 | 5.28k | return_error(gs_error_stackunderflow); |
1410 | 5.28k | } |
1411 | | |
1412 | | /* Get refs to the args and pop them */ |
1413 | 493k | point_arg = ctx->stack_top[-1]; |
1414 | 493k | pdfi_countup(point_arg); |
1415 | 493k | fontname = (pdf_name *)ctx->stack_top[-2]; |
1416 | 493k | pdfi_countup(fontname); |
1417 | 493k | pdfi_pop(ctx, 2); |
1418 | | |
1419 | | /* Get the point_size */ |
1420 | 493k | code = pdfi_obj_to_real(ctx, point_arg, &point_size); |
1421 | 493k | if (code < 0) |
1422 | 1.11k | goto exit0; |
1423 | | |
1424 | 492k | code = pdfi_load_resource_font(ctx, stream_dict, page_dict, fontname, point_size); |
1425 | | |
1426 | | /* If we failed to load font, try to load an internal one */ |
1427 | 492k | if (code < 0) |
1428 | 138k | code = pdfi_font_set_internal_name(ctx, fontname, point_size); |
1429 | 493k | exit0: |
1430 | 493k | pdfi_countdown(fontname); |
1431 | 493k | pdfi_countdown(point_arg); |
1432 | 493k | return code; |
1433 | 492k | } |
1434 | | |
1435 | | int pdfi_free_font(pdf_obj *font) |
1436 | 217k | { |
1437 | 217k | pdf_font *f = (pdf_font *)font; |
1438 | | |
1439 | 217k | switch (f->pdfi_font_type) { |
1440 | 4.02k | case e_pdf_font_type0: |
1441 | 4.02k | return pdfi_free_font_type0((pdf_obj *)font); |
1442 | 0 | break; |
1443 | 189k | case e_pdf_font_type1: |
1444 | 189k | return pdfi_free_font_type1((pdf_obj *)font); |
1445 | 0 | break; |
1446 | 2.98k | case e_pdf_font_cff: |
1447 | 2.98k | return pdfi_free_font_cff((pdf_obj *)font); |
1448 | 622 | case e_pdf_font_type3: |
1449 | 622 | return pdfi_free_font_type3((pdf_obj *)font); |
1450 | 0 | break; |
1451 | 16.8k | case e_pdf_font_truetype: |
1452 | 16.8k | return pdfi_free_font_truetype((pdf_obj *)font); |
1453 | 0 | break; |
1454 | 3.43k | case e_pdf_cidfont_type2: |
1455 | 3.43k | return pdfi_free_font_cidtype2((pdf_obj *)font); |
1456 | 0 | break; |
1457 | 497 | case e_pdf_cidfont_type0: |
1458 | 497 | return pdfi_free_font_cidtype0((pdf_obj *)font); |
1459 | 0 | break; |
1460 | 0 | case e_pdf_cidfont_type1: |
1461 | 0 | case e_pdf_cidfont_type4: |
1462 | 0 | default: |
1463 | 0 | return gs_note_error(gs_error_typecheck); |
1464 | 0 | break; |
1465 | 217k | } |
1466 | 0 | return 0; |
1467 | 217k | } |
1468 | | |
1469 | | static inline int pdfi_encoding_name_to_index(pdf_name *name) |
1470 | 59.8k | { |
1471 | 59.8k | int ind = gs_error_undefined; |
1472 | 59.8k | if (pdfi_type_of(name) == PDF_NAME) { |
1473 | 59.8k | if (pdfi_name_is(name, "StandardEncoding")) { |
1474 | 26.2k | ind = ENCODING_INDEX_STANDARD; |
1475 | 33.5k | } else { |
1476 | 33.5k | if (pdfi_name_is(name, "WinAnsiEncoding")){ |
1477 | 26.6k | ind = ENCODING_INDEX_WINANSI; |
1478 | 26.6k | } else { |
1479 | 6.90k | if (pdfi_name_is(name, "MacRomanEncoding")){ |
1480 | 6.70k | ind = ENCODING_INDEX_MACROMAN; |
1481 | 6.70k | } else { |
1482 | 201 | if (pdfi_name_is(name, "MacExpertEncoding")){ |
1483 | 10 | ind = ENCODING_INDEX_MACEXPERT; |
1484 | 10 | } |
1485 | 201 | } |
1486 | 6.90k | } |
1487 | 33.5k | } |
1488 | 59.8k | } |
1489 | 59.8k | return ind; |
1490 | 59.8k | } |
1491 | | |
1492 | | /* |
1493 | | * Routine to fill in an array with each of the glyph names from a given |
1494 | | * 'standard' Encoding. |
1495 | | */ |
1496 | | static int pdfi_build_Encoding(pdf_context *ctx, pdf_name *name, pdf_array *Encoding) |
1497 | 58.9k | { |
1498 | 58.9k | int i, code = 0; |
1499 | 58.9k | unsigned char gs_encoding; |
1500 | 58.9k | gs_glyph temp; |
1501 | 58.9k | gs_const_string str; |
1502 | 58.9k | pdf_name *n = NULL; |
1503 | | |
1504 | 58.9k | if (pdfi_array_size(Encoding) < 256) |
1505 | 0 | return gs_note_error(gs_error_rangecheck); |
1506 | | |
1507 | 58.9k | code = pdfi_encoding_name_to_index(name); |
1508 | 58.9k | if (code < 0) |
1509 | 189 | return code; |
1510 | 58.7k | gs_encoding = (unsigned char)code; |
1511 | 58.7k | code = 0; |
1512 | | |
1513 | 15.1M | for (i = 0;i<256;i++) { |
1514 | 15.0M | temp = gs_c_known_encode(i, gs_encoding); |
1515 | 15.0M | gs_c_glyph_name(temp, &str); |
1516 | 15.0M | code = pdfi_name_alloc(ctx, (byte *)str.data, str.size, (pdf_obj **)&n); |
1517 | 15.0M | if (code < 0) |
1518 | 0 | return code; |
1519 | 15.0M | pdfi_countup(n); |
1520 | 15.0M | code = pdfi_array_put(ctx, Encoding, (uint64_t)i, (pdf_obj *)n); |
1521 | 15.0M | pdfi_countdown(n); |
1522 | 15.0M | if (code < 0) |
1523 | 0 | return code; |
1524 | 15.0M | } |
1525 | 58.7k | return 0; |
1526 | 58.7k | } |
1527 | | |
1528 | | /* |
1529 | | * Create and fill in a pdf_array with an Encoding for a font. pdf_Encoding must be either |
1530 | | * a name (eg StandardEncoding) or a dictionary. If its a name we use that to create the |
1531 | | * entries, if its a dictionary we start by getting the BaseEncoding and using that to |
1532 | | * create an array of glyph names as above, *or* for a symbolic font, we use the "predef_Encoding" |
1533 | | * which is the encoding from the font description itself (i.e. the /Encoding array |
1534 | | * from a Type 1 font. We then get the Differences array from the dictionary and use that to |
1535 | | * refine the Encoding. |
1536 | | */ |
1537 | | int pdfi_create_Encoding(pdf_context *ctx, pdf_obj *pdf_Encoding, pdf_obj *font_Encoding, pdf_obj **Encoding) |
1538 | 62.5k | { |
1539 | 62.5k | int code = 0, i; |
1540 | | |
1541 | 62.5k | code = pdfi_array_alloc(ctx, 256, (pdf_array **)Encoding); |
1542 | 62.5k | if (code < 0) |
1543 | 0 | return code; |
1544 | 62.5k | pdfi_countup(*Encoding); |
1545 | | |
1546 | 62.5k | switch (pdfi_type_of(pdf_Encoding)) { |
1547 | 53.6k | case PDF_NAME: |
1548 | 53.6k | code = pdfi_build_Encoding(ctx, (pdf_name *)pdf_Encoding, (pdf_array *)*Encoding); |
1549 | 53.6k | if (code < 0) { |
1550 | 189 | pdfi_countdown(*Encoding); |
1551 | 189 | *Encoding = NULL; |
1552 | 189 | return code; |
1553 | 189 | } |
1554 | 53.4k | break; |
1555 | 53.4k | case PDF_DICT: |
1556 | 8.90k | { |
1557 | 8.90k | pdf_name *n = NULL; |
1558 | 8.90k | pdf_array *a = NULL; |
1559 | 8.90k | pdf_obj *o = NULL; |
1560 | 8.90k | int offset = 0; |
1561 | 8.90k | bool b_e_known; |
1562 | | |
1563 | 8.90k | if (pdfi_type_of(pdf_Encoding) == PDF_DICT) { |
1564 | 8.90k | code = pdfi_dict_known(ctx, (pdf_dict *)pdf_Encoding, "BaseEncoding", &b_e_known); |
1565 | 8.90k | if (code < 0) |
1566 | 0 | b_e_known = false; |
1567 | 8.90k | } |
1568 | 0 | else { |
1569 | 0 | b_e_known = false; |
1570 | 0 | } |
1571 | | |
1572 | 8.90k | if (b_e_known == false && font_Encoding != NULL && pdfi_type_of(font_Encoding) == PDF_ARRAY) { |
1573 | 3.56k | pdf_array *fenc = (pdf_array *)font_Encoding; |
1574 | 916k | for (i = 0; i < pdfi_array_size(fenc) && code >= 0; i++) { |
1575 | 913k | code = pdfi_array_get(ctx, fenc, (uint64_t)i, &o); |
1576 | 913k | if (code >= 0) |
1577 | 913k | code = pdfi_array_put(ctx, (pdf_array *)*Encoding, (uint64_t)i, o); |
1578 | 913k | pdfi_countdown(o); |
1579 | 913k | } |
1580 | 3.56k | if (code < 0) { |
1581 | 0 | pdfi_countdown(*Encoding); |
1582 | 0 | *Encoding = NULL; |
1583 | 0 | return code; |
1584 | 0 | } |
1585 | 3.56k | } |
1586 | 5.33k | else { |
1587 | 5.33k | code = pdfi_dict_get(ctx, (pdf_dict *)pdf_Encoding, "BaseEncoding", (pdf_obj **)&n); |
1588 | 5.33k | if (code >= 0) { |
1589 | 860 | if (pdfi_encoding_name_to_index(n) < 0) { |
1590 | 2 | pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_FONT_BASEENC, "pdfi_create_Encoding", NULL); |
1591 | 2 | pdfi_countdown(n); |
1592 | 2 | n = NULL; |
1593 | 2 | code = gs_error_undefined; |
1594 | 2 | } |
1595 | 858 | else if (pdfi_name_is(n, "StandardEncoding") == true) { |
1596 | 0 | pdfi_set_warning(ctx, 0, NULL, W_PDF_INVALID_FONT_BASEENC, "pdfi_create_Encoding", NULL); |
1597 | 0 | } |
1598 | 860 | } |
1599 | | |
1600 | 5.33k | if (code < 0) { |
1601 | 4.47k | code = pdfi_name_alloc(ctx, (byte *)"StandardEncoding", 16, (pdf_obj **)&n); |
1602 | 4.47k | if (code < 0) { |
1603 | 0 | pdfi_countdown(*Encoding); |
1604 | 0 | *Encoding = NULL; |
1605 | 0 | return code; |
1606 | 0 | } |
1607 | 4.47k | pdfi_countup(n); |
1608 | 4.47k | } |
1609 | | |
1610 | 5.33k | code = pdfi_build_Encoding(ctx, n, (pdf_array *)*Encoding); |
1611 | 5.33k | if (code < 0) { |
1612 | 0 | pdfi_countdown(*Encoding); |
1613 | 0 | *Encoding = NULL; |
1614 | 0 | pdfi_countdown(n); |
1615 | 0 | return code; |
1616 | 0 | } |
1617 | 5.33k | pdfi_countdown(n); |
1618 | 5.33k | } |
1619 | 8.90k | code = pdfi_dict_knownget_type(ctx, (pdf_dict *)pdf_Encoding, "Differences", PDF_ARRAY, (pdf_obj **)&a); |
1620 | 8.90k | if (code <= 0) { |
1621 | 100 | if (code < 0) { |
1622 | 0 | pdfi_countdown(*Encoding); |
1623 | 0 | *Encoding = NULL; |
1624 | 0 | } |
1625 | 100 | return code; |
1626 | 100 | } |
1627 | | |
1628 | 1.01M | for (i=0;i < pdfi_array_size(a);i++) { |
1629 | 1.00M | pdf_obj_type type; |
1630 | 1.00M | code = pdfi_array_get(ctx, a, (uint64_t)i, &o); |
1631 | 1.00M | if (code < 0) |
1632 | 0 | break; |
1633 | 1.00M | type = pdfi_type_of(o); |
1634 | 1.00M | if (type == PDF_NAME) { |
1635 | 923k | if (offset < pdfi_array_size((pdf_array *)*Encoding)) |
1636 | 922k | code = pdfi_array_put(ctx, (pdf_array *)*Encoding, (uint64_t)offset, o); |
1637 | 923k | pdfi_countdown(o); |
1638 | 923k | offset++; |
1639 | 923k | if (code < 0) |
1640 | 0 | break; |
1641 | 923k | } else if (type == PDF_INT) { |
1642 | 82.4k | offset = ((pdf_num *)o)->value.i; |
1643 | 82.4k | pdfi_countdown(o); |
1644 | 82.4k | } else { |
1645 | 11 | code = gs_note_error(gs_error_typecheck); |
1646 | 11 | pdfi_countdown(o); |
1647 | 11 | break; |
1648 | 11 | } |
1649 | 1.00M | } |
1650 | 8.80k | pdfi_countdown(a); |
1651 | 8.80k | if (code < 0) { |
1652 | 11 | pdfi_countdown(*Encoding); |
1653 | 11 | *Encoding = NULL; |
1654 | 11 | return code; |
1655 | 11 | } |
1656 | 8.78k | break; |
1657 | 8.80k | } |
1658 | 8.78k | default: |
1659 | 24 | pdfi_countdown(*Encoding); |
1660 | 24 | *Encoding = NULL; |
1661 | 24 | return gs_note_error(gs_error_typecheck); |
1662 | 62.5k | } |
1663 | 62.2k | return 0; |
1664 | 62.5k | } |
1665 | | |
1666 | | gs_glyph pdfi_encode_char(gs_font * pfont, gs_char chr, gs_glyph_space_t not_used) |
1667 | 36.8M | { |
1668 | 36.8M | int code; |
1669 | 36.8M | unsigned int nindex = 0; |
1670 | 36.8M | gs_glyph g = GS_NO_GLYPH; |
1671 | | |
1672 | 36.8M | if (pfont->FontType == ft_encrypted || pfont->FontType == ft_encrypted2 |
1673 | 36.8M | || pfont->FontType == ft_user_defined || pfont->FontType == ft_TrueType |
1674 | 36.8M | || pfont->FontType == ft_PDF_user_defined) { |
1675 | 36.8M | pdf_font *font = (pdf_font *)pfont->client_data; |
1676 | 36.8M | pdf_context *ctx = (pdf_context *)font->ctx; |
1677 | | |
1678 | 36.8M | if (font->Encoding != NULL) { /* safety */ |
1679 | 36.8M | pdf_name *GlyphName = NULL; |
1680 | 36.8M | code = pdfi_array_get(ctx, font->Encoding, (uint64_t)chr, (pdf_obj **)&GlyphName); |
1681 | 36.8M | if (code >= 0) { |
1682 | 36.8M | if (pdfi_type_of(GlyphName) != PDF_NAME) |
1683 | | /* Can't signal an error, just return the 'not found' case */ |
1684 | 0 | return g; |
1685 | | |
1686 | 36.8M | code = (*ctx->get_glyph_index)(pfont, (byte *)GlyphName->data, GlyphName->length, &nindex); |
1687 | 36.8M | pdfi_countdown(GlyphName); |
1688 | 36.8M | if (code >= 0) |
1689 | 36.8M | g = (gs_glyph)nindex; |
1690 | 36.8M | } |
1691 | 36.8M | } |
1692 | 36.8M | } |
1693 | | |
1694 | 36.8M | return g; |
1695 | 36.8M | } |
1696 | | |
1697 | | int pdfi_tounicode_char_to_unicode(pdf_context *ctx, pdf_cmap *tounicode, gs_glyph glyph, int ch, ushort *unicode_return, unsigned int length) |
1698 | 418k | { |
1699 | 418k | int i, l = 0; |
1700 | 418k | int code = gs_error_undefined; |
1701 | 418k | unsigned char *ucode = (unsigned char *)unicode_return; |
1702 | | |
1703 | 418k | if (tounicode != NULL) { |
1704 | 120k | gs_cmap_lookups_enum_t lenum; |
1705 | 120k | gs_cmap_lookups_enum_init((const gs_cmap_t *)tounicode->gscmap, 0, &lenum); |
1706 | 41.2M | while (l == 0 && gs_cmap_enum_next_lookup(ctx->memory, &lenum) == 0) { |
1707 | 41.0M | gs_cmap_lookups_enum_t counter = lenum; |
1708 | 82.1M | while (l == 0 && gs_cmap_enum_next_entry(&counter) == 0) { |
1709 | 41.0M | if (counter.entry.value_type == CODE_VALUE_CID) { |
1710 | 41.0M | unsigned int v = 0; |
1711 | 122M | for (i = 0; i < counter.entry.key_size; i++) { |
1712 | 81.5M | v |= (counter.entry.key[0][counter.entry.key_size - i - 1]) << (i * 8); |
1713 | 81.5M | } |
1714 | 41.0M | if (ch == v) { |
1715 | 111k | if (counter.entry.value.size == 1) { |
1716 | 0 | l = 2; |
1717 | 0 | if (ucode != NULL && length >= l) { |
1718 | 0 | ucode[0] = counter.entry.value.data[0]; |
1719 | 0 | ucode[1] = counter.entry.value.data[1]; |
1720 | 0 | } |
1721 | 0 | } |
1722 | 111k | else if (counter.entry.value.size == 2) { |
1723 | 111k | l = 2; |
1724 | 111k | if (ucode != NULL && length >= l) { |
1725 | 79.1k | ucode[0] = counter.entry.value.data[0]; |
1726 | 79.1k | ucode[1] = counter.entry.value.data[1]; |
1727 | 79.1k | } |
1728 | 111k | } |
1729 | 484 | else if (counter.entry.value.size == 3) { |
1730 | 8 | l = 4; |
1731 | 8 | if (ucode != NULL && length >= l) { |
1732 | 4 | ucode[0] = counter.entry.value.data[0]; |
1733 | 4 | ucode[1] = counter.entry.value.data[1]; |
1734 | 4 | ucode[2] = counter.entry.value.data[2]; |
1735 | 4 | ucode[3] = 0; |
1736 | 4 | } |
1737 | 8 | } |
1738 | 476 | else { |
1739 | 476 | l = 4; |
1740 | 476 | if (ucode != NULL && length >= l) { |
1741 | 444 | ucode[0] = counter.entry.value.data[0]; |
1742 | 444 | ucode[1] = counter.entry.value.data[1]; |
1743 | 444 | ucode[2] = counter.entry.value.data[1]; |
1744 | 444 | ucode[3] = counter.entry.value.data[3]; |
1745 | 444 | } |
1746 | 476 | } |
1747 | 111k | } |
1748 | 41.0M | } |
1749 | 41.0M | } |
1750 | 41.0M | } |
1751 | 120k | if (l > 0) |
1752 | 111k | code = l; |
1753 | 120k | } |
1754 | | |
1755 | 418k | return code; |
1756 | 418k | } |
1757 | | |
1758 | | /* Get the unicode valude for a glyph FIXME - not written yet |
1759 | | */ |
1760 | | int pdfi_decode_glyph(gs_font * font, gs_glyph glyph, int ch, ushort *unicode_return, unsigned int length) |
1761 | 310k | { |
1762 | 310k | pdf_font *pdffont = (pdf_font *)font->client_data; |
1763 | 310k | int code = 0; |
1764 | | |
1765 | 310k | if (pdffont->pdfi_font_type != e_pdf_cidfont_type0 && pdffont->pdfi_font_type != e_pdf_cidfont_type1 |
1766 | 310k | && pdffont->pdfi_font_type != e_pdf_cidfont_type2 && pdffont->pdfi_font_type != e_pdf_cidfont_type4) { |
1767 | 284k | code = pdfi_tounicode_char_to_unicode(pdffont->ctx, (pdf_cmap *)pdffont->ToUnicode, glyph, ch, unicode_return, length); |
1768 | 284k | } |
1769 | 310k | if (code < 0) code = 0; |
1770 | | |
1771 | 310k | return code; |
1772 | 310k | } |
1773 | | |
1774 | | int pdfi_glyph_index(gs_font *pfont, byte *str, uint size, uint *glyph) |
1775 | 0 | { |
1776 | 0 | int code = 0; |
1777 | 0 | pdf_font *font = (pdf_font *)pfont->client_data; |
1778 | |
|
1779 | 0 | code = pdfi_get_name_index(font->ctx, (char *)str, size, glyph); |
1780 | |
|
1781 | 0 | return code; |
1782 | 0 | } |
1783 | | |
1784 | | int pdfi_glyph_name(gs_font * pfont, gs_glyph glyph, gs_const_string * pstr) |
1785 | 0 | { |
1786 | 0 | int code = gs_error_invalidfont; |
1787 | |
|
1788 | 0 | if (pfont->FontType == ft_encrypted || pfont->FontType == ft_encrypted2 |
1789 | 0 | || pfont->FontType == ft_user_defined || pfont->FontType == ft_TrueType |
1790 | 0 | || pfont->FontType == ft_PDF_user_defined) { |
1791 | 0 | pdf_font *font = (pdf_font *)pfont->client_data; |
1792 | |
|
1793 | 0 | code = pdfi_name_from_index(font->ctx, glyph, (unsigned char **)&pstr->data, &pstr->size); |
1794 | 0 | } |
1795 | |
|
1796 | 0 | return code; |
1797 | 0 | } |
1798 | | |
1799 | | |
1800 | | static int pdfi_global_glyph_code(const gs_font *pfont, gs_const_string *gstr, gs_glyph *pglyph) |
1801 | 7 | { |
1802 | 7 | int code = 0; |
1803 | 7 | if (pfont->FontType == ft_encrypted) { |
1804 | 0 | code = pdfi_t1_global_glyph_code(pfont, gstr, pglyph); |
1805 | 0 | } |
1806 | 7 | else if (pfont->FontType == ft_encrypted2) { |
1807 | 7 | code = pdfi_cff_global_glyph_code(pfont, gstr, pglyph); |
1808 | 7 | } |
1809 | 0 | else { |
1810 | 0 | code = gs_note_error(gs_error_invalidaccess); |
1811 | 0 | } |
1812 | 7 | return code; |
1813 | 7 | } |
1814 | | |
1815 | | int pdfi_map_glyph_name_via_agl(pdf_dict *cstrings, pdf_name *gname, pdf_string **cstring) |
1816 | 128k | { |
1817 | 128k | single_glyph_list_t *sgl = (single_glyph_list_t *)&(SingleGlyphList); |
1818 | 128k | int i, code, ucode = gs_error_undefined; |
1819 | 128k | *cstring = NULL; |
1820 | | |
1821 | 128k | if (gname->length == 7 && strncmp((char *)gname->data, "uni", 3) == 0) { |
1822 | 384 | char u[5] = {0}; |
1823 | 384 | memcpy(u, gname->data + 3, 4); |
1824 | 384 | code = sscanf(u, "%x", &ucode); |
1825 | 384 | if (code <= 0) |
1826 | 0 | ucode = gs_error_undefined; |
1827 | 384 | } |
1828 | | |
1829 | 128k | if (ucode == gs_error_undefined) { |
1830 | 463M | for (i = 0; sgl[i].Glyph != 0x00; i++) { |
1831 | 463M | if (sgl[i].Glyph[0] == gname->data[0] |
1832 | 463M | && strlen(sgl[i].Glyph) == gname->length |
1833 | 463M | && !strncmp((char *)sgl[i].Glyph, (char *)gname->data, gname->length)) { |
1834 | 54.1k | ucode = (int)sgl[i].Unicode; |
1835 | 54.1k | break; |
1836 | 54.1k | } |
1837 | 463M | } |
1838 | 128k | } |
1839 | 128k | if (ucode > 0) { |
1840 | 228M | for (i = 0; sgl[i].Glyph != 0x00; i++) { |
1841 | 228M | if (sgl[i].Unicode == (unsigned short)ucode) { |
1842 | 54.8k | pdf_string *s; |
1843 | 54.8k | code = pdfi_dict_get((pdf_context *)cstrings->ctx, cstrings, (char *)sgl[i].Glyph, (pdf_obj **)&s); |
1844 | 54.8k | if (code >= 0) { |
1845 | 334 | *cstring = s; |
1846 | 334 | break; |
1847 | 334 | } |
1848 | 54.8k | } |
1849 | 228M | } |
1850 | 54.5k | if (*cstring == NULL) { |
1851 | 54.2k | char u[16] = {0}; |
1852 | 54.2k | code = gs_snprintf(u, 16, "uni%04x", ucode); |
1853 | 54.2k | if (code > 0) { |
1854 | 54.2k | pdf_string *s; |
1855 | 54.2k | code = pdfi_dict_get((pdf_context *)cstrings->ctx, cstrings, u, (pdf_obj **)&s); |
1856 | 54.2k | if (code >= 0) { |
1857 | 0 | *cstring = s; |
1858 | 0 | } |
1859 | 54.2k | } |
1860 | 54.2k | } |
1861 | 54.5k | } |
1862 | | |
1863 | 128k | if (*cstring == NULL) |
1864 | 128k | code = gs_note_error(gs_error_undefined); |
1865 | 334 | else |
1866 | 334 | code = 0; |
1867 | | |
1868 | 128k | return code; |
1869 | 128k | } |
1870 | | |
1871 | | int pdfi_init_font_directory(pdf_context *ctx) |
1872 | 40.8k | { |
1873 | 40.8k | ctx->font_dir = gs_font_dir_alloc2(ctx->memory, ctx->memory); |
1874 | 40.8k | if (ctx->font_dir == NULL) { |
1875 | 0 | return_error(gs_error_VMerror); |
1876 | 0 | } |
1877 | 40.8k | ctx->font_dir->global_glyph_code = pdfi_global_glyph_code; |
1878 | 40.8k | return 0; |
1879 | 40.8k | } |
1880 | | |
1881 | | /* Loads a (should be!) non-embedded font by name |
1882 | | Only currently works for Type 1 fonts set. |
1883 | | */ |
1884 | | int pdfi_load_font_by_name_string(pdf_context *ctx, const byte *fontname, size_t length, |
1885 | | pdf_obj **ppdffont) |
1886 | 143k | { |
1887 | 143k | pdf_obj *fname = NULL; |
1888 | 143k | pdf_obj *fontobjtype = NULL; |
1889 | 143k | pdf_dict *fdict = NULL; |
1890 | 143k | int code; |
1891 | 143k | gs_font *pgsfont = NULL; |
1892 | 143k | const char *fs = "Font"; |
1893 | | |
1894 | 143k | code = pdfi_name_alloc(ctx, (byte *)fontname, length, &fname); |
1895 | 143k | if (code < 0) |
1896 | 0 | return code; |
1897 | 143k | pdfi_countup(fname); |
1898 | | |
1899 | 143k | code = pdfi_name_alloc(ctx, (byte *)fs, strlen(fs), &fontobjtype); |
1900 | 143k | if (code < 0) |
1901 | 0 | goto exit; |
1902 | 143k | pdfi_countup(fontobjtype); |
1903 | | |
1904 | 143k | code = pdfi_dict_alloc(ctx, 1, &fdict); |
1905 | 143k | if (code < 0) |
1906 | 0 | goto exit; |
1907 | 143k | pdfi_countup(fdict); |
1908 | | |
1909 | 143k | code = pdfi_dict_put(ctx, fdict, "BaseFont", fname); |
1910 | 143k | if (code < 0) |
1911 | 0 | goto exit; |
1912 | | |
1913 | 143k | code = pdfi_dict_put(ctx, fdict, "Type", fontobjtype); |
1914 | 143k | if (code < 0) |
1915 | 0 | goto exit; |
1916 | | |
1917 | 143k | code = pdfi_load_font(ctx, NULL, NULL, fdict, &pgsfont, false); |
1918 | 143k | if (code < 0) |
1919 | 422 | goto exit; |
1920 | | |
1921 | 142k | *ppdffont = (pdf_obj *)pgsfont->client_data; |
1922 | | |
1923 | 143k | exit: |
1924 | 143k | pdfi_countdown(fontobjtype); |
1925 | 143k | pdfi_countdown(fname); |
1926 | 143k | pdfi_countdown(fdict); |
1927 | 143k | return code; |
1928 | 142k | } |
1929 | | |
1930 | | |
1931 | | int pdfi_font_create_widths(pdf_context *ctx, pdf_dict *fontdict, pdf_font *font, double scale) |
1932 | 188k | { |
1933 | 188k | int code = 0; |
1934 | 188k | pdf_obj *obj = NULL; |
1935 | 188k | int i; |
1936 | | |
1937 | 188k | font->Widths = NULL; |
1938 | | |
1939 | 188k | if (font->FontDescriptor != NULL) { |
1940 | 35.9k | code = pdfi_dict_knownget(ctx, font->FontDescriptor, "MissingWidth", &obj); |
1941 | 35.9k | if (code > 0) { |
1942 | 1.30k | if (pdfi_type_of(obj) == PDF_INT) { |
1943 | 1.30k | font->MissingWidth = ((pdf_num *) obj)->value.i * scale; |
1944 | 1.30k | } |
1945 | 0 | else if (pdfi_type_of(obj) == PDF_REAL) { |
1946 | 0 | font->MissingWidth = ((pdf_num *) obj)->value.d * scale; |
1947 | 0 | } |
1948 | 0 | else { |
1949 | 0 | font->MissingWidth = 0; |
1950 | 0 | } |
1951 | 1.30k | pdfi_countdown(obj); |
1952 | 1.30k | obj = NULL; |
1953 | 1.30k | } |
1954 | 34.6k | else { |
1955 | 34.6k | font->MissingWidth = 0; |
1956 | 34.6k | } |
1957 | 35.9k | } |
1958 | 152k | else { |
1959 | 152k | font->MissingWidth = 1000.0 * scale; |
1960 | 152k | } |
1961 | | |
1962 | 188k | code = pdfi_dict_knownget_type(ctx, fontdict, "Widths", PDF_ARRAY, (pdf_obj **)&obj); |
1963 | 188k | if (code > 0) { |
1964 | 37.0k | if (pdfi_array_size((pdf_array *)obj) < font->LastChar - font->FirstChar + 1) { |
1965 | 531 | code = gs_note_error(gs_error_rangecheck); |
1966 | 531 | goto error; |
1967 | 531 | } |
1968 | | |
1969 | 36.5k | font->Widths = (double *)gs_alloc_bytes(OBJ_MEMORY(font), sizeof(double) * (font->LastChar - font->FirstChar + 1), "pdfi_font_create_widths(Widths)"); |
1970 | 36.5k | if (font->Widths == NULL) { |
1971 | 0 | code = gs_note_error(gs_error_VMerror); |
1972 | 0 | goto error; |
1973 | 0 | } |
1974 | 36.5k | memset(font->Widths, 0x00, sizeof(double) * (font->LastChar - font->FirstChar + 1)); |
1975 | 4.24M | for (i = 0; i < (font->LastChar - font->FirstChar + 1); i++) { |
1976 | 4.20M | code = pdfi_array_get_number(ctx, (pdf_array *)obj, (uint64_t)i, &font->Widths[i]); |
1977 | 4.20M | if (code < 0) |
1978 | 60 | goto error; |
1979 | 4.20M | font->Widths[i] *= scale; |
1980 | 4.20M | } |
1981 | 36.5k | } |
1982 | 188k | error: |
1983 | 188k | pdfi_countdown(obj); |
1984 | 188k | if (code < 0) { |
1985 | 1.42k | gs_free_object(OBJ_MEMORY(font), font->Widths, "pdfi_font_create_widths(Widths)"); |
1986 | 1.42k | font->Widths = NULL; |
1987 | 1.42k | } |
1988 | 188k | return code; |
1989 | 188k | } |
1990 | | |
1991 | | void pdfi_font_set_first_last_char(pdf_context *ctx, pdf_dict *fontdict, pdf_font *font) |
1992 | 208k | { |
1993 | 208k | double f, l; |
1994 | 208k | int code; |
1995 | | |
1996 | 208k | if (fontdict == NULL) { |
1997 | 20.3k | f = (double)0; |
1998 | 20.3k | l = (double)255; |
1999 | 20.3k | } |
2000 | 188k | else { |
2001 | 188k | code = pdfi_dict_get_number(ctx, fontdict, "FirstChar", &f); |
2002 | 188k | if (code < 0 || f < 0 || f > 255) |
2003 | 150k | f = (double)0; |
2004 | | |
2005 | 188k | code = pdfi_dict_get_number(ctx, fontdict, "LastChar", &l); |
2006 | 188k | if (code < 0 || l < 0 || l > 255) |
2007 | 150k | l = (double)255; |
2008 | 188k | } |
2009 | 208k | if (f <= l) { |
2010 | 208k | font->FirstChar = f; |
2011 | 208k | font->LastChar = l; |
2012 | 208k | } |
2013 | 12 | else { |
2014 | 12 | font->FirstChar = 0; |
2015 | 12 | font->LastChar = 255; |
2016 | 12 | } |
2017 | 208k | } |
2018 | | |
2019 | | /* Patch or create a new XUID based on the existing UID/XUID, a simple hash |
2020 | | of the input file name and the font dictionary object number. |
2021 | | This allows improved glyph cache efficiency, also ensures pdfwrite understands |
2022 | | which fonts are repetitions, and which are different. |
2023 | | Currently cannot return an error - if we can't allocate the new XUID values array, |
2024 | | we just skip it, and assume the font is compliant. |
2025 | | */ |
2026 | | int pdfi_font_generate_pseudo_XUID(pdf_context *ctx, pdf_dict *fontdict, gs_font_base *pfont) |
2027 | 208k | { |
2028 | 208k | gs_const_string fn; |
2029 | 208k | int i; |
2030 | 208k | uint32_t hash = 0; |
2031 | 208k | long *xvalues; |
2032 | 208k | int xuidlen = 3; |
2033 | | |
2034 | 208k | sfilename(ctx->main_stream->s, &fn); |
2035 | 208k | if (fn.size > 0 && fontdict!= NULL && fontdict->object_num != 0) { |
2036 | 0 | for (i = 0; i < fn.size; i++) { |
2037 | 0 | hash = ((((hash & 0xf8000000) >> 27) ^ (hash << 5)) & 0x7ffffffff) ^ fn.data[i]; |
2038 | 0 | } |
2039 | 0 | hash = ((((hash & 0xf8000000) >> 27) ^ (hash << 5)) & 0x7ffffffff) ^ fontdict->object_num; |
2040 | 0 | if (uid_is_XUID(&pfont->UID)) |
2041 | 0 | xuidlen += uid_XUID_size(&pfont->UID); |
2042 | 0 | else if (uid_is_valid(&pfont->UID)) |
2043 | 0 | xuidlen++; |
2044 | |
|
2045 | 0 | xvalues = (long *)gs_alloc_bytes(pfont->memory, xuidlen * sizeof(long), "pdfi_font_generate_pseudo_XUID"); |
2046 | 0 | if (xvalues == NULL) { |
2047 | 0 | return 0; |
2048 | 0 | } |
2049 | 0 | xvalues[0] = 1000000; /* "Private" value */ |
2050 | 0 | xvalues[1] = hash; |
2051 | |
|
2052 | 0 | xvalues[2] = ctx->device_state.HighLevelDevice ? pfont->id : 0; |
2053 | |
|
2054 | 0 | if (uid_is_XUID(&pfont->UID)) { |
2055 | 0 | for (i = 0; i < uid_XUID_size(&pfont->UID); i++) { |
2056 | 0 | xvalues[i + 3] = uid_XUID_values(&pfont->UID)[i]; |
2057 | 0 | } |
2058 | 0 | uid_free(&pfont->UID, pfont->memory, "pdfi_font_generate_pseudo_XUID"); |
2059 | 0 | } |
2060 | 0 | else if (uid_is_valid(&pfont->UID)) |
2061 | 0 | xvalues[3] = pfont->UID.id; |
2062 | |
|
2063 | 0 | uid_set_XUID(&pfont->UID, xvalues, xuidlen); |
2064 | 0 | } |
2065 | 208k | return 0; |
2066 | 208k | } |
2067 | | |
2068 | | /* Convenience function for using fonts created by |
2069 | | pdfi_load_font_by_name_string |
2070 | | */ |
2071 | | int pdfi_set_font_internal(pdf_context *ctx, pdf_obj *fontobj, double point_size) |
2072 | 142k | { |
2073 | 142k | int code; |
2074 | 142k | pdf_font *pdffont = (pdf_font *)fontobj; |
2075 | | |
2076 | 142k | if (pdfi_type_of(pdffont) != PDF_FONT || pdffont->pfont == NULL) |
2077 | 0 | return_error(gs_error_invalidfont); |
2078 | | |
2079 | 142k | code = gs_setPDFfontsize(ctx->pgs, point_size); |
2080 | 142k | if (code < 0) |
2081 | 0 | return code; |
2082 | | |
2083 | 142k | return pdfi_gs_setfont(ctx, (gs_font *)pdffont->pfont); |
2084 | 142k | } |
2085 | | |
2086 | | /* Convenience function for setting font by name |
2087 | | * Keeps one ref to the font, which will be in the graphics state font ->client_data |
2088 | | */ |
2089 | | static int pdfi_font_set_internal_inner(pdf_context *ctx, const byte *fontname, size_t length, |
2090 | | double point_size) |
2091 | 143k | { |
2092 | 143k | int code = 0; |
2093 | 143k | pdf_obj *font = NULL; |
2094 | | |
2095 | | |
2096 | 143k | code = pdfi_load_font_by_name_string(ctx, fontname, length, &font); |
2097 | 143k | if (code < 0) goto exit; |
2098 | | |
2099 | 142k | code = pdfi_set_font_internal(ctx, font, point_size); |
2100 | | |
2101 | 143k | exit: |
2102 | 143k | pdfi_countdown(font); |
2103 | 143k | return code; |
2104 | 142k | } |
2105 | | |
2106 | | int pdfi_font_set_internal_string(pdf_context *ctx, const char *fontname, double point_size) |
2107 | 4.80k | { |
2108 | 4.80k | return pdfi_font_set_internal_inner(ctx, (const byte *)fontname, strlen(fontname), point_size); |
2109 | 4.80k | } |
2110 | | |
2111 | | int pdfi_font_set_internal_name(pdf_context *ctx, pdf_name *fontname, double point_size) |
2112 | 138k | { |
2113 | 138k | if (pdfi_type_of(fontname) != PDF_NAME) |
2114 | 0 | return_error(gs_error_typecheck); |
2115 | 138k | else |
2116 | 138k | return pdfi_font_set_internal_inner(ctx, fontname->data, fontname->length, point_size); |
2117 | 138k | } |