diff --git a/PdfForQtLib/sources/pdfutils.cpp b/PdfForQtLib/sources/pdfutils.cpp index bcf2307..4e32120 100644 --- a/PdfForQtLib/sources/pdfutils.cpp +++ b/PdfForQtLib/sources/pdfutils.cpp @@ -284,6 +284,12 @@ void PDFClosedIntervalSet::addInterval(PDFInteger low, PDFInteger high) normalize(); } +void PDFClosedIntervalSet::merge(const PDFClosedIntervalSet& other) +{ + m_intervals.insert(m_intervals.end(), other.m_intervals.cbegin(), other.m_intervals.cend()); + normalize(); +} + bool PDFClosedIntervalSet::isCovered(PDFInteger low, PDFInteger high) { PDFClosedIntervalSet temporary; diff --git a/PdfForQtLib/sources/pdfutils.h b/PdfForQtLib/sources/pdfutils.h index f2055c9..bb65382 100644 --- a/PdfForQtLib/sources/pdfutils.h +++ b/PdfForQtLib/sources/pdfutils.h @@ -604,6 +604,9 @@ public: /// \param value Value void addValue(PDFInteger value) { addInterval(value, value); } + /// Merge with other interval set + void merge(const PDFClosedIntervalSet& other); + /// Returns true, if given closed range is subset of /// this interval set. bool isCovered(PDFInteger low, PDFInteger high); diff --git a/PdfTool/PdfTool.pro b/PdfTool/PdfTool.pro index 06e0b6e..ad166f2 100644 --- a/PdfTool/PdfTool.pro +++ b/PdfTool/PdfTool.pro @@ -46,6 +46,7 @@ SOURCES += \ pdftoolinfo.cpp \ pdftoolinfojavascript.cpp \ pdftoolinfonameddestinations.cpp \ + pdftoolinfopageboxes.cpp \ pdftoolverifysignatures.cpp \ pdftoolxml.cpp @@ -65,5 +66,6 @@ HEADERS += \ pdftoolinfo.h \ pdftoolinfojavascript.h \ pdftoolinfonameddestinations.h \ + pdftoolinfopageboxes.h \ pdftoolverifysignatures.h \ pdftoolxml.h diff --git a/PdfTool/pdftoolinfopageboxes.cpp b/PdfTool/pdftoolinfopageboxes.cpp new file mode 100644 index 0000000..e6c7d7b --- /dev/null +++ b/PdfTool/pdftoolinfopageboxes.cpp @@ -0,0 +1,160 @@ +// Copyright (C) 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 . + +#include "pdftoolinfopageboxes.h" +#include "pdfutils.h" + +namespace pdftool +{ + +static PDFToolInfoPageBoxesApplication s_infoPageBoxesApplication; + +QString PDFToolInfoPageBoxesApplication::getStandardString(StandardString standardString) const +{ + switch (standardString) + { + case Command: + return "info-page-boxes"; + + case Name: + return PDFToolTranslationContext::tr("Info (page boxes)"); + + case Description: + return PDFToolTranslationContext::tr("Retrieve informations about page boxes in a document."); + + default: + Q_ASSERT(false); + break; + } + + return QString(); +} + +struct PDFPageBoxInfo +{ + bool operator==(const PDFPageBoxInfo& other) const + { + return mediaBox == other.mediaBox && + cropBox == other.cropBox && + bleedBox == other.bleedBox && + trimBox == other.trimBox && + artBox == other.artBox; + } + + pdf::PDFClosedIntervalSet pages; + QRectF mediaBox; + QRectF cropBox; + QRectF bleedBox; + QRectF trimBox; + QRectF artBox; +}; + +int PDFToolInfoPageBoxesApplication::execute(const PDFToolOptions& options) +{ + pdf::PDFDocument document; + QByteArray sourceData; + if (!readDocument(options, document, &sourceData)) + { + return ErrorDocumentReading; + } + + QString parseError; + std::vector pages = options.getPageRange(document.getCatalog()->getPageCount(), parseError, true); + + if (!parseError.isEmpty()) + { + PDFConsole::writeError(parseError, options.outputCodec); + return ErrorInvalidArguments; + } + + std::vector infos; + for (const pdf::PDFInteger pageIndex : pages) + { + const pdf::PDFPage* page = document.getCatalog()->getPage(pageIndex); + + PDFPageBoxInfo info; + info.mediaBox = page->getMediaBoxMM(); + info.cropBox = page->getCropBoxMM(); + info.bleedBox = page->getBleedBoxMM(); + info.trimBox = page->getTrimBoxMM(); + info.artBox = page->getArtBoxMM(); + + auto it = std::find(infos.begin(), infos.end(), info); + if (it != infos.end()) + { + it->pages.addValue(pageIndex + 1); + } + else + { + info.pages.addValue(pageIndex + 1); + infos.emplace_back(qMove(info)); + } + } + + QLocale locale; + + PDFOutputFormatter formatter(options.outputStyle, options.outputCodec); + formatter.beginDocument("info-page-boxes", PDFToolTranslationContext::tr("Page boxes in document %1").arg(options.document)); + + auto writeBox = [&formatter, &locale](const QString& name, const QString& title, const QRectF& rect) + { + formatter.beginTableRow(name); + formatter.writeTableColumn("title", title); + + if (rect.isValid()) + { + formatter.writeTableColumn("value", QString("[ %1 %2 %3 %4 ]").arg(locale.toString(rect.left()), locale.toString(rect.top()), locale.toString(rect.right()), locale.toString(rect.bottom()))); + } + else + { + formatter.writeTableColumn("value", "null"); + } + + formatter.endTableRow(); + }; + + for (const PDFPageBoxInfo& info : infos) + { + formatter.endl(); + formatter.beginTable("page-range", PDFToolTranslationContext::tr("Pages %1").arg(info.pages.toText())); + + formatter.beginTableHeaderRow("header"); + formatter.writeTableHeaderColumn("box", PDFToolTranslationContext::tr("Box"), Qt::AlignLeft); + formatter.writeTableHeaderColumn("value", PDFToolTranslationContext::tr("Value"), Qt::AlignLeft); + formatter.endTableHeaderRow(); + + writeBox("media", PDFToolTranslationContext::tr("Media"), info.mediaBox); + writeBox("crop", PDFToolTranslationContext::tr("Crop"), info.cropBox); + writeBox("bleed", PDFToolTranslationContext::tr("Bleed"), info.bleedBox); + writeBox("trim", PDFToolTranslationContext::tr("Trim"), info.trimBox); + writeBox("art", PDFToolTranslationContext::tr("Art"), info.artBox); + + formatter.endTable(); + } + + formatter.endDocument(); + PDFConsole::writeText(formatter.getString(), options.outputCodec); + + return ExitSuccess; +} + +PDFToolAbstractApplication::Options PDFToolInfoPageBoxesApplication::getOptionsFlags() const +{ + return ConsoleFormat | OpenDocument | PageSelector; +} + +} // namespace pdftool diff --git a/PdfTool/pdftoolinfopageboxes.h b/PdfTool/pdftoolinfopageboxes.h new file mode 100644 index 0000000..73d3f12 --- /dev/null +++ b/PdfTool/pdftoolinfopageboxes.h @@ -0,0 +1,37 @@ +// Copyright (C) 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 PDFTOOLINFOPAGEBOXES_H +#define PDFTOOLINFOPAGEBOXES_H + +#include "pdftoolabstractapplication.h" + +namespace pdftool +{ + +class PDFToolInfoPageBoxesApplication : public PDFToolAbstractApplication +{ +public: + virtual QString getStandardString(StandardString standardString) const override; + virtual int execute(const PDFToolOptions& options) override; + virtual Options getOptionsFlags() const override; +}; + +} // namespace pdftool + + +#endif // PDFTOOLINFOPAGEBOXES_H