]>
Commit | Line | Data |
---|---|---|
9c72faab | 1 | //======================================================================== |
2 | // | |
3 | // Page.cc | |
4 | // | |
5 | // Copyright 1996 Derek B. Noonburg | |
6 | // | |
7 | //======================================================================== | |
8 | ||
9 | #ifdef __GNUC__ | |
10 | #pragma implementation | |
11 | #endif | |
12 | ||
13 | #include <stddef.h> | |
14 | #include "Object.h" | |
15 | #include "Array.h" | |
16 | #include "Dict.h" | |
17 | #include "XRef.h" | |
52118ca3 | 18 | #include "Link.h" |
9c72faab | 19 | #include "OutputDev.h" |
20 | #ifndef PDF_PARSER_ONLY | |
21 | #include "Gfx.h" | |
52118ca3 | 22 | #include "FormWidget.h" |
9c72faab | 23 | #endif |
24 | #include "Error.h" | |
25 | ||
26 | #include "Params.h" | |
27 | #include "Page.h" | |
28 | ||
29 | //------------------------------------------------------------------------ | |
30 | // PageAttrs | |
31 | //------------------------------------------------------------------------ | |
32 | ||
33 | PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { | |
753453e4 | 34 | Object obj1; |
9c72faab | 35 | double w, h; |
36 | ||
37 | // get old/default values | |
38 | if (attrs) { | |
753453e4 | 39 | mediaBox = attrs->mediaBox; |
40 | cropBox = attrs->cropBox; | |
41 | haveCropBox = attrs->haveCropBox; | |
9c72faab | 42 | rotate = attrs->rotate; |
43 | attrs->resources.copy(&resources); | |
44 | } else { | |
45 | // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary | |
46 | // but some (non-compliant) PDF files don't specify a MediaBox | |
753453e4 | 47 | mediaBox.x1 = 0; |
48 | mediaBox.y1 = 0; | |
49 | mediaBox.x2 = 612; | |
50 | mediaBox.y2 = 792; | |
51 | cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0; | |
52 | haveCropBox = gFalse; | |
9c72faab | 53 | rotate = 0; |
54 | resources.initNull(); | |
55 | } | |
56 | ||
57 | // media box | |
753453e4 | 58 | readBox(dict, "MediaBox", &mediaBox); |
9c72faab | 59 | |
60 | // crop box | |
753453e4 | 61 | cropBox = mediaBox; |
62 | haveCropBox = readBox(dict, "CropBox", &cropBox); | |
9c72faab | 63 | |
64 | // if the MediaBox is excessively larger than the CropBox, | |
65 | // just use the CropBox | |
66 | limitToCropBox = gFalse; | |
753453e4 | 67 | if (haveCropBox) { |
68 | w = 0.25 * (cropBox.x2 - cropBox.x1); | |
69 | h = 0.25 * (cropBox.y2 - cropBox.y1); | |
70 | if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w || | |
71 | (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) { | |
72 | limitToCropBox = gTrue; | |
73 | } | |
9c72faab | 74 | } |
75 | ||
753453e4 | 76 | // other boxes |
77 | bleedBox = cropBox; | |
78 | readBox(dict, "BleedBox", &bleedBox); | |
79 | trimBox = cropBox; | |
80 | readBox(dict, "TrimBox", &trimBox); | |
81 | artBox = cropBox; | |
82 | readBox(dict, "ArtBox", &artBox); | |
83 | ||
9c72faab | 84 | // rotate |
85 | dict->lookup("Rotate", &obj1); | |
753453e4 | 86 | if (obj1.isInt()) { |
9c72faab | 87 | rotate = obj1.getInt(); |
753453e4 | 88 | } |
9c72faab | 89 | obj1.free(); |
753453e4 | 90 | while (rotate < 0) { |
9c72faab | 91 | rotate += 360; |
753453e4 | 92 | } |
93 | while (rotate >= 360) { | |
9c72faab | 94 | rotate -= 360; |
753453e4 | 95 | } |
9c72faab | 96 | |
97 | // resource dictionary | |
98 | dict->lookup("Resources", &obj1); | |
99 | if (obj1.isDict()) { | |
100 | resources.free(); | |
101 | obj1.copy(&resources); | |
102 | } | |
103 | obj1.free(); | |
104 | } | |
105 | ||
106 | PageAttrs::~PageAttrs() { | |
107 | resources.free(); | |
108 | } | |
109 | ||
753453e4 | 110 | GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) { |
111 | PDFRectangle tmp; | |
112 | Object obj1, obj2; | |
113 | GBool ok; | |
114 | ||
115 | dict->lookup(key, &obj1); | |
116 | if (obj1.isArray() && obj1.arrayGetLength() == 4) { | |
117 | ok = gTrue; | |
118 | obj1.arrayGet(0, &obj2); | |
119 | if (obj2.isNum()) { | |
120 | tmp.x1 = obj2.getNum(); | |
121 | } else { | |
122 | ok = gFalse; | |
123 | } | |
124 | obj2.free(); | |
125 | obj1.arrayGet(1, &obj2); | |
126 | if (obj2.isNum()) { | |
127 | tmp.y1 = obj2.getNum(); | |
128 | } else { | |
129 | ok = gFalse; | |
130 | } | |
131 | obj2.free(); | |
132 | obj1.arrayGet(2, &obj2); | |
133 | if (obj2.isNum()) { | |
134 | tmp.x2 = obj2.getNum(); | |
135 | } else { | |
136 | ok = gFalse; | |
137 | } | |
138 | obj2.free(); | |
139 | obj1.arrayGet(3, &obj2); | |
140 | if (obj2.isNum()) { | |
141 | tmp.y2 = obj2.getNum(); | |
142 | } else { | |
143 | ok = gFalse; | |
144 | } | |
145 | obj2.free(); | |
146 | if (ok) { | |
147 | *box = tmp; | |
148 | } | |
149 | } else { | |
150 | ok = gFalse; | |
151 | } | |
152 | obj1.free(); | |
153 | return ok; | |
154 | } | |
155 | ||
9c72faab | 156 | //------------------------------------------------------------------------ |
157 | // Page | |
158 | //------------------------------------------------------------------------ | |
159 | ||
753453e4 | 160 | Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA, |
161 | GBool printCommandsA) { | |
9c72faab | 162 | |
163 | ok = gTrue; | |
753453e4 | 164 | xref = xrefA; |
165 | num = numA; | |
166 | printCommands = printCommandsA; | |
9c72faab | 167 | |
168 | // get attributes | |
753453e4 | 169 | attrs = attrsA; |
9c72faab | 170 | |
171 | // annotations | |
172 | pageDict->lookupNF("Annots", &annots); | |
173 | if (!(annots.isRef() || annots.isArray() || annots.isNull())) { | |
174 | error(-1, "Page annotations object (page %d) is wrong type (%s)", | |
175 | num, annots.getTypeName()); | |
176 | annots.free(); | |
177 | goto err2; | |
178 | } | |
179 | ||
180 | // contents | |
181 | pageDict->lookupNF("Contents", &contents); | |
182 | if (!(contents.isRef() || contents.isArray() || | |
183 | contents.isNull())) { | |
184 | error(-1, "Page contents object (page %d) is wrong type (%s)", | |
185 | num, contents.getTypeName()); | |
186 | contents.free(); | |
187 | goto err1; | |
188 | } | |
189 | ||
190 | return; | |
191 | ||
192 | err2: | |
193 | annots.initNull(); | |
194 | err1: | |
195 | contents.initNull(); | |
196 | ok = gFalse; | |
197 | } | |
198 | ||
199 | Page::~Page() { | |
200 | delete attrs; | |
201 | annots.free(); | |
202 | contents.free(); | |
203 | } | |
204 | ||
b5cb0608 | 205 | void Page::display(OutputDev *out, double dpi, int rotate, |
52118ca3 | 206 | Links *links, Catalog *catalog) { |
9c72faab | 207 | #ifndef PDF_PARSER_ONLY |
753453e4 | 208 | PDFRectangle *box, *cropBox; |
9c72faab | 209 | Gfx *gfx; |
210 | Object obj; | |
52118ca3 | 211 | Link *link; |
212 | int i; | |
213 | FormWidgets *formWidgets; | |
9c72faab | 214 | |
753453e4 | 215 | box = getBox(); |
216 | cropBox = getCropBox(); | |
217 | ||
9c72faab | 218 | if (printCommands) { |
219 | printf("***** MediaBox = ll:%g,%g ur:%g,%g\n", | |
753453e4 | 220 | box->x1, box->y1, box->x2, box->y2); |
9c72faab | 221 | if (isCropped()) { |
222 | printf("***** CropBox = ll:%g,%g ur:%g,%g\n", | |
753453e4 | 223 | cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2); |
9c72faab | 224 | } |
225 | printf("***** Rotate = %d\n", attrs->getRotate()); | |
226 | } | |
52118ca3 | 227 | |
9c72faab | 228 | rotate += getRotate(); |
52118ca3 | 229 | if (rotate >= 360) { |
9c72faab | 230 | rotate -= 360; |
52118ca3 | 231 | } else if (rotate < 0) { |
9c72faab | 232 | rotate += 360; |
52118ca3 | 233 | } |
753453e4 | 234 | gfx = new Gfx(xref, out, num, attrs->getResourceDict(), |
235 | dpi, box, isCropped(), cropBox, rotate, printCommands); | |
236 | contents.fetch(xref, &obj); | |
52118ca3 | 237 | if (!obj.isNull()) { |
9c72faab | 238 | gfx->display(&obj); |
52118ca3 | 239 | } |
9c72faab | 240 | obj.free(); |
52118ca3 | 241 | |
242 | // draw links | |
243 | if (links) { | |
244 | for (i = 0; i < links->getNumLinks(); ++i) { | |
245 | link = links->getLink(i); | |
246 | out->drawLink(link, catalog); | |
247 | } | |
248 | out->dump(); | |
249 | } | |
250 | ||
251 | // draw AcroForm widgets | |
252 | //~ need to reset CTM ??? | |
753453e4 | 253 | formWidgets = new FormWidgets(xref, annots.fetch(xref, &obj)); |
52118ca3 | 254 | obj.free(); |
255 | if (printCommands && formWidgets->getNumWidgets() > 0) { | |
256 | printf("***** AcroForm widgets\n"); | |
257 | } | |
258 | for (i = 0; i < formWidgets->getNumWidgets(); ++i) { | |
259 | formWidgets->getWidget(i)->draw(gfx); | |
260 | } | |
b5cb0608 | 261 | if (formWidgets->getNumWidgets() > 0) { |
262 | out->dump(); | |
263 | } | |
52118ca3 | 264 | delete formWidgets; |
265 | ||
9c72faab | 266 | delete gfx; |
267 | #endif | |
268 | } |