1 //========================================================================
2 //
3 // Page.cc
4 //
5 // Copyright 1996-2007 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 //========================================================================
10 //
11 // Modified under the Poppler project - http://poppler.freedesktop.org
12 //
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
15 //
16 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
17 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
18 // Copyright (C) 2005-2010 Albert Astals Cid <aacid@kde.org>
19 // Copyright (C) 2006-2008 Pino Toscano <pino@kde.org>
20 // Copyright (C) 2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
21 // Copyright (C) 2006 Scott Turner <scotty1024@mac.com>
22 // Copyright (C) 2006-2010 Carlos Garcia Campos <carlosgc@gnome.org>
23 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
24 // Copyright (C) 2008 Iñigo Martínez <inigomartinez@gmail.com>
25 // Copyright (C) 2008 Brad Hards <bradh@kde.org>
26 // Copyright (C) 2008 Ilya Gorenbein <igorenbein@finjan.com>
27 //
28 // To see a description of the changes please see the Changelog file that
29 // came with your tarball or type make ChangeLog if you are building from git
30 //
31 //========================================================================
32
33 #include <config.h>
34
35 #ifdef USE_GCC_PRAGMAS
36 #pragma implementation
37 #endif
38
39 #include <stddef.h>
40 #include <limits.h>
41 #include "GlobalParams.h"
42 #include "Object.h"
43 #include "Array.h"
44 #include "Dict.h"
45 #include "XRef.h"
46 #include "Link.h"
47 #include "OutputDev.h"
48 #ifndef PDF_PARSER_ONLY
49 #include "Gfx.h"
50 #include "GfxState.h"
51 #include "Annot.h"
52 #include "TextOutputDev.h"
53 #include "Form.h"
54 #endif
55 #include "Error.h"
56 #include "Page.h"
57 #include "Catalog.h"
58 #include "Form.h"
59
60 //------------------------------------------------------------------------
61 // PDFRectangle
62 //------------------------------------------------------------------------
63
clipTo(PDFRectangle * rect)64 void PDFRectangle::clipTo(PDFRectangle *rect) {
65 if (x1 < rect->x1) {
66 x1 = rect->x1;
67 } else if (x1 > rect->x2) {
68 x1 = rect->x2;
69 }
70 if (x2 < rect->x1) {
71 x2 = rect->x1;
72 } else if (x2 > rect->x2) {
73 x2 = rect->x2;
74 }
75 if (y1 < rect->y1) {
76 y1 = rect->y1;
77 } else if (y1 > rect->y2) {
78 y1 = rect->y2;
79 }
80 if (y2 < rect->y1) {
81 y2 = rect->y1;
82 } else if (y2 > rect->y2) {
83 y2 = rect->y2;
84 }
85 }
86
87 //------------------------------------------------------------------------
88 // PageAttrs
89 //------------------------------------------------------------------------
90
PageAttrs(PageAttrs * attrs,Dict * dict)91 PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
92 Object obj1;
93 PDFRectangle mBox;
94 const GBool isPage = dict->is("Page");
95
96 // get old/default values
97 if (attrs) {
98 mediaBox = attrs->mediaBox;
99 cropBox = attrs->cropBox;
100 haveCropBox = attrs->haveCropBox;
101 rotate = attrs->rotate;
102 attrs->resources.copy(&resources);
103 } else {
104 // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
105 // but some (non-compliant) PDF files don't specify a MediaBox
106 mediaBox.x1 = 0;
107 mediaBox.y1 = 0;
108 mediaBox.x2 = 612;
109 mediaBox.y2 = 792;
110 cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
111 haveCropBox = gFalse;
112 rotate = 0;
113 resources.initNull();
114 }
115
116 // media box
117 if (readBox(dict, "MediaBox", &mBox)) {
118 mediaBox = mBox;
119 }
120
121 // crop box
122 if (readBox(dict, "CropBox", &cropBox)) {
123 haveCropBox = gTrue;
124 }
125 if (!haveCropBox) {
126 cropBox = mediaBox;
127 }
128
129 if (isPage) {
130 // cropBox can not be bigger than mediaBox
131 if (cropBox.x2 - cropBox.x1 > mediaBox.x2 - mediaBox.x1)
132 {
133 cropBox.x1 = mediaBox.x1;
134 cropBox.x2 = mediaBox.x2;
135 }
136 if (cropBox.y2 - cropBox.y1 > mediaBox.y2 - mediaBox.y1)
137 {
138 cropBox.y1 = mediaBox.y1;
139 cropBox.y2 = mediaBox.y2;
140 }
141 }
142
143 // other boxes
144 bleedBox = cropBox;
145 readBox(dict, "BleedBox", &bleedBox);
146 trimBox = cropBox;
147 readBox(dict, "TrimBox", &trimBox);
148 artBox = cropBox;
149 readBox(dict, "ArtBox", &artBox);
150
151 if (isPage) {
152 // clip all other boxes to the media box
153 cropBox.clipTo(&mediaBox);
154 bleedBox.clipTo(&mediaBox);
155 trimBox.clipTo(&mediaBox);
156 artBox.clipTo(&mediaBox);
157 }
158
159 // rotate
160 dict->lookup("Rotate", &obj1);
161 if (obj1.isInt()) {
162 rotate = obj1.getInt();
163 }
164 obj1.free();
165 while (rotate < 0) {
166 rotate += 360;
167 }
168 while (rotate >= 360) {
169 rotate -= 360;
170 }
171
172 // misc attributes
173 dict->lookup("LastModified", &lastModified);
174 dict->lookup("BoxColorInfo", &boxColorInfo);
175 dict->lookup("Group", &group);
176 dict->lookup("Metadata", &metadata);
177 dict->lookup("PieceInfo", &pieceInfo);
178 dict->lookup("SeparationInfo", &separationInfo);
179
180 // resource dictionary
181 dict->lookup("Resources", &obj1);
182 if (obj1.isDict()) {
183 resources.free();
184 obj1.copy(&resources);
185 }
186 obj1.free();
187 }
188
~PageAttrs()189 PageAttrs::~PageAttrs() {
190 lastModified.free();
191 boxColorInfo.free();
192 group.free();
193 metadata.free();
194 pieceInfo.free();
195 separationInfo.free();
196 resources.free();
197 }
198
readBox(Dict * dict,char * key,PDFRectangle * box)199 GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
200 PDFRectangle tmp;
201 double t;
202 Object obj1, obj2;
203 GBool ok;
204
205 dict->lookup(key, &obj1);
206 if (obj1.isArray() && obj1.arrayGetLength() == 4) {
207 ok = gTrue;
208 obj1.arrayGet(0, &obj2);
209 if (obj2.isNum()) {
210 tmp.x1 = obj2.getNum();
211 } else {
212 ok = gFalse;
213 }
214 obj2.free();
215 obj1.arrayGet(1, &obj2);
216 if (obj2.isNum()) {
217 tmp.y1 = obj2.getNum();
218 } else {
219 ok = gFalse;
220 }
221 obj2.free();
222 obj1.arrayGet(2, &obj2);
223 if (obj2.isNum()) {
224 tmp.x2 = obj2.getNum();
225 } else {
226 ok = gFalse;
227 }
228 obj2.free();
229 obj1.arrayGet(3, &obj2);
230 if (obj2.isNum()) {
231 tmp.y2 = obj2.getNum();
232 } else {
233 ok = gFalse;
234 }
235 obj2.free();
236 if (tmp.x1 == 0 && tmp.x2 == 0 && tmp.y1 == 0 && tmp.y2 == 0)
237 ok = gFalse;
238 if (ok) {
239 if (tmp.x1 > tmp.x2) {
240 t = tmp.x1; tmp.x1 = tmp.x2; tmp.x2 = t;
241 }
242 if (tmp.y1 > tmp.y2) {
243 t = tmp.y1; tmp.y1 = tmp.y2; tmp.y2 = t;
244 }
245 *box = tmp;
246 }
247 } else {
248 ok = gFalse;
249 }
250 obj1.free();
251 return ok;
252 }
253
254 //------------------------------------------------------------------------
255 // Page
256 //------------------------------------------------------------------------
257
Page(XRef * xrefA,int numA,Dict * pageDict,Ref pageRefA,PageAttrs * attrsA,Form * form)258 Page::Page(XRef *xrefA, int numA, Dict *pageDict, Ref pageRefA, PageAttrs *attrsA, Form *form) {
259 Object tmp;
260
261 ok = gTrue;
262 xref = xrefA;
263 num = numA;
264 duration = -1;
265 pageWidgets = NULL;
266
267 pageObj.initDict(pageDict);
268 pageRef = pageRefA;
269
270 // get attributes
271 attrs = attrsA;
272
273 // transtion
274 pageDict->lookupNF("Trans", &trans);
275 if (!(trans.isRef() || trans.isDict() || trans.isNull())) {
276 error(-1, "Page transition object (page %d) is wrong type (%s)",
277 num, trans.getTypeName());
278 trans.free();
279 }
280
281 // duration
282 pageDict->lookupNF("Dur", &tmp);
283 if (!(tmp.isNum() || tmp.isNull())) {
284 error(-1, "Page duration object (page %d) is wrong type (%s)",
285 num, tmp.getTypeName());
286 } else if (tmp.isNum()) {
287 duration = tmp.getNum();
288 }
289 tmp.free();
290
291 // annotations
292 pageDict->lookupNF("Annots", &annots);
293 if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
294 error(-1, "Page annotations object (page %d) is wrong type (%s)",
295 num, annots.getTypeName());
296 annots.free();
297 goto err2;
298 }
299
300 // forms
301 pageWidgets = new FormPageWidgets(xrefA, this->getAnnots(&tmp),num,form);
302 tmp.free();
303
304 // contents
305 pageDict->lookupNF("Contents", &contents);
306 if (!(contents.isRef() || contents.isArray() ||
307 contents.isNull())) {
308 error(-1, "Page contents object (page %d) is wrong type (%s)",
309 num, contents.getTypeName());
310 contents.free();
311 goto err1;
312 }
313
314 // thumb
315 pageDict->lookupNF("Thumb", &thumb);
316 if (!(thumb.isStream() || thumb.isNull() || thumb.isRef())) {
317 error(-1, "Page thumb object (page %d) is wrong type (%s)",
318 num, thumb.getTypeName());
319 thumb.initNull();
320 }
321
322 // actions
323 pageDict->lookupNF("AA", &actions);
324 if (!(actions.isDict() || actions.isNull())) {
325 error(-1, "Page additional action object (page %d) is wrong type (%s)",
326 num, actions.getTypeName());
327 actions.initNull();
328 }
329
330 return;
331
332 trans.initNull();
333 err2:
334 annots.initNull();
335 err1:
336 contents.initNull();
337 ok = gFalse;
338 }
339
~Page()340 Page::~Page() {
341 delete pageWidgets;
342 delete attrs;
343 pageObj.free();
344 annots.free();
345 contents.free();
346 trans.free();
347 thumb.free();
348 actions.free();
349 }
350
getAnnots(Catalog * catalog)351 Annots *Page::getAnnots(Catalog *catalog) {
352 Annots *annots;
353 Object obj;
354
355 annots = new Annots(xref, catalog, getAnnots(&obj));
356 obj.free();
357 return annots;
358 }
359
addAnnot(Annot * annot)360 void Page::addAnnot(Annot *annot) {
361 Object obj1;
362 Object tmp;
363 Ref annotRef = annot->getRef ();
364
365 if (annots.isNull()) {
366 Ref annotsRef;
367 // page doesn't have annots array,
368 // we have to create it
369
370 obj1.initArray(xref);
371 obj1.arrayAdd(tmp.initRef (annotRef.num, annotRef.gen));
372 tmp.free();
373
374 annotsRef = xref->addIndirectObject (&obj1);
375 annots.initRef(annotsRef.num, annotsRef.gen);
376 pageObj.dictSet ("Annots", &annots);
377 xref->setModifiedObject (&pageObj, pageRef);
378 } else {
379 getAnnots(&obj1);
380 if (obj1.isArray()) {
381 obj1.arrayAdd (tmp.initRef (annotRef.num, annotRef.gen));
382 if (annots.isRef())
383 xref->setModifiedObject (&obj1, annots.getRef());
384 else
385 xref->setModifiedObject (&pageObj, pageRef);
386 }
387 obj1.free();
388 }
389
390 annot->setPage(&pageRef, num);
391 }
392
getLinks(Catalog * catalog)393 Links *Page::getLinks(Catalog *catalog) {
394 Links *links;
395 Object obj;
396
397 links = new Links(getAnnots(&obj), catalog->getBaseURI());
398 obj.free();
399 return links;
400 }
401
display(OutputDev * out,double hDPI,double vDPI,int rotate,GBool useMediaBox,GBool crop,GBool printing,Catalog * catalog,GBool (* abortCheckCbk)(void * data),void * abortCheckCbkData,GBool (* annotDisplayDecideCbk)(Annot * annot,void * user_data),void * annotDisplayDecideCbkData)402 void Page::display(OutputDev *out, double hDPI, double vDPI,
403 int rotate, GBool useMediaBox, GBool crop,
404 GBool printing, Catalog *catalog,
405 GBool (*abortCheckCbk)(void *data),
406 void *abortCheckCbkData,
407 GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
408 void *annotDisplayDecideCbkData) {
409 displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, -1, -1, -1, -1, printing, catalog,
410 abortCheckCbk, abortCheckCbkData,
411 annotDisplayDecideCbk, annotDisplayDecideCbkData);
412 }
413
createGfx(OutputDev * out,double hDPI,double vDPI,int rotate,GBool useMediaBox,GBool crop,int sliceX,int sliceY,int sliceW,int sliceH,GBool printing,Catalog * catalog,GBool (* abortCheckCbk)(void * data),void * abortCheckCbkData,GBool (* annotDisplayDecideCbk)(Annot * annot,void * user_data),void * annotDisplayDecideCbkData)414 Gfx *Page::createGfx(OutputDev *out, double hDPI, double vDPI,
415 int rotate, GBool useMediaBox, GBool crop,
416 int sliceX, int sliceY, int sliceW, int sliceH,
417 GBool printing, Catalog *catalog,
418 GBool (*abortCheckCbk)(void *data),
419 void *abortCheckCbkData,
420 GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
421 void *annotDisplayDecideCbkData) {
422 PDFRectangle *mediaBox, *cropBox;
423 PDFRectangle box;
424 Gfx *gfx;
425
426 rotate += getRotate();
427 if (rotate >= 360) {
428 rotate -= 360;
429 } else if (rotate < 0) {
430 rotate += 360;
431 }
432
433 makeBox(hDPI, vDPI, rotate, useMediaBox, out->upsideDown(),
434 sliceX, sliceY, sliceW, sliceH, &box, &crop);
435 cropBox = getCropBox();
436 mediaBox = getMediaBox();
437
438 if (globalParams->getPrintCommands()) {
439 printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
440 mediaBox->x1, mediaBox->y1, mediaBox->x2, mediaBox->y2);
441 printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
442 cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
443 printf("***** Rotate = %d\n", attrs->getRotate());
444 }
445
446 gfx = new Gfx(xref, out, num, attrs->getResourceDict(), catalog,
447 hDPI, vDPI, &box, crop ? cropBox : (PDFRectangle *)NULL,
448 rotate, abortCheckCbk, abortCheckCbkData);
449
450 return gfx;
451 }
452
displaySlice(OutputDev * out,double hDPI,double vDPI,int rotate,GBool useMediaBox,GBool crop,int sliceX,int sliceY,int sliceW,int sliceH,GBool printing,Catalog * catalog,GBool (* abortCheckCbk)(void * data),void * abortCheckCbkData,GBool (* annotDisplayDecideCbk)(Annot * annot,void * user_data),void * annotDisplayDecideCbkData)453 void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
454 int rotate, GBool useMediaBox, GBool crop,
455 int sliceX, int sliceY, int sliceW, int sliceH,
456 GBool printing, Catalog *catalog,
457 GBool (*abortCheckCbk)(void *data),
458 void *abortCheckCbkData,
459 GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
460 void *annotDisplayDecideCbkData) {
461 Gfx *gfx;
462 Object obj;
463 Annots *annotList;
464 int i;
465
466 if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop,
467 sliceX, sliceY, sliceW, sliceH,
468 printing, catalog,
469 abortCheckCbk, abortCheckCbkData)) {
470 return;
471 }
472
473 gfx = createGfx(out, hDPI, vDPI, rotate, useMediaBox, crop,
474 sliceX, sliceY, sliceW, sliceH,
475 printing, catalog,
476 abortCheckCbk, abortCheckCbkData,
477 annotDisplayDecideCbk, annotDisplayDecideCbkData);
478
479 contents.fetch(xref, &obj);
480 if (!obj.isNull()) {
481 gfx->saveState();
482 gfx->display(&obj);
483 gfx->restoreState();
484 }
485 obj.free();
486
487 // draw annotations
488 annotList = new Annots(xref, catalog, getAnnots(&obj));
489 obj.free();
490
491 if (annotList->getNumAnnots() > 0) {
492 if (globalParams->getPrintCommands()) {
493 printf("***** Annotations\n");
494 }
495 for (i = 0; i < annotList->getNumAnnots(); ++i) {
496 Annot *annot = annotList->getAnnot(i);
497 if ((annotDisplayDecideCbk &&
498 (*annotDisplayDecideCbk)(annot, annotDisplayDecideCbkData)) ||
499 !annotDisplayDecideCbk) {
500 annotList->getAnnot(i)->draw(gfx, printing);
501 }
502 }
503 out->dump();
504 }
505 delete annotList;
506
507 delete gfx;
508 }
509
display(Gfx * gfx)510 void Page::display(Gfx *gfx) {
511 Object obj;
512
513 contents.fetch(xref, &obj);
514 if (!obj.isNull()) {
515 gfx->saveState();
516 gfx->display(&obj);
517 gfx->restoreState();
518 }
519 obj.free();
520 }
521
loadThumb(unsigned char ** data_out,int * width_out,int * height_out,int * rowstride_out)522 GBool Page::loadThumb(unsigned char **data_out,
523 int *width_out, int *height_out,
524 int *rowstride_out)
525 {
526 unsigned int pixbufdatasize;
527 int width, height, bits;
528 Object obj1, fetched_thumb;
529 Dict *dict;
530 GfxColorSpace *colorSpace;
531 GBool success = gFalse;
532 Stream *str;
533 GfxImageColorMap *colorMap;
534
535 /* Get stream dict */
536 thumb.fetch(xref, &fetched_thumb);
537 if (!fetched_thumb.isStream()) {
538 fetched_thumb.free();
539 return gFalse;
540 }
541
542 dict = fetched_thumb.streamGetDict();
543 str = fetched_thumb.getStream();
544
545 if (!dict->lookupInt("Width", "W", &width))
546 goto fail1;
547 if (!dict->lookupInt("Height", "H", &height))
548 goto fail1;
549 if (!dict->lookupInt("BitsPerComponent", "BPC", &bits))
550 goto fail1;
551
552 /* Check for invalid dimensions and integer overflow. */
553 if (width <= 0 || height <= 0)
554 goto fail1;
555 if (width > INT_MAX / 3 / height)
556 goto fail1;
557 pixbufdatasize = width * height * 3;
558
559 /* Get color space */
560 dict->lookup ("ColorSpace", &obj1);
561 if (obj1.isNull ()) {
562 obj1.free ();
563 dict->lookup ("CS", &obj1);
564 }
565 colorSpace = GfxColorSpace::parse(&obj1, NULL);
566 obj1.free();
567 if (!colorSpace) {
568 fprintf (stderr, "Error: Cannot parse color space\n");
569 goto fail1;
570 }
571
572 dict->lookup("Decode", &obj1);
573 if (obj1.isNull()) {
574 obj1.free();
575 dict->lookup("D", &obj1);
576 }
577 colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
578 obj1.free();
579 if (!colorMap->isOk()) {
580 fprintf (stderr, "Error: invalid colormap\n");
581 delete colorMap;
582 goto fail1;
583 }
584
585 if (data_out) {
586 unsigned char *pixbufdata = (unsigned char *) gmalloc(pixbufdatasize);
587 unsigned char *p = pixbufdata;
588 ImageStream *imgstr = new ImageStream(str, width,
589 colorMap->getNumPixelComps(),
590 colorMap->getBits());
591 imgstr->reset();
592 for (int row = 0; row < height; ++row) {
593 for (int col = 0; col < width; ++col) {
594 Guchar pix[gfxColorMaxComps];
595 GfxRGB rgb;
596
597 imgstr->getPixel(pix);
598 colorMap->getRGB(pix, &rgb);
599
600 *p++ = colToByte(rgb.r);
601 *p++ = colToByte(rgb.g);
602 *p++ = colToByte(rgb.b);
603 }
604 }
605 *data_out = pixbufdata;
606 imgstr->close();
607 delete imgstr;
608 }
609
610 success = gTrue;
611
612 if (width_out)
613 *width_out = width;
614 if (height_out)
615 *height_out = height;
616 if (rowstride_out)
617 *rowstride_out = width * 3;
618
619 delete colorMap;
620 fail1:
621 fetched_thumb.free();
622
623 return success;
624 }
625
makeBox(double hDPI,double vDPI,int rotate,GBool useMediaBox,GBool upsideDown,double sliceX,double sliceY,double sliceW,double sliceH,PDFRectangle * box,GBool * crop)626 void Page::makeBox(double hDPI, double vDPI, int rotate,
627 GBool useMediaBox, GBool upsideDown,
628 double sliceX, double sliceY, double sliceW, double sliceH,
629 PDFRectangle *box, GBool *crop) {
630 PDFRectangle *mediaBox, *cropBox, *baseBox;
631 double kx, ky;
632
633 mediaBox = getMediaBox();
634 cropBox = getCropBox();
635 if (sliceW >= 0 && sliceH >= 0) {
636 baseBox = useMediaBox ? mediaBox : cropBox;
637 kx = 72.0 / hDPI;
638 ky = 72.0 / vDPI;
639 if (rotate == 90) {
640 if (upsideDown) {
641 box->x1 = baseBox->x1 + ky * sliceY;
642 box->x2 = baseBox->x1 + ky * (sliceY + sliceH);
643 } else {
644 box->x1 = baseBox->x2 - ky * (sliceY + sliceH);
645 box->x2 = baseBox->x2 - ky * sliceY;
646 }
647 box->y1 = baseBox->y1 + kx * sliceX;
648 box->y2 = baseBox->y1 + kx * (sliceX + sliceW);
649 } else if (rotate == 180) {
650 box->x1 = baseBox->x2 - kx * (sliceX + sliceW);
651 box->x2 = baseBox->x2 - kx * sliceX;
652 if (upsideDown) {
653 box->y1 = baseBox->y1 + ky * sliceY;
654 box->y2 = baseBox->y1 + ky * (sliceY + sliceH);
655 } else {
656 box->y1 = baseBox->y2 - ky * (sliceY + sliceH);
657 box->y2 = baseBox->y2 - ky * sliceY;
658 }
659 } else if (rotate == 270) {
660 if (upsideDown) {
661 box->x1 = baseBox->x2 - ky * (sliceY + sliceH);
662 box->x2 = baseBox->x2 - ky * sliceY;
663 } else {
664 box->x1 = baseBox->x1 + ky * sliceY;
665 box->x2 = baseBox->x1 + ky * (sliceY + sliceH);
666 }
667 box->y1 = baseBox->y2 - kx * (sliceX + sliceW);
668 box->y2 = baseBox->y2 - kx * sliceX;
669 } else {
670 box->x1 = baseBox->x1 + kx * sliceX;
671 box->x2 = baseBox->x1 + kx * (sliceX + sliceW);
672 if (upsideDown) {
673 box->y1 = baseBox->y2 - ky * (sliceY + sliceH);
674 box->y2 = baseBox->y2 - ky * sliceY;
675 } else {
676 box->y1 = baseBox->y1 + ky * sliceY;
677 box->y2 = baseBox->y1 + ky * (sliceY + sliceH);
678 }
679 }
680 } else if (useMediaBox) {
681 *box = *mediaBox;
682 } else {
683 *box = *cropBox;
684 *crop = gFalse;
685 }
686 }
687
processLinks(OutputDev * out,Catalog * catalog)688 void Page::processLinks(OutputDev *out, Catalog *catalog) {
689 Links *links;
690 int i;
691
692 links = getLinks(catalog);
693 for (i = 0; i < links->getNumLinks(); ++i) {
694 out->processLink(links->getLink(i), catalog);
695 }
696 delete links;
697 }
698
getDefaultCTM(double * ctm,double hDPI,double vDPI,int rotate,GBool useMediaBox,GBool upsideDown)699 void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI,
700 int rotate, GBool useMediaBox, GBool upsideDown) {
701 GfxState *state;
702 int i;
703 rotate += getRotate();
704 if (rotate >= 360) {
705 rotate -= 360;
706 } else if (rotate < 0) {
707 rotate += 360;
708 }
709 state = new GfxState(hDPI, vDPI,
710 useMediaBox ? getMediaBox() : getCropBox(),
711 rotate, upsideDown);
712 for (i = 0; i < 6; ++i) {
713 ctm[i] = state->getCTM()[i];
714 }
715 delete state;
716 }
717