⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 annot.cc

📁 这是一个做pdf阅读器的源代码文件,是大家学习阅读器资料的很好参考
💻 CC
📖 第 1 页 / 共 3 页
字号:
//========================================================================//// 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 {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -