]>
git.ipfire.org Git - thirdparty/cups.git/blob - pdftops/Link.cxx
1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
23 //------------------------------------------------------------------------
25 static GString
*getFileSpecName(Object
*fileSpecObj
);
27 //------------------------------------------------------------------------
29 //------------------------------------------------------------------------
31 LinkDest::LinkDest(Array
*a
, GBool pageIsRefA
) {
35 pageIsRef
= pageIsRefA
;
36 left
= bottom
= right
= top
= zoom
= 0;
41 if (!a
->getNF(0, &obj1
)->isRef()) {
42 error(-1, "Bad annotation destination");
45 pageRef
.num
= obj1
.getRefNum();
46 pageRef
.gen
= obj1
.getRefGen();
49 if (!a
->get(0, &obj1
)->isInt()) {
50 error(-1, "Bad annotation destination");
53 pageNum
= obj1
.getInt() + 1;
57 // get destination type
61 if (obj1
.isName("XYZ")) {
66 } else if (obj2
.isNum()) {
70 error(-1, "Bad annotation destination position");
77 } else if (obj2
.isNum()) {
81 error(-1, "Bad annotation destination position");
88 } else if (obj2
.isNum()) {
92 error(-1, "Bad annotation destination position");
98 } else if (obj1
.isName("Fit")) {
102 } else if (obj1
.isName("FitH")) {
104 if (!a
->get(2, &obj2
)->isNum()) {
105 error(-1, "Bad annotation destination position");
112 } else if (obj1
.isName("FitV")) {
114 if (!a
->get(2, &obj2
)->isNum()) {
115 error(-1, "Bad annotation destination position");
118 left
= obj2
.getNum();
122 } else if (obj1
.isName("FitR")) {
124 if (!a
->get(2, &obj2
)->isNum()) {
125 error(-1, "Bad annotation destination position");
128 left
= obj2
.getNum();
130 if (!a
->get(3, &obj2
)->isNum()) {
131 error(-1, "Bad annotation destination position");
134 bottom
= obj2
.getNum();
136 if (!a
->get(4, &obj2
)->isNum()) {
137 error(-1, "Bad annotation destination position");
140 right
= obj2
.getNum();
142 if (!a
->get(5, &obj2
)->isNum()) {
143 error(-1, "Bad annotation destination position");
150 } else if (obj1
.isName("FitB")) {
154 } else if (obj1
.isName("FitBH")) {
156 if (!a
->get(2, &obj2
)->isNum()) {
157 error(-1, "Bad annotation destination position");
164 } else if (obj1
.isName("FitBV")) {
166 if (!a
->get(2, &obj2
)->isNum()) {
167 error(-1, "Bad annotation destination position");
170 left
= obj2
.getNum();
175 error(-1, "Unknown annotation destination type");
189 LinkDest::LinkDest(LinkDest
*dest
) {
191 pageIsRef
= dest
->pageIsRef
;
193 pageRef
= dest
->pageRef
;
195 pageNum
= dest
->pageNum
;
197 bottom
= dest
->bottom
;
201 changeLeft
= dest
->changeLeft
;
202 changeTop
= dest
->changeTop
;
203 changeZoom
= dest
->changeZoom
;
207 //------------------------------------------------------------------------
209 //------------------------------------------------------------------------
211 LinkGoTo::LinkGoTo(Object
*destObj
) {
216 if (destObj
->isName()) {
217 namedDest
= new GString(destObj
->getName());
218 } else if (destObj
->isString()) {
219 namedDest
= destObj
->getString()->copy();
221 // destination dictionary
222 } else if (destObj
->isArray()) {
223 dest
= new LinkDest(destObj
->getArray(), gTrue
);
231 error(-1, "Illegal annotation destination");
235 LinkGoTo::~LinkGoTo() {
242 //------------------------------------------------------------------------
244 //------------------------------------------------------------------------
246 LinkGoToR::LinkGoToR(Object
*fileSpecObj
, Object
*destObj
) {
251 fileName
= getFileSpecName(fileSpecObj
);
254 if (destObj
->isName()) {
255 namedDest
= new GString(destObj
->getName());
256 } else if (destObj
->isString()) {
257 namedDest
= destObj
->getString()->copy();
259 // destination dictionary
260 } else if (destObj
->isArray()) {
261 dest
= new LinkDest(destObj
->getArray(), gFalse
);
269 error(-1, "Illegal annotation destination");
273 LinkGoToR::~LinkGoToR() {
283 //------------------------------------------------------------------------
285 //------------------------------------------------------------------------
287 LinkLaunch::LinkLaunch(Object
*actionObj
) {
293 if (actionObj
->isDict()) {
294 if (!actionObj
->dictLookup("F", &obj1
)->isNull()) {
295 fileName
= getFileSpecName(&obj1
);
298 //~ This hasn't been defined by Adobe yet, so assume it looks
299 //~ just like the Win dictionary until they say otherwise.
300 if (actionObj
->dictLookup("Unix", &obj1
)->isDict()) {
301 obj1
.dictLookup("F", &obj2
);
302 fileName
= getFileSpecName(&obj2
);
304 if (obj1
.dictLookup("P", &obj2
)->isString())
305 params
= obj2
.getString()->copy();
308 error(-1, "Bad launch-type link action");
315 LinkLaunch::~LinkLaunch() {
322 //------------------------------------------------------------------------
324 //------------------------------------------------------------------------
326 LinkURI::LinkURI(Object
*uriObj
, GString
*baseURI
) {
332 if (uriObj
->isString()) {
333 uri2
= uriObj
->getString()->copy();
335 n
= strcspn(uri2
->getCString(), "/:");
336 if (n
== uri2
->getLength() || uri2
->getChar(n
) == '/') {
337 uri
= baseURI
->copy();
338 c
= uri
->getChar(uri
->getLength() - 1);
339 if (c
== '/' || c
== '?') {
340 if (uri2
->getChar(0) == '/') {
344 if (uri2
->getChar(0) != '/') {
357 error(-1, "Illegal URI-type link");
361 LinkURI::~LinkURI() {
366 //------------------------------------------------------------------------
368 //------------------------------------------------------------------------
370 LinkNamed::LinkNamed(Object
*nameObj
) {
372 if (nameObj
->isName()) {
373 name
= new GString(nameObj
->getName());
377 LinkNamed::~LinkNamed() {
383 //------------------------------------------------------------------------
385 //------------------------------------------------------------------------
387 LinkUnknown::LinkUnknown(char *actionA
) {
388 action
= new GString(actionA
);
391 LinkUnknown::~LinkUnknown() {
395 //------------------------------------------------------------------------
397 //------------------------------------------------------------------------
399 Link::Link(Dict
*dict
, GString
*baseURI
) {
400 Object obj1
, obj2
, obj3
, obj4
;
407 if (!dict
->lookup("Rect", &obj1
)->isArray()) {
408 error(-1, "Annotation rectangle is wrong type");
411 if (!obj1
.arrayGet(0, &obj2
)->isNum()) {
412 error(-1, "Bad annotation rectangle");
417 if (!obj1
.arrayGet(1, &obj2
)->isNum()) {
418 error(-1, "Bad annotation rectangle");
423 if (!obj1
.arrayGet(2, &obj2
)->isNum()) {
424 error(-1, "Bad annotation rectangle");
429 if (!obj1
.arrayGet(3, &obj2
)->isNum()) {
430 error(-1, "Bad annotation rectangle");
449 if (!dict
->lookup("Border", &obj1
)->isNull()) {
450 if (obj1
.isArray() && obj1
.arrayGetLength() >= 3) {
451 if (obj1
.arrayGet(2, &obj2
)->isNum()) {
452 borderW
= obj2
.getNum();
454 error(-1, "Bad annotation border");
461 // look for destination
462 if (!dict
->lookup("Dest", &obj1
)->isNull()) {
463 action
= new LinkGoTo(&obj1
);
468 if (dict
->lookup("A", &obj1
)->isDict()) {
469 obj1
.dictLookup("S", &obj2
);
472 if (obj2
.isName("GoTo")) {
473 obj1
.dictLookup("D", &obj3
);
474 action
= new LinkGoTo(&obj3
);
478 } else if (obj2
.isName("GoToR")) {
479 obj1
.dictLookup("F", &obj3
);
480 obj1
.dictLookup("D", &obj4
);
481 action
= new LinkGoToR(&obj3
, &obj4
);
486 } else if (obj2
.isName("Launch")) {
487 action
= new LinkLaunch(&obj1
);
490 } else if (obj2
.isName("URI")) {
491 obj1
.dictLookup("URI", &obj3
);
492 action
= new LinkURI(&obj3
, baseURI
);
496 } else if (obj2
.isName("Named")) {
497 obj1
.dictLookup("N", &obj3
);
498 action
= new LinkNamed(&obj3
);
502 } else if (obj2
.isName()) {
503 action
= new LinkUnknown(obj2
.getName());
505 // action is missing or wrong type
507 error(-1, "Bad annotation action");
514 error(-1, "Missing annotation destination/action");
520 // check for bad action
521 if (action
&& action
->isOk())
537 //------------------------------------------------------------------------
539 //------------------------------------------------------------------------
541 Links::Links(Object
*annots
, GString
*baseURI
) {
551 if (annots
->isArray()) {
552 for (i
= 0; i
< annots
->arrayGetLength(); ++i
) {
553 if (annots
->arrayGet(i
, &obj1
)->isDict()) {
554 if (obj1
.dictLookup("Subtype", &obj2
)->isName("Link")) {
555 link
= new Link(obj1
.getDict(), baseURI
);
557 if (numLinks
>= size
) {
559 links
= (Link
**)grealloc(links
, size
* sizeof(Link
*));
561 links
[numLinks
++] = link
;
576 for (i
= 0; i
< numLinks
; ++i
)
581 LinkAction
*Links::find(double x
, double y
) {
584 for (i
= 0; i
< numLinks
; ++i
) {
585 if (links
[i
]->inRect(x
, y
)) {
586 return links
[i
]->getAction();
592 GBool
Links::onLink(double x
, double y
) {
595 for (i
= 0; i
< numLinks
; ++i
) {
596 if (links
[i
]->inRect(x
, y
))
602 //------------------------------------------------------------------------
604 // Extract a file name from a file specification (string or dictionary).
605 static GString
*getFileSpecName(Object
*fileSpecObj
) {
612 if (fileSpecObj
->isString()) {
613 name
= fileSpecObj
->getString()->copy();
616 } else if (fileSpecObj
->isDict()) {
617 if (!fileSpecObj
->dictLookup("Unix", &obj1
)->isString()) {
619 fileSpecObj
->dictLookup("F", &obj1
);
622 name
= obj1
.getString()->copy();
624 error(-1, "Illegal file spec in link");
629 error(-1, "Illegal file spec in link");