2021-09-27 11:14:20 +02:00
|
|
|
// Copyright (C) 2021 Jakub Melka
|
|
|
|
//
|
|
|
|
// This file is part of PDF4QT.
|
|
|
|
//
|
|
|
|
// PDF4QT 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
|
|
|
|
// with the written consent of the copyright owner, any later version.
|
|
|
|
//
|
|
|
|
// PDF4QT 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 PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#ifndef PDFDOCUMENTMANIPULATOR_H
|
|
|
|
#define PDFDOCUMENTMANIPULATOR_H
|
|
|
|
|
|
|
|
#include "pdfdocument.h"
|
|
|
|
#include "pdfutils.h"
|
|
|
|
|
|
|
|
#include <QImage>
|
|
|
|
|
|
|
|
namespace pdf
|
|
|
|
{
|
|
|
|
|
|
|
|
/// Document page assembler/manipulator. Can assemble document(s) pages
|
|
|
|
/// to a new document, where pages are inserted/removed/moved, or joined
|
|
|
|
/// from another documents, or blank pages/image pages inserted. Document
|
|
|
|
/// is also optimized.
|
2023-12-04 20:04:40 +01:00
|
|
|
class PDF4QTLIBCORESHARED_EXPORT PDFDocumentManipulator
|
2021-09-27 11:14:20 +02:00
|
|
|
{
|
|
|
|
Q_DECLARE_TR_FUNCTIONS(pdf::PDFDocumentManipulator)
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit PDFDocumentManipulator() = default;
|
|
|
|
|
|
|
|
/// Selects outline creation mode, when multiple documents
|
|
|
|
/// are merged into one. For single document manipulation,
|
|
|
|
/// this has no meaning.
|
|
|
|
enum class OutlineMode
|
|
|
|
{
|
|
|
|
NoOutline,
|
|
|
|
Join,
|
|
|
|
DocumentParts
|
|
|
|
};
|
|
|
|
|
|
|
|
struct AssembledPage
|
|
|
|
{
|
|
|
|
PDFInteger documentIndex = -1; ///< Source document index. If page is not from a document, value is -1.
|
|
|
|
PDFInteger imageIndex = -1; ///< Source image index. If page is not from a image, value is -1.
|
|
|
|
PDFInteger pageIndex = -1; ///< Source document page index. If page is not from a document, value is -1.
|
|
|
|
QSizeF pageSize; ///< Unrotated page size
|
|
|
|
PageRotation pageRotation = PageRotation::None; ///< Page rotation
|
|
|
|
|
|
|
|
constexpr bool isDocumentPage() const { return documentIndex != -1; }
|
|
|
|
constexpr bool isImagePage() const { return imageIndex != -1; }
|
|
|
|
constexpr bool isBlankPage() const { return documentIndex == -1 && imageIndex == -1; }
|
|
|
|
};
|
|
|
|
|
|
|
|
using AssembledPages = std::vector<AssembledPage>;
|
|
|
|
|
|
|
|
/// Adds document with given index to available document list
|
|
|
|
/// \param documentIndex Document index
|
|
|
|
/// \param document Document
|
|
|
|
void addDocument(int documentIndex, const PDFDocument* document) { m_documents[documentIndex] = document; }
|
|
|
|
|
|
|
|
/// Adds image with given index to available image list
|
|
|
|
/// \param imageIndex Image index
|
|
|
|
/// \param image Image
|
|
|
|
void addImage(int imageIndex, QImage image) { m_images[imageIndex] = std::move(image); }
|
|
|
|
|
|
|
|
/// Assembles pages into a new document. Returns true, if a new document
|
|
|
|
/// was assembled, otherwise error message is being returned. Assebmled
|
|
|
|
/// document can be accessed trough a given getters.
|
|
|
|
/// \param pages Pages
|
|
|
|
/// \returns True or error message
|
|
|
|
PDFOperationResult assemble(const AssembledPages& pages);
|
|
|
|
|
|
|
|
/// Returns reference to an assembled document. This function should
|
|
|
|
/// be called only, if method \p assemble returns true, otherwise
|
|
|
|
/// undefined document can be returned.
|
|
|
|
/// \returns Assembled document
|
|
|
|
const PDFDocument& getAssembledDocument() const { return m_assembledDocument; }
|
|
|
|
|
|
|
|
/// Returns rvalue reference to an assembled document. This function should
|
|
|
|
/// be called only, if method \p assemble returns true, otherwise
|
|
|
|
/// undefined document can be returned.
|
|
|
|
/// \returns Assembled document
|
|
|
|
PDFDocument&& takeAssembledDocument() { return std::move(m_assembledDocument); }
|
|
|
|
|
2021-10-13 17:51:16 +02:00
|
|
|
static AssembledPages createAllDocumentPages(int documentIndex, const PDFDocument* document);
|
|
|
|
|
2021-09-27 11:14:20 +02:00
|
|
|
static constexpr AssembledPage createDocumentPage(int documentIndex, int pageIndex, QSizeF pageSize, PageRotation pageRotation) { return AssembledPage{ documentIndex, -1, pageIndex, pageSize, pageRotation}; }
|
|
|
|
static constexpr AssembledPage createImagePage(int imageIndex, QSizeF pageSize, PageRotation pageRotation) { return AssembledPage{ -1, imageIndex, -1, pageSize, pageRotation}; }
|
|
|
|
static constexpr AssembledPage createBlankPage(QSizeF pageSize, PageRotation pageRotation) { return AssembledPage{ -1, -1, -1, pageSize, pageRotation}; }
|
|
|
|
|
|
|
|
OutlineMode getOutlineMode() const;
|
|
|
|
void setOutlineMode(OutlineMode outlineMode);
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
struct ProcessedPage
|
|
|
|
{
|
|
|
|
AssembledPage assembledPage;
|
|
|
|
PDFObjectReference targetPageReference;
|
|
|
|
};
|
|
|
|
|
|
|
|
using ProcessedPages = std::vector<ProcessedPage>;
|
|
|
|
|
|
|
|
enum AssembleFlag
|
|
|
|
{
|
|
|
|
None = 0x0000,
|
|
|
|
SingleDocument = 0x0001, ///< We are assembling a single page document (possibly with blank pages / image pages
|
|
|
|
RemovedPages = 0x0002, ///< Document contains removed pages
|
|
|
|
};
|
|
|
|
Q_DECLARE_FLAGS(AssembleFlags, AssembleFlag)
|
|
|
|
|
|
|
|
enum MergedObjectType
|
|
|
|
{
|
|
|
|
MOT_OCProperties,
|
|
|
|
MOT_Form,
|
|
|
|
MOT_Names,
|
|
|
|
MOT_Last
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Processes pages given a page list and a document builder.
|
|
|
|
/// \param documentBuilder Document builder
|
|
|
|
/// \param pages Pages to be processed
|
|
|
|
/// \returns Processed pages
|
|
|
|
ProcessedPages processPages(PDFDocumentBuilder& documentBuilder, const AssembledPages& pages);
|
|
|
|
|
|
|
|
/// Collects objects and copies them into the target document builder.
|
|
|
|
/// \param documentBuilder Document builder
|
|
|
|
/// \param pages Pages to be copied
|
|
|
|
/// \returns Processed pages
|
|
|
|
ProcessedPages collectObjectsAndCopyPages(PDFDocumentBuilder& documentBuilder, const AssembledPages& pages);
|
|
|
|
|
|
|
|
void classify(const AssembledPages& pages);
|
|
|
|
void initializeMergedObjects(PDFDocumentBuilder& documentBuilder);
|
|
|
|
void finalizeMergedObjects(PDFDocumentBuilder& documentBuilder);
|
|
|
|
void finalizeDocument(PDFDocument* document);
|
|
|
|
void addOutlineAndDocumentParts(PDFDocumentBuilder& documentBuilder,
|
|
|
|
const AssembledPages& pages,
|
|
|
|
const std::vector<PDFObjectReference>& adjustedPages);
|
|
|
|
|
|
|
|
std::map<PDFInteger, const PDFDocument*> m_documents;
|
|
|
|
std::map<PDFInteger, QImage> m_images;
|
|
|
|
AssembleFlags m_flags = None;
|
|
|
|
std::array<PDFObjectReference, MOT_Last> m_mergedObjects = { };
|
|
|
|
PDFDocument m_assembledDocument;
|
|
|
|
OutlineMode m_outlineMode = OutlineMode::DocumentParts;
|
|
|
|
std::map<PDFInteger, PDFObjectReference> m_outlines;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace pdf
|
|
|
|
|
|
|
|
#endif // PDFDOCUMENTMANIPULATOR_H
|