Added Handling 'Form' which has not Resources dictionary.
Fixed a bug in font-embedding.
@@ -55,7 +55,13 @@ | ||
55 | 55 | static const char *dictNames[NDict]; |
56 | 56 | P2PResources(XRef *xrefA); |
57 | 57 | ~P2PResources(); |
58 | - void output(P2POutputStream *str, P2PFontResource *fontResource); | |
58 | + void output(P2POutputStream *str); | |
59 | + void setP2PFontResource(P2PFontResource *fontResourceA) { | |
60 | + fontResource = fontResourceA; | |
61 | + } | |
62 | + P2PFontResource *getP2PFontResource() { | |
63 | + return fontResource; | |
64 | + } | |
59 | 65 | /* merge resources and return mapping table */ |
60 | 66 | P2PResourceMap *merge(Dict *res); |
61 | 67 | P2PResourceMap *merge(P2PResources *res); |
@@ -87,6 +93,9 @@ | ||
87 | 93 | unsigned int resourceNo; |
88 | 94 | P2PPatternDict *patternDict; |
89 | 95 | int nPattern; |
96 | + P2PFontResource *fontResource; | |
97 | + P2PObject **oldForms; | |
98 | + int nOldForms; | |
90 | 99 | |
91 | 100 | void mergeOneDict(Dict *dst, Dict *src, Dict *map, GBool unify); |
92 | 101 | #ifdef HAVE_UGOOSTRING_H |
@@ -99,6 +108,7 @@ | ||
99 | 108 | #else |
100 | 109 | void addMap(char *org, char *mapped, Dict *map); |
101 | 110 | #endif |
111 | + void handleOldForm(P2PResourceMap *map); | |
102 | 112 | }; |
103 | 113 | |
104 | 114 | /* resource name mapping table */ |
@@ -98,10 +98,11 @@ | ||
98 | 98 | PDFRectangle artBox; |
99 | 99 | P2PResources *resources; |
100 | 100 | XRef *xref; |
101 | + P2PFontResource *fontResource; | |
101 | 102 | |
102 | - void outputContents(P2POutputStream *str, P2PFontResource *fontResource); | |
103 | + void outputContents(P2POutputStream *str); | |
103 | 104 | void outputSelf(P2POutputStream *str, P2PPageTree *tree, |
104 | - P2PObject *copiedObj, P2PFontResource *fontResource); | |
105 | + P2PObject *copiedObj); | |
105 | 106 | static void outputPDFRectangle(PDFRectangle *rect, P2POutputStream *str); |
106 | 107 | static void outputPDFRectangleForPath(PDFRectangle *rect, |
107 | 108 | P2POutputStream *str); |
@@ -743,7 +743,8 @@ | ||
743 | 743 | P2PObject *p; |
744 | 744 | int faceIndex = 0; |
745 | 745 | |
746 | - if (dict->lookupNF(const_cast<char *>("FontDescriptor"),&obj) == 0) { | |
746 | + if (dict->lookupNF(const_cast<char *>("FontDescriptor"),&obj) == 0 | |
747 | + || obj.isNull()) { | |
747 | 748 | /* no FontDescriptor */ |
748 | 749 | error(-1,const_cast<char *>("Font:%s has no FontDescriptor entry.\n"),name); |
749 | 750 | return; |
@@ -880,7 +881,8 @@ | ||
880 | 881 | Dict *dict = fontDict.getDict(); |
881 | 882 | int num = -1, gen = -1; |
882 | 883 | |
883 | - if (dict->lookup(const_cast<char *>("DescendantFonts"),&obj) == 0) { | |
884 | + if (dict->lookup(const_cast<char *>("DescendantFonts"),&obj) == 0 | |
885 | + || obj.isNull()) { | |
884 | 886 | /* no DescendantFonts */ |
885 | 887 | error(-1,const_cast<char *>("Font:%s has no DescendantFonts entry.\n"),name); |
886 | 888 | return; |
@@ -32,6 +32,7 @@ | ||
32 | 32 | #include "goo/gmem.h" |
33 | 33 | #include "P2PResources.h" |
34 | 34 | #include "P2PFont.h" |
35 | +#include "P2PForm.h" | |
35 | 36 | |
36 | 37 | P2PResourceMap::P2PResourceMap() |
37 | 38 | { |
@@ -73,6 +74,9 @@ | ||
73 | 74 | resourceNo = 0; |
74 | 75 | patternDict = 0; |
75 | 76 | nPattern = 0; |
77 | + fontResource = 0; | |
78 | + oldForms = 0; | |
79 | + nOldForms = 0; | |
76 | 80 | } |
77 | 81 | |
78 | 82 | P2PResources::~P2PResources() |
@@ -85,9 +89,12 @@ | ||
85 | 89 | } |
86 | 90 | } |
87 | 91 | if (patternDict != 0) delete[] patternDict; |
92 | + if (oldForms != 0) delete[] oldForms; | |
93 | + /* fontResource is deleted in other Class, | |
94 | + Don't delete it */ | |
88 | 95 | } |
89 | 96 | |
90 | -void P2PResources::output(P2POutputStream *str, P2PFontResource *fontResource) | |
97 | +void P2PResources::output(P2POutputStream *str) | |
91 | 98 | { |
92 | 99 | int i; |
93 | 100 | str->puts("<<"); |
@@ -115,6 +122,30 @@ | ||
115 | 122 | } |
116 | 123 | str->puts(">>\n"); |
117 | 124 | } |
125 | + } else if (i == XObject && nOldForms > 0 && dictionaries[i] != 0) { | |
126 | + int j; | |
127 | + | |
128 | + /* There is any old form in XObject dictionary */ | |
129 | + Dict *xobjDict = dictionaries[i]; | |
130 | + int n = xobjDict->getLength(); | |
131 | + str->printf(" /%s << ",dictNames[i]); | |
132 | + for (j = 0;j < n;j++) { | |
133 | + char *key = xobjDict->getKey(j); | |
134 | + | |
135 | + P2POutput::outputName(key,str); | |
136 | + str->putchar(' '); | |
137 | + if (j < nOldForms && oldForms[j] != 0) { | |
138 | + oldForms[j]->outputRef(str); | |
139 | + } else { | |
140 | + Object obj; | |
141 | + | |
142 | + xobjDict->getValNF(j,&obj); | |
143 | + P2POutput::outputObject(&obj,str,xref); | |
144 | + obj.free(); | |
145 | + } | |
146 | + str->putchar('\n'); | |
147 | + } | |
148 | + str->puts(">>\n"); | |
118 | 149 | } else { |
119 | 150 | if (dictionaries[i] != 0) { |
120 | 151 | str->printf(" /%s ",dictNames[i]); |
@@ -132,6 +163,49 @@ | ||
132 | 163 | str->puts(">>"); |
133 | 164 | } |
134 | 165 | |
166 | +void P2PResources::handleOldForm(P2PResourceMap *map) | |
167 | +{ | |
168 | + int n; | |
169 | + int i; | |
170 | + | |
171 | + /* find Forms without Resources and replace them */ | |
172 | + Dict *xobjDict = dictionaries[XObject]; | |
173 | + if (xobjDict == 0) return; | |
174 | + n = xobjDict->getLength(); | |
175 | + for (i = 0;i < n;i++) { | |
176 | + Object xobj; | |
177 | + Object obj; | |
178 | + Dict *strDict; | |
179 | + P2PForm *form; | |
180 | + int num, gen; | |
181 | + char *key; | |
182 | + | |
183 | + xobjDict->getVal(i,&xobj); | |
184 | + if (!xobj.isStream()) continue; | |
185 | + strDict = xobj.streamGetDict(); | |
186 | + strDict->lookupNF("Subtype",&obj); | |
187 | + if (!obj.isName() || strcmp("Form",obj.getName()) != 0) continue; | |
188 | + obj.free(); | |
189 | + strDict->lookupNF("Resources",&obj); | |
190 | + if (!obj.isNull()) continue; | |
191 | + /* found a Form without Resource, | |
192 | + replace it with a refrence to a P2PForm */ | |
193 | + form = new P2PForm(&xobj,this,map); | |
194 | + xobj.free(); | |
195 | + if (nOldForms < n) { | |
196 | + P2PObject **oldp = oldForms; | |
197 | + nOldForms = n; | |
198 | + oldForms = new P2PObject *[n]; | |
199 | + if (oldp != 0) { | |
200 | + memcpy(oldForms,oldp,n*sizeof(P2PForm *)); | |
201 | + } else { | |
202 | + memset(oldForms,0,n*sizeof(P2PForm *)); | |
203 | + } | |
204 | + } | |
205 | + oldForms[i] = form; | |
206 | + } | |
207 | +} | |
208 | + | |
135 | 209 | P2PResourceMap *P2PResources::merge(Dict *res) |
136 | 210 | { |
137 | 211 | P2PResourceMap *map = 0; |
@@ -155,6 +229,7 @@ | ||
155 | 229 | obj.free(); |
156 | 230 | } |
157 | 231 | } |
232 | + handleOldForm(map); | |
158 | 233 | return map; |
159 | 234 | } |
160 | 235 |
@@ -178,7 +253,7 @@ | ||
178 | 253 | i != Pattern); |
179 | 254 | } |
180 | 255 | } |
181 | - | |
256 | + handleOldForm(map); | |
182 | 257 | return map; |
183 | 258 | } |
184 | 259 |
@@ -48,6 +48,7 @@ | ||
48 | 48 | numOrgPages = 1; |
49 | 49 | orgPages = new OrgPage [1]; |
50 | 50 | orgPages[0].page = orgPageA; |
51 | + fontResource = 0; | |
51 | 52 | |
52 | 53 | xref = xrefA; |
53 | 54 | mediaBox = *orgPageA->getMediaBox(); |
@@ -93,6 +94,7 @@ | ||
93 | 94 | numOrgPages = 1; |
94 | 95 | orgPages = new OrgPage [1]; |
95 | 96 | orgPages[0].page = 0; |
97 | + fontResource = 0; | |
96 | 98 | |
97 | 99 | xref = xrefA; |
98 | 100 | if (mediaBoxA != 0) { |
@@ -219,6 +221,7 @@ | ||
219 | 221 | bleedBox = cropBox; |
220 | 222 | trimBox = cropBox; |
221 | 223 | artBox = cropBox; |
224 | + fontResource = 0; | |
222 | 225 | |
223 | 226 | if (n == 8 || n == 6 || n == 2) { |
224 | 227 | /* Rotating is reqiured, layout change is needed. |
@@ -260,6 +263,10 @@ | ||
260 | 263 | |
261 | 264 | P2PPage::~P2PPage() |
262 | 265 | { |
266 | + if (fontResource != 0) { | |
267 | + delete fontResource; | |
268 | + fontResource = 0; | |
269 | + } | |
263 | 270 | if (resources != 0) { |
264 | 271 | delete resources; |
265 | 272 | resources = 0; |
@@ -302,7 +309,7 @@ | ||
302 | 309 | } |
303 | 310 | |
304 | 311 | void P2PPage::outputSelf(P2POutputStream *str, P2PPageTree *tree, |
305 | - P2PObject *copiedObj, P2PFontResource *fontResource) | |
312 | + P2PObject *copiedObj) | |
306 | 313 | { |
307 | 314 | if (copiedObj == 0) { |
308 | 315 | outputBegin(str); |
@@ -337,7 +344,7 @@ | ||
337 | 344 | |
338 | 345 | str->puts("\n/Resources "); |
339 | 346 | if (resources != 0) { |
340 | - resources->output(str,fontResource); | |
347 | + resources->output(str); | |
341 | 348 | } else { |
342 | 349 | Dict *dict = orgPages[0].page->getResourceDict(); |
343 | 350 |
@@ -367,7 +374,7 @@ | ||
367 | 374 | } |
368 | 375 | } |
369 | 376 | |
370 | -void P2PPage::outputContents(P2POutputStream *str, P2PFontResource *fontResource) | |
377 | +void P2PPage::outputContents(P2POutputStream *str) | |
371 | 378 | { |
372 | 379 | int i; |
373 | 380 | int start; |
@@ -465,9 +472,10 @@ | ||
465 | 472 | |
466 | 473 | void P2PPage::output(P2POutputStream *str, P2PPageTree *tree, P2PObject *copiedObj) |
467 | 474 | { |
468 | - P2PFontResource fontResource; | |
469 | - P2PFontResource *fr = 0; | |
470 | - | |
475 | + if (fontResource != 0) { | |
476 | + delete fontResource; | |
477 | + fontResource = 0; | |
478 | + } | |
471 | 479 | if (resources == 0 && orgPages[0].page != 0/* not empty page */) { |
472 | 480 | /* make P2PResource for pattern handling */ |
473 | 481 | /* when number-upped, page must have P2PResource already. |
@@ -476,21 +484,26 @@ | ||
476 | 484 | orgPages[0].mappingTable |
477 | 485 | = resources->merge(orgPages[0].page->getResourceDict()); |
478 | 486 | } |
479 | - /* setup pattern dict for translation */ | |
480 | - if (resources != 0) resources->setupPattern(); | |
481 | 487 | if (copiedObj == 0) { |
482 | 488 | if (P2PDoc::options.fontEmbedding && orgPages[0].page != 0) { |
483 | 489 | /* only not empty page */ |
490 | + fontResource = new P2PFontResource(); | |
484 | 491 | if (resources != 0) { |
485 | - fontResource.setup(resources,xref); | |
492 | + fontResource->setup(resources,xref); | |
486 | 493 | } else { |
487 | - fontResource.setup(orgPages[0].page->getResourceDict(),xref); | |
494 | + fontResource->setup(orgPages[0].page->getResourceDict(),xref); | |
488 | 495 | } |
489 | - fr = &fontResource; | |
490 | 496 | } |
491 | 497 | } |
492 | - outputContents(str,fr); | |
493 | - outputSelf(str,tree,copiedObj,fr); | |
498 | + if (resources != 0) { | |
499 | + /* setup pattern dict for translation */ | |
500 | + resources->setupPattern(); | |
501 | + | |
502 | + resources->setP2PFontResource(fontResource); | |
503 | + } | |
504 | + | |
505 | + outputContents(str); | |
506 | + outputSelf(str,tree,copiedObj); | |
494 | 507 | } |
495 | 508 | |
496 | 509 | void P2PPage::fit(PDFRectangle *box, double zoom) |
@@ -38,7 +38,7 @@ | ||
38 | 38 | PDFFTrueTypeFont.cc PDFFTrueTypeFont.h P2PPattern.cc P2PPattern.h\ |
39 | 39 | P2PCharCodeToUnicode.cc P2PCharCodeToUnicode.h\ |
40 | 40 | P2PCMap.cc P2PCMap.h parseargs.h parseargs.cc\ |
41 | - UGooString.cc UGooString.h | |
41 | + UGooString.cc UGooString.h P2PForm.cc | |
42 | 42 | |
43 | 43 | filterdir = @CUPS_SERVERBIN@/filter |
44 | 44 | filter_PROGRAMS=pdftopdf |
@@ -56,4 +56,4 @@ | ||
56 | 56 | P2PXRef.cc P2PXRef.h pdftopdf.cc P2PFont.cc P2PFont.h\ |
57 | 57 | PDFFTrueTypeFont.cc PDFFTrueTypeFont.h P2PPattern.cc P2PPattern.h\ |
58 | 58 | P2PCharCodeToUnicode.cc P2PCharCodeToUnicode.h\ |
59 | - P2PCMap.cc P2PCMap.h UGooString.cc UGooString.h | |
59 | + P2PCMap.cc P2PCMap.h UGooString.cc UGooString.h P2PForm.cc |
@@ -0,0 +1,119 @@ | ||
1 | +/* | |
2 | + | |
3 | +Copyright (c) 2006-2010, BBR Inc. All rights reserved. | |
4 | + | |
5 | +Permission is hereby granted, free of charge, to any person obtaining | |
6 | +a copy of this software and associated documentation files (the | |
7 | +"Software"), to deal in the Software without restriction, including | |
8 | +without limitation the rights to use, copy, modify, merge, publish, | |
9 | +distribute, sublicense, and/or sell copies of the Software, and to | |
10 | +permit persons to whom the Software is furnished to do so, subject to | |
11 | +the following conditions: | |
12 | + | |
13 | +The above copyright notice and this permission notice shall be included | |
14 | +in all copies or substantial portions of the Software. | |
15 | + | |
16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
23 | + | |
24 | +*/ | |
25 | +/* | |
26 | + P2PForm.h | |
27 | + pdftopdf form | |
28 | + Note: Only use this for Forms without Resource entry. | |
29 | +*/ | |
30 | +#include "P2PDoc.h" | |
31 | +#include "P2PGfx.h" | |
32 | +#include "P2PXRef.h" | |
33 | +#include "P2PForm.h" | |
34 | + | |
35 | +P2PForm::P2PForm(Object *orgFormA, P2PResources *resourcesA, | |
36 | + P2PResourceMap *mapA) | |
37 | +{ | |
38 | + /* assumed orgFormA is Reference */ | |
39 | + orgFormA->copy(&orgForm); | |
40 | + resources = resourcesA; | |
41 | + mappingTable = mapA; | |
42 | + P2PXRef::put(this); | |
43 | +} | |
44 | + | |
45 | +P2PForm::~P2PForm() | |
46 | +{ | |
47 | + /* resources and mappingTable are deleted in other class. | |
48 | + Don't delete them here */ | |
49 | + orgForm.free(); | |
50 | +} | |
51 | + | |
52 | +void P2PForm::output(P2POutputStream *str, XRef *xref) | |
53 | +{ | |
54 | + int i; | |
55 | + int n; | |
56 | + Dict *dict; | |
57 | + int len; | |
58 | + Object lenobj; | |
59 | + P2PObj *pobj = new P2PObj(); | |
60 | + | |
61 | + outputBegin(str); | |
62 | + | |
63 | + str->puts("<< /Length "); | |
64 | + P2PXRef::put(pobj); | |
65 | + pobj->outputRef(str); | |
66 | + if (P2PDoc::options.contentsCompress && str->canDeflate()) { | |
67 | + str->puts(" /Filter /FlateDecode "); | |
68 | + } | |
69 | + | |
70 | + dict = orgForm.streamGetDict(); | |
71 | + n = dict->getLength(); | |
72 | + for (i = 0;i < n;i++) { | |
73 | +#ifdef HAVE_UGOOSTRING_H | |
74 | + char *key = dict->getKey(i)->getCString(); | |
75 | +#else | |
76 | + char *key = dict->getKey(i); | |
77 | +#endif | |
78 | + Object obj; | |
79 | + | |
80 | + if (strcmp(key,"Filter") == 0 || strcmp(key,"Length") == 0) continue; | |
81 | + P2POutput::outputName(key,str); | |
82 | + str->putchar(' '); | |
83 | + dict->getValNF(i,&obj); | |
84 | + P2POutput::outputObject(&obj,str,xref); | |
85 | + obj.free(); | |
86 | + str->putchar('\n'); | |
87 | +#ifdef HAVE_UGOOSTRING_H | |
88 | + delete[] key; | |
89 | +#endif | |
90 | + } | |
91 | + str->puts("/Resources "); | |
92 | + resources->output(str); | |
93 | + str->puts(" >>\n"); | |
94 | + | |
95 | + | |
96 | + /* output contents */ | |
97 | + P2PGfx output(xref,str,resources->getP2PFontResource(),resources); | |
98 | + int start; | |
99 | + | |
100 | + str->puts("stream\n"); | |
101 | + start = str->getPosition(); | |
102 | + if (P2PDoc::options.contentsCompress) str->startDeflate(); | |
103 | + | |
104 | + P2PMatrix identMatrix; | |
105 | + | |
106 | + output.outputContents(&orgForm,mappingTable,0,&identMatrix); | |
107 | + | |
108 | + if (P2PDoc::options.contentsCompress) str->endDeflate(); | |
109 | + len = str->getPosition()-start; | |
110 | + str->puts("\nendstream\n"); | |
111 | + | |
112 | + outputEnd(str); | |
113 | + | |
114 | + /* set length object value */ | |
115 | + lenobj.initInt(len); | |
116 | + pobj->setObj(&lenobj); | |
117 | + lenobj.free(); | |
118 | + pobj->output(str,xref); | |
119 | +} |
@@ -0,0 +1,50 @@ | ||
1 | +/* | |
2 | + | |
3 | +Copyright (c) 2006-2010, BBR Inc. All rights reserved. | |
4 | + | |
5 | +Permission is hereby granted, free of charge, to any person obtaining | |
6 | +a copy of this software and associated documentation files (the | |
7 | +"Software"), to deal in the Software without restriction, including | |
8 | +without limitation the rights to use, copy, modify, merge, publish, | |
9 | +distribute, sublicense, and/or sell copies of the Software, and to | |
10 | +permit persons to whom the Software is furnished to do so, subject to | |
11 | +the following conditions: | |
12 | + | |
13 | +The above copyright notice and this permission notice shall be included | |
14 | +in all copies or substantial portions of the Software. | |
15 | + | |
16 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
17 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
23 | + | |
24 | +*/ | |
25 | +/* | |
26 | + P2PForm.h | |
27 | + pdftopdf form | |
28 | + Note: Only use this for Forms without Resource entry. | |
29 | +*/ | |
30 | +#ifndef _P2PFORM_H_ | |
31 | +#define _P2PFORM_H_ | |
32 | + | |
33 | +#include "Object.h" | |
34 | +#include "P2PObject.h" | |
35 | +#include "P2POutputStream.h" | |
36 | +#include "XRef.h" | |
37 | +#include "P2PResources.h" | |
38 | + | |
39 | +class P2PForm : public P2PObject { | |
40 | +public: | |
41 | + P2PForm(Object *orgFormA, P2PResources *resourcesA, P2PResourceMap *mapA); | |
42 | + virtual ~P2PForm(); | |
43 | + void output(P2POutputStream *str, XRef *xref); | |
44 | +private: | |
45 | + Object orgForm; | |
46 | + P2PResources *resources; | |
47 | + P2PResourceMap *mappingTable; /* resource name mapping table */ | |
48 | +}; | |
49 | + | |
50 | +#endif |