676 lines
18 KiB
C++
676 lines
18 KiB
C++
//========================================================================
|
|
//
|
|
// XFAScanner.cc
|
|
//
|
|
// Copyright 2020 Glyph & Cog, LLC
|
|
//
|
|
//========================================================================
|
|
|
|
#include <aconf.h>
|
|
|
|
#ifdef USE_GCC_PRAGMAS
|
|
#pragma implementation
|
|
#endif
|
|
|
|
#include "GString.h"
|
|
#include "GHash.h"
|
|
#include "Object.h"
|
|
#include "Error.h"
|
|
#include "Zoox.h"
|
|
#include "XFAScanner.h"
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// fields have two names:
|
|
//
|
|
// name:
|
|
// - nodes with bind=global set the index to 0 ("foo[0]") regardless
|
|
// of the number of nodes with the same name
|
|
// - nodes with bind=none are dropped from the name
|
|
// - <area> nodes are dropped from the name
|
|
// - used for field value lookup in <xfa:datasets>
|
|
//
|
|
// fullName:
|
|
// - all named nodes are treated the same, regardless of bind=global
|
|
// or bind=none
|
|
// - <area> nodes are included in the name, but don't reset the
|
|
// numbering (i.e., <area> nodes are "transparent" with respect to
|
|
// node numbering)
|
|
// - used for field value lookup in <form>
|
|
// - used for matching with AcroForm names
|
|
//
|
|
// Both names use indexes on all nodes, even if there's only one node
|
|
// with the name -- this isn't correct for XFA naming, but it matches
|
|
// the AcroForm behavior.
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
XFAFieldLayoutInfo::XFAFieldLayoutInfo(XFAFieldLayoutHAlign hAlignA,
|
|
XFAFieldLayoutVAlign vAlignA) {
|
|
hAlign = hAlignA;
|
|
vAlign = vAlignA;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
XFAFieldPictureInfo::XFAFieldPictureInfo(XFAFieldPictureSubtype subtypeA,
|
|
GString *formatA) {
|
|
subtype = subtypeA;
|
|
format = formatA;
|
|
}
|
|
|
|
XFAFieldPictureInfo::~XFAFieldPictureInfo() {
|
|
delete format;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
XFAFieldBarcodeInfo::XFAFieldBarcodeInfo(GString *barcodeTypeA,
|
|
double wideNarrowRatioA,
|
|
double moduleWidthA,
|
|
double moduleHeightA,
|
|
int dataLengthA,
|
|
int errorCorrectionLevelA,
|
|
GString *textLocationA) {
|
|
barcodeType = barcodeTypeA;
|
|
wideNarrowRatio = wideNarrowRatioA;
|
|
moduleWidth = moduleWidthA;
|
|
moduleHeight = moduleHeightA;
|
|
dataLength = dataLengthA;
|
|
errorCorrectionLevel = errorCorrectionLevelA;
|
|
textLocation = textLocationA;
|
|
}
|
|
|
|
XFAFieldBarcodeInfo::~XFAFieldBarcodeInfo() {
|
|
delete barcodeType;
|
|
delete textLocation;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
XFAField::XFAField(GString *nameA, GString *fullNameA, GString *valueA,
|
|
XFAFieldLayoutInfo *layoutInfoA,
|
|
XFAFieldPictureInfo *pictureInfoA,
|
|
XFAFieldBarcodeInfo *barcodeInfoA)
|
|
: name(nameA)
|
|
, fullName(fullNameA)
|
|
, value(valueA)
|
|
, layoutInfo(layoutInfoA)
|
|
, pictureInfo(pictureInfoA)
|
|
, barcodeInfo(barcodeInfoA)
|
|
{
|
|
}
|
|
|
|
XFAField::~XFAField() {
|
|
delete name;
|
|
delete fullName;
|
|
delete value;
|
|
delete layoutInfo;
|
|
delete pictureInfo;
|
|
delete barcodeInfo;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
XFAScanner *XFAScanner::load(Object *xfaObj) {
|
|
GString *xfaData = readXFAStreams(xfaObj);
|
|
if (!xfaData) {
|
|
return NULL;
|
|
}
|
|
ZxDoc *xml = ZxDoc::loadMem(xfaData->getCString(), xfaData->getLength());
|
|
delete xfaData;
|
|
if (!xml) {
|
|
error(errSyntaxError, -1, "Invalid XML in XFA form");
|
|
return NULL;
|
|
}
|
|
|
|
XFAScanner *scanner = new XFAScanner();
|
|
|
|
if (xml->getRoot()) {
|
|
GHash *formValues = scanner->scanFormValues(xml->getRoot());
|
|
ZxElement *dataElem = NULL;
|
|
ZxElement *datasets =
|
|
xml->getRoot()->findFirstChildElement("xfa:datasets");
|
|
if (datasets) {
|
|
dataElem = datasets->findFirstChildElement("xfa:data");
|
|
}
|
|
ZxElement *tmpl = xml->getRoot()->findFirstChildElement("template");
|
|
if (tmpl) {
|
|
scanner->scanNode(tmpl, NULL, NULL, NULL, NULL, NULL,
|
|
dataElem, formValues);
|
|
}
|
|
deleteGHash(formValues, GString);
|
|
}
|
|
|
|
delete xml;
|
|
|
|
return scanner;
|
|
}
|
|
|
|
XFAScanner::XFAScanner() {
|
|
fields = new GHash();
|
|
}
|
|
|
|
XFAScanner::~XFAScanner() {
|
|
deleteGHash(fields, XFAField);
|
|
}
|
|
|
|
XFAField *XFAScanner::findField(GString *acroFormFieldName) {
|
|
return (XFAField *)fields->lookup(acroFormFieldName);
|
|
}
|
|
|
|
GString *XFAScanner::readXFAStreams(Object *xfaObj) {
|
|
GString *data = new GString();
|
|
char buf[4096];
|
|
int n;
|
|
if (xfaObj->isStream()) {
|
|
xfaObj->streamReset();
|
|
while ((n = xfaObj->getStream()->getBlock(buf, sizeof(buf))) > 0) {
|
|
data->append(buf, n);
|
|
}
|
|
} else if (xfaObj->isArray()) {
|
|
for (int i = 1; i < xfaObj->arrayGetLength(); i += 2) {
|
|
Object obj;
|
|
if (!xfaObj->arrayGet(i, &obj)->isStream()) {
|
|
error(errSyntaxError, -1, "XFA array element is wrong type");
|
|
obj.free();
|
|
delete data;
|
|
return NULL;
|
|
}
|
|
obj.streamReset();
|
|
while ((n = obj.getStream()->getBlock(buf, sizeof(buf))) > 0) {
|
|
data->append(buf, n);
|
|
}
|
|
obj.free();
|
|
}
|
|
} else {
|
|
error(errSyntaxError, -1, "XFA object is wrong type");
|
|
return NULL;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
GHash *XFAScanner::scanFormValues(ZxElement *xmlRoot) {
|
|
GHash *formValues = new GHash(gTrue);
|
|
ZxElement *formElem = xmlRoot->findFirstChildElement("form");
|
|
if (formElem) {
|
|
scanFormNode(formElem, NULL, formValues);
|
|
}
|
|
return formValues;
|
|
}
|
|
|
|
void XFAScanner::scanFormNode(ZxElement *elem, GString *fullName,
|
|
GHash *formValues) {
|
|
GHash *fullNameIdx = new GHash();
|
|
for (ZxNode *node = elem->getFirstChild();
|
|
node;
|
|
node = node->getNextChild()) {
|
|
if (node->isElement("value")) {
|
|
if (fullName) {
|
|
ZxNode *child1Node = ((ZxElement *)node)->getFirstChild();
|
|
if (child1Node && child1Node->isElement()) {
|
|
ZxNode *child2Node = ((ZxElement *)child1Node)->getFirstChild();
|
|
if (child2Node && child2Node->isCharData()) {
|
|
formValues->add(fullName->copy(),
|
|
((ZxCharData *)child2Node)->getData()->copy());
|
|
}
|
|
}
|
|
}
|
|
} else if (node->isElement()) {
|
|
ZxAttr *nameAttr = ((ZxElement *)node)->findAttr("name");
|
|
if (nameAttr && (node->isElement("subform") ||
|
|
node->isElement("field"))) {
|
|
GString *nodeName = nameAttr->getValue();
|
|
GString *childFullName;
|
|
if (fullName) {
|
|
childFullName = GString::format("{0:t}.{1:t}", fullName, nodeName);
|
|
} else {
|
|
childFullName = nodeName->copy();
|
|
}
|
|
int idx = fullNameIdx->lookupInt(nodeName);
|
|
childFullName->appendf("[{0:d}]", idx);
|
|
fullNameIdx->replace(nodeName, idx + 1);
|
|
scanFormNode((ZxElement *)node, childFullName, formValues);
|
|
delete childFullName;
|
|
} else if (node->isElement("subform")) {
|
|
scanFormNode((ZxElement *)node, fullName, formValues);
|
|
}
|
|
}
|
|
}
|
|
delete fullNameIdx;
|
|
}
|
|
|
|
void XFAScanner::scanNode(ZxElement *elem,
|
|
GString *parentName, GString *parentFullName,
|
|
GHash *nameIdx, GHash *fullNameIdx,
|
|
GString *exclGroupName, ZxElement *dataElem,
|
|
GHash *formValues) {
|
|
GString *nodeName = getNodeName(elem);
|
|
GHash *childNameIdx;
|
|
if (!nameIdx || nodeName) {
|
|
childNameIdx = new GHash();
|
|
} else {
|
|
childNameIdx = nameIdx;
|
|
}
|
|
GString *nodeFullName = getNodeFullName(elem);
|
|
GHash *childFullNameIdx;
|
|
if (!fullNameIdx || (nodeFullName && !elem->isElement("area"))) {
|
|
childFullNameIdx = new GHash();
|
|
} else {
|
|
childFullNameIdx = fullNameIdx;
|
|
}
|
|
|
|
GString *childName;
|
|
if (nodeName) {
|
|
if (parentName) {
|
|
childName = GString::format("{0:t}.{1:t}", parentName, nodeName);
|
|
} else {
|
|
childName = nodeName->copy();
|
|
}
|
|
int idx = nameIdx->lookupInt(nodeName);
|
|
nameIdx->replace(nodeName, idx + 1);
|
|
if (nodeIsBindGlobal(elem)) {
|
|
childName->appendf("[0]");
|
|
} else {
|
|
childName->appendf("[{0:d}]", idx);
|
|
}
|
|
} else {
|
|
childName = parentName;
|
|
}
|
|
GString *childFullName;
|
|
if (nodeFullName) {
|
|
if (parentFullName) {
|
|
childFullName = GString::format("{0:t}.{1:t}",
|
|
parentFullName, nodeFullName);
|
|
} else {
|
|
childFullName = nodeFullName->copy();
|
|
}
|
|
int idx = fullNameIdx->lookupInt(nodeFullName);
|
|
fullNameIdx->replace(nodeFullName, idx + 1);
|
|
childFullName->appendf("[{0:d}]", idx);
|
|
} else {
|
|
childFullName = parentFullName;
|
|
}
|
|
|
|
if (elem->isElement("field")) {
|
|
scanField(elem, childName, childFullName, exclGroupName,
|
|
dataElem, formValues);
|
|
} else {
|
|
GString *childExclGroupName;
|
|
if (elem->isElement("exclGroup")) {
|
|
childExclGroupName = childName;
|
|
} else {
|
|
childExclGroupName = NULL;
|
|
}
|
|
for (ZxNode *child = elem->getFirstChild();
|
|
child;
|
|
child = child->getNextChild()) {
|
|
if (child->isElement()) {
|
|
scanNode((ZxElement *)child, childName, childFullName,
|
|
childNameIdx, childFullNameIdx, childExclGroupName,
|
|
dataElem, formValues);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (childName != parentName) {
|
|
delete childName;
|
|
}
|
|
if (childFullName != parentFullName) {
|
|
delete childFullName;
|
|
}
|
|
if (childNameIdx != nameIdx) {
|
|
delete childNameIdx;
|
|
}
|
|
if (childFullNameIdx != fullNameIdx) {
|
|
delete childFullNameIdx;
|
|
}
|
|
}
|
|
|
|
void XFAScanner::scanField(ZxElement *elem, GString *name, GString *fullName,
|
|
GString *exclGroupName, ZxElement *dataElem,
|
|
GHash *formValues) {
|
|
GString *value = getFieldValue(elem, name, fullName, exclGroupName,
|
|
dataElem, formValues);
|
|
XFAFieldLayoutInfo *layoutInfo = getFieldLayoutInfo(elem);
|
|
XFAFieldPictureInfo *pictureInfo = getFieldPictureInfo(elem);
|
|
XFAFieldBarcodeInfo *barcodeInfo = getFieldBarcodeInfo(elem);
|
|
XFAField *field = new XFAField(name->copy(), fullName->copy(), value,
|
|
layoutInfo, pictureInfo, barcodeInfo);
|
|
fields->add(field->fullName, field);
|
|
}
|
|
|
|
GString *XFAScanner::getFieldValue(ZxElement *elem, GString *name,
|
|
GString *fullName, GString *exclGroupName,
|
|
ZxElement *dataElem, GHash *formValues) {
|
|
GString *val = NULL;
|
|
|
|
//--- check the <xfa:datasets> packet
|
|
val = getDatasetsValue(name->getCString(), dataElem);
|
|
if (!val && exclGroupName) {
|
|
val = (GString *)getDatasetsValue(exclGroupName->getCString(), dataElem);
|
|
}
|
|
|
|
//--- check the <form> element
|
|
if (!val) {
|
|
val = (GString *)formValues->lookup(fullName);
|
|
}
|
|
|
|
//--- check the <value> element within the field
|
|
if (!val) {
|
|
ZxElement *valueElem = elem->findFirstChildElement("value");
|
|
if (valueElem) {
|
|
ZxNode *child1Node = valueElem->getFirstChild();
|
|
if (child1Node && child1Node->isElement()) {
|
|
ZxNode *child2Node = ((ZxElement *)child1Node)->getFirstChild();
|
|
if (child2Node && child2Node->isCharData()) {
|
|
val = ((ZxCharData *)child2Node)->getData();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--- get the checkbutton item value
|
|
GString *checkbuttonItem = NULL;
|
|
ZxElement *uiElem = elem->findFirstChildElement("ui");
|
|
if (uiElem) {
|
|
ZxNode *uiChild = uiElem->getFirstChild();
|
|
if (uiChild && uiChild->isElement("checkButton")) {
|
|
ZxElement *itemsElem = elem->findFirstChildElement("items");
|
|
if (itemsElem) {
|
|
ZxNode *node1 = itemsElem->getFirstChild();
|
|
if (node1 && node1->isElement()) {
|
|
ZxNode *node2 = ((ZxElement *)node1)->getFirstChild();
|
|
if (node2 && node2->isCharData()) {
|
|
checkbuttonItem = ((ZxCharData *)node2)->getData();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// convert XFA checkbutton value to AcroForm-style On/Off value
|
|
if (checkbuttonItem && val) {
|
|
if (val->cmp(checkbuttonItem)) {
|
|
val = new GString("Off");
|
|
} else {
|
|
val = new GString("On");
|
|
}
|
|
} else if (val) {
|
|
val = val->copy();
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
GString *XFAScanner::getDatasetsValue(char *partName, ZxElement *elem) {
|
|
if (!elem) {
|
|
return NULL;
|
|
}
|
|
|
|
// partName = xxxx[nn].yyyy----
|
|
char *p = strchr(partName, '[');
|
|
if (!p) {
|
|
return NULL;
|
|
}
|
|
int partLen = (int)(p - partName);
|
|
int idx = atoi(p + 1);
|
|
p = strchr(p + 1, '.');
|
|
if (p) {
|
|
++p;
|
|
}
|
|
|
|
int curIdx = 0;
|
|
for (ZxNode *node = elem->getFirstChild();
|
|
node;
|
|
node = node->getNextChild()) {
|
|
if (!node->isElement()) {
|
|
continue;
|
|
}
|
|
GString *nodeName = ((ZxElement *)node)->getType();
|
|
if (nodeName->getLength() != partLen ||
|
|
strncmp(nodeName->getCString(), partName, partLen)) {
|
|
continue;
|
|
}
|
|
if (curIdx != idx) {
|
|
++curIdx;
|
|
continue;
|
|
}
|
|
if (p) {
|
|
GString *val = getDatasetsValue(p, (ZxElement *)node);
|
|
if (val) {
|
|
return val;
|
|
}
|
|
break;
|
|
} else {
|
|
ZxNode *child = ((ZxElement *)node)->getFirstChild();
|
|
if (!child || !child->isCharData()) {
|
|
return NULL;
|
|
}
|
|
return ((ZxCharData *)child)->getData();
|
|
}
|
|
}
|
|
|
|
// search for an 'ancestor match'
|
|
if (p) {
|
|
return getDatasetsValue(p, elem);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
XFAFieldLayoutInfo *XFAScanner::getFieldLayoutInfo(ZxElement *elem) {
|
|
ZxElement *paraElem = elem->findFirstChildElement("para");
|
|
if (!paraElem) {
|
|
return NULL;
|
|
}
|
|
XFAFieldLayoutHAlign hAlign = xfaFieldLayoutHAlignLeft;
|
|
ZxAttr *hAlignAttr = paraElem->findAttr("hAlign");
|
|
if (hAlignAttr) {
|
|
if (!hAlignAttr->getValue()->cmp("left")) {
|
|
hAlign = xfaFieldLayoutHAlignLeft;
|
|
} else if (!hAlignAttr->getValue()->cmp("center")) {
|
|
hAlign = xfaFieldLayoutHAlignCenter;
|
|
} else if (!hAlignAttr->getValue()->cmp("right")) {
|
|
hAlign = xfaFieldLayoutHAlignRight;
|
|
}
|
|
}
|
|
XFAFieldLayoutVAlign vAlign = xfaFieldLayoutVAlignTop;
|
|
ZxAttr *vAlignAttr = paraElem->findAttr("vAlign");
|
|
if (vAlignAttr) {
|
|
if (!vAlignAttr->getValue()->cmp("top")) {
|
|
vAlign = xfaFieldLayoutVAlignTop;
|
|
} else if (!vAlignAttr->getValue()->cmp("middle")) {
|
|
vAlign = xfaFieldLayoutVAlignMiddle;
|
|
} else if (!vAlignAttr->getValue()->cmp("bottom")) {
|
|
vAlign = xfaFieldLayoutVAlignBottom;
|
|
}
|
|
}
|
|
return new XFAFieldLayoutInfo(hAlign, vAlign);
|
|
}
|
|
|
|
XFAFieldPictureInfo *XFAScanner::getFieldPictureInfo(ZxElement *elem) {
|
|
ZxElement *uiElem = elem->findFirstChildElement("ui");
|
|
if (!uiElem) {
|
|
return NULL;
|
|
}
|
|
XFAFieldPictureSubtype subtype;
|
|
if (uiElem->findFirstChildElement("dateTimeEdit")) {
|
|
subtype = xfaFieldPictureDateTime;
|
|
} else if (uiElem->findFirstChildElement("numericEdit")) {
|
|
subtype = xfaFieldPictureNumeric;
|
|
} else if (uiElem->findFirstChildElement("textEdit")) {
|
|
subtype = xfaFieldPictureText;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
|
|
ZxElement *formatElem, *pictureElem;
|
|
ZxNode *pictureChildNode;
|
|
if (!(formatElem = elem->findFirstChildElement("format")) ||
|
|
!(pictureElem = formatElem->findFirstChildElement("picture")) ||
|
|
!(pictureChildNode = pictureElem->getFirstChild()) ||
|
|
!pictureChildNode->isCharData()) {
|
|
return NULL;
|
|
}
|
|
GString *format = ((ZxCharData *)pictureChildNode)->getData()->copy();
|
|
|
|
return new XFAFieldPictureInfo(subtype, format);
|
|
}
|
|
|
|
XFAFieldBarcodeInfo *XFAScanner::getFieldBarcodeInfo(ZxElement *elem) {
|
|
ZxElement *uiElem, *barcodeElem;
|
|
if (!(uiElem = elem->findFirstChildElement("ui")) ||
|
|
!(barcodeElem = uiElem->findFirstChildElement("barcode"))) {
|
|
return NULL;
|
|
}
|
|
|
|
ZxAttr *attr;
|
|
if (!(attr = barcodeElem->findAttr("type"))) {
|
|
return NULL;
|
|
}
|
|
GString *barcodeType = attr->getValue()->copy();
|
|
|
|
double wideNarrowRatio = 3;
|
|
if ((attr = barcodeElem->findAttr("wideNarrowRatio"))) {
|
|
char *s = attr->getValue()->getCString();
|
|
char *colon = strchr(s, ':');
|
|
if (colon) {
|
|
GString *numStr = new GString(s, (int)(colon - s));
|
|
double num = atof(numStr->getCString());
|
|
delete numStr;
|
|
double den = atof(colon + 1);
|
|
if (den == 0) {
|
|
wideNarrowRatio = num;
|
|
} else {
|
|
wideNarrowRatio = num / den;
|
|
}
|
|
} else {
|
|
wideNarrowRatio = atof(s);
|
|
}
|
|
}
|
|
|
|
double moduleWidth = (0.25 / 25.4) * 72.0; // 0.25mm
|
|
if ((attr = barcodeElem->findAttr("moduleWidth"))) {
|
|
moduleWidth = getMeasurement(attr->getValue());
|
|
}
|
|
|
|
double moduleHeight = (5.0 / 25.4) * 72.0; // 5mm
|
|
if ((attr = barcodeElem->findAttr("moduleHeight"))) {
|
|
moduleHeight = getMeasurement(attr->getValue());
|
|
}
|
|
|
|
int dataLength = 0;
|
|
if ((attr = barcodeElem->findAttr("dataLength"))) {
|
|
dataLength = atoi(attr->getValue()->getCString());
|
|
}
|
|
|
|
int errorCorrectionLevel = 0;
|
|
if ((attr = barcodeElem->findAttr("errorCorrectionLevel"))) {
|
|
errorCorrectionLevel = atoi(attr->getValue()->getCString());
|
|
}
|
|
|
|
GString *textLocation;
|
|
if ((attr = barcodeElem->findAttr("textLocation"))) {
|
|
textLocation = attr->getValue()->copy();
|
|
} else {
|
|
textLocation = new GString("below");
|
|
}
|
|
|
|
return new XFAFieldBarcodeInfo(barcodeType, wideNarrowRatio,
|
|
moduleWidth, moduleHeight, dataLength,
|
|
errorCorrectionLevel, textLocation);
|
|
}
|
|
|
|
double XFAScanner::getMeasurement(GString *s) {
|
|
int i = 0;
|
|
GBool neg = gFalse;
|
|
if (i < s->getLength() && s->getChar(i) == '+') {
|
|
++i;
|
|
} else if (i < s->getLength() && s->getChar(i) == '-') {
|
|
neg = gTrue;
|
|
++i;
|
|
}
|
|
double val = 0;
|
|
while (i < s->getLength() && s->getChar(i) >= '0' && s->getChar(i) <= '9') {
|
|
val = val * 10 + s->getChar(i) - '0';
|
|
++i;
|
|
}
|
|
if (i < s->getLength() && s->getChar(i) == '.') {
|
|
++i;
|
|
double mul = 0.1;
|
|
while (i < s->getLength() &&
|
|
s->getChar(i) >= '0' && s->getChar(i) <= '9') {
|
|
val += mul * (s->getChar(i) - '0');
|
|
mul *= 0.1;
|
|
++i;
|
|
}
|
|
}
|
|
if (neg) {
|
|
val = -val;
|
|
}
|
|
if (i+1 < s->getLength()) {
|
|
if (s->getChar(i) == 'i' && s->getChar(i+1) == 'n') {
|
|
val *= 72;
|
|
} else if (s->getChar(i) == 'p' && s->getChar(i+1) == 't') {
|
|
// no change
|
|
} else if (s->getChar(i) == 'c' && s->getChar(i+1) == 'm') {
|
|
val *= 72 / 2.54;
|
|
} else if (s->getChar(i) == 'm' && s->getChar(i+1) == 'm') {
|
|
val *= 72 / 25.4;
|
|
} else {
|
|
// default to inches
|
|
val *= 72;
|
|
}
|
|
} else {
|
|
// default to inches
|
|
val *= 72;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
GString *XFAScanner::getNodeName(ZxElement *elem) {
|
|
if (elem->isElement("template") ||
|
|
elem->isElement("area") ||
|
|
elem->isElement("draw")) {
|
|
return NULL;
|
|
}
|
|
if (!elem->isElement("field") && nodeIsBindNone(elem)) {
|
|
return NULL;
|
|
}
|
|
ZxAttr *nameAttr = elem->findAttr("name");
|
|
if (!nameAttr) {
|
|
return NULL;
|
|
}
|
|
return nameAttr->getValue();
|
|
}
|
|
|
|
GString *XFAScanner::getNodeFullName(ZxElement *elem) {
|
|
if (elem->isElement("template") ||
|
|
elem->isElement("draw")) {
|
|
return NULL;
|
|
}
|
|
ZxAttr *nameAttr = elem->findAttr("name");
|
|
if (!nameAttr) {
|
|
return NULL;
|
|
}
|
|
return nameAttr->getValue();
|
|
}
|
|
|
|
GBool XFAScanner::nodeIsBindGlobal(ZxElement *elem) {
|
|
ZxElement *bindElem = elem->findFirstChildElement("bind");
|
|
if (!bindElem) {
|
|
return gFalse;
|
|
}
|
|
ZxAttr *attr = bindElem->findAttr("match");
|
|
return attr && !attr->getValue()->cmp("global");
|
|
}
|
|
|
|
GBool XFAScanner::nodeIsBindNone(ZxElement *elem) {
|
|
ZxElement *bindElem = elem->findFirstChildElement("bind");
|
|
if (!bindElem) {
|
|
return gFalse;
|
|
}
|
|
ZxAttr *attr = bindElem->findAttr("match");
|
|
return attr && !attr->getValue()->cmp("none");
|
|
}
|