// Copyright (C) 2019-2020 Jakub Melka // // This file is part of PdfForQt. // // PdfForQt is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // PdfForQt is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with PDFForQt. If not, see . #ifndef PDFSTRUCTURETREE_H #define PDFSTRUCTURETREE_H #include "pdfobject.h" #include "pdfobjectutils.h" namespace pdf { class PDFObjectStorage; struct PDFStructureTreeAttributeDefinition; class PDFFORQTLIBSHARED_EXPORT PDFStructureTreeAttribute { public: explicit PDFStructureTreeAttribute(); enum class Owner { Invalid, /// Defined for user owner User, /// Defined for NSO (namespace owner) NSO, Layout, List, PrintField, Table, Artifact, XML_1_00, HTML_3_20, HTML_4_01, HTML_5_00, OEB_1_00, RTF_1_05, CSS_1_00, CSS_2_00, CSS_3_00, RDFa_1_10, ARIA_1_1, }; enum Attribute { User, // Standard layout attributes Placement, WritingMode, BackgroundColor, BorderColor, BorderStyle, BorderThickness, Color, Padding, // Block element attributes SpaceBefore, SpaceAfter, StartIndent, EndIndent, TextIndent, TextAlign, BBox, Width, Height, BlockAlign, InlineAlign, TBorderStyle, TPadding, LineHeight, BaselineShift, TextDecorationType, TextDecorationColor, TextDecorationThickness, ColumnCount, ColumnWidths, ColumnGap, GlyphOrientationVertical, RubyAlign, RubyPosition, // List attributes ListNumbering, ContinuedList, ContinuedFrom, // PrintField attributes Role, Checked, Desc, // Table attributes RowSpan, ColSpan, Headers, Scope, Short, // Artifact attributes Type, Subtype, LastAttribute }; /// Returns attribute type Attribute getType() const; /// Returns attribute owner Owner getOwner() const { return m_owner; } /// Returns true, if attribute is inheritable bool isInheritable() const; /// Returns attribute revision number PDFInteger getRevision() const { return m_revision; } /// Returns namespace for this attribute (or empty reference, if it doesn't exists) PDFObjectReference getNamespace() const { return m_namespace; } /// Returns attribute value const PDFObject& getValue() const { return m_value; } /// Returns default attribute value PDFObject getDefaultValue() const; /// Returns user property name. This function should be called only for /// user properties. If error occurs, then empty string is returned. /// \param storage Storage (for resolving of indirect objects) QString getUserPropertyName(const PDFObjectStorage* storage) const; /// Returns user property value. This function should be called only for /// user properties. If error occurs, then empty string is returned. /// \param storage Storage (for resolving of indirect objects) PDFObject getUserPropertyValue(const PDFObjectStorage* storage) const; /// Returns user property formatted value. This function should be called only for /// user properties. If error occurs, then empty string is returned. /// \param storage Storage (for resolving of indirect objects) QString getUserPropertyFormattedValue(const PDFObjectStorage* storage) const; /// Returns true, if user property is hidden. This function should be called only for /// user properties. If error occurs, then empty string is returned. /// \param storage Storage (for resolving of indirect objects) bool getUserPropertyIsHidden(const PDFObjectStorage* storage) const; private: const PDFStructureTreeAttributeDefinition* m_definition = nullptr; /// Attribute owner Owner m_owner = Owner::Invalid; /// Revision number PDFInteger m_revision = 0; /// Namespace PDFObjectReference m_namespace; /// Value of attribute. In case of standard attribute, attribute /// value is directly stored here. In case of user attribute, /// then user attribute dictionary is stored here. PDFObject m_value; }; class PDFStructureTree; class PDFStructureItem; using PDFStructureItemPointer = QSharedPointer; /// Root class for all structure tree items class PDFStructureItem { public: explicit inline PDFStructureItem(PDFStructureItem* parent, PDFStructureTree* root) : m_parent(parent), m_root(root) { } virtual ~PDFStructureItem() = default; virtual PDFStructureTree* asStructureTree() { return nullptr; } virtual const PDFStructureTree* asStructureTree() const { return nullptr; } const PDFStructureItem* getParent() const { return m_parent; } const PDFStructureTree* getTree() const { return m_root; } std::size_t getChildCount() const { return m_children.size(); } const PDFStructureItem* getChild(size_t i) const { return m_children.at(i).get(); } /// Parses structure tree item from the object. If error occurs, /// null pointer is returned. /// \param storage Storage /// \param object Structure tree item object /// \param context Parsing context static PDFStructureItemPointer parse(const PDFObjectStorage* storage, PDFObject object, PDFMarkedObjectsContext* context); protected: PDFStructureItem* m_parent; PDFStructureTree* m_root; std::vector m_children; }; /// Structure tree, contains structure element hierarchy class PDFStructureTree : public PDFStructureItem { public: explicit inline PDFStructureTree() : PDFStructureItem(nullptr, this) { } virtual PDFStructureTree* asStructureTree() override { return this; } virtual const PDFStructureTree* asStructureTree() const override { return this; } /// Returns parents from parent tree for given entry. If entry /// is not found, then empty vector is returned. /// \param id Id std::vector getParents(PDFInteger id) const; /// Parses structure tree from the object. If error occurs, empty structure /// tree is returned. /// \param storage Storage /// \param object Structure tree root object static PDFStructureTree parse(const PDFObjectStorage* storage, PDFObject object); private: struct ParentTreeEntry { PDFInteger id = 0; PDFObjectReference reference; bool operator<(const ParentTreeEntry& other) const { return id < other.id; } }; using ParentTreeEntries = std::vector; std::map m_idTreeMap; ParentTreeEntries m_parentTreeEntries; }; } // namespace pdf #endif // PDFSTRUCTURETREE_H