summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc396
1 files changed, 161 insertions, 235 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
index 465bda6194a..82ef600be73 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/Annot.cc
@@ -2,15 +2,18 @@
//
// Annot.cc
//
-// Copyright 2000-2022 Glyph & Cog, LLC
+// Copyright 2000-2003 Glyph & Cog, LLC
//
//========================================================================
#include <aconf.h>
+#ifdef USE_GCC_PRAGMAS
+#pragma implementation
+#endif
+
#include <stdlib.h>
#include <math.h>
-#include <limits.h>
#include "gmem.h"
#include "gmempp.h"
#include "GList.h"
@@ -275,8 +278,6 @@ Annot::Annot(PDFDoc *docA, Dict *dict, Ref *refA) {
obj3.free();
} else if (obj2.isRef()) {
obj2.copy(&appearance);
- } else if (obj2.isStream()) {
- obj2.copy(&appearance);
}
obj1.free();
obj2.free();
@@ -305,48 +306,29 @@ Annot::~Annot() {
ocObj.free();
}
-void Annot::generateAnnotAppearance(Object *annotObj) {
+void Annot::generateAnnotAppearance() {
Object obj;
- appearance.fetch(doc->getXRef(), &obj);
- GBool alreadyHaveAppearance = obj.isStream();
- obj.free();
- if (alreadyHaveAppearance) {
- return;
- }
- if (!type || (type->cmp("Line") &&
- type->cmp("PolyLine") &&
- type->cmp("Polygon") &&
- type->cmp("FreeText"))) {
- return;
- }
-
- Object annotObj2;
- if (!annotObj) {
- getObject(&annotObj2);
- annotObj = &annotObj2;
- }
- if (!annotObj->isDict()) {
- annotObj2.free();
- return;
- }
-
- if (!type->cmp("Line")) {
- generateLineAppearance(annotObj);
- } else if (!type->cmp("PolyLine")) {
- generatePolyLineAppearance(annotObj);
- } else if (!type->cmp("Polygon")) {
- generatePolygonAppearance(annotObj);
- } else if (!type->cmp("FreeText")) {
- generateFreeTextAppearance(annotObj);
+ appearance.fetch(doc->getXRef(), &obj);
+ if (!obj.isStream()) {
+ if (type) {
+ if (!type->cmp("Line")) {
+ generateLineAppearance();
+ } else if (!type->cmp("PolyLine")) {
+ generatePolyLineAppearance();
+ } else if (!type->cmp("Polygon")) {
+ generatePolygonAppearance();
+ } else if (!type->cmp("FreeText")) {
+ generateFreeTextAppearance();
+ }
+ }
}
-
- annotObj2.free();
+ obj.free();
}
//~ this doesn't draw the caption
-void Annot::generateLineAppearance(Object *annotObj) {
- Object gfxStateDict, appearDict, obj1, obj2;
+void Annot::generateLineAppearance() {
+ Object annotObj, gfxStateDict, appearDict, obj1, obj2;
MemStream *appearStream;
double x1, y1, x2, y2, dx, dy, len, w;
double lx1, ly1, lx2, ly2;
@@ -357,10 +339,15 @@ void Annot::generateLineAppearance(Object *annotObj) {
AnnotLineEndType lineEnd1, lineEnd2;
GBool fill;
+ if (!getObject(&annotObj)->isDict()) {
+ annotObj.free();
+ return;
+ }
+
appearBuf = new GString();
//----- check for transparency
- if (annotObj->dictLookup("CA", &obj1)->isNum()) {
+ if (annotObj.dictLookup("CA", &obj1)->isNum()) {
gfxStateDict.initDict(doc->getXRef());
gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2));
appearBuf->append("/GS1 gs\n");
@@ -371,7 +358,7 @@ void Annot::generateLineAppearance(Object *annotObj) {
setLineStyle(borderStyle, &w);
setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps());
fill = gFalse;
- if (annotObj->dictLookup("IC", &obj1)->isArray()) {
+ if (annotObj.dictLookup("IC", &obj1)->isArray()) {
if (setFillColor(&obj1)) {
fill = gTrue;
}
@@ -379,14 +366,14 @@ void Annot::generateLineAppearance(Object *annotObj) {
obj1.free();
//----- get line properties
- if (annotObj->dictLookup("L", &obj1)->isArray() &&
+ if (annotObj.dictLookup("L", &obj1)->isArray() &&
obj1.arrayGetLength() == 4) {
if (obj1.arrayGet(0, &obj2)->isNum()) {
x1 = obj2.getNum();
} else {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
obj2.free();
if (obj1.arrayGet(1, &obj2)->isNum()) {
@@ -394,7 +381,7 @@ void Annot::generateLineAppearance(Object *annotObj) {
} else {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
obj2.free();
if (obj1.arrayGet(2, &obj2)->isNum()) {
@@ -402,7 +389,7 @@ void Annot::generateLineAppearance(Object *annotObj) {
} else {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
obj2.free();
if (obj1.arrayGet(3, &obj2)->isNum()) {
@@ -410,16 +397,16 @@ void Annot::generateLineAppearance(Object *annotObj) {
} else {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
obj2.free();
} else {
obj1.free();
- return;
+ goto err1;
}
obj1.free();
lineEnd1 = lineEnd2 = annotLineEndNone;
- if (annotObj->dictLookup("LE", &obj1)->isArray() &&
+ if (annotObj.dictLookup("LE", &obj1)->isArray() &&
obj1.arrayGetLength() == 2) {
lineEnd1 = parseLineEndType(obj1.arrayGet(0, &obj2));
obj2.free();
@@ -427,19 +414,19 @@ void Annot::generateLineAppearance(Object *annotObj) {
obj2.free();
}
obj1.free();
- if (annotObj->dictLookup("LL", &obj1)->isNum()) {
+ if (annotObj.dictLookup("LL", &obj1)->isNum()) {
leaderLen = obj1.getNum();
} else {
leaderLen = 0;
}
obj1.free();
- if (annotObj->dictLookup("LLE", &obj1)->isNum()) {
+ if (annotObj.dictLookup("LLE", &obj1)->isNum()) {
leaderExtLen = obj1.getNum();
} else {
leaderExtLen = 0;
}
obj1.free();
- if (annotObj->dictLookup("LLO", &obj1)->isNum()) {
+ if (annotObj.dictLookup("LLO", &obj1)->isNum()) {
leaderOffLen = obj1.getNum();
} else {
leaderOffLen = 0;
@@ -526,19 +513,27 @@ void Annot::generateLineAppearance(Object *annotObj) {
appearBuf->getLength(), &appearDict);
appearance.free();
appearance.initStream(appearStream);
+
+ err1:
+ annotObj.free();
}
//~ this doesn't handle line ends (arrows)
-void Annot::generatePolyLineAppearance(Object *annotObj) {
- Object gfxStateDict, appearDict, obj1, obj2;
+void Annot::generatePolyLineAppearance() {
+ Object annotObj, gfxStateDict, appearDict, obj1, obj2;
MemStream *appearStream;
double x1, y1, w;
int i;
+ if (!getObject(&annotObj)->isDict()) {
+ annotObj.free();
+ return;
+ }
+
appearBuf = new GString();
//----- check for transparency
- if (annotObj->dictLookup("CA", &obj1)->isNum()) {
+ if (annotObj.dictLookup("CA", &obj1)->isNum()) {
gfxStateDict.initDict(doc->getXRef());
gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2));
appearBuf->append("/GS1 gs\n");
@@ -549,7 +544,7 @@ void Annot::generatePolyLineAppearance(Object *annotObj) {
setLineStyle(borderStyle, &w);
setStrokeColor(borderStyle->getColor(), borderStyle->getNumColorComps());
// fill = gFalse;
- // if (annotObj->dictLookup("IC", &obj1)->isArray()) {
+ // if (annotObj.dictLookup("IC", &obj1)->isArray()) {
// if (setFillColor(&obj1)) {
// fill = gTrue;
// }
@@ -557,22 +552,22 @@ void Annot::generatePolyLineAppearance(Object *annotObj) {
// obj1.free();
//----- draw line
- if (!annotObj->dictLookup("Vertices", &obj1)->isArray()) {
+ if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) {
obj1.free();
- return;
+ goto err1;
}
for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) {
if (!obj1.arrayGet(i, &obj2)->isNum()) {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
x1 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(i+1, &obj2)->isNum()) {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
y1 = obj2.getNum();
obj2.free();
@@ -611,18 +606,26 @@ void Annot::generatePolyLineAppearance(Object *annotObj) {
appearBuf->getLength(), &appearDict);
appearance.free();
appearance.initStream(appearStream);
+
+ err1:
+ annotObj.free();
}
-void Annot::generatePolygonAppearance(Object *annotObj) {
- Object gfxStateDict, appearDict, obj1, obj2;
+void Annot::generatePolygonAppearance() {
+ Object annotObj, gfxStateDict, appearDict, obj1, obj2;
MemStream *appearStream;
double x1, y1;
int i;
+ if (!getObject(&annotObj)->isDict()) {
+ annotObj.free();
+ return;
+ }
+
appearBuf = new GString();
//----- check for transparency
- if (annotObj->dictLookup("CA", &obj1)->isNum()) {
+ if (annotObj.dictLookup("CA", &obj1)->isNum()) {
gfxStateDict.initDict(doc->getXRef());
gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2));
appearBuf->append("/GS1 gs\n");
@@ -630,30 +633,30 @@ void Annot::generatePolygonAppearance(Object *annotObj) {
obj1.free();
//----- set fill color
- if (!annotObj->dictLookup("IC", &obj1)->isArray() ||
+ if (!annotObj.dictLookup("IC", &obj1)->isArray() ||
!setFillColor(&obj1)) {
obj1.free();
- return;
+ goto err1;
}
obj1.free();
//----- fill polygon
- if (!annotObj->dictLookup("Vertices", &obj1)->isArray()) {
+ if (!annotObj.dictLookup("Vertices", &obj1)->isArray()) {
obj1.free();
- return;
+ goto err1;
}
for (i = 0; i+1 < obj1.arrayGetLength(); i += 2) {
if (!obj1.arrayGet(i, &obj2)->isNum()) {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
x1 = obj2.getNum();
obj2.free();
if (!obj1.arrayGet(i+1, &obj2)->isNum()) {
obj2.free();
obj1.free();
- return;
+ goto err1;
}
y1 = obj2.getNum();
obj2.free();
@@ -692,23 +695,31 @@ void Annot::generatePolygonAppearance(Object *annotObj) {
appearBuf->getLength(), &appearDict);
appearance.free();
appearance.initStream(appearStream);
+
+ err1:
+ annotObj.free();
}
//~ this doesn't handle rich text
//~ this doesn't handle the callout
//~ this doesn't handle the RD field
-void Annot::generateFreeTextAppearance(Object *annotObj) {
- Object gfxStateDict, appearDict, obj1, obj2;
+void Annot::generateFreeTextAppearance() {
+ Object annotObj, gfxStateDict, appearDict, obj1, obj2;
Object resources, gsResources, fontResources, defaultFont;
GString *text, *da;
double lineWidth;
int quadding, rot;
MemStream *appearStream;
+ if (!getObject(&annotObj)->isDict()) {
+ annotObj.free();
+ return;
+ }
+
appearBuf = new GString();
//----- check for transparency
- if (annotObj->dictLookup("CA", &obj1)->isNum()) {
+ if (annotObj.dictLookup("CA", &obj1)->isNum()) {
gfxStateDict.initDict(doc->getXRef());
gfxStateDict.dictAdd(copyString("ca"), obj1.copy(&obj2));
appearBuf->append("/GS1 gs\n");
@@ -716,19 +727,19 @@ void Annot::generateFreeTextAppearance(Object *annotObj) {
obj1.free();
//----- draw the text
- if (annotObj->dictLookup("Contents", &obj1)->isString()) {
+ if (annotObj.dictLookup("Contents", &obj1)->isString()) {
text = obj1.getString()->copy();
} else {
text = new GString();
}
obj1.free();
- if (annotObj->dictLookup("Q", &obj1)->isInt()) {
+ if (annotObj.dictLookup("Q", &obj1)->isInt()) {
quadding = obj1.getInt();
} else {
quadding = 0;
}
obj1.free();
- if (annotObj->dictLookup("DA", &obj1)->isString()) {
+ if (annotObj.dictLookup("DA", &obj1)->isString()) {
da = obj1.getString()->copy();
} else {
da = new GString();
@@ -736,7 +747,7 @@ void Annot::generateFreeTextAppearance(Object *annotObj) {
obj1.free();
// the "Rotate" field is not defined in the PDF spec, but Acrobat
// looks at it
- if (annotObj->dictLookup("Rotate", &obj1)->isInt()) {
+ if (annotObj.dictLookup("Rotate", &obj1)->isInt()) {
rot = obj1.getInt();
} else {
rot = 0;
@@ -786,6 +797,8 @@ void Annot::generateFreeTextAppearance(Object *annotObj) {
appearBuf->getLength(), &appearDict);
appearance.free();
appearance.initStream(appearStream);
+
+ annotObj.free();
}
void Annot::setLineStyle(AnnotBorderStyle *bs, double *lineWidth) {
@@ -1331,192 +1344,105 @@ Object *Annot::getObject(Object *obj) {
}
//------------------------------------------------------------------------
-// PageAnnots
-//------------------------------------------------------------------------
-
-class PageAnnots {
-public:
-
- PageAnnots();
- ~PageAnnots();
-
- GList *annots; // list of annots on the page [Annot]
- GBool appearancesGenerated; // set after appearances have been generated
-};
-
-PageAnnots::PageAnnots() {
- annots = new GList();
- appearancesGenerated = gFalse;
-}
-
-PageAnnots::~PageAnnots() {
- deleteGList(annots, Annot);
-}
-
-//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
-Annots::Annots(PDFDoc *docA) {
- doc = docA;
- pageAnnots = (PageAnnots **)gmallocn(doc->getNumPages(), sizeof(PageAnnots*));
- for (int page = 1; page <= doc->getNumPages(); ++page) {
- pageAnnots[page - 1] = NULL;
- }
- formFieldRefsSize = 0;
- formFieldRefs = NULL;
-}
-
-Annots::~Annots() {
- for (int page = 1; page <= doc->getNumPages(); ++page) {
- delete pageAnnots[page - 1];
- }
- gfree(pageAnnots);
- gfree(formFieldRefs);
-}
-
-void Annots::loadAnnots(int page) {
- if (pageAnnots[page - 1]) {
- return;
- }
-
- pageAnnots[page - 1] = new PageAnnots();
-
- Object annotsObj;
- doc->getCatalog()->getPage(page)->getAnnots(&annotsObj);
- if (!annotsObj.isArray()) {
- annotsObj.free();
- return;
- }
-
- loadFormFieldRefs();
-
- for (int i = 0; i < annotsObj.arrayGetLength(); ++i) {
- Object annotObj;
- Ref annotRef;
- if (annotsObj.arrayGetNF(i, &annotObj)->isRef()) {
- annotRef = annotObj.getRef();
- annotObj.free();
- annotsObj.arrayGet(i, &annotObj);
- } else {
- annotRef.num = annotRef.gen = -1;
- }
- if (!annotObj.isDict()) {
- annotObj.free();
- continue;
- }
-
- // skip any annotations which are used as AcroForm fields --
- // they'll be rendered by the AcroForm module
- if (annotRef.num >= 0 && annotRef.num < formFieldRefsSize &&
- formFieldRefs[annotRef.num]) {
- annotObj.free();
- continue;
- }
-
- Annot *annot = new Annot(doc, annotObj.getDict(), &annotRef);
- annotObj.free();
- if (annot->isOk()) {
- pageAnnots[page - 1]->annots->append(annot);
- } else {
- delete annot;
- }
- }
-
- annotsObj.free();
-}
-
-// Build a set of object refs for AcroForm fields.
-void Annots::loadFormFieldRefs() {
- if (formFieldRefs) {
- return;
- }
-
- AcroForm *form = doc->getCatalog()->getForm();
- if (!form) {
- return;
- }
+Annots::Annots(PDFDoc *docA, Object *annotsObj) {
+ Annot *annot;
+ Object obj1, obj2;
+ Ref ref;
+ GBool drawWidgetAnnots;
+ int size;
+ int i;
- int newFormFieldRefsSize = 256;
- for (int i = 0; i < form->getNumFields(); ++i) {
- AcroFormField *field = form->getField(i);
- Object fieldRef;
- field->getFieldRef(&fieldRef);
- if (fieldRef.getRefNum() >= formFieldRefsSize) {
- while (fieldRef.getRefNum() >= newFormFieldRefsSize &&
- newFormFieldRefsSize <= INT_MAX / 2) {
- newFormFieldRefsSize *= 2;
- }
- if (fieldRef.getRefNum() >= newFormFieldRefsSize) {
- continue;
+ doc = docA;
+ annots = NULL;
+ size = 0;
+ nAnnots = 0;
+
+ if (annotsObj->isArray()) {
+ // Kludge: some PDF files define an empty AcroForm, but still
+ // include Widget-type annotations -- in that case, we want to
+ // draw the widgets (since the form code won't). This really
+ // ought to look for Widget-type annotations that are not included
+ // in any form field.
+ drawWidgetAnnots = !doc->getCatalog()->getForm() ||
+ doc->getCatalog()->getForm()->getNumFields() == 0;
+ for (i = 0; i < annotsObj->arrayGetLength(); ++i) {
+ if (annotsObj->arrayGetNF(i, &obj1)->isRef()) {
+ ref = obj1.getRef();
+ obj1.free();
+ annotsObj->arrayGet(i, &obj1);
+ } else {
+ ref.num = ref.gen = -1;
}
- formFieldRefs = (char *)grealloc(formFieldRefs, newFormFieldRefsSize);
- for (int j = formFieldRefsSize; j < newFormFieldRefsSize; ++j) {
- formFieldRefs[j] = (char)0;
+ if (obj1.isDict()) {
+ if (drawWidgetAnnots ||
+ !obj1.dictLookup("Subtype", &obj2)->isName("Widget")) {
+ annot = new Annot(doc, obj1.getDict(), &ref);
+ if (annot->isOk()) {
+ if (nAnnots >= size) {
+ size += 16;
+ annots = (Annot **)greallocn(annots, size, sizeof(Annot *));
+ }
+ annots[nAnnots++] = annot;
+ } else {
+ delete annot;
+ }
+ }
+ obj2.free();
}
- formFieldRefsSize = newFormFieldRefsSize;
+ obj1.free();
}
- formFieldRefs[fieldRef.getRefNum()] = (char)1;
- fieldRef.free();
}
}
-int Annots::getNumAnnots(int page) {
- loadAnnots(page);
- return pageAnnots[page - 1]->annots->getLength();
-}
+Annots::~Annots() {
+ int i;
-Annot *Annots::getAnnot(int page, int idx) {
- loadAnnots(page);
- return (Annot *)pageAnnots[page - 1]->annots->get(idx);
+ for (i = 0; i < nAnnots; ++i) {
+ delete annots[i];
+ }
+ gfree(annots);
}
-Annot *Annots::find(int page, double x, double y) {
- loadAnnots(page);
- PageAnnots *pa = pageAnnots[page - 1];
- for (int i = pa->annots->getLength() - 1; i >= 0; --i) {
- Annot *annot = (Annot *)pa->annots->get(i);
- if (annot->inRect(x, y)) {
- return annot;
+Annot *Annots::find(double x, double y) {
+ int i;
+
+ for (i = nAnnots - 1; i >= 0; --i) {
+ if (annots[i]->inRect(x, y)) {
+ return annots[i];
}
}
return NULL;
}
-int Annots::findIdx(int page, double x, double y) {
- loadAnnots(page);
- PageAnnots *pa = pageAnnots[page - 1];
- for (int i = pa->annots->getLength() - 1; i >= 0; --i) {
- Annot *annot = (Annot *)pa->annots->get(i);
- if (annot->inRect(x, y)) {
+int Annots::findIdx(double x, double y) {
+ int i;
+
+ for (i = nAnnots - 1; i >= 0; --i) {
+ if (annots[i]->inRect(x, y)) {
return i;
}
}
return -1;
}
-void Annots::add(int page, Object *annotObj) {
- if (!annotObj->isDict()) {
- return;
- }
- Ref annotRef = {-1, -1};
- Annot *annot = new Annot(doc, annotObj->getDict(), &annotRef);
- if (annot->isOk()) {
- annot->generateAnnotAppearance(annotObj);
- pageAnnots[page - 1]->annots->append(annot);
- } else {
- delete annot;
+void Annots::generateAnnotAppearances() {
+ int i;
+
+ for (i = 0; i < nAnnots; ++i) {
+ annots[i]->generateAnnotAppearance();
}
}
-void Annots::generateAnnotAppearances(int page) {
- loadAnnots(page);
- PageAnnots *pa = pageAnnots[page - 1];
- if (!pa->appearancesGenerated) {
- for (int i = 0; i < pa->annots->getLength(); ++i) {
- Annot *annot = (Annot *)pa->annots->get(i);
- annot->generateAnnotAppearance(NULL);
+Annot *Annots::findAnnot(Ref *ref) {
+ int i;
+
+ for (i = 0; i < nAnnots; ++i) {
+ if (annots[i]->match(ref)) {
+ return annots[i];
}
- pa->appearancesGenerated = gTrue;
}
+ return NULL;
}