]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/Annot.cxx
19efb9c88c99e112a7c937f23e2a7adf8bfdbc08
1 //========================================================================
5 // Copyright 2000-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
23 //------------------------------------------------------------------------
25 //------------------------------------------------------------------------
27 Annot::Annot(XRef
*xrefA
, Dict
*acroForm
, Dict
*dict
) {
28 Object apObj
, asObj
, obj1
, obj2
;
29 GBool regen
, isTextField
;
36 if (dict
->lookup("Rect", &obj1
)->isArray() &&
37 obj1
.arrayGetLength() == 4) {
38 //~ should check object types here
39 obj1
.arrayGet(0, &obj2
);
42 obj1
.arrayGet(1, &obj2
);
45 obj1
.arrayGet(2, &obj2
);
48 obj1
.arrayGet(3, &obj2
);
52 t
= xMin
; xMin
= xMax
; xMax
= t
;
55 t
= yMin
; yMin
= yMax
; yMax
= t
;
58 //~ this should return an error
64 // check if field apperances need to be regenerated
67 acroForm
->lookup("NeedAppearances", &obj1
);
68 if (obj1
.isBool() && obj1
.getBool()) {
74 // check for a text-type field
75 isTextField
= dict
->lookup("FT", &obj1
)->isName("Tx");
78 #if 0 //~ appearance stream generation is not finished yet
79 if (regen
&& isTextField
) {
80 generateAppearance(acroForm
, dict
);
83 if (dict
->lookup("AP", &apObj
)->isDict()) {
84 if (dict
->lookup("AS", &asObj
)->isName()) {
85 if (apObj
.dictLookup("N", &obj1
)->isDict()) {
86 if (obj1
.dictLookupNF(asObj
.getName(), &obj2
)->isRef()) {
87 obj2
.copy(&appearance
);
91 if (obj1
.dictLookupNF("Off", &obj2
)->isRef()) {
92 obj2
.copy(&appearance
);
100 if (apObj
.dictLookupNF("N", &obj1
)->isRef()) {
101 obj1
.copy(&appearance
);
109 #if 0 //~ appearance stream generation is not finished yet
121 void Annot::generateAppearance(Dict
*acroForm
, Dict
*dict
) {
122 MemStream
*appearStream
;
123 Object daObj
, vObj
, drObj
, appearDict
, obj1
, obj2
;
124 GString
*daStr
, *daStr1
, *vStr
, *s
;
130 //~ DA can be inherited
131 if (dict
->lookup("DA", &daObj
)->isString()) {
132 daStr
= daObj
.getString();
134 // look for a font size
135 //~ may want to parse the DS entry in place of this (if it exists)
138 for (i1
= daStr
->getLength() - 2; i1
>= 0; --i1
) {
139 if (daStr
->getChar(i1
) == 'T' && daStr
->getChar(i1
+1) == 'f') {
140 for (--i1
; i1
>= 0 && Lexer::isSpace(daStr
->getChar(i1
)); --i1
) ;
141 for (i0
= i1
; i0
>= 0 && !Lexer::isSpace(daStr
->getChar(i0
)); --i0
) ;
145 s
= new GString(daStr
, i0
, i1
- i0
);
146 fontSize
= atof(s
->getCString());
151 fontSize
= 0.67 * (yMax
- yMin
);
152 daStr1
= new GString(daStr
, 0, i0
);
153 sprintf(buf
, "%.2f", fontSize
);
155 daStr1
->append(daStr
->getCString() + i1
,
156 daStr
->getLength() - i1
);
163 // build the appearance stream contents
164 appearBuf
= new GString();
165 appearBuf
->append("/Tx BMC\n");
166 appearBuf
->append("q BT\n");
167 appearBuf
->append(daStr1
? daStr1
: daStr
)->append("\n");
168 if (dict
->lookup("V", &vObj
)->isString()) {
169 //~ handle quadding -- this requires finding the font and using
170 //~ the encoding and char widths
171 sprintf(buf
, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax
- yMin
- fontSize
);
172 appearBuf
->append(buf
);
173 sprintf(buf
, "%g TL\n", fontSize
);
174 appearBuf
->append(buf
);
175 vStr
= vObj
.getString();
177 while (i0
< vStr
->getLength()) {
179 i1
< vStr
->getLength() &&
180 vStr
->getChar(i1
) != '\n' && vStr
->getChar(i1
) != '\r';
183 appearBuf
->append("T*\n");
185 appearBuf
->append('(');
186 for (; i0
< i1
; ++i0
) {
187 c
= vStr
->getChar(i0
);
188 if (c
== '(' || c
== ')' || c
== '\\') {
189 appearBuf
->append('\\');
190 appearBuf
->append(c
);
191 } else if (c
< 0x20 || c
>= 0x80) {
192 sprintf(buf
, "\\%03o", c
);
193 appearBuf
->append(buf
);
195 appearBuf
->append(c
);
198 appearBuf
->append(") Tj\n");
199 if (i1
+ 1 < vStr
->getLength() &&
200 vStr
->getChar(i1
) == '\r' && vStr
->getChar(i1
+ 1) == '\n') {
208 appearBuf
->append("ET Q\n");
209 appearBuf
->append("EMC\n");
211 // build the appearance stream dictionary
212 appearDict
.initDict(xref
);
213 appearDict
.dictAdd(copyString("Length"),
214 obj1
.initInt(appearBuf
->getLength()));
215 appearDict
.dictAdd(copyString("Subtype"), obj1
.initName("Form"));
216 obj1
.initArray(xref
);
217 obj1
.arrayAdd(obj2
.initReal(0));
218 obj1
.arrayAdd(obj2
.initReal(0));
219 obj1
.arrayAdd(obj2
.initReal(xMax
- xMin
));
220 obj1
.arrayAdd(obj2
.initReal(yMax
- yMin
));
221 appearDict
.dictAdd(copyString("BBox"), &obj1
);
223 // find the resource dictionary
224 dict
->lookup("DR", &drObj
);
225 if (!drObj
.isDict()) {
226 dict
->lookup("Parent", &obj1
);
227 while (obj1
.isDict()) {
229 obj1
.dictLookup("DR", &drObj
);
230 if (drObj
.isDict()) {
233 obj1
.dictLookup("Parent", &obj2
);
238 if (!drObj
.isDict()) {
241 acroForm
->lookup("DR", &drObj
);
245 if (drObj
.isDict()) {
246 appearDict
.dictAdd(copyString("Resources"), drObj
.copy(&obj1
));
250 // build the appearance stream
251 appearStream
= new MemStream(appearBuf
->getCString(), 0,
252 appearBuf
->getLength(), &appearDict
);
253 appearance
.initStream(appearStream
);
263 void Annot::draw(Gfx
*gfx
) {
266 fprintf(stderr
, "DEBUG: Annot::draw(gfx=%p)\n", gfx
);
268 if (appearance
.fetch(xref
, &obj
)->isStream()) {
269 gfx
->doAnnot(&obj
, xMin
, yMin
, xMax
, yMax
);
274 //------------------------------------------------------------------------
276 //------------------------------------------------------------------------
278 Annots::Annots(XRef
*xref
, Catalog
*catalog
, Object
*annotsObj
) {
289 acroForm
= catalog
->getAcroForm()->isDict() ?
290 catalog
->getAcroForm()->getDict() : NULL
;
291 if (annotsObj
->isArray()) {
292 for (i
= 0; i
< annotsObj
->arrayGetLength(); ++i
) {
293 if (annotsObj
->arrayGet(i
, &obj1
)->isDict()) {
294 annot
= new Annot(xref
, acroForm
, obj1
.getDict());
296 if (nAnnots
>= size
) {
298 annots
= (Annot
**)greallocn(annots
, size
, sizeof(Annot
*));
300 annots
[nAnnots
++] = annot
;
313 for (i
= 0; i
< nAnnots
; ++i
) {