mirror of https://github.com/JakubMelka/PDF4QT.git
XFA: form pagination
This commit is contained in:
parent
38bc1f40fc
commit
ecd04a8668
|
@ -504,6 +504,7 @@ public:
|
|||
Annotation = 0x0002, ///< Annotations 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)
|
||||
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)
|
||||
|
|
|
@ -1515,6 +1515,7 @@ public:
|
|||
void markReset() { m_modificationFlags.setFlag(PDFModifiedDocument::Reset); }
|
||||
void markAnnotationsChanged() { m_modificationFlags.setFlag(PDFModifiedDocument::Annotation); }
|
||||
void markFormFieldChanged() { m_modificationFlags.setFlag(PDFModifiedDocument::FormField); }
|
||||
void markXFAPagination() { m_modificationFlags.setFlag(PDFModifiedDocument::XFA_Pagination); }
|
||||
|
||||
private:
|
||||
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()
|
||||
{
|
||||
qDeleteAll(m_widgetEditors);
|
||||
|
|
|
@ -687,6 +687,11 @@ public:
|
|||
QList<PDFRenderError>& errors,
|
||||
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; }
|
||||
|
||||
signals:
|
||||
|
|
|
@ -9679,8 +9679,11 @@ public:
|
|||
|
||||
using LayoutItems = std::vector<LayoutItem>;
|
||||
|
||||
void setLayoutItems(PDFInteger pageIndex, LayoutItems layoutItems) { m_layout.layoutItems[pageIndex] = std::move(layoutItems); }
|
||||
void setParagraphSettings(std::vector<xfa::XFA_ParagraphSettings> paragraphSettings) { m_layout.paragraphSettings = std::move(paragraphSettings); }
|
||||
std::vector<QSizeF> getPageSizes() const { return m_layout.pageSizes; }
|
||||
|
||||
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,
|
||||
const PDFPage* page,
|
||||
|
@ -9691,6 +9694,7 @@ private:
|
|||
|
||||
struct Layout
|
||||
{
|
||||
std::vector<QSizeF> pageSizes;
|
||||
std::map<PDFInteger, LayoutItems> layoutItems;
|
||||
std::vector<xfa::XFA_ParagraphSettings> paragraphSettings;
|
||||
};
|
||||
|
@ -10648,6 +10652,7 @@ void PDFXFALayoutEngine::performLayout(PDFXFAEngineImpl* engine, const xfa::XFA_
|
|||
|
||||
node->accept(this);
|
||||
|
||||
std::vector<QSizeF> pageSizes;
|
||||
std::map<PDFInteger, std::vector<Layout>> layoutPerPage;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
pageSizes.reserve(layoutPerPage.size());
|
||||
|
||||
PDFInteger pageIndex = 0;
|
||||
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->setPageSizes(std::move(pageSizes));
|
||||
engine->setParagraphSettings(std::move(m_paragraphSettings));
|
||||
}
|
||||
|
||||
|
@ -11364,6 +11375,11 @@ void PDFXFAEngine::setDocument(const PDFModifiedDocument& document, PDFForm* for
|
|||
m_impl->setDocument(document, form);
|
||||
}
|
||||
|
||||
std::vector<QSizeF> PDFXFAEngine::getPageSizes() const
|
||||
{
|
||||
return m_impl->getPageSizes();
|
||||
}
|
||||
|
||||
void PDFXFAEngine::draw(const QMatrix& pagePointToDevicePointMatrix,
|
||||
const PDFPage* page,
|
||||
QList<PDFRenderError>& errors,
|
||||
|
@ -11381,6 +11397,13 @@ PDFXFAEngineImpl::PDFXFAEngineImpl() :
|
|||
|
||||
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())
|
||||
{
|
||||
m_document = document;
|
||||
|
|
|
@ -38,6 +38,9 @@ public:
|
|||
|
||||
void setDocument(const PDFModifiedDocument& document, PDFForm* form);
|
||||
|
||||
/// Returns list of page sizes (after paging is complete)
|
||||
std::vector<QSizeF> getPageSizes() const;
|
||||
|
||||
/// Draws XFA form
|
||||
/// \param pagePointToDevicePointMatrix Page point to device point matrix
|
||||
/// \param page Page
|
||||
|
|
|
@ -1562,6 +1562,11 @@ void PDFProgramController::onDocumentReadingFinished()
|
|||
pdf::PDFModifiedDocument document(m_pdfDocument.data(), m_optionalContentActivity);
|
||||
setDocument(document);
|
||||
|
||||
if (m_formManager)
|
||||
{
|
||||
m_formManager->performPaging();
|
||||
}
|
||||
|
||||
pdf::PDFDocumentRequirements requirements = pdf::PDFDocumentRequirements::parse(&m_pdfDocument->getStorage(), m_pdfDocument->getCatalog()->getRequirements());
|
||||
constexpr pdf::PDFDocumentRequirements::Requirements requirementFlags = pdf::PDFDocumentRequirements::Requirements(pdf::PDFDocumentRequirements::OCInteract |
|
||||
pdf::PDFDocumentRequirements::OCAutoStates |
|
||||
|
|
Loading…
Reference in New Issue