]> git.ipfire.org Git - thirdparty/cups.git/blame - pdftops/Page.cxx
Merge changes from CUPS 1.4svn-r7199.
[thirdparty/cups.git] / pdftops / Page.cxx
CommitLineData
ef416fc2 1//========================================================================
2//
3// Page.cc
4//
5// Copyright 1996-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <config.h>
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#include <stddef.h>
16#include "GlobalParams.h"
17#include "Object.h"
18#include "Array.h"
19#include "Dict.h"
20#include "XRef.h"
21#include "Link.h"
22#include "OutputDev.h"
23#ifndef PDF_PARSER_ONLY
24#include "Gfx.h"
25#include "GfxState.h"
26#include "Annot.h"
27#endif
28#include "Error.h"
29#include "Page.h"
30
31//------------------------------------------------------------------------
32// PageAttrs
33//------------------------------------------------------------------------
34
35PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
36 Object obj1;
37
38 // get old/default values
39 if (attrs) {
40 mediaBox = attrs->mediaBox;
41 cropBox = attrs->cropBox;
42 haveCropBox = attrs->haveCropBox;
43 rotate = attrs->rotate;
44 attrs->resources.copy(&resources);
45 } else {
46 // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
47 // but some (non-compliant) PDF files don't specify a MediaBox
48 mediaBox.x1 = 0;
49 mediaBox.y1 = 0;
50 mediaBox.x2 = 612;
51 mediaBox.y2 = 792;
52 cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
53 haveCropBox = gFalse;
54 rotate = 0;
55 resources.initNull();
56 }
57
58 // media box
59 readBox(dict, "MediaBox", &mediaBox);
60
61 // crop box
62 if (readBox(dict, "CropBox", &cropBox)) {
63 haveCropBox = gTrue;
64 }
65 if (!haveCropBox) {
66 cropBox = mediaBox;
67 }
68
69 // other boxes
70 bleedBox = cropBox;
71 readBox(dict, "BleedBox", &bleedBox);
72 trimBox = cropBox;
73 readBox(dict, "TrimBox", &trimBox);
74 artBox = cropBox;
75 readBox(dict, "ArtBox", &artBox);
76
77 // rotate
78 dict->lookup("Rotate", &obj1);
79 if (obj1.isInt()) {
80 rotate = obj1.getInt();
81 }
82 obj1.free();
83 while (rotate < 0) {
84 rotate += 360;
85 }
86 while (rotate >= 360) {
87 rotate -= 360;
88 }
89
90 // misc attributes
91 dict->lookup("LastModified", &lastModified);
92 dict->lookup("BoxColorInfo", &boxColorInfo);
93 dict->lookup("Group", &group);
94 dict->lookup("Metadata", &metadata);
95 dict->lookup("PieceInfo", &pieceInfo);
96 dict->lookup("SeparationInfo", &separationInfo);
97
98 // resource dictionary
99 dict->lookup("Resources", &obj1);
100 if (obj1.isDict()) {
101 resources.free();
102 obj1.copy(&resources);
103 }
104 obj1.free();
105}
106
107PageAttrs::~PageAttrs() {
108 lastModified.free();
109 boxColorInfo.free();
110 group.free();
111 metadata.free();
112 pieceInfo.free();
113 separationInfo.free();
114 resources.free();
115}
116
117GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
118 PDFRectangle tmp;
119 double t;
120 Object obj1, obj2;
121 GBool ok;
122
123 dict->lookup(key, &obj1);
124 if (obj1.isArray() && obj1.arrayGetLength() == 4) {
125 ok = gTrue;
126 obj1.arrayGet(0, &obj2);
127 if (obj2.isNum()) {
128 tmp.x1 = obj2.getNum();
129 } else {
130 ok = gFalse;
131 }
132 obj2.free();
133 obj1.arrayGet(1, &obj2);
134 if (obj2.isNum()) {
135 tmp.y1 = obj2.getNum();
136 } else {
137 ok = gFalse;
138 }
139 obj2.free();
140 obj1.arrayGet(2, &obj2);
141 if (obj2.isNum()) {
142 tmp.x2 = obj2.getNum();
143 } else {
144 ok = gFalse;
145 }
146 obj2.free();
147 obj1.arrayGet(3, &obj2);
148 if (obj2.isNum()) {
149 tmp.y2 = obj2.getNum();
150 } else {
151 ok = gFalse;
152 }
153 obj2.free();
154 if (ok) {
155 if (tmp.x1 > tmp.x2) {
156 t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t;
157 }
158 if (tmp.y1 > tmp.y2) {
159 t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t;
160 }
161 *box = tmp;
162 }
163 } else {
164 ok = gFalse;
165 }
166 obj1.free();
167 return ok;
168}
169
170//------------------------------------------------------------------------
171// Page
172//------------------------------------------------------------------------
173
174Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
175 ok = gTrue;
176 xref = xrefA;
177 num = numA;
178
179 // get attributes
180 attrs = attrsA;
181
182 // annotations
183 pageDict->lookupNF("Annots", &annots);
184 if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
185 error(-1, "Page annotations object (page %d) is wrong type (%s)",
186 num, annots.getTypeName());
187 annots.free();
188 goto err2;
189 }
190
191 // contents
192 pageDict->lookupNF("Contents", &contents);
193 if (!(contents.isRef() || contents.isArray() ||
194 contents.isNull())) {
195 error(-1, "Page contents object (page %d) is wrong type (%s)",
196 num, contents.getTypeName());
197 contents.free();
198 goto err1;
199 }
200
201 return;
202
203 err2:
204 annots.initNull();
205 err1:
206 contents.initNull();
207 ok = gFalse;
208}
209
210Page::~Page() {
211 delete attrs;
212 annots.free();
213 contents.free();
214}
215
216void Page::display(OutputDev *out, double hDPI, double vDPI,
217 int rotate, GBool useMediaBox, GBool crop,
218 Links *links, Catalog *catalog,
219 GBool (*abortCheckCbk)(void *data),
220 void *abortCheckCbkData) {
221 displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop,
222 -1, -1, -1, -1, links, catalog,
223 abortCheckCbk, abortCheckCbkData);
224}
225
226void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
227 int rotate, GBool useMediaBox, GBool crop,
228 int sliceX, int sliceY, int sliceW, int sliceH,
229 Links *links, Catalog *catalog,
230 GBool (*abortCheckCbk)(void *data),
231 void *abortCheckCbkData) {
232#ifndef PDF_PARSER_ONLY
233 PDFRectangle *mediaBox, *cropBox, *baseBox;
234 PDFRectangle box;
235 Gfx *gfx;
236 Object obj;
237 Link *link;
238 Annots *annotList;
239 double kx, ky;
240 int i;
241
242 rotate += getRotate();
243 if (rotate >= 360) {
244 rotate -= 360;
245 } else if (rotate < 0) {
246 rotate += 360;
247 }
248
249 mediaBox = getMediaBox();
250 cropBox = getCropBox();
251 if (sliceW >= 0 && sliceH >= 0) {
252 baseBox = useMediaBox ? mediaBox : cropBox;
253 kx = 72.0 / hDPI;
254 ky = 72.0 / vDPI;
255 if (rotate == 90) {
256 if (out->upsideDown()) {
257 box.x1 = baseBox->x1 + ky * sliceY;
258 box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
259 } else {
260 box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
261 box.x2 = baseBox->x2 - ky * sliceY;
262 }
263 box.y1 = baseBox->y1 + kx * sliceX;
264 box.y2 = baseBox->y1 + kx * (sliceX + sliceW);
265 } else if (rotate == 180) {
266 box.x1 = baseBox->x2 - kx * (sliceX + sliceW);
267 box.x2 = baseBox->x2 - kx * sliceX;
268 if (out->upsideDown()) {
269 box.y1 = baseBox->y1 + ky * sliceY;
270 box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
271 } else {
272 box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
273 box.y2 = baseBox->y2 - ky * sliceY;
274 }
275 } else if (rotate == 270) {
276 if (out->upsideDown()) {
277 box.x1 = baseBox->x2 - ky * (sliceY + sliceH);
278 box.x2 = baseBox->x2 - ky * sliceY;
279 } else {
280 box.x1 = baseBox->x1 + ky * sliceY;
281 box.x2 = baseBox->x1 + ky * (sliceY + sliceH);
282 }
283 box.y1 = baseBox->y2 - kx * (sliceX + sliceW);
284 box.y2 = baseBox->y2 - kx * sliceX;
285 } else {
286 box.x1 = baseBox->x1 + kx * sliceX;
287 box.x2 = baseBox->x1 + kx * (sliceX + sliceW);
288 if (out->upsideDown()) {
289 box.y1 = baseBox->y2 - ky * (sliceY + sliceH);
290 box.y2 = baseBox->y2 - ky * sliceY;
291 } else {
292 box.y1 = baseBox->y1 + ky * sliceY;
293 box.y2 = baseBox->y1 + ky * (sliceY + sliceH);
294 }
295 }
296 } else if (useMediaBox) {
297 box = *mediaBox;
298 } else {
299 box = *cropBox;
300 crop = gFalse;
301 }
302
303 if (globalParams->getPrintCommands()) {
304 printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
305 mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2);
306 printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
307 cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
308 printf("***** Rotate = %d\n", attrs->getRotate());
309 }
310
311 gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
312 hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL,
313 rotate, abortCheckCbk, abortCheckCbkData);
314 contents.fetch(xref, &obj);
315 if (!obj.isNull()) {
316 gfx->saveState();
317 gfx->display(&obj);
318 gfx->restoreState();
319 }
320 obj.free();
321
322 // draw links
323 if (links) {
324 gfx->saveState();
325 for (i = 0; i < links->getNumLinks(); ++i) {
326 link = links->getLink(i);
327 out->drawLink(link, catalog);
328 }
329 gfx->restoreState();
330 out->dump();
331 }
332
333 // draw non-link annotations
334 annotList = new Annots(xref, catalog, annots.fetch(xref, &obj));
335 obj.free();
336 if (annotList->getNumAnnots() > 0) {
337 if (globalParams->getPrintCommands()) {
338 printf("***** Annotations\n");
339 }
340 for (i = 0; i < annotList->getNumAnnots(); ++i) {
341 annotList->getAnnot(i)->draw(gfx);
342 }
343 out->dump();
344 }
345 delete annotList;
346
347 delete gfx;
348#endif
349}
350
351void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
352 int rotate, GBool upsideDown) {
353 GfxState *state;
354 int i;
355
356 rotate += getRotate();
357 if (rotate >= 360) {
358 rotate -= 360;
359 } else if (rotate < 0) {
360 rotate += 360;
361 }
362 state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown);
363 for (i = 0; i < 6; ++i) {
364 ctm[i] = state->getCTM()[i];
365 }
366 delete state;
367}