Initial revision
[swftools.git] / pdf2swf / xpdf / Page.cc
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"
18 #include "Link.h"
19 #include "OutputDev.h"
20 #ifndef PDF_PARSER_ONLY
21 #include "Gfx.h"
22 #include "FormWidget.h"
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) {
34   Object obj1, obj2;
35   double w, h;
36
37   // get old/default values
38   if (attrs) {
39     x1 = attrs->x1;
40     y1 = attrs->y1;
41     x2 = attrs->x2;
42     y2 = attrs->y2;
43     cropX1 = attrs->cropX1;
44     cropY1 = attrs->cropY1;
45     cropX2 = attrs->cropX2;
46     cropY2 = attrs->cropY2;
47     rotate = attrs->rotate;
48     attrs->resources.copy(&resources);
49   } else {
50     // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
51     // but some (non-compliant) PDF files don't specify a MediaBox
52     x1 = 0;
53     y1 = 0;
54     x2 = 612;
55     y2 = 792;
56     cropX1 = cropY1 = cropX2 = cropY2 = 0;
57     rotate = 0;
58     resources.initNull();
59   }
60
61   // media box
62   dict->lookup("MediaBox", &obj1);
63   if (obj1.isArray() && obj1.arrayGetLength() == 4) {
64     obj1.arrayGet(0, &obj2);
65     if (obj2.isNum())
66       x1 = obj2.getNum();
67     obj2.free();
68     obj1.arrayGet(1, &obj2);
69     if (obj2.isNum())
70       y1 = obj2.getNum();
71     obj2.free();
72     obj1.arrayGet(2, &obj2);
73     if (obj2.isNum())
74       x2 = obj2.getNum();
75     obj2.free();
76     obj1.arrayGet(3, &obj2);
77     if (obj2.isNum())
78       y2 = obj2.getNum();
79     obj2.free();
80   }
81   obj1.free();
82
83   // crop box
84   dict->lookup("CropBox", &obj1);
85   if (obj1.isArray() && obj1.arrayGetLength() == 4) {
86     obj1.arrayGet(0, &obj2);
87     if (obj2.isNum())
88       cropX1 = obj2.getNum();
89     obj2.free();
90     obj1.arrayGet(1, &obj2);
91     if (obj2.isNum())
92       cropY1 = obj2.getNum();
93     obj2.free();
94     obj1.arrayGet(2, &obj2);
95     if (obj2.isNum())
96       cropX2 = obj2.getNum();
97     obj2.free();
98     obj1.arrayGet(3, &obj2);
99     if (obj2.isNum())
100       cropY2 = obj2.getNum();
101     obj2.free();
102   }
103   obj1.free();
104
105   // if the MediaBox is excessively larger than the CropBox,
106   // just use the CropBox
107   limitToCropBox = gFalse;
108   w = 0.25 * (cropX2 - cropX1);
109   h = 0.25 * (cropY2 - cropY1);
110   if (cropX2 > cropX1 &&
111       ((cropX1 - x1) + (x2 - cropX2) > w ||
112        (cropY1 - y1) + (y2 - cropY2) > h)) {
113     limitToCropBox = gTrue;
114   }
115
116   // rotate
117   dict->lookup("Rotate", &obj1);
118   if (obj1.isInt())
119     rotate = obj1.getInt();
120   obj1.free();
121   while (rotate < 0)
122     rotate += 360;
123   while (rotate >= 360)
124     rotate -= 360;
125
126   // resource dictionary
127   dict->lookup("Resources", &obj1);
128   if (obj1.isDict()) {
129     resources.free();
130     obj1.copy(&resources);
131   }
132   obj1.free();
133 }
134
135 PageAttrs::~PageAttrs() {
136   resources.free();
137 }
138
139 //------------------------------------------------------------------------
140 // Page
141 //------------------------------------------------------------------------
142
143 Page::Page(int num1, Dict *pageDict, PageAttrs *attrs1) {
144
145   ok = gTrue;
146   num = num1;
147
148   // get attributes
149   attrs = attrs1;
150
151   // annotations
152   pageDict->lookupNF("Annots", &annots);
153   if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
154     error(-1, "Page annotations object (page %d) is wrong type (%s)",
155           num, annots.getTypeName());
156     annots.free();
157     goto err2;
158   }
159
160   // contents
161   pageDict->lookupNF("Contents", &contents);
162   if (!(contents.isRef() || contents.isArray() ||
163         contents.isNull())) {
164     error(-1, "Page contents object (page %d) is wrong type (%s)",
165           num, contents.getTypeName());
166     contents.free();
167     goto err1;
168   }
169
170   return;
171
172  err2:
173   annots.initNull();
174  err1:
175   contents.initNull();
176   ok = gFalse;
177 }
178
179 Page::~Page() {
180   delete attrs;
181   annots.free();
182   contents.free();
183 }
184
185 void Page::display(OutputDev *out, double dpi, int rotate,
186                    Links *links, Catalog *catalog) {
187 #ifndef PDF_PARSER_ONLY
188   Gfx *gfx;
189   Object obj;
190   Link *link;
191   int i;
192   FormWidgets *formWidgets;
193
194   if (printCommands) {
195     printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
196            getX1(), getY1(), getX2(), getY2());
197     if (isCropped()) {
198       printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
199              getCropX1(), getCropY1(), getCropX2(), getCropY2());
200     }
201     printf("***** Rotate = %d\n", attrs->getRotate());
202   }
203
204   rotate += getRotate();
205   if (rotate >= 360) {
206     rotate -= 360;
207   } else if (rotate < 0) {
208     rotate += 360;
209   }
210   gfx = new Gfx(out, num, attrs->getResourceDict(),
211                 dpi, getX1(), getY1(), getX2(), getY2(), isCropped(),
212                 getCropX1(), getCropY1(), getCropX2(), getCropY2(), rotate);
213   contents.fetch(&obj);
214   if (!obj.isNull()) {
215     gfx->display(&obj);
216   }
217   obj.free();
218
219   // draw links
220   if (links) {
221     for (i = 0; i < links->getNumLinks(); ++i) {
222       link = links->getLink(i);
223       out->drawLink(link, catalog);
224     }
225     out->dump();
226   }
227
228   // draw AcroForm widgets
229   //~ need to reset CTM ???
230   formWidgets = new FormWidgets(annots.fetch(&obj));
231   obj.free();
232   if (printCommands && formWidgets->getNumWidgets() > 0) {
233     printf("***** AcroForm widgets\n");
234   }
235   for (i = 0; i < formWidgets->getNumWidgets(); ++i) {
236     formWidgets->getWidget(i)->draw(gfx);
237   }
238   if (formWidgets->getNumWidgets() > 0) {
239     out->dump();
240   }
241   delete formWidgets;
242
243   delete gfx;
244 #endif
245 }