summaryrefslogtreecommitdiffstats
path: root/kpdf/xpdf/xpdf/Annot.cc
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2020-12-13 19:22:19 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2020-12-13 21:14:47 +0900
commitc57343e948aa9f3346ad866ad88d4b1330d098b8 (patch)
tree143dc455ce45167d0ae2809678967eeeb1e62ac6 /kpdf/xpdf/xpdf/Annot.cc
parentd56dba4d2f900eb73d5ee00586c1b2d84b132b3f (diff)
downloadtdegraphics-c57343e948aa9f3346ad866ad88d4b1330d098b8.tar.gz
tdegraphics-c57343e948aa9f3346ad866ad88d4b1330d098b8.zip
Renaming of files in preparation for code style tools.
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it> (cherry picked from commit 14d0fbe96c6abdb9da80e99953aec672f999948c)
Diffstat (limited to 'kpdf/xpdf/xpdf/Annot.cc')
-rw-r--r--kpdf/xpdf/xpdf/Annot.cc1556
1 files changed, 0 insertions, 1556 deletions
diff --git a/kpdf/xpdf/xpdf/Annot.cc b/kpdf/xpdf/xpdf/Annot.cc
deleted file mode 100644
index 23df25df..00000000
--- a/kpdf/xpdf/xpdf/Annot.cc
+++ /dev/null
@@ -1,1556 +0,0 @@
-//========================================================================
-//
-// Annot.cc
-//
-// Copyright 2000-2003 Glyph & Cog, LLC
-//
-//========================================================================
-
-#include <aconf.h>
-
-#ifdef USE_GCC_PRAGMAS
-#pragma implementation
-#endif
-
-#include <stdlib.h>
-#include <math.h>
-#include "gmem.h"
-#include "GList.h"
-#include "Error.h"
-#include "Object.h"
-#include "Catalog.h"
-#include "Gfx.h"
-#include "GfxFont.h"
-#include "Lexer.h"
-#include "Annot.h"
-
-//------------------------------------------------------------------------
-
-#define annotFlagHidden 0x0002
-#define annotFlagPrint 0x0004
-#define annotFlagNoView 0x0020
-
-#define fieldFlagReadOnly 0x00000001
-#define fieldFlagRequired 0x00000002
-#define fieldFlagNoExport 0x00000004
-#define fieldFlagMultiline 0x00001000
-#define fieldFlagPassword 0x00002000
-#define fieldFlagNoToggleToOff 0x00004000
-#define fieldFlagRadio 0x00008000
-#define fieldFlagPushbutton 0x00010000
-#define fieldFlagCombo 0x00020000
-#define fieldFlagEdit 0x00040000
-#define fieldFlagSort 0x00080000
-#define fieldFlagFileSelect 0x00100000
-#define fieldFlagMultiSelect 0x00200000
-#define fieldFlagDoNotSpellCheck 0x00400000
-#define fieldFlagDoNotScroll 0x00800000
-#define fieldFlagComb 0x01000000
-#define fieldFlagRichText 0x02000000
-#define fieldFlagRadiosInUnison 0x02000000
-#define fieldFlagCommitOnSelChange 0x04000000
-
-#define fieldQuadLeft 0
-#define fieldQuadCenter 1
-#define fieldQuadRight 2
-
-// distance of Bezier control point from center for circle approximation
-// = (4 * (sqrt(2) - 1) / 3) * r
-#define bezierCircle 0.55228475
-
-//------------------------------------------------------------------------
-// AnnotBorderStyle
-//------------------------------------------------------------------------
-
-AnnotBorderStyle::AnnotBorderStyle(AnnotBorderType typeA, double widthA,
- double *dashA, int dashLengthA,
- double rA, double gA, double bA) {
- type = typeA;
- width = widthA;
- dash = dashA;
- dashLength = dashLengthA;
- r = rA;
- g = gA;
- b = bA;
-}
-
-AnnotBorderStyle::~AnnotBorderStyle() {
- if (dash) {
- gfree(dash);
- }
-}
-
-//------------------------------------------------------------------------
-// Annot
-//------------------------------------------------------------------------
-
-Annot::Annot(XRef *xrefA, Dict * /*acroForm*/, Dict *dict, Ref *refA) {
- Object apObj, asObj, obj1, obj2, obj3;
- AnnotBorderType borderType;
- double borderWidth;
- double *borderDash;
- int borderDashLength;
- double borderR, borderG, borderB;
- double t;
- int i;
-
- ok = gTrue;
- xref = xrefA;
- ref = *refA;
- type = NULL;
- appearBuf = NULL;
- borderStyle = NULL;
-
- //----- parse the type
-
- if (dict->lookup("Subtype", &obj1)->isName()) {
- type = new GString(obj1.getName());
- }
- obj1.free();
-
- //----- parse the rectangle
-
- if (dict->lookup("Rect", &obj1)->isArray() &&
- obj1.arrayGetLength() == 4) {
- xMin = yMin = xMax = yMax = 0;
- if (obj1.arrayGet(0, &obj2)->isNum()) {
- xMin = obj2.getNum();
- }
- obj2.free();
- if (obj1.arrayGet(1, &obj2)->isNum()) {
- yMin = obj2.getNum();
- }
- obj2.free();
- if (obj1.arrayGet(2, &obj2)->isNum()) {
- xMax = obj2.getNum();
- }
- obj2.free();
- if (obj1.arrayGet(3, &obj2)->isNum()) {
- yMax = obj2.getNum();
- }
- obj2.free();
- if (xMin > xMax) {
- t = xMin; xMin = xMax; xMax = t;
- }
- if (yMin > yMax) {
- t = yMin; yMin = yMax; yMax = t;
- }
- } else {
- error(-1, "Bad bounding box for annotation");
- ok = gFalse;
- }
- obj1.free();
-
- //----- parse the flags
-
- if (dict->lookup("F", &obj1)->isInt()) {
- flags = obj1.getInt();
- } else {
- flags = 0;
- }
- obj1.free();
-
- //----- parse the border style
-
- borderType = annotBorderSolid;
- borderWidth = 1;
- borderDash = NULL;
- borderDashLength = 0;
- borderR = 0;
- borderG = 0;
- borderB = 1;
- if (dict->lookup("BS", &obj1)->isDict()) {
- if (obj1.dictLookup("S", &obj2)->isName()) {
- if (obj2.isName("S")) {
- borderType = annotBorderSolid;
- } else if (obj2.isName("D")) {
- borderType = annotBorderDashed;
- } else if (obj2.isName("B")) {
- borderType = annotBorderBeveled;
- } else if (obj2.isName("I")) {
- borderType = annotBorderInset;
- } else if (obj2.isName("U")) {
- borderType = annotBorderUnderlined;
- }
- }
- obj2.free();
- if (obj1.dictLookup("W", &obj2)->isNum()) {
- borderWidth = obj2.getNum();
- }
- obj2.free();
- if (obj1.dictLookup("D", &obj2)->isArray()) {
- borderDashLength = obj2.arrayGetLength();
- borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
- for (i = 0; i < borderDashLength; ++i) {
- if (obj2.arrayGet(i, &obj3)->isNum()) {
- borderDash[i] = obj3.getNum();
- } else {
- borderDash[i] = 1;
- }
- obj3.free();
- }
- }
- obj2.free();
- } else {
- obj1.free();
- if (dict->lookup("Border", &obj1)->isArray()) {
- if (obj1.arrayGetLength() >= 3) {
- if (obj1.arrayGet(2, &obj2)->isNum()) {
- borderWidth = obj2.getNum();
- }
- obj2.free();
- if (obj1.arrayGetLength() >= 4) {
- if (obj1.arrayGet(3, &obj2)->isArray()) {
- borderType = annotBorderDashed;
- borderDashLength = obj2.arrayGetLength();
- borderDash = (double *)gmallocn(borderDashLength, sizeof(double));
- for (i = 0; i < borderDashLength; ++i) {
- if (obj2.arrayGet(i, &obj3)->isNum()) {
- borderDash[i] = obj3.getNum();
- } else {
- borderDash[i] = 1;
- }
- obj3.free();
- }
- } else {
- // Adobe draws no border at all if the last element is of
- // the wrong type.
- borderWidth = 0;
- }
- obj2.free();
- }
- }
- }
- }
- obj1.free();
- if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) {
- if (obj1.arrayGet(0, &obj2)->isNum()) {
- borderR = obj2.getNum();
- }
- obj1.free();
- if (obj1.arrayGet(1, &obj2)->isNum()) {
- borderG = obj2.getNum();
- }
- obj1.free();
- if (obj1.arrayGet(2, &obj2)->isNum()) {
- borderB = obj2.getNum();
- }
- obj1.free();
- }
- obj1.free();
- borderStyle = new AnnotBorderStyle(borderType, borderWidth,
- borderDash, borderDashLength,
- borderR, borderG, borderB);
-
- //----- get the annotation appearance
-
- if (dict->lookup("AP", &apObj)->isDict()) {
- if (dict->lookup("AS", &asObj)->isName()) {
- if (apObj.dictLookup("N", &obj1)->isDict()) {
- if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) {
- obj2.copy(&appearance);
- ok = gTrue;
- } else {
- obj2.free();
- if (obj1.dictLookupNF("Off", &obj2)->isRef()) {
- obj2.copy(&appearance);
- }
- }
- obj2.free();
- }
- obj1.free();
- } else {
- if (apObj.dictLookupNF("N", &obj1)->isRef()) {
- obj1.copy(&appearance);
- }
- obj1.free();
- }
- asObj.free();
- }
- apObj.free();
-}
-
-Annot::~Annot() {
- if (type) {
- delete type;
- }
- appearance.free();
- if (appearBuf) {
- delete appearBuf;
- }
- if (borderStyle) {
- delete borderStyle;
- }
-}
-
-void Annot::generateFieldAppearance(Dict *field, Dict *annot, Dict *acroForm) {
- Object mkObj, ftObj, appearDict, drObj, obj1, obj2, obj3;
- Dict *mkDict;
- MemStream *appearStream;
- GfxFontDict *fontDict;
- GBool hasCaption;
- double w, dx, dy, r;
- double *dash;
- GString *caption, *da;
- GString **text;
- GBool *selection;
- int dashLength, ff, quadding, comb, nOptions, topIdx, i, j;
-
- // must be a Widget annotation
- if (type->cmp("Widget")) {
- return;
- }
-
- appearBuf = new GString();
-
- // get the appearance characteristics (MK) dictionary
- if (annot->lookup("MK", &mkObj)->isDict()) {
- mkDict = mkObj.getDict();
- } else {
- mkDict = NULL;
- }
-
- // draw the background
- if (mkDict) {
- if (mkDict->lookup("BG", &obj1)->isArray() &&
- obj1.arrayGetLength() > 0) {
- setColor(obj1.getArray(), gTrue, 0);
- appearBuf->appendf("0 0 {0:.2f} {1:.2f} re f\n",
- xMax - xMin, yMax - yMin);
- }
- obj1.free();
- }
-
- // get the field type
- fieldLookup(field, "FT", &ftObj);
-
- // get the field flags (Ff) value
- if (fieldLookup(field, "Ff", &obj1)->isInt()) {
- ff = obj1.getInt();
- } else {
- ff = 0;
- }
- obj1.free();
-
- // draw the border
- if (mkDict) {
- w = borderStyle->getWidth();
- if (w > 0) {
- mkDict->lookup("BC", &obj1);
- if (!(obj1.isArray() && obj1.arrayGetLength() > 0)) {
- mkDict->lookup("BG", &obj1);
- }
- if (obj1.isArray() && obj1.arrayGetLength() > 0) {
- dx = xMax - xMin;
- dy = yMax - yMin;
-
- // radio buttons with no caption have a round border
- hasCaption = mkDict->lookup("CA", &obj2)->isString();
- obj2.free();
- if (ftObj.isName("Btn") && (ff & fieldFlagRadio) && !hasCaption) {
- r = 0.5 * (dx < dy ? dx : dy);
- switch (borderStyle->getType()) {
- case annotBorderDashed:
- appearBuf->append("[");
- borderStyle->getDash(&dash, &dashLength);
- for (i = 0; i < dashLength; ++i) {
- appearBuf->appendf(" {0:.2f}", dash[i]);
- }
- appearBuf->append("] 0 d\n");
- // fall through to the solid case
- case annotBorderSolid:
- case annotBorderUnderlined:
- appearBuf->appendf("{0:.2f} w\n", w);
- setColor(obj1.getArray(), gFalse, 0);
- drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * w, gFalse);
- break;
- case annotBorderBeveled:
- case annotBorderInset:
- appearBuf->appendf("{0:.2f} w\n", 0.5 * w);
- setColor(obj1.getArray(), gFalse, 0);
- drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * w, gFalse);
- setColor(obj1.getArray(), gFalse,
- borderStyle->getType() == annotBorderBeveled ? 1 : -1);
- drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * w);
- setColor(obj1.getArray(), gFalse,
- borderStyle->getType() == annotBorderBeveled ? -1 : 1);
- drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * w);
- break;
- }
-
- } else {
- switch (borderStyle->getType()) {
- case annotBorderDashed:
- appearBuf->append("[");
- borderStyle->getDash(&dash, &dashLength);
- for (i = 0; i < dashLength; ++i) {
- appearBuf->appendf(" {0:.2f}", dash[i]);
- }
- appearBuf->append("] 0 d\n");
- // fall through to the solid case
- case annotBorderSolid:
- appearBuf->appendf("{0:.2f} w\n", w);
- setColor(obj1.getArray(), gFalse, 0);
- appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n",
- 0.5 * w, dx - w, dy - w);
- break;
- case annotBorderBeveled:
- case annotBorderInset:
- setColor(obj1.getArray(), gTrue,
- borderStyle->getType() == annotBorderBeveled ? 1 : -1);
- appearBuf->append("0 0 m\n");
- appearBuf->appendf("0 {0:.2f} l\n", dy);
- appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
- appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w);
- appearBuf->appendf("{0:.2f} {1:.2f} l\n", w, dy - w);
- appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
- appearBuf->append("f\n");
- setColor(obj1.getArray(), gTrue,
- borderStyle->getType() == annotBorderBeveled ? -1 : 1);
- appearBuf->append("0 0 m\n");
- appearBuf->appendf("{0:.2f} 0 l\n", dx);
- appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
- appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w);
- appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, w);
- appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
- appearBuf->append("f\n");
- break;
- case annotBorderUnderlined:
- appearBuf->appendf("{0:.2f} w\n", w);
- setColor(obj1.getArray(), gFalse, 0);
- appearBuf->appendf("0 0 m {0:.2f} 0 l s\n", dx);
- break;
- }
-
- // clip to the inside of the border
- appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n",
- w, dx - 2 * w, dy - 2 * w);
- }
- }
- obj1.free();
- }
- }
-
- // get the resource dictionary
- acroForm->lookup("DR", &drObj);
-
- // build the font dictionary
- if (drObj.isDict() && drObj.dictLookup("Font", &obj1)->isDict()) {
- fontDict = new GfxFontDict(xref, NULL, obj1.getDict());
- } else {
- fontDict = NULL;
- }
- obj1.free();
-
- // get the default appearance string
- if (fieldLookup(field, "DA", &obj1)->isNull()) {
- obj1.free();
- acroForm->lookup("DA", &obj1);
- }
- if (obj1.isString()) {
- da = obj1.getString()->copy();
- } else {
- da = NULL;
- }
- obj1.free();
-
- // draw the field contents
- if (ftObj.isName("Btn")) {
- caption = NULL;
- if (mkDict) {
- if (mkDict->lookup("CA", &obj1)->isString()) {
- caption = obj1.getString()->copy();
- }
- obj1.free();
- }
- // radio button
- if (ff & fieldFlagRadio) {
- //~ Acrobat doesn't draw a caption if there is no AP dict (?)
- if (fieldLookup(field, "V", &obj1)->isName()) {
- if (annot->lookup("AS", &obj2)->isName(obj1.getName())) {
- if (caption) {
- drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
- gFalse, gTrue);
- } else {
- if (mkDict) {
- if (mkDict->lookup("BC", &obj3)->isArray() &&
- obj3.arrayGetLength() > 0) {
- dx = xMax - xMin;
- dy = yMax - yMin;
- setColor(obj3.getArray(), gTrue, 0);
- drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy),
- gTrue);
- }
- obj3.free();
- }
- }
- }
- obj2.free();
- }
- obj1.free();
- // pushbutton
- } else if (ff & fieldFlagPushbutton) {
- if (caption) {
- drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
- gFalse, gFalse);
- }
- // checkbox
- } else {
- // According to the PDF spec the off state must be named "Off",
- // and the on state can be named anything, but Acrobat apparently
- // looks for "Yes" and treats anything else as off.
- if (fieldLookup(field, "V", &obj1)->isName("Yes")) {
- if (!caption) {
- caption = new GString("3"); // ZapfDingbats checkmark
- }
- drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
- gFalse, gTrue);
- }
- obj1.free();
- }
- if (caption) {
- delete caption;
- }
- } else if (ftObj.isName("Tx")) {
- //~ value strings can be Unicode
- if (fieldLookup(field, "V", &obj1)->isString()) {
- if (fieldLookup(field, "Q", &obj2)->isInt()) {
- quadding = obj2.getInt();
- } else {
- quadding = fieldQuadLeft;
- }
- obj2.free();
- comb = 0;
- if (ff & fieldFlagComb) {
- if (fieldLookup(field, "MaxLen", &obj2)->isInt()) {
- comb = obj2.getInt();
- }
- obj2.free();
- }
- drawText(obj1.getString(), da, fontDict,
- ff & fieldFlagMultiline, comb, quadding, gTrue, gFalse);
- }
- obj1.free();
- } else if (ftObj.isName("Ch")) {
- //~ value/option strings can be Unicode
- if (fieldLookup(field, "Q", &obj1)->isInt()) {
- quadding = obj1.getInt();
- } else {
- quadding = fieldQuadLeft;
- }
- obj1.free();
- // combo box
- if (ff & fieldFlagCombo) {
- if (fieldLookup(field, "V", &obj1)->isString()) {
- drawText(obj1.getString(), da, fontDict,
- gFalse, 0, quadding, gTrue, gFalse);
- //~ Acrobat draws a popup icon on the right side
- }
- obj1.free();
- // list box
- } else {
- if (field->lookup("Opt", &obj1)->isArray()) {
- nOptions = obj1.arrayGetLength();
- // get the option text
- text = (GString **)gmallocn(nOptions, sizeof(GString *));
- for (i = 0; i < nOptions; ++i) {
- text[i] = NULL;
- obj1.arrayGet(i, &obj2);
- if (obj2.isString()) {
- text[i] = obj2.getString()->copy();
- } else if (obj2.isArray() && obj2.arrayGetLength() == 2) {
- if (obj2.arrayGet(1, &obj3)->isString()) {
- text[i] = obj3.getString()->copy();
- }
- obj3.free();
- }
- obj2.free();
- if (!text[i]) {
- text[i] = new GString();
- }
- }
- // get the selected option(s)
- selection = (GBool *)gmallocn(nOptions, sizeof(GBool));
- //~ need to use the I field in addition to the V field
- fieldLookup(field, "V", &obj2);
- for (i = 0; i < nOptions; ++i) {
- selection[i] = gFalse;
- if (obj2.isString()) {
- if (!obj2.getString()->cmp(text[i])) {
- selection[i] = gTrue;
- }
- } else if (obj2.isArray()) {
- for (j = 0; j < obj2.arrayGetLength(); ++j) {
- if (obj2.arrayGet(j, &obj3)->isString() &&
- !obj3.getString()->cmp(text[i])) {
- selection[i] = gTrue;
- }
- obj3.free();
- }
- }
- }
- obj2.free();
- // get the top index
- if (field->lookup("TI", &obj2)->isInt()) {
- topIdx = obj2.getInt();
- } else {
- topIdx = 0;
- }
- obj2.free();
- // draw the text
- drawListBox(text, selection, nOptions, topIdx, da, fontDict, quadding);
- for (i = 0; i < nOptions; ++i) {
- delete text[i];
- }
- gfree(text);
- gfree(selection);
- }
- obj1.free();
- }
- } else if (ftObj.isName("Sig")) {
- //~unimp
- } else {
- error(-1, "Unknown field type");
- }
-
- if (da) {
- delete da;
- }
-
- // build the appearance stream dictionary
- appearDict.initDict(xref);
- appearDict.dictAdd(copyString("Length"),
- obj1.initInt(appearBuf->getLength()));
- appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form"));
- obj1.initArray(xref);
- obj1.arrayAdd(obj2.initReal(0));
- obj1.arrayAdd(obj2.initReal(0));
- obj1.arrayAdd(obj2.initReal(xMax - xMin));
- obj1.arrayAdd(obj2.initReal(yMax - yMin));
- appearDict.dictAdd(copyString("BBox"), &obj1);
-
- // set the resource dictionary
- if (drObj.isDict()) {
- appearDict.dictAdd(copyString("Resources"), drObj.copy(&obj1));
- }
- drObj.free();
-
- // build the appearance stream
- appearStream = new MemStream(appearBuf->getCString(), 0,
- appearBuf->getLength(), &appearDict);
- appearance.free();
- appearance.initStream(appearStream);
-
- if (fontDict) {
- delete fontDict;
- }
- ftObj.free();
- mkObj.free();
-}
-
-// Set the current fill or stroke color, based on <a> (which should
-// have 1, 3, or 4 elements). If <adjust> is +1, color is brightened;
-// if <adjust> is -1, color is darkened; otherwise color is not
-// modified.
-void Annot::setColor(Array *a, GBool fill, int adjust) {
- Object obj1;
- double color[4];
- int nComps, i;
-
- nComps = a->getLength();
- if (nComps > 4) {
- nComps = 4;
- }
- for (i = 0; i < nComps && i < 4; ++i) {
- if (a->get(i, &obj1)->isNum()) {
- color[i] = obj1.getNum();
- } else {
- color[i] = 0;
- }
- obj1.free();
- }
- if (nComps == 4) {
- adjust = -adjust;
- }
- if (adjust > 0) {
- for (i = 0; i < nComps; ++i) {
- color[i] = 0.5 * color[i] + 0.5;
- }
- } else if (adjust < 0) {
- for (i = 0; i < nComps; ++i) {
- color[i] = 0.5 * color[i];
- }
- }
- if (nComps == 4) {
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:c}\n",
- color[0], color[1], color[2], color[3],
- fill ? 'k' : 'K');
- } else if (nComps == 3) {
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:s}\n",
- color[0], color[1], color[2],
- fill ? "rg" : "RG");
- } else {
- appearBuf->appendf("{0:.2f} {1:c}\n",
- color[0],
- fill ? 'g' : 'G');
- }
-}
-
-// Draw the variable text or caption for a field.
-void Annot::drawText(GString *text, GString *da, GfxFontDict *fontDict,
- GBool multiline, int comb, int quadding,
- GBool txField, GBool forceZapfDingbats) {
- GList *daToks;
- GString *tok;
- GfxFont *font;
- double fontSize, fontSize2, border, x, xPrev, y, w, w2, wMax;
- int tfPos, tmPos, i, j, k, c;
-
- //~ if there is no MK entry, this should use the existing content stream,
- //~ and only replace the marked content portion of it
- //~ (this is only relevant for Tx fields)
-
- // parse the default appearance string
- tfPos = tmPos = -1;
- if (da) {
- daToks = new GList();
- i = 0;
- while (i < da->getLength()) {
- while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) {
- ++i;
- }
- if (i < da->getLength()) {
- for (j = i + 1;
- j < da->getLength() && !Lexer::isSpace(da->getChar(j));
- ++j) ;
- daToks->append(new GString(da, i, j - i));
- i = j;
- }
- }
- for (i = 2; i < daToks->getLength(); ++i) {
- if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) {
- tfPos = i - 2;
- } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) {
- tmPos = i - 6;
- }
- }
- } else {
- daToks = NULL;
- }
-
- // force ZapfDingbats
- //~ this should create the font if needed (?)
- if (forceZapfDingbats) {
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos);
- if (tok->cmp("/ZaDb")) {
- tok->clear();
- tok->append("/ZaDb");
- }
- }
- }
-
- // get the font and font size
- font = NULL;
- fontSize = 0;
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos);
- if (tok->getLength() >= 1 && tok->getChar(0) == '/') {
- if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) {
- error(-1, "Unknown font in field's DA string");
- }
- } else {
- error(-1, "Invalid font name in 'Tf' operator in field's DA string");
- }
- tok = (GString *)daToks->get(tfPos + 1);
- fontSize = atof(tok->getCString());
- } else {
- error(-1, "Missing 'Tf' operator in field's DA string");
- }
-
- // get the border width
- border = borderStyle->getWidth();
-
- // setup
- if (txField) {
- appearBuf->append("/Tx BMC\n");
- }
- appearBuf->append("q\n");
- appearBuf->append("BT\n");
-
- // multi-line text
- if (multiline) {
- // note: the comb flag is ignored in multiline mode
-
- wMax = xMax - xMin - 2 * border - 4;
-
- // compute font autosize
- if (fontSize == 0) {
- for (fontSize = 20; fontSize > 1; --fontSize) {
- y = yMax - yMin;
- w2 = 0;
- i = 0;
- while (i < text->getLength()) {
- getNextLine(text, i, font, fontSize, wMax, &j, &w, &k);
- if (w > w2) {
- w2 = w;
- }
- i = k;
- y -= fontSize;
- }
- // approximate the descender for the last line
- if (y >= 0.33 * fontSize) {
- break;
- }
- }
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos + 1);
- tok->clear();
- tok->appendf("{0:.2f}", fontSize);
- }
- }
-
- // starting y coordinate
- // (note: each line of text starts with a Td operator that moves
- // down a line)
- y = yMax - yMin;
-
- // set the font matrix
- if (tmPos >= 0) {
- tok = (GString *)daToks->get(tmPos + 4);
- tok->clear();
- tok->append('0');
- tok = (GString *)daToks->get(tmPos + 5);
- tok->clear();
- tok->appendf("{0:.2f}", y);
- }
-
- // write the DA string
- if (daToks) {
- for (i = 0; i < daToks->getLength(); ++i) {
- appearBuf->append((GString *)daToks->get(i))->append(' ');
- }
- }
-
- // write the font matrix (if not part of the DA string)
- if (tmPos < 0) {
- appearBuf->appendf("1 0 0 1 0 {0:.2f} Tm\n", y);
- }
-
- // write a series of lines of text
- i = 0;
- xPrev = 0;
- while (i < text->getLength()) {
-
- getNextLine(text, i, font, fontSize, wMax, &j, &w, &k);
-
- // compute text start position
- switch (quadding) {
- case fieldQuadLeft:
- default:
- x = border + 2;
- break;
- case fieldQuadCenter:
- x = (xMax - xMin - w) / 2;
- break;
- case fieldQuadRight:
- x = xMax - xMin - border - 2 - w;
- break;
- }
-
- // draw the line
- appearBuf->appendf("{0:.2f} {1:.2f} Td\n", x - xPrev, -fontSize);
- appearBuf->append('(');
- for (; i < j; ++i) {
- c = text->getChar(i) & 0xff;
- if (c == '(' || c == ')' || c == '\\') {
- appearBuf->append('\\');
- appearBuf->append(c);
- } else if (c < 0x20 || c >= 0x80) {
- appearBuf->appendf("\\{0:03o}", c);
- } else {
- appearBuf->append(c);
- }
- }
- appearBuf->append(") Tj\n");
-
- // next line
- i = k;
- xPrev = x;
- }
-
- // single-line text
- } else {
- //~ replace newlines with spaces? - what does Acrobat do?
-
- // comb formatting
- if (comb > 0) {
-
- // compute comb spacing
- w = (xMax - xMin - 2 * border) / comb;
-
- // compute font autosize
- if (fontSize == 0) {
- fontSize = yMax - yMin - 2 * border;
- if (w < fontSize) {
- fontSize = w;
- }
- fontSize = floor(fontSize);
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos + 1);
- tok->clear();
- tok->appendf("{0:.2f}", fontSize);
- }
- }
-
- // compute text start position
- switch (quadding) {
- case fieldQuadLeft:
- default:
- x = border + 2;
- break;
- case fieldQuadCenter:
- x = border + 2 + 0.5 * (comb - text->getLength()) * w;
- break;
- case fieldQuadRight:
- x = border + 2 + (comb - text->getLength()) * w;
- break;
- }
- y = 0.5 * (yMax - yMin) - 0.4 * fontSize;
-
- // set the font matrix
- if (tmPos >= 0) {
- tok = (GString *)daToks->get(tmPos + 4);
- tok->clear();
- tok->appendf("{0:.2f}", x);
- tok = (GString *)daToks->get(tmPos + 5);
- tok->clear();
- tok->appendf("{0:.2f}", y);
- }
-
- // write the DA string
- if (daToks) {
- for (i = 0; i < daToks->getLength(); ++i) {
- appearBuf->append((GString *)daToks->get(i))->append(' ');
- }
- }
-
- // write the font matrix (if not part of the DA string)
- if (tmPos < 0) {
- appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y);
- }
-
- // write the text string
- //~ this should center (instead of left-justify) each character within
- //~ its comb cell
- for (i = 0; i < text->getLength(); ++i) {
- if (i > 0) {
- appearBuf->appendf("{0:.2f} 0 Td\n", w);
- }
- appearBuf->append('(');
- c = text->getChar(i) & 0xff;
- if (c == '(' || c == ')' || c == '\\') {
- appearBuf->append('\\');
- appearBuf->append(c);
- } else if (c < 0x20 || c >= 0x80) {
- appearBuf->appendf("{0:.2f} 0 Td\n", w);
- } else {
- appearBuf->append(c);
- }
- appearBuf->append(") Tj\n");
- }
-
- // regular (non-comb) formatting
- } else {
-
- // compute string width
- if (font && !font->isCIDFont()) {
- w = 0;
- for (i = 0; i < text->getLength(); ++i) {
- w += ((Gfx8BitFont *)font)->getWidth(text->getChar(i));
- }
- } else {
- // otherwise, make a crude estimate
- w = text->getLength() * 0.5;
- }
-
- // compute font autosize
- if (fontSize == 0) {
- fontSize = yMax - yMin - 2 * border;
- fontSize2 = (xMax - xMin - 4 - 2 * border) / w;
- if (fontSize2 < fontSize) {
- fontSize = fontSize2;
- }
- fontSize = floor(fontSize);
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos + 1);
- tok->clear();
- tok->appendf("{0:.2f}", fontSize);
- }
- }
-
- // compute text start position
- w *= fontSize;
- switch (quadding) {
- case fieldQuadLeft:
- default:
- x = border + 2;
- break;
- case fieldQuadCenter:
- x = (xMax - xMin - w) / 2;
- break;
- case fieldQuadRight:
- x = xMax - xMin - border - 2 - w;
- break;
- }
- y = 0.5 * (yMax - yMin) - 0.4 * fontSize;
-
- // set the font matrix
- if (tmPos >= 0) {
- tok = (GString *)daToks->get(tmPos + 4);
- tok->clear();
- tok->appendf("{0:.2f}", x);
- tok = (GString *)daToks->get(tmPos + 5);
- tok->clear();
- tok->appendf("{0:.2f}", y);
- }
-
- // write the DA string
- if (daToks) {
- for (i = 0; i < daToks->getLength(); ++i) {
- appearBuf->append((GString *)daToks->get(i))->append(' ');
- }
- }
-
- // write the font matrix (if not part of the DA string)
- if (tmPos < 0) {
- appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y);
- }
-
- // write the text string
- appearBuf->append('(');
- for (i = 0; i < text->getLength(); ++i) {
- c = text->getChar(i) & 0xff;
- if (c == '(' || c == ')' || c == '\\') {
- appearBuf->append('\\');
- appearBuf->append(c);
- } else if (c < 0x20 || c >= 0x80) {
- appearBuf->appendf("\\{0:03o}", c);
- } else {
- appearBuf->append(c);
- }
- }
- appearBuf->append(") Tj\n");
- }
- }
-
- // cleanup
- appearBuf->append("ET\n");
- appearBuf->append("Q\n");
- if (txField) {
- appearBuf->append("EMC\n");
- }
-
- if (daToks) {
- deleteGList(daToks, GString);
- }
-}
-
-// Draw the variable text or caption for a field.
-void Annot::drawListBox(GString **text, GBool *selection,
- int nOptions, int topIdx,
- GString *da, GfxFontDict *fontDict, GBool quadding) {
- GList *daToks;
- GString *tok;
- GfxFont *font;
- double fontSize, fontSize2, border, x, y, w, wMax;
- int tfPos, tmPos, i, j, c;
-
- //~ if there is no MK entry, this should use the existing content stream,
- //~ and only replace the marked content portion of it
- //~ (this is only relevant for Tx fields)
-
- // parse the default appearance string
- tfPos = tmPos = -1;
- if (da) {
- daToks = new GList();
- i = 0;
- while (i < da->getLength()) {
- while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) {
- ++i;
- }
- if (i < da->getLength()) {
- for (j = i + 1;
- j < da->getLength() && !Lexer::isSpace(da->getChar(j));
- ++j) ;
- daToks->append(new GString(da, i, j - i));
- i = j;
- }
- }
- for (i = 2; i < daToks->getLength(); ++i) {
- if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf")) {
- tfPos = i - 2;
- } else if (i >= 6 && !((GString *)daToks->get(i))->cmp("Tm")) {
- tmPos = i - 6;
- }
- }
- } else {
- daToks = NULL;
- }
-
- // get the font and font size
- font = NULL;
- fontSize = 0;
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos);
- if (tok->getLength() >= 1 && tok->getChar(0) == '/') {
- if (!fontDict || !(font = fontDict->lookup(tok->getCString() + 1))) {
- error(-1, "Unknown font in field's DA string");
- }
- } else {
- error(-1, "Invalid font name in 'Tf' operator in field's DA string");
- }
- tok = (GString *)daToks->get(tfPos + 1);
- fontSize = atof(tok->getCString());
- } else {
- error(-1, "Missing 'Tf' operator in field's DA string");
- }
-
- // get the border width
- border = borderStyle->getWidth();
-
- // compute font autosize
- if (fontSize == 0) {
- wMax = 0;
- for (i = 0; i < nOptions; ++i) {
- if (font && !font->isCIDFont()) {
- w = 0;
- for (j = 0; j < text[i]->getLength(); ++j) {
- w += ((Gfx8BitFont *)font)->getWidth(text[i]->getChar(j));
- }
- } else {
- // otherwise, make a crude estimate
- w = text[i]->getLength() * 0.5;
- }
- if (w > wMax) {
- wMax = w;
- }
- }
- fontSize = yMax - yMin - 2 * border;
- fontSize2 = (xMax - xMin - 4 - 2 * border) / wMax;
- if (fontSize2 < fontSize) {
- fontSize = fontSize2;
- }
- fontSize = floor(fontSize);
- if (tfPos >= 0) {
- tok = (GString *)daToks->get(tfPos + 1);
- tok->clear();
- tok->appendf("{0:.2f}", fontSize);
- }
- }
-
- // draw the text
- y = yMax - yMin - 1.1 * fontSize;
- for (i = topIdx; i < nOptions; ++i) {
-
- // setup
- appearBuf->append("q\n");
-
- // draw the background if selected
- if (selection[i]) {
- appearBuf->append("0 g f\n");
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n",
- border,
- y - 0.2 * fontSize,
- xMax - xMin - 2 * border,
- 1.1 * fontSize);
- }
-
- // setup
- appearBuf->append("BT\n");
-
- // compute string width
- if (font && !font->isCIDFont()) {
- w = 0;
- for (j = 0; j < text[i]->getLength(); ++j) {
- w += ((Gfx8BitFont *)font)->getWidth(text[i]->getChar(j));
- }
- } else {
- // otherwise, make a crude estimate
- w = text[i]->getLength() * 0.5;
- }
-
- // compute text start position
- w *= fontSize;
- switch (quadding) {
- case fieldQuadLeft:
- default:
- x = border + 2;
- break;
- case fieldQuadCenter:
- x = (xMax - xMin - w) / 2;
- break;
- case fieldQuadRight:
- x = xMax - xMin - border - 2 - w;
- break;
- }
-
- // set the font matrix
- if (tmPos >= 0) {
- tok = (GString *)daToks->get(tmPos + 4);
- tok->clear();
- tok->appendf("{0:.2f}", x);
- tok = (GString *)daToks->get(tmPos + 5);
- tok->clear();
- tok->appendf("{0:.2f}", y);
- }
-
- // write the DA string
- if (daToks) {
- for (j = 0; j < daToks->getLength(); ++j) {
- appearBuf->append((GString *)daToks->get(j))->append(' ');
- }
- }
-
- // write the font matrix (if not part of the DA string)
- if (tmPos < 0) {
- appearBuf->appendf("1 0 0 1 {0:.2f} {1:.2f} Tm\n", x, y);
- }
-
- // change the text color if selected
- if (selection[i]) {
- appearBuf->append("1 g\n");
- }
-
- // write the text string
- appearBuf->append('(');
- for (j = 0; j < text[i]->getLength(); ++j) {
- c = text[i]->getChar(j) & 0xff;
- if (c == '(' || c == ')' || c == '\\') {
- appearBuf->append('\\');
- appearBuf->append(c);
- } else if (c < 0x20 || c >= 0x80) {
- appearBuf->appendf("\\{0:03o}", c);
- } else {
- appearBuf->append(c);
- }
- }
- appearBuf->append(") Tj\n");
-
- // cleanup
- appearBuf->append("ET\n");
- appearBuf->append("Q\n");
-
- // next line
- y -= 1.1 * fontSize;
- }
-
- if (daToks) {
- deleteGList(daToks, GString);
- }
-}
-
-// Figure out how much text will fit on the next line. Returns:
-// *end = one past the last character to be included
-// *width = width of the characters start .. end-1
-// *next = index of first character on the following line
-void Annot::getNextLine(GString *text, int start,
- GfxFont *font, double fontSize, double wMax,
- int *end, double *width, int *next) {
- double w, dw;
- int j, k, c;
-
- // figure out how much text will fit on the line
- //~ what does Adobe do with tabs?
- w = 0;
- for (j = start; j < text->getLength() && w <= wMax; ++j) {
- c = text->getChar(j) & 0xff;
- if (c == 0x0a || c == 0x0d) {
- break;
- }
- if (font && !font->isCIDFont()) {
- dw = ((Gfx8BitFont *)font)->getWidth(c) * fontSize;
- } else {
- // otherwise, make a crude estimate
- dw = 0.5 * fontSize;
- }
- w += dw;
- }
- if (w > wMax) {
- for (k = j; k > start && text->getChar(k-1) != ' '; --k) ;
- for (; k > start && text->getChar(k-1) == ' '; --k) ;
- if (k > start) {
- j = k;
- }
- if (j == start) {
- // handle the pathological case where the first character is
- // too wide to fit on the line all by itself
- j = start + 1;
- }
- }
- *end = j;
-
- // compute the width
- w = 0;
- for (k = start; k < j; ++k) {
- if (font && !font->isCIDFont()) {
- dw = ((Gfx8BitFont *)font)->getWidth(text->getChar(k)) * fontSize;
- } else {
- // otherwise, make a crude estimate
- dw = 0.5 * fontSize;
- }
- w += dw;
- }
- *width = w;
-
- // next line
- while (j < text->getLength() && text->getChar(j) == ' ') {
- ++j;
- }
- if (j < text->getLength() && text->getChar(j) == 0x0d) {
- ++j;
- }
- if (j < text->getLength() && text->getChar(j) == 0x0a) {
- ++j;
- }
- *next = j;
-}
-
-// Draw an (approximate) circle of radius <r> centered at (<cx>, <cy>).
-// If <fill> is true, the circle is filled; otherwise it is stroked.
-void Annot::drawCircle(double cx, double cy, double r, GBool fill) {
- appearBuf->appendf("{0:.2f} {1:.2f} m\n",
- cx + r, cy);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx + r, cy + bezierCircle * r,
- cx + bezierCircle * r, cy + r,
- cx, cy + r);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx - bezierCircle * r, cy + r,
- cx - r, cy + bezierCircle * r,
- cx - r, cy);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx - r, cy - bezierCircle * r,
- cx - bezierCircle * r, cy - r,
- cx, cy - r);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx + bezierCircle * r, cy - r,
- cx + r, cy - bezierCircle * r,
- cx + r, cy);
- appearBuf->append(fill ? "f\n" : "s\n");
-}
-
-// Draw the top-left half of an (approximate) circle of radius <r>
-// centered at (<cx>, <cy>).
-void Annot::drawCircleTopLeft(double cx, double cy, double r) {
- double r2;
-
- r2 = r / sqrt(2.0);
- appearBuf->appendf("{0:.2f} {1:.2f} m\n",
- cx + r2, cy + r2);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx + (1 - bezierCircle) * r2,
- cy + (1 + bezierCircle) * r2,
- cx - (1 - bezierCircle) * r2,
- cy + (1 + bezierCircle) * r2,
- cx - r2,
- cy + r2);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx - (1 + bezierCircle) * r2,
- cy + (1 - bezierCircle) * r2,
- cx - (1 + bezierCircle) * r2,
- cy - (1 - bezierCircle) * r2,
- cx - r2,
- cy - r2);
- appearBuf->append("S\n");
-}
-
-// Draw the bottom-right half of an (approximate) circle of radius <r>
-// centered at (<cx>, <cy>).
-void Annot::drawCircleBottomRight(double cx, double cy, double r) {
- double r2;
-
- r2 = r / sqrt(2.0);
- appearBuf->appendf("{0:.2f} {1:.2f} m\n",
- cx - r2, cy - r2);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx - (1 - bezierCircle) * r2,
- cy - (1 + bezierCircle) * r2,
- cx + (1 - bezierCircle) * r2,
- cy - (1 + bezierCircle) * r2,
- cx + r2,
- cy - r2);
- appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
- cx + (1 + bezierCircle) * r2,
- cy - (1 - bezierCircle) * r2,
- cx + (1 + bezierCircle) * r2,
- cy + (1 - bezierCircle) * r2,
- cx + r2,
- cy + r2);
- appearBuf->append("S\n");
-}
-
-// Look up an inheritable field dictionary entry.
-Object *Annot::fieldLookup(Dict *field, char *key, Object *obj) {
- Dict *dict;
- Object parent;
-
- dict = field;
- if (!dict->lookup(key, obj)->isNull()) {
- return obj;
- }
- obj->free();
- if (dict->lookup("Parent", &parent)->isDict()) {
- fieldLookup(parent.getDict(), key, obj);
- } else {
- obj->initNull();
- }
- parent.free();
- return obj;
-}
-
-void Annot::draw(Gfx *gfx, GBool printing) {
- Object obj;
- GBool isLink;
-
- // check the flags
- if ((flags & annotFlagHidden) ||
- (printing && !(flags & annotFlagPrint)) ||
- (!printing && (flags & annotFlagNoView))) {
- return;
- }
-
- // draw the appearance stream
- isLink = type && !type->cmp("Link");
- appearance.fetch(xref, &obj);
- gfx->drawAnnot(&obj, isLink ? borderStyle : (AnnotBorderStyle *)NULL,
- xMin, yMin, xMax, yMax);
- obj.free();
-}
-
-//------------------------------------------------------------------------
-// Annots
-//------------------------------------------------------------------------
-
-Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
- Dict *acroForm;
- Annot *annot;
- Object obj1;
- Ref ref;
- int size;
- int i;
-
- annots = NULL;
- size = 0;
- nAnnots = 0;
-
- acroForm = catalog->getAcroForm()->isDict() ?
- catalog->getAcroForm()->getDict() : NULL;
- if (annotsObj->isArray()) {
- 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;
- }
- if (obj1.isDict()) {
- annot = new Annot(xref, acroForm, obj1.getDict(), &ref);
- if (annot->isOk()) {
- if (nAnnots >= size) {
- size += 16;
- annots = (Annot **)greallocn(annots, size, sizeof(Annot *));
- }
- annots[nAnnots++] = annot;
- } else {
- delete annot;
- }
- }
- obj1.free();
- }
- }
-}
-
-Annots::~Annots() {
- int i;
-
- for (i = 0; i < nAnnots; ++i) {
- delete annots[i];
- }
- gfree(annots);
-}
-
-void Annots::generateAppearances(Dict *acroForm) {
- Object obj1, obj2;
- Ref ref;
- int i;
-
- if (acroForm->lookup("Fields", &obj1)->isArray()) {
- for (i = 0; i < obj1.arrayGetLength(); ++i) {
- if (obj1.arrayGetNF(i, &obj2)->isRef()) {
- ref = obj2.getRef();
- obj2.free();
- obj1.arrayGet(i, &obj2);
- } else {
- ref.num = ref.gen = -1;
- }
- if (obj2.isDict()) {
- scanFieldAppearances(obj2.getDict(), &ref, NULL, acroForm);
- }
- obj2.free();
- }
- }
- obj1.free();
-}
-
-void Annots::scanFieldAppearances(Dict *node, Ref *ref, Dict *parent,
- Dict *acroForm) {
- Annot *annot;
- Object obj1, obj2;
- Ref ref2;
- int i;
-
- // non-terminal node: scan the children
- if (node->lookup("Kids", &obj1)->isArray()) {
- for (i = 0; i < obj1.arrayGetLength(); ++i) {
- if (obj1.arrayGetNF(i, &obj2)->isRef()) {
- ref2 = obj2.getRef();
- obj2.free();
- obj1.arrayGet(i, &obj2);
- } else {
- ref2.num = ref2.gen = -1;
- }
- if (obj2.isDict()) {
- scanFieldAppearances(obj2.getDict(), &ref2, node, acroForm);
- }
- obj2.free();
- }
- obj1.free();
- return;
- }
- obj1.free();
-
- // terminal node: this is either a combined annot/field dict, or an
- // annot dict whose parent is a field
- if ((annot = findAnnot(ref))) {
- node->lookupNF("Parent", &obj1);
- if (!parent || !obj1.isNull()) {
- annot->generateFieldAppearance(node, node, acroForm);
- } else {
- annot->generateFieldAppearance(parent, node, acroForm);
- }
- obj1.free();
- }
-}
-
-Annot *Annots::findAnnot(Ref *ref) {
- int i;
-
- for (i = 0; i < nAnnots; ++i) {
- if (annots[i]->match(ref)) {
- return annots[i];
- }
- }
- return NULL;
-}