+ if (appearBuf) {
+ delete appearBuf;
+ }
+}
+
+void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
+ MemStream *appearStream;
+ Object daObj, vObj, drObj, appearDict, obj1, obj2;
+ GString *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 GString(daStr, i0, i1 - i0);
+ fontSize = atof(s->getCString());
+ delete s;
+
+ // autosize the font
+ if (fontSize == 0) {
+ fontSize = 0.67 * (yMax - yMin);
+ daStr1 = new GString(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 GString();
+ 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(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);
+
+ // 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(copyString("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();