//========================================================================
//
// Annot.cc
//
// Copyright 2000-2003 Glyph & Cog, LLC
//
//========================================================================

#include <config.h>

#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif

#include <stdlib.h>
#include "goo/gmem.h"
#include "Object.h"
#include "Catalog.h"
#include "Gfx.h"
#include "Lexer.h"
#include "UGooString.h"
#include "Annot.h"

//------------------------------------------------------------------------
// Annot
//------------------------------------------------------------------------

Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict) {
  Object apObj, asObj, obj1, obj2;
  GBool regen, isTextField;
  double t;

  ok = gFalse;
  xref = xrefA;
  appearBuf = NULL;

  if (dict->lookup("Rect", &obj1)->isArray() &&
      obj1.arrayGetLength() == 4) {
    //~ should check object types here
    obj1.arrayGet(0, &obj2);
    xMin = obj2.getNum();
    obj2.free();
    obj1.arrayGet(1, &obj2);
    yMin = obj2.getNum();
    obj2.free();
    obj1.arrayGet(2, &obj2);
    xMax = obj2.getNum();
    obj2.free();
    obj1.arrayGet(3, &obj2);
    yMax = obj2.getNum();
    obj2.free();
    if (xMin > xMax) {
      t = xMin; xMin = xMax; xMax = t;
    }
    if (yMin > yMax) {
      t = yMin; yMin = yMax; yMax = t;
    }
  } else {
    //~ this should return an error
    xMin = yMin = 0;
    xMax = yMax = 1;
  }
  obj1.free();

  // check if field apperances need to be regenerated
  regen = gFalse;
  if (acroForm) {
    acroForm->lookup("NeedAppearances", &obj1);
    if (obj1.isBool() && obj1.getBool()) {
      regen = gTrue;
    }
    obj1.free();
  }

  // check for a text-type field
  isTextField = dict->lookup("FT", &obj1)->isName("Tx");
  obj1.free();

#if 0 //~ appearance stream generation is not finished yet
  if (regen && isTextField) {
    generateAppearance(acroForm, dict);
  } else {
#endif
    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);
	      ok = gTrue;
	    }
	  }
	  obj2.free();
	}
	obj1.free();
      } else {
	if (apObj.dictLookupNF("N", &obj1)->isRef()) {
	  obj1.copy(&appearance);
	  ok = gTrue;
	}
	obj1.free();
      }
      asObj.free();
    }
    apObj.free();
#if 0 //~ appearance stream generation is not finished yet
  }
#endif
}

Annot::~Annot() {
  appearance.free();
  if (appearBuf) {
    delete appearBuf;
  }
}

void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
  MemStream *appearStream;
  Object daObj, vObj, drObj, appearDict, obj1, obj2;
  GooString *daStr, *daStr1, *vStr, *s;
  char buf[256];
  double fontSize;
  int c;
  int i0, i1;

  //~ DA can be inherited
  if (dict->lookup("DA", &daObj)->isString()) {
    daStr = daObj.getString();

    // look for a font size
    //~ may want to parse the DS entry in place of this (if it exists)
    daStr1 = NULL;
    fontSize = 10;
    for (i1 = daStr->getLength() - 2; i1 >= 0; --i1) {
      if (daStr->getChar(i1) == 'T' && daStr->getChar(i1+1) == 'f') {
	for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ;
	for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ;
	if (i0 >= 0) {
	  ++i0;
	  ++i1;
	  s = new GooString(daStr, i0, i1 - i0);
	  fontSize = atof(s->getCString());
	  delete s;

	  // autosize the font
	  if (fontSize == 0) {
	    fontSize = 0.67 * (yMax - yMin);
	    daStr1 = new GooString(daStr, 0, i0);
	    sprintf(buf, "%.2f", fontSize);
	    daStr1->append(buf);
	    daStr1->append(daStr->getCString() + i1,
			   daStr->getLength() - i1);
	  }
	}
	break;
      }
    }

    // build the appearance stream contents
    appearBuf = new GooString();
    appearBuf->append("/Tx BMC\n");
    appearBuf->append("q BT\n");
    appearBuf->append(daStr1 ? daStr1 : daStr)->append("\n");
    if (dict->lookup("V", &vObj)->isString()) {
      //~ handle quadding -- this requires finding the font and using
      //~   the encoding and char widths
      sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize);
      appearBuf->append(buf);
      sprintf(buf, "%g TL\n", fontSize);
      appearBuf->append(buf);
      vStr = vObj.getString();
      i0 = 0;
      while (i0 < vStr->getLength()) {
	for (i1 = i0;
	     i1 < vStr->getLength() &&
	       vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r';
	     ++i1) ;
	if (i0 > 0) {
	  appearBuf->append("T*\n");
	}
	appearBuf->append('(');
	for (; i0 < i1; ++i0) {
	  c = vStr->getChar(i0);
	  if (c == '(' || c == ')' || c == '\\') {
	    appearBuf->append('\\');
	    appearBuf->append(c);
	  } else if (c < 0x20 || c >= 0x80) {
	    sprintf(buf, "\\%03o", c);
	    appearBuf->append(buf);
	  } else {
	    appearBuf->append(c);
	  }
	}
	appearBuf->append(") Tj\n");
	if (i1 + 1 < vStr->getLength() &&
	    vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') {
	  i0 = i1 + 2;
	} else {
	  i0 = i1 + 1;
	}
      }
    }
    vObj.free();
    appearBuf->append("ET Q\n");
    appearBuf->append("EMC\n");

    // build the appearance stream dictionary
    appearDict.initDict(xref);
    appearDict.dictAdd("Length", obj1.initInt(appearBuf->getLength()));
    appearDict.dictAdd("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("BBox", &obj1);

    // find the resource dictionary
    dict->lookup("DR", &drObj);
    if (!drObj.isDict()) {
      dict->lookup("Parent", &obj1);
      while (obj1.isDict()) {
	drObj.free();
	obj1.dictLookup("DR", &drObj);
	if (drObj.isDict()) {
	  break;
	}
	obj1.dictLookup("Parent", &obj2);
	obj1.free();
	obj1 = obj2;
      }
      obj1.free();
      if (!drObj.isDict()) {
	if (acroForm) {
	  drObj.free();
	  acroForm->lookup("DR", &drObj);
	}
      }
    }
    if (drObj.isDict()) {
      appearDict.dictAdd("Resources", drObj.copy(&obj1));
    }
    drObj.free();

    // build the appearance stream
    appearStream = new MemStream(appearBuf->getCString(), 0,
				 appearBuf->getLength(), &appearDict);
    appearance.initStream(appearStream);
    ok = gTrue;

    if (daStr1) {
      delete daStr1;
    }
  }
  daObj.free();
}

void Annot::draw(Gfx *gfx) {
  Object obj;

  if (appearance.fetch(xref, &obj)->isStream()) {
    gfx->doAnnot(&obj, xMin, yMin, xMax, yMax);
  }
  obj.free();
}

//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------

Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
  Dict *acroForm;
  Annot *annot;
  Object obj1;
  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->arrayGet(i, &obj1)->isDict()) {
	annot = new Annot(xref, acroForm, obj1.getDict());
	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);
}
