XFA: template tree definition

This commit is contained in:
Jakub Melka 2021-10-29 14:28:26 +02:00
parent cb6cb58d68
commit 68704cd8e5
5 changed files with 3134 additions and 5 deletions

View File

@ -1486,6 +1486,13 @@ void XFACodeGenerator::loadClasses(const QDomDocument& document)
// Class name // Class name
myClass.className = element.attribute("name"); myClass.className = element.attribute("name");
QDomElement valueElement = element.firstChildElement("value");
if (!valueElement.isNull())
{
QString valueType = valueElement.attribute("type");
myClass.valueType = createType("node_value", "nodeValue", valueType);
}
// Attributes // Attributes
QDomNodeList attributes = element.elementsByTagName("property"); QDomNodeList attributes = element.elementsByTagName("property");
const int attributeCount = attributes.size(); const int attributeCount = attributes.size();
@ -1505,6 +1512,24 @@ void XFACodeGenerator::loadClasses(const QDomDocument& document)
myClass.attributes.emplace_back(std::move(attribute)); myClass.attributes.emplace_back(std::move(attribute));
} }
// Subnodes
QDomNodeList subnodes = element.elementsByTagName("item");
const int subnodeCount = subnodes.size();
for (int ai = 0; ai < subnodeCount; ++ai)
{
QDomElement subnodeElement = subnodes.item(ai).toElement();
QString className = subnodeElement.attribute("class");
QString min = subnodeElement.attribute("min");
QString max = subnodeElement.attribute("max");
Subnode subnode;
subnode.subnodeName = std::move(className);
subnode.min = min.toInt();
subnode.max = (max == "n") ? std::numeric_limits<int>::max() : max.toInt();
myClass.subnodes.emplace_back(std::move(subnode));
}
m_classes.emplace_back(std::move(myClass)); m_classes.emplace_back(std::move(myClass));
} }
} }
@ -1555,11 +1580,13 @@ const XFACodeGenerator::Type* XFACodeGenerator::createType(QString id, QString n
QString finalTypeName = typeName; QString finalTypeName = typeName;
int i = 1; int i = 1;
while (m_types.count(finalTypeName)) while (m_usedTypes.count(finalTypeName))
{ {
finalTypeName = typeName + QString::number(i++); finalTypeName = typeName + QString::number(i++);
} }
m_usedTypes.insert(finalTypeName);
QString enumValues = enumValuesString.remove(QChar::Space); QString enumValues = enumValuesString.remove(QChar::Space);
type.enumValues = enumValues.split("|"); type.enumValues = enumValues.split("|");
@ -1585,6 +1612,14 @@ QString XFACodeGenerator::generateSource() const
stream << "namespace xfa" << Qt::endl; stream << "namespace xfa" << Qt::endl;
stream << "{" << Qt::endl << Qt::endl; stream << "{" << Qt::endl << Qt::endl;
// Forward declarations
for (const Class& myClass : m_classes)
{
stream << QString("class XFA_%1;").arg(myClass.className) << Qt::endl;
}
stream << Qt::endl;
stream << "class XFA_BaseNode : public XFA_AbstractNode" << Qt::endl; stream << "class XFA_BaseNode : public XFA_AbstractNode" << Qt::endl;
stream << "{" << Qt::endl; stream << "{" << Qt::endl;
stream << "public:" << Qt::endl; stream << "public:" << Qt::endl;
@ -1630,12 +1665,55 @@ QString XFACodeGenerator::generateSource() const
attributeGetters << attributeGetter; attributeGetters << attributeGetter;
} }
stream << Qt::endl;
QStringList subnodeGetters;
QStringList subnodeDeclarations;
for (const Subnode& subnode : myClass.subnodes)
{
if (subnode.max == 1)
{
QString subnodeFieldName = QString("m_%1").arg(subnode.subnodeName);
QString subnodeTypeName = QString("XFA_%1").arg(subnode.subnodeName);
QString subnodeGetterName = subnode.subnodeName;
subnodeGetterName[0] = subnodeGetterName.front().toUpper();
QString subnodeDeclaration = QString(" XFA_Node<%1> %2;").arg(subnodeTypeName, subnodeFieldName);
QString subnodeGetter = QString(" const %1* get%2() const { return %3.getValue(); }").arg(subnodeTypeName, subnodeGetterName, subnodeFieldName);
subnodeDeclarations << subnodeDeclaration;
subnodeGetters << subnodeGetter;
}
else
{
QString subnodeFieldName = QString("m_%1").arg(subnode.subnodeName);
QString subnodeTypeName = QString("std::vector<XFA_Node<XFA_%1>>").arg(subnode.subnodeName);
QString subnodeGetterName = subnode.subnodeName;
subnodeGetterName[0] = subnodeGetterName.front().toUpper();
QString subnodeDeclaration = QString(" %1 %2;").arg(subnodeTypeName, subnodeFieldName);
QString subnodeGetter = QString(" const %1& get%2() const { return %3; }").arg(subnodeTypeName, subnodeGetterName, subnodeFieldName);
subnodeDeclarations << subnodeDeclaration;
subnodeGetters << subnodeGetter;
}
}
for (const QString& getter : attributeGetters) for (const QString& getter : attributeGetters)
{ {
stream << getter << Qt::endl; stream << getter << Qt::endl;
} }
stream << Qt::endl; stream << Qt::endl;
for (const QString& getter : subnodeGetters)
{
stream << getter << Qt::endl;
}
stream << Qt::endl;
if (myClass.valueType)
{
stream << QString(" const %1* getNodeValue() const { return m_nodeValue.getValue(); }").arg(myClass.valueType->typeName) << Qt::endl << Qt::endl;
}
stream << "private:" << Qt::endl; stream << "private:" << Qt::endl;
stream << " /* properties */" << Qt::endl; stream << " /* properties */" << Qt::endl;
@ -1646,6 +1724,19 @@ QString XFACodeGenerator::generateSource() const
stream << Qt::endl; stream << Qt::endl;
stream << " /* subnodes */" << Qt::endl;
for (const QString& getter : subnodeDeclarations)
{
stream << getter << Qt::endl;
}
if (myClass.valueType)
{
stream << Qt::endl;
stream << QString(" XFA_Value<%1> m_nodeValue;").arg(myClass.valueType->typeName) << Qt::endl;
}
stream << "};" << Qt::endl << Qt::endl; stream << "};" << Qt::endl << Qt::endl;
} }
@ -1668,6 +1759,9 @@ QString XFACodeGenerator::getEnumValueName(QString enumName) const
} }
enumName.replace("-", "_"); enumName.replace("-", "_");
enumName.replace('\\', "Backslash");
enumName.replace('/', "Slash");
enumName.replace('.', "_");
} }
return enumName; return enumName;

View File

@ -26,6 +26,8 @@
#include <QObjectList> #include <QObjectList>
#include <QComboBox> #include <QComboBox>
#include <set>
namespace codegen namespace codegen
{ {
@ -469,11 +471,20 @@ private:
QString defaultValue; QString defaultValue;
}; };
struct Subnode
{
QString subnodeName;
int min = 0;
int max = 0;
};
struct Class struct Class
{ {
QString className; QString className;
QString valueType; const Type* valueType = nullptr;
QString nodeValue;
std::vector<Attribute> attributes; std::vector<Attribute> attributes;
std::vector<Subnode> subnodes;
}; };
void loadClasses(const QDomDocument& document); void loadClasses(const QDomDocument& document);
@ -485,6 +496,7 @@ private:
std::vector<Class> m_classes; std::vector<Class> m_classes;
std::map<QString, Type> m_types; std::map<QString, Type> m_types;
std::set<QString> m_usedTypes;
}; };
} // namespace codegen } // namespace codegen

File diff suppressed because it is too large Load Diff

View File

@ -80,7 +80,10 @@ template<typename Value>
using XFA_Attribute = PDFXFAValueHolder<Value, XFA_InplaceTag>; using XFA_Attribute = PDFXFAValueHolder<Value, XFA_InplaceTag>;
template<typename Value> template<typename Value>
using XFA_Node = PDFXFAValueHolder<Value, typename Value::StorageTag>; using XFA_Node = PDFXFAValueHolder<Value, XFA_SharedMemoryTag>;
template<typename Value>
using XFA_Value = PDFXFAValueHolder<Value, XFA_InplaceTag>;
class XFA_Measurement class XFA_Measurement
{ {

View File

@ -682,7 +682,7 @@
<property name="fontHorizontalScale" type="cdata"/> <property name="fontHorizontalScale" type="cdata"/>
<property name="fontVerticalScale" type="cdata"/> <property name="fontVerticalScale" type="cdata"/>
<property name="id" type="cdata"/> <property name="id" type="cdata"/>
<property name="kerningMode" type="none | pair"/ default="none"> <property name="kerningMode" type="none | pair" default="none"/>
<property name="letterSpacing" type="cdata"/> <property name="letterSpacing" type="cdata"/>
<property name="lineThrough" type="0 | 1 | 2" default="0"/> <property name="lineThrough" type="0 | 1 | 2" default="0"/>
<property name="lineThroughPeriod" type="all | word" default="all"/> <property name="lineThroughPeriod" type="all | word" default="all"/>