📄 annot.cc
字号:
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -