Commit | Line | Data |
---|---|---|
cac27b87 HG |
1 | --- ./texk/web2c/pdftexdir/pdftoepdf.cc 2016-11-25 18:09:21.000000000 +0000 |
2 | +++ ../pdftoepdf.cc 2018-01-23 08:50:08.583460101 +0000 | |
3 | @@ -1,5 +1,5 @@ | |
4 | /* | |
5 | -Copyright 1996-2016 Han The Thanh, <thanh@pdftex.org> | |
6 | +Copyright 1996-2017 Han The Thanh, <thanh@pdftex.org> | |
7 | ||
8 | This file is part of pdfTeX. | |
9 | ||
10 | @@ -17,6 +17,15 @@ | |
11 | with this program. If not, see <http://www.gnu.org/licenses/>. | |
12 | */ | |
13 | ||
14 | +/* | |
15 | +This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at | |
16 | +https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk | |
17 | +by Arch Linux. A little modifications are made to avoid a crash for | |
18 | +some kind of pdf images, such as figure_missing.pdf in gnuplot. | |
19 | +The poppler should be 0.59.0 or newer versions. | |
20 | +POPPLER_VERSION should be defined. | |
21 | +*/ | |
22 | + | |
23 | /* Do this early in order to avoid a conflict between | |
24 | MINGW32 <rpcndr.h> defining 'boolean' as 'unsigned char' and | |
25 | <kpathsea/types.h> defining Pascal's boolean as 'int'. | |
26 | @@ -39,10 +48,7 @@ | |
27 | #include <goo/gfile.h> | |
28 | #define GString GooString | |
29 | #else | |
30 | -#include <aconf.h> | |
31 | -#include <GString.h> | |
32 | -#include <gmem.h> | |
33 | -#include <gfile.h> | |
34 | +#error POPPLER_VERSION should be defined. | |
35 | #endif | |
36 | #include <assert.h> | |
37 | ||
38 | @@ -84,31 +90,6 @@ | |
39 | #define MASK_SUPPRESS_PTEX_PAGENUMBER 0x04 | |
40 | #define MASK_SUPPRESS_PTEX_INFODICT 0x08 | |
41 | ||
42 | -// PdfObject encapsulates the xpdf Object type, | |
43 | -// and properly frees its resources on destruction. | |
44 | -// Use obj-> to access members of the Object, | |
45 | -// and &obj to get a pointer to the object. | |
46 | -// It is no longer necessary to call Object::free explicitely. | |
47 | - | |
48 | -class PdfObject { | |
49 | - public: | |
50 | - PdfObject() { // nothing | |
51 | - } ~PdfObject() { | |
52 | - iObject.free(); | |
53 | - } | |
54 | - Object *operator->() { | |
55 | - return &iObject; | |
56 | - } | |
57 | - Object *operator&() { | |
58 | - return &iObject; | |
59 | - } | |
60 | - private: // no copying or assigning | |
61 | - PdfObject(const PdfObject &); | |
62 | - void operator=(const PdfObject &); | |
63 | - public: | |
64 | - Object iObject; | |
65 | -}; | |
66 | - | |
67 | // When copying the Resources of the selected page, all objects are copied | |
68 | // recusively top-down. Indirect objects however are not fetched during | |
69 | // copying, but get a new object number from pdfTeX and then will be | |
70 | @@ -212,18 +193,6 @@ | |
71 | delete pdf_doc; | |
72 | } | |
73 | ||
74 | -// Replacement for | |
75 | -// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; } | |
76 | - | |
77 | -static void initDictFromDict(PdfObject & obj, Dict * dict) | |
78 | -{ | |
79 | - obj->initDict(xref); | |
80 | - for (int i = 0, l = dict->getLength(); i < l; i++) { | |
81 | - Object obj1; | |
82 | - obj->dictAdd(copyString(dict->getKey(i)), dict->getValNF(i, &obj1)); | |
83 | - } | |
84 | -} | |
85 | - | |
86 | // -------------------------------------------------------------------- | |
87 | ||
88 | static int addEncoding(GfxFont * gfont) | |
89 | @@ -320,10 +289,10 @@ | |
90 | ||
91 | static void copyDictEntry(Object * obj, int i) | |
92 | { | |
93 | - PdfObject obj1; | |
94 | + Object obj1; | |
95 | copyName(obj->dictGetKey(i)); | |
96 | pdf_puts(" "); | |
97 | - obj->dictGetValNF(i, &obj1); | |
98 | + obj1 = obj->dictGetValNF(i); | |
99 | copyObject(&obj1); | |
100 | pdf_puts("\n"); | |
101 | } | |
102 | @@ -376,17 +345,17 @@ | |
103 | static void copyProcSet(Object * obj) | |
104 | { | |
105 | int i, l; | |
106 | - PdfObject procset; | |
107 | + Object procset; | |
108 | if (!obj->isArray()) | |
109 | pdftex_fail("PDF inclusion: invalid ProcSet array type <%s>", | |
110 | obj->getTypeName()); | |
111 | pdf_puts("/ProcSet [ "); | |
112 | for (i = 0, l = obj->arrayGetLength(); i < l; ++i) { | |
113 | - obj->arrayGetNF(i, &procset); | |
114 | - if (!procset->isName()) | |
115 | + procset = obj->arrayGetNF(i); | |
116 | + if (!procset.isName()) | |
117 | pdftex_fail("PDF inclusion: invalid ProcSet entry type <%s>", | |
118 | - procset->getTypeName()); | |
119 | - copyName(procset->getName()); | |
120 | + procset.getTypeName()); | |
121 | + copyName(procset.getName()); | |
122 | pdf_puts(" "); | |
123 | } | |
124 | pdf_puts("]\n"); | |
125 | @@ -394,10 +363,29 @@ | |
126 | ||
127 | #define REPLACE_TYPE1C true | |
128 | ||
129 | +static bool embeddableFont(Object * fontdesc) | |
130 | +{ | |
131 | + Object fontfile, ffsubtype; | |
132 | + | |
133 | + if (!fontdesc->isDict()) | |
134 | + return false; | |
135 | + fontfile = fontdesc->dictLookup("FontFile"); | |
136 | + if (fontfile.isStream()) | |
137 | + return true; | |
138 | + if (REPLACE_TYPE1C) { | |
139 | + fontfile = fontdesc->dictLookup("FontFile3"); | |
140 | + if (!fontfile.isStream()) | |
141 | + return false; | |
142 | + ffsubtype = fontfile.streamGetDict()->lookup("Subtype"); | |
143 | + return ffsubtype.isName() && !strcmp(ffsubtype.getName(), "Type1C"); | |
144 | + } | |
145 | + return false; | |
146 | +} | |
147 | + | |
148 | static void copyFont(char *tag, Object * fontRef) | |
149 | { | |
150 | - PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset, | |
151 | - fontfile, ffsubtype, stemV; | |
152 | + Object fontdict, subtype, basefont, fontdescRef, fontdesc, charset, | |
153 | + stemV; | |
154 | GfxFont *gfont; | |
155 | fd_entry *fd; | |
156 | fm_entry *fontmap; | |
157 | @@ -413,33 +401,39 @@ | |
158 | } | |
159 | // Only handle included Type1 (and Type1C) fonts; anything else will be copied. | |
160 | // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true. | |
161 | - if (!fixedinclusioncopyfont && fontRef->fetch(xref, &fontdict)->isDict() | |
162 | - && fontdict->dictLookup("Subtype", &subtype)->isName() | |
163 | - && !strcmp(subtype->getName(), "Type1") | |
164 | - && fontdict->dictLookup("BaseFont", &basefont)->isName() | |
165 | - && fontdict->dictLookupNF("FontDescriptor", &fontdescRef)->isRef() | |
166 | - && fontdescRef->fetch(xref, &fontdesc)->isDict() | |
167 | - && (fontdesc->dictLookup("FontFile", &fontfile)->isStream() | |
168 | - || (REPLACE_TYPE1C | |
169 | - && fontdesc->dictLookup("FontFile3", &fontfile)->isStream() | |
170 | - && fontfile->streamGetDict()->lookup("Subtype", | |
171 | - &ffsubtype)->isName() | |
172 | - && !strcmp(ffsubtype->getName(), "Type1C"))) | |
173 | - && (fontmap = lookup_fontmap(basefont->getName())) != NULL) { | |
174 | + fontdict = fontRef->fetch(xref); | |
175 | + fontdesc = Object(objNull); | |
176 | + if (fontdict.isDict()) { | |
177 | + subtype = fontdict.dictLookup("Subtype"); | |
178 | + basefont = fontdict.dictLookup("BaseFont"); | |
179 | + fontdescRef = fontdict.dictLookupNF("FontDescriptor"); | |
180 | + if (fontdescRef.isRef()) { | |
181 | + fontdesc = fontdescRef.fetch(xref); | |
182 | + } | |
183 | + } | |
184 | + if (!fixedinclusioncopyfont && fontdict.isDict() | |
185 | + && subtype.isName() | |
186 | + && !strcmp(subtype.getName(), "Type1") | |
187 | + && basefont.isName() | |
188 | + && fontdescRef.isRef() | |
189 | + && fontdesc.isDict() | |
190 | + && embeddableFont(&fontdesc) | |
191 | + && (fontmap = lookup_fontmap(basefont.getName())) != NULL) { | |
192 | // round /StemV value, since the PDF input is a float | |
193 | // (see Font Descriptors in PDF reference), but we only store an | |
194 | // integer, since we don't want to change the struct. | |
195 | - fontdesc->dictLookup("StemV", &stemV); | |
196 | - fd = epdf_create_fontdescriptor(fontmap, zround(stemV->getNum())); | |
197 | - if (fontdesc->dictLookup("CharSet", &charset) && | |
198 | - charset->isString() && is_subsetable(fontmap)) | |
199 | - epdf_mark_glyphs(fd, charset->getString()->getCString()); | |
200 | + stemV = fontdesc.dictLookup("StemV"); | |
201 | + fd = epdf_create_fontdescriptor(fontmap, zround(stemV.getNum())); | |
202 | + charset = fontdesc.dictLookup("CharSet"); | |
203 | + if (!charset.isNull() && | |
204 | + charset.isString() && is_subsetable(fontmap)) | |
205 | + epdf_mark_glyphs(fd, charset.getString()->getCString()); | |
206 | else | |
207 | embed_whole_font(fd); | |
208 | - addFontDesc(fontdescRef->getRef(), fd); | |
209 | + addFontDesc(fontdescRef.getRef(), fd); | |
210 | copyName(tag); | |
211 | gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(), | |
212 | - fontdict->getDict()); | |
213 | + fontdict.getDict()); | |
214 | pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd, | |
215 | addEncoding(gfont))); | |
216 | } else { | |
217 | @@ -451,24 +445,24 @@ | |
218 | ||
219 | static void copyFontResources(Object * obj) | |
220 | { | |
221 | - PdfObject fontRef; | |
222 | + Object fontRef; | |
223 | int i, l; | |
224 | if (!obj->isDict()) | |
225 | pdftex_fail("PDF inclusion: invalid font resources dict type <%s>", | |
226 | obj->getTypeName()); | |
227 | pdf_puts("/Font << "); | |
228 | for (i = 0, l = obj->dictGetLength(); i < l; ++i) { | |
229 | - obj->dictGetValNF(i, &fontRef); | |
230 | - if (fontRef->isRef()) | |
231 | + fontRef = obj->dictGetValNF(i); | |
232 | + if (fontRef.isRef()) | |
233 | copyFont(obj->dictGetKey(i), &fontRef); | |
234 | - else if (fontRef->isDict()) { // some programs generate pdf with embedded font object | |
235 | + else if (fontRef.isDict()) { // some programs generate pdf with embedded font object | |
236 | copyName(obj->dictGetKey(i)); | |
237 | pdf_puts(" "); | |
238 | copyObject(&fontRef); | |
239 | } | |
240 | else | |
241 | pdftex_fail("PDF inclusion: invalid font in reference type <%s>", | |
242 | - fontRef->getTypeName()); | |
243 | + fontRef.getTypeName()); | |
244 | } | |
245 | pdf_puts(">>\n"); | |
246 | } | |
247 | @@ -557,7 +551,7 @@ | |
248 | ||
249 | static void copyObject(Object * obj) | |
250 | { | |
251 | - PdfObject obj1; | |
252 | + Object obj1; | |
253 | int i, l, c; | |
254 | Ref ref; | |
255 | char *p; | |
256 | @@ -601,8 +595,8 @@ | |
257 | } else if (obj->isArray()) { | |
258 | pdf_puts("["); | |
259 | for (i = 0, l = obj->arrayGetLength(); i < l; ++i) { | |
260 | - obj->arrayGetNF(i, &obj1); | |
261 | - if (!obj1->isName()) | |
262 | + obj1 = obj->arrayGetNF(i); | |
263 | + if (!obj1.isName()) | |
264 | pdf_puts(" "); | |
265 | copyObject(&obj1); | |
266 | } | |
267 | @@ -612,9 +606,8 @@ | |
268 | copyDict(obj); | |
269 | pdf_puts(">>"); | |
270 | } else if (obj->isStream()) { | |
271 | - initDictFromDict(obj1, obj->streamGetDict()); | |
272 | pdf_puts("<<\n"); | |
273 | - copyDict(&obj1); | |
274 | + copyDict(obj->getStream()->getDictObject()); | |
275 | pdf_puts(">>\n"); | |
276 | pdf_puts("stream\n"); | |
277 | copyStream(obj->getStream()->getUndecodedStream()); | |
278 | @@ -638,9 +631,8 @@ | |
279 | InObj *r; | |
280 | for (r = inObjList; r != 0; r = r->next) { | |
281 | if (!r->written) { | |
282 | - Object obj1; | |
283 | r->written = 1; | |
284 | - xref->fetch(r->ref.num, r->ref.gen, &obj1); | |
285 | + Object obj1 = xref->fetch(r->ref.num, r->ref.gen); | |
286 | if (r->type == objFont) { | |
287 | assert(!obj1.isStream()); | |
288 | pdfbeginobj(r->num, 2); // \pdfobjcompresslevel = 2 is for this | |
289 | @@ -656,7 +648,6 @@ | |
290 | pdf_puts("\n"); | |
291 | pdfendobj(); | |
292 | } | |
293 | - obj1.free(); | |
294 | } | |
295 | } | |
296 | } | |
297 | @@ -685,7 +676,7 @@ | |
298 | #ifdef POPPLER_VERSION | |
299 | r->font->decRefCnt(); | |
300 | #else | |
301 | - delete r->font; | |
302 | +#error POPPLER_VERSION should be defined. | |
303 | #endif | |
304 | delete r; | |
305 | } | |
306 | @@ -728,7 +719,7 @@ | |
307 | #ifdef POPPLER_VERSION | |
308 | int pdf_major_version_found, pdf_minor_version_found; | |
309 | #else | |
310 | - float pdf_version_found, pdf_version_wanted; | |
311 | +#error POPPLER_VERSION should be defined. | |
312 | #endif | |
313 | // initialize | |
314 | if (!isInit) { | |
315 | @@ -760,19 +751,7 @@ | |
316 | } | |
317 | } | |
318 | #else | |
319 | - pdf_version_found = pdf_doc->doc->getPDFVersion(); | |
320 | - pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1); | |
321 | - if (pdf_version_found > pdf_version_wanted + 0.01) { | |
322 | - char msg[] = | |
323 | - "PDF inclusion: found PDF version <%.1f>, but at most version <%.1f> allowed"; | |
324 | - if (pdf_inclusion_errorlevel > 0) { | |
325 | - pdftex_fail(msg, pdf_version_found, pdf_version_wanted); | |
326 | - } else if (pdf_inclusion_errorlevel < 0) { | |
327 | - ; /* do nothing */ | |
328 | - } else { /* = 0, give warning */ | |
329 | - pdftex_warn(msg, pdf_version_found, pdf_version_wanted); | |
330 | - } | |
331 | - } | |
332 | +#error POPPLER_VERSION should be defined. | |
333 | #endif | |
334 | epdf_num_pages = pdf_doc->doc->getCatalog()->getNumPages(); | |
335 | if (page_name) { | |
336 | @@ -839,8 +818,8 @@ | |
337 | Page *page; | |
338 | Ref *pageRef; | |
339 | Dict *pageDict; | |
340 | - PdfObject contents, obj1, obj2, pageObj, dictObj; | |
341 | - PdfObject groupDict; | |
342 | + Object contents, obj1, obj2, pageObj, dictObj; | |
343 | + Object groupDict; | |
344 | bool writeSepGroup = false; | |
345 | Object info; | |
346 | char *key; | |
347 | @@ -867,8 +846,8 @@ | |
348 | encodingList = 0; | |
349 | page = pdf_doc->doc->getCatalog()->getPage(epdf_selected_page); | |
350 | pageRef = pdf_doc->doc->getCatalog()->getPageRef(epdf_selected_page); | |
351 | - xref->fetch(pageRef->num, pageRef->gen, &pageObj); | |
352 | - pageDict = pageObj->getDict(); | |
353 | + pageObj = xref->fetch(pageRef->num, pageRef->gen); | |
354 | + pageDict = pageObj.getDict(); | |
355 | rotate = page->getRotate(); | |
356 | PDFRectangle *pagebox; | |
357 | // write the Page header | |
358 | @@ -886,7 +865,7 @@ | |
359 | pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) epdf_selected_page); | |
360 | } | |
361 | if ((suppress_ptex_info & MASK_SUPPRESS_PTEX_INFODICT) == 0) { | |
362 | - pdf_doc->doc->getDocInfoNF(&info); | |
363 | + info = pdf_doc->doc->getDocInfoNF(); | |
364 | if (info.isRef()) { | |
365 | // the info dict must be indirect (PDF Ref p. 61) | |
366 | pdf_printf("/%s.InfoDict ", pdfkeyprefix); | |
367 | @@ -942,14 +921,14 @@ | |
368 | pdf_puts(stripzeros(s)); | |
369 | ||
370 | // Metadata validity check (as a stream it must be indirect) | |
371 | - pageDict->lookupNF("Metadata", &dictObj); | |
372 | - if (!dictObj->isNull() && !dictObj->isRef()) | |
373 | + dictObj = pageDict->lookupNF("Metadata"); | |
374 | + if (!dictObj.isNull() && !dictObj.isRef()) | |
375 | pdftex_warn("PDF inclusion: /Metadata must be indirect object"); | |
376 | ||
377 | // copy selected items in Page dictionary except Resources & Group | |
378 | for (i = 0; pageDictKeys[i] != NULL; i++) { | |
379 | - pageDict->lookupNF(pageDictKeys[i], &dictObj); | |
380 | - if (!dictObj->isNull()) { | |
381 | + dictObj = pageDict->lookupNF(pageDictKeys[i]); | |
382 | + if (!dictObj.isNull()) { | |
383 | pdf_newline(); | |
384 | pdf_printf("/%s ", pageDictKeys[i]); | |
385 | copyObject(&dictObj); // preserves indirection | |
386 | @@ -957,8 +936,8 @@ | |
387 | } | |
388 | ||
389 | // handle page group | |
390 | - pageDict->lookupNF("Group", &dictObj); | |
391 | - if (!dictObj->isNull()) { | |
392 | + dictObj = pageDict->lookupNF("Group"); | |
393 | + if (!dictObj.isNull()) { | |
394 | if (pdfpagegroupval == 0) { | |
395 | // another pdf with page group was included earlier on the | |
396 | // same page; copy the Group entry as is. See manual for | |
397 | @@ -972,11 +951,36 @@ | |
398 | copyObject(&dictObj); | |
399 | } else { | |
400 | // write Group dict as a separate object, since the Page dict also refers to it | |
401 | - pageDict->lookup("Group", &dictObj); | |
402 | - if (!dictObj->isDict()) | |
403 | + dictObj = pageDict->lookup("Group"); | |
404 | + if (!dictObj.isDict()) | |
405 | pdftex_fail("PDF inclusion: /Group dict missing"); | |
406 | writeSepGroup = true; | |
407 | - initDictFromDict(groupDict, page->getGroup()); | |
408 | +/* | |
409 | +This part is only a single line | |
410 | + groupDict = Object(page->getGroup()); | |
411 | +in the original patch. In this case, however, pdftex crashes at | |
412 | +"delete pdf_doc->doc" in "delete_document()" for inclusion of some | |
413 | +kind of pdf images, for example, figure_missing.pdf in gnuplot. | |
414 | +A change | |
415 | + groupDict = Object(page->getGroup()).copy(); | |
416 | +does not improve the situation. | |
417 | +The changes below seem to work fine. | |
418 | +*/ | |
419 | +// begin modification | |
420 | + groupDict = pageDict->lookup("Group"); | |
421 | + Dict dic1 = page->getGroup(); | |
422 | + Dict dic2 = groupDict.getDict(); | |
423 | + // replace dic2 in groupDict with dic1 | |
424 | + l = dic2.getLength(); | |
425 | + for (i = 0; i < l; i++) { | |
426 | + groupDict.dictRemove(dic2.getKey(i)); | |
427 | + } | |
428 | + l = dic1.getLength(); | |
429 | + for (i = 0; i < l; i++) { | |
430 | + groupDict.dictAdd(copyString(dic1.getKey(i)), | |
431 | + dic1.getValNF(i)); | |
432 | + } | |
433 | +// end modification | |
434 | pdf_printf("/Group %ld 0 R\n", (long)pdfpagegroupval); | |
435 | } | |
436 | } | |
437 | @@ -989,14 +993,14 @@ | |
438 | pdftex_warn | |
439 | ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref)"); | |
440 | } else { | |
441 | - initDictFromDict(obj1, page->getResourceDict()); | |
442 | + Object *obj1 = page->getResourceDictObject(); | |
443 | if (!obj1->isDict()) | |
444 | pdftex_fail("PDF inclusion: invalid resources dict type <%s>", | |
445 | obj1->getTypeName()); | |
446 | pdf_newline(); | |
447 | pdf_puts("/Resources <<\n"); | |
448 | for (i = 0, l = obj1->dictGetLength(); i < l; ++i) { | |
449 | - obj1->dictGetVal(i, &obj2); | |
450 | + obj2 = obj1->dictGetVal(i); | |
451 | key = obj1->dictGetKey(i); | |
452 | if (strcmp("Font", key) == 0) | |
453 | copyFontResources(&obj2); | |
454 | @@ -1009,8 +1013,8 @@ | |
455 | } | |
456 | ||
457 | // write the page contents | |
458 | - page->getContents(&contents); | |
459 | - if (contents->isStream()) { | |
460 | + contents = page->getContents(); | |
461 | + if (contents.isStream()) { | |
462 | ||
463 | // Variant A: get stream and recompress under control | |
464 | // of \pdfcompresslevel | |
465 | @@ -1021,36 +1025,35 @@ | |
466 | ||
467 | // Variant B: copy stream without recompressing | |
468 | // | |
469 | - contents->streamGetDict()->lookup("F", &obj1); | |
470 | - if (!obj1->isNull()) { | |
471 | + obj1 = contents.streamGetDict()->lookup("F"); | |
472 | + if (!obj1.isNull()) { | |
473 | pdftex_fail("PDF inclusion: Unsupported external stream"); | |
474 | } | |
475 | - contents->streamGetDict()->lookup("Length", &obj1); | |
476 | - assert(!obj1->isNull()); | |
477 | + obj1 = contents.streamGetDict()->lookup("Length"); | |
478 | + assert(!obj1.isNull()); | |
479 | pdf_puts("/Length "); | |
480 | copyObject(&obj1); | |
481 | pdf_puts("\n"); | |
482 | - contents->streamGetDict()->lookup("Filter", &obj1); | |
483 | - if (!obj1->isNull()) { | |
484 | + obj1 = contents.streamGetDict()->lookup("Filter"); | |
485 | + if (!obj1.isNull()) { | |
486 | pdf_puts("/Filter "); | |
487 | copyObject(&obj1); | |
488 | pdf_puts("\n"); | |
489 | - contents->streamGetDict()->lookup("DecodeParms", &obj1); | |
490 | - if (!obj1->isNull()) { | |
491 | + obj1 = contents.streamGetDict()->lookup("DecodeParms"); | |
492 | + if (!obj1.isNull()) { | |
493 | pdf_puts("/DecodeParms "); | |
494 | copyObject(&obj1); | |
495 | pdf_puts("\n"); | |
496 | } | |
497 | } | |
498 | pdf_puts(">>\nstream\n"); | |
499 | - copyStream(contents->getStream()->getUndecodedStream()); | |
500 | + copyStream(contents.getStream()->getUndecodedStream()); | |
501 | pdfendstream(); | |
502 | - } else if (contents->isArray()) { | |
503 | + } else if (contents.isArray()) { | |
504 | pdfbeginstream(); | |
505 | - for (i = 0, l = contents->arrayGetLength(); i < l; ++i) { | |
506 | - Object contentsobj; | |
507 | - copyStream((contents->arrayGet(i, &contentsobj))->getStream()); | |
508 | - contentsobj.free(); | |
509 | + for (i = 0, l = contents.arrayGetLength(); i < l; ++i) { | |
510 | + Object contentsobj = contents.arrayGet(i); | |
511 | + copyStream(contentsobj.getStream()); | |
512 | if (i < l - 1) | |
513 | pdf_newline(); // add a newline after each stream except the last | |
514 | } | |
515 | --- ./texk/web2c/pdftexdir/pdftosrc.cc 2016-11-25 18:09:21.000000000 +0000 | |
516 | +++ ../pdftosrc.cc 2018-01-23 08:50:03.531537552 +0000 | |
517 | @@ -1,5 +1,5 @@ | |
518 | /* | |
519 | -Copyright 1996-2014 Han The Thanh, <thanh@pdftex.org> | |
520 | +Copyright 1996-2017 Han The Thanh, <thanh@pdftex.org> | |
521 | ||
522 | This file is part of pdfTeX. | |
523 | ||
524 | @@ -16,6 +16,14 @@ | |
525 | You should have received a copy of the GNU General Public License along | |
526 | with this program. If not, see <http://www.gnu.org/licenses/>. | |
527 | */ | |
528 | + | |
529 | +/* | |
530 | +This is based on the patch texlive-poppler-0.59.patch <2017-09-19> at | |
531 | +https://git.archlinux.org/svntogit/packages.git/plain/texlive-bin/trunk | |
532 | +by Arch Linux. The poppler should be 0.59.0 or newer versions. | |
533 | +POPPLER_VERSION should be defined. | |
534 | +*/ | |
535 | + | |
536 | #include <w2c/config.h> | |
537 | ||
538 | #include <stdlib.h> | |
539 | @@ -32,10 +40,7 @@ | |
540 | #include <goo/gmem.h> | |
541 | #include <goo/gfile.h> | |
542 | #else | |
543 | -#include <aconf.h> | |
544 | -#include <GString.h> | |
545 | -#include <gmem.h> | |
546 | -#include <gfile.h> | |
547 | +#error POPPLER_VERSION should be defined. | |
548 | #endif | |
549 | #include <assert.h> | |
550 | ||
551 | @@ -86,22 +91,20 @@ | |
552 | objgen = atoi(argv[3]); | |
553 | } | |
554 | xref = doc->getXRef(); | |
555 | - catalogDict.initNull(); | |
556 | - xref->getCatalog(&catalogDict); | |
557 | + catalogDict = xref->getCatalog(); | |
558 | if (!catalogDict.isDict("Catalog")) { | |
559 | fprintf(stderr, "No Catalog found\n"); | |
560 | exit(1); | |
561 | } | |
562 | - srcStream.initNull(); | |
563 | + srcStream = Object(objNull); | |
564 | if (objnum == 0) { | |
565 | - catalogDict.dictLookup("SourceObject", &srcStream); | |
566 | + srcStream = catalogDict.dictLookup("SourceObject"); | |
567 | static char const_SourceFile[] = "SourceFile"; | |
568 | if (!srcStream.isStream(const_SourceFile)) { | |
569 | fprintf(stderr, "No SourceObject found\n"); | |
570 | exit(1); | |
571 | } | |
572 | - srcName.initNull(); | |
573 | - srcStream.getStream()->getDict()->lookup("SourceName", &srcName); | |
574 | + srcName = srcStream.getStream()->getDict()->lookup("SourceName"); | |
575 | if (!srcName.isString()) { | |
576 | fprintf(stderr, "No SourceName found\n"); | |
577 | exit(1); | |
578 | @@ -110,7 +113,7 @@ | |
579 | // We cannot free srcName, as objname shares its string. | |
580 | // srcName.free(); | |
581 | } else if (objnum > 0) { | |
582 | - xref->fetch(objnum, objgen, &srcStream); | |
583 | + srcStream = xref->fetch(objnum, objgen); | |
584 | if (!srcStream.isStream()) { | |
585 | fprintf(stderr, "Not a Stream object\n"); | |
586 | exit(1); | |
587 | @@ -153,35 +156,34 @@ | |
588 | (e->type == xrefEntryFree ? "f" : "n")); | |
589 | else { // e->offset is the object number of the object stream | |
590 | Stream *str; | |
591 | + Lexer *lexer; | |
592 | Parser *parser; | |
593 | Object objStr, obj1, obj2; | |
594 | int nObjects, first, n; | |
595 | int localOffset = 0; | |
596 | Guint firstOffset; | |
597 | ||
598 | - assert(xref->fetch(e->offset, 0, &objStr)->isStream()); | |
599 | - nObjects = objStr.streamGetDict()->lookup("N", &obj1)->getInt(); | |
600 | - obj1.free(); | |
601 | - first = objStr.streamGetDict()->lookup("First", &obj1)->getInt(); | |
602 | - obj1.free(); | |
603 | + objStr = xref->fetch(e->offset, 0); | |
604 | + assert(objStr.isStream()); | |
605 | + obj1 = objStr.streamGetDict()->lookup("N"); | |
606 | + nObjects = obj1.getInt(); | |
607 | + obj1 = objStr.streamGetDict()->lookup("First"); | |
608 | + first = obj1.getInt(); | |
609 | firstOffset = objStr.getStream()->getBaseStream()->getStart() + first; | |
610 | ||
611 | // parse the header: object numbers and offsets | |
612 | objStr.streamReset(); | |
613 | - obj1.initNull(); | |
614 | - str = new EmbedStream(objStr.getStream(), &obj1, gTrue, first); | |
615 | - parser = new Parser(xref, new Lexer(xref, str), gFalse); | |
616 | + str = new EmbedStream(objStr.getStream(), Object(objNull), gTrue, first); | |
617 | + lexer = new Lexer(xref, str); | |
618 | + parser = new Parser(xref, lexer, gFalse); | |
619 | for (n = 0; n < nObjects; ++n) { | |
620 | - parser->getObj(&obj1); | |
621 | - parser->getObj(&obj2); | |
622 | + obj1 = parser->getObj(); | |
623 | + obj2 = parser->getObj(); | |
624 | if (n == e->gen) | |
625 | localOffset = obj2.getInt(); | |
626 | - obj1.free(); | |
627 | - obj2.free(); | |
628 | } | |
629 | while (str->getChar() != EOF) ; | |
630 | delete parser; | |
631 | - objStr.free(); | |
632 | ||
633 | fprintf(outfile, "%.10lu 00000 n\n", | |
634 | (long unsigned)(firstOffset + localOffset)); | |
635 | @@ -192,7 +194,6 @@ | |
636 | s->reset(); | |
637 | while ((c = s->getChar()) != EOF) | |
638 | fputc(c, outfile); | |
639 | - srcStream.free(); | |
640 | } | |
641 | if (objnum == 0) | |
642 | fprintf(stderr, "Source file extracted to %s\n", outname); | |
643 | @@ -201,7 +202,6 @@ | |
644 | else | |
645 | fprintf(stderr, "Cross-reference table extracted to %s\n", outname); | |
646 | fclose(outfile); | |
647 | - catalogDict.free(); | |
648 | delete doc; | |
649 | delete globalParams; | |
650 | } |