mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
XFA: form pagination
This commit is contained in:
@ -504,6 +504,7 @@ public:
|
|||||||
Annotation = 0x0002, ///< Annotations changed
|
Annotation = 0x0002, ///< Annotations changed
|
||||||
FormField = 0x0004, ///< Form field content changed
|
FormField = 0x0004, ///< Form field content changed
|
||||||
Authorization = 0x0008, ///< Authorization has changed (for example, old document is granted user access, but for new, owner access)
|
Authorization = 0x0008, ///< Authorization has changed (for example, old document is granted user access, but for new, owner access)
|
||||||
|
XFA_Pagination = 0x0010, ///< XFA pagination has been performed (this flag can be set only when Reset flag has been set and not any other flag)
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(ModificationFlags, ModificationFlag)
|
Q_DECLARE_FLAGS(ModificationFlags, ModificationFlag)
|
||||||
|
@ -1515,6 +1515,7 @@ public:
|
|||||||
void markReset() { m_modificationFlags.setFlag(PDFModifiedDocument::Reset); }
|
void markReset() { m_modificationFlags.setFlag(PDFModifiedDocument::Reset); }
|
||||||
void markAnnotationsChanged() { m_modificationFlags.setFlag(PDFModifiedDocument::Annotation); }
|
void markAnnotationsChanged() { m_modificationFlags.setFlag(PDFModifiedDocument::Annotation); }
|
||||||
void markFormFieldChanged() { m_modificationFlags.setFlag(PDFModifiedDocument::FormField); }
|
void markFormFieldChanged() { m_modificationFlags.setFlag(PDFModifiedDocument::FormField); }
|
||||||
|
void markXFAPagination() { m_modificationFlags.setFlag(PDFModifiedDocument::XFA_Pagination); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PDFDocument* m_originalDocument;
|
const PDFDocument* m_originalDocument;
|
||||||
|
@ -1668,6 +1668,75 @@ void PDFFormManager::drawXFAForm(const QMatrix& pagePointToDevicePointMatrix,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFFormManager::performPaging()
|
||||||
|
{
|
||||||
|
if (!hasXFAForm() || !m_document)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QSizeF> pageSizes = m_xfaEngine.getPageSizes();
|
||||||
|
|
||||||
|
const PDFCatalog* catalog = m_document->getCatalog();
|
||||||
|
const size_t pageCount = catalog->getPageCount();
|
||||||
|
std::vector<QSizeF> oldPageSizes;
|
||||||
|
oldPageSizes.reserve(pageCount);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pageCount; ++i)
|
||||||
|
{
|
||||||
|
oldPageSizes.push_back(catalog->getPage(i)->getMediaBox().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = pageSizes.size() != oldPageSizes.size();
|
||||||
|
if (!changed)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pageCount; ++i)
|
||||||
|
{
|
||||||
|
changed = changed ||
|
||||||
|
!qFuzzyCompare(pageSizes[i].width(), oldPageSizes[i].width()) ||
|
||||||
|
!qFuzzyCompare(pageSizes[i].height(), oldPageSizes[i].height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed && !oldPageSizes.empty())
|
||||||
|
{
|
||||||
|
PDFDocumentModifier modifier(m_document);
|
||||||
|
modifier.getBuilder()->setFormManager(this);
|
||||||
|
modifier.markReset();
|
||||||
|
|
||||||
|
PDFDocumentBuilder* builder = modifier.getBuilder();
|
||||||
|
builder->flattenPageTree();
|
||||||
|
std::vector<PDFObjectReference> pages = builder->getPages();
|
||||||
|
|
||||||
|
// Do we have more pages?
|
||||||
|
if (pages.size() > pageSizes.size())
|
||||||
|
{
|
||||||
|
pages.resize(pageSizes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have less pages?
|
||||||
|
while (pages.size() < pageSizes.size())
|
||||||
|
{
|
||||||
|
std::vector<pdf::PDFObjectReference> references = pdf::PDFDocumentBuilder::createReferencesFromObjects(builder->copyFrom(pdf::PDFDocumentBuilder::createObjectsFromReferences({ pages.front() }), *builder->getStorage(), true));
|
||||||
|
Q_ASSERT(references.size() == 1);
|
||||||
|
pages.push_back(references.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(pages.size() == pageSizes.size());
|
||||||
|
for (size_t i = 0; i < pages.size(); ++i)
|
||||||
|
{
|
||||||
|
builder->setPageMediaBox(pages[i], QRectF(QPointF(0, 0), pageSizes[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder->setPages(std::move(pages));
|
||||||
|
|
||||||
|
if (modifier.finalize())
|
||||||
|
{
|
||||||
|
emit documentModified(PDFModifiedDocument(modifier.getDocument(), nullptr, modifier.getFlags()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PDFFormManager::clearEditors()
|
void PDFFormManager::clearEditors()
|
||||||
{
|
{
|
||||||
qDeleteAll(m_widgetEditors);
|
qDeleteAll(m_widgetEditors);
|
||||||
|
@ -687,6 +687,11 @@ public:
|
|||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
QPainter* painter);
|
QPainter* painter);
|
||||||
|
|
||||||
|
/// Performs paging, when XFA form needs to change page count and size.
|
||||||
|
/// If some change needs to be done, then signal \p documentModified
|
||||||
|
/// is emitted.
|
||||||
|
void performPaging();
|
||||||
|
|
||||||
virtual int getInputPriority() const override { return FormPriority; }
|
virtual int getInputPriority() const override { return FormPriority; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -9679,8 +9679,11 @@ public:
|
|||||||
|
|
||||||
using LayoutItems = std::vector<LayoutItem>;
|
using LayoutItems = std::vector<LayoutItem>;
|
||||||
|
|
||||||
void setLayoutItems(PDFInteger pageIndex, LayoutItems layoutItems) { m_layout.layoutItems[pageIndex] = std::move(layoutItems); }
|
std::vector<QSizeF> getPageSizes() const { return m_layout.pageSizes; }
|
||||||
void setParagraphSettings(std::vector<xfa::XFA_ParagraphSettings> paragraphSettings) { m_layout.paragraphSettings = std::move(paragraphSettings); }
|
|
||||||
|
inline void setPageSizes(std::vector<QSizeF> pageSizes) { m_layout.pageSizes = std::move(pageSizes); }
|
||||||
|
inline void setLayoutItems(PDFInteger pageIndex, LayoutItems layoutItems) { m_layout.layoutItems[pageIndex] = std::move(layoutItems); }
|
||||||
|
inline void setParagraphSettings(std::vector<xfa::XFA_ParagraphSettings> paragraphSettings) { m_layout.paragraphSettings = std::move(paragraphSettings); }
|
||||||
|
|
||||||
void draw(const QMatrix& pagePointToDevicePointMatrix,
|
void draw(const QMatrix& pagePointToDevicePointMatrix,
|
||||||
const PDFPage* page,
|
const PDFPage* page,
|
||||||
@ -9691,6 +9694,7 @@ private:
|
|||||||
|
|
||||||
struct Layout
|
struct Layout
|
||||||
{
|
{
|
||||||
|
std::vector<QSizeF> pageSizes;
|
||||||
std::map<PDFInteger, LayoutItems> layoutItems;
|
std::map<PDFInteger, LayoutItems> layoutItems;
|
||||||
std::vector<xfa::XFA_ParagraphSettings> paragraphSettings;
|
std::vector<xfa::XFA_ParagraphSettings> paragraphSettings;
|
||||||
};
|
};
|
||||||
@ -10648,6 +10652,7 @@ void PDFXFALayoutEngine::performLayout(PDFXFAEngineImpl* engine, const xfa::XFA_
|
|||||||
|
|
||||||
node->accept(this);
|
node->accept(this);
|
||||||
|
|
||||||
|
std::vector<QSizeF> pageSizes;
|
||||||
std::map<PDFInteger, std::vector<Layout>> layoutPerPage;
|
std::map<PDFInteger, std::vector<Layout>> layoutPerPage;
|
||||||
|
|
||||||
for (Layout& layout : m_layout)
|
for (Layout& layout : m_layout)
|
||||||
@ -10661,6 +10666,8 @@ void PDFXFALayoutEngine::performLayout(PDFXFAEngineImpl* engine, const xfa::XFA_
|
|||||||
layoutPerPage[layout.pageIndex].emplace_back(std::move(layout));
|
layoutPerPage[layout.pageIndex].emplace_back(std::move(layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pageSizes.reserve(layoutPerPage.size());
|
||||||
|
|
||||||
PDFInteger pageIndex = 0;
|
PDFInteger pageIndex = 0;
|
||||||
for (const auto& layoutSinglePage : layoutPerPage)
|
for (const auto& layoutSinglePage : layoutPerPage)
|
||||||
{
|
{
|
||||||
@ -10688,9 +10695,13 @@ void PDFXFALayoutEngine::performLayout(PDFXFAEngineImpl* engine, const xfa::XFA_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PageInfo& pageInfo = m_pages.at(layoutSinglePage.first);
|
||||||
|
pageSizes.push_back(pageInfo.mediaBox.size());
|
||||||
|
|
||||||
engine->setLayoutItems(pageIndex++, std::move(layoutItems));
|
engine->setLayoutItems(pageIndex++, std::move(layoutItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine->setPageSizes(std::move(pageSizes));
|
||||||
engine->setParagraphSettings(std::move(m_paragraphSettings));
|
engine->setParagraphSettings(std::move(m_paragraphSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11364,6 +11375,11 @@ void PDFXFAEngine::setDocument(const PDFModifiedDocument& document, PDFForm* for
|
|||||||
m_impl->setDocument(document, form);
|
m_impl->setDocument(document, form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<QSizeF> PDFXFAEngine::getPageSizes() const
|
||||||
|
{
|
||||||
|
return m_impl->getPageSizes();
|
||||||
|
}
|
||||||
|
|
||||||
void PDFXFAEngine::draw(const QMatrix& pagePointToDevicePointMatrix,
|
void PDFXFAEngine::draw(const QMatrix& pagePointToDevicePointMatrix,
|
||||||
const PDFPage* page,
|
const PDFPage* page,
|
||||||
QList<PDFRenderError>& errors,
|
QList<PDFRenderError>& errors,
|
||||||
@ -11381,6 +11397,13 @@ PDFXFAEngineImpl::PDFXFAEngineImpl() :
|
|||||||
|
|
||||||
void PDFXFAEngineImpl::setDocument(const PDFModifiedDocument& document, PDFForm* form)
|
void PDFXFAEngineImpl::setDocument(const PDFModifiedDocument& document, PDFForm* form)
|
||||||
{
|
{
|
||||||
|
if (document.hasFlag(PDFModifiedDocument::XFA_Pagination))
|
||||||
|
{
|
||||||
|
// Do nothing - pagination of XFA was performed,
|
||||||
|
// nothing else has changed.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_document != document || document.hasReset())
|
if (m_document != document || document.hasReset())
|
||||||
{
|
{
|
||||||
m_document = document;
|
m_document = document;
|
||||||
|
@ -38,6 +38,9 @@ public:
|
|||||||
|
|
||||||
void setDocument(const PDFModifiedDocument& document, PDFForm* form);
|
void setDocument(const PDFModifiedDocument& document, PDFForm* form);
|
||||||
|
|
||||||
|
/// Returns list of page sizes (after paging is complete)
|
||||||
|
std::vector<QSizeF> getPageSizes() const;
|
||||||
|
|
||||||
/// Draws XFA form
|
/// Draws XFA form
|
||||||
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
||||||
/// \param page Page
|
/// \param page Page
|
||||||
|
@ -1562,6 +1562,11 @@ void PDFProgramController::onDocumentReadingFinished()
|
|||||||
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
|
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
|
||||||
setDocument(document);
|
setDocument(document);
|
||||||
|
|
||||||
|
if (m_formManager)
|
||||||
|
{
|
||||||
|
m_formManager->performPaging();
|
||||||
|
}
|
||||||
|
|
||||||
pdf::PDFDocumentRequirements requirements = pdf::PDFDocumentRequirements::parse(&m_pdfDocument->getStorage(), m_pdfDocument->getCatalog()->getRequirements());
|
pdf::PDFDocumentRequirements requirements = pdf::PDFDocumentRequirements::parse(&m_pdfDocument->getStorage(), m_pdfDocument->getCatalog()->getRequirements());
|
||||||
constexpr pdf::PDFDocumentRequirements::Requirements requirementFlags = pdf::PDFDocumentRequirements::Requirements(pdf::PDFDocumentRequirements::OCInteract |
|
constexpr pdf::PDFDocumentRequirements::Requirements requirementFlags = pdf::PDFDocumentRequirements::Requirements(pdf::PDFDocumentRequirements::OCInteract |
|
||||||
pdf::PDFDocumentRequirements::OCAutoStates |
|
pdf::PDFDocumentRequirements::OCAutoStates |
|
||||||
|
Reference in New Issue
Block a user