mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	DocDiff application: create document report, overlay
This commit is contained in:
		@@ -26,6 +26,8 @@
 | 
			
		||||
#include "pdfdocumentreader.h"
 | 
			
		||||
#include "pdfdrawspacecontroller.h"
 | 
			
		||||
#include "pdfdocumentmanipulator.h"
 | 
			
		||||
#include "pdfdocumentbuilder.h"
 | 
			
		||||
#include "pdfdocumentwriter.h"
 | 
			
		||||
 | 
			
		||||
#include <QToolBar>
 | 
			
		||||
#include <QDesktopWidget>
 | 
			
		||||
@@ -65,6 +67,7 @@ MainWindow::MainWindow(QWidget* parent) :
 | 
			
		||||
    m_settingsDockWidget = new SettingsDockWidget(&m_settings, this);
 | 
			
		||||
    addDockWidget(Qt::LeftDockWidgetArea, m_settingsDockWidget);;
 | 
			
		||||
    connect(m_settingsDockWidget, &SettingsDockWidget::colorsChanged, this, &MainWindow::onColorsChanged);
 | 
			
		||||
    connect(m_settingsDockWidget, &SettingsDockWidget::transparencySliderChanged, this, &MainWindow::updateOverlayTransparency);
 | 
			
		||||
 | 
			
		||||
    m_differencesDockWidget = new DifferencesDockWidget(this, &m_diffResult, &m_filteredDiffResult, &m_diffNavigator, &m_settings);
 | 
			
		||||
    addDockWidget(Qt::LeftDockWidgetArea, m_differencesDockWidget);
 | 
			
		||||
@@ -171,6 +174,7 @@ MainWindow::MainWindow(QWidget* parent) :
 | 
			
		||||
 | 
			
		||||
    loadSettings();
 | 
			
		||||
    updateAll(false);
 | 
			
		||||
    updateOverlayTransparency();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MainWindow::~MainWindow()
 | 
			
		||||
@@ -403,8 +407,10 @@ bool MainWindow::canPerformOperation(Operation operation) const
 | 
			
		||||
            return m_diffNavigator.canGoNext();
 | 
			
		||||
 | 
			
		||||
        case Operation::CreateCompareReport:
 | 
			
		||||
        case Operation::ShowPageswithDifferences:
 | 
			
		||||
        case Operation::SaveDifferencesToXML:
 | 
			
		||||
            return m_filteredDiffResult.isChanged();
 | 
			
		||||
 | 
			
		||||
        case Operation::ShowPageswithDifferences:
 | 
			
		||||
            return m_diffResult.isChanged();
 | 
			
		||||
 | 
			
		||||
        case Operation::DisplayDifferences:
 | 
			
		||||
@@ -610,9 +616,31 @@ void MainWindow::performOperation(Operation operation)
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case Operation::CreateCompareReport:
 | 
			
		||||
            Q_ASSERT(false);
 | 
			
		||||
        {
 | 
			
		||||
            if (m_filteredDiffResult.isSame())
 | 
			
		||||
            {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save As"), m_settings.directory, tr("Portable Document (*.pdf);;All files (*.*)"));
 | 
			
		||||
            if (!saveFileName.isEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                pdf::PDFDocumentBuilder builder(m_pdfWidget->getDrawWidgetProxy()->getDocument());
 | 
			
		||||
                m_drawInterface.drawAnnotations(m_pdfWidget->getDrawWidgetProxy()->getDocument(), &builder);
 | 
			
		||||
 | 
			
		||||
                pdf::PDFDocument document = builder.build();
 | 
			
		||||
                pdf::PDFDocumentWriter writer(m_progress);
 | 
			
		||||
                pdf::PDFOperationResult result = writer.write(saveFileName, &document, QFile::exists(saveFileName));
 | 
			
		||||
                if (!result)
 | 
			
		||||
                {
 | 
			
		||||
                    QMessageBox::critical(this, tr("Error"), result.getErrorMessage());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
        {
 | 
			
		||||
@@ -765,6 +793,14 @@ void MainWindow::updateCustomPageLayout()
 | 
			
		||||
    m_pdfWidget->getDrawWidgetProxy()->setPageLayout(pdf::PageLayout::Custom);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::updateOverlayTransparency()
 | 
			
		||||
{
 | 
			
		||||
    const pdf::PDFReal value = m_settingsDockWidget->getTransparencySliderValue() * 0.01;
 | 
			
		||||
    m_pdfWidget->getDrawWidgetProxy()->setGroupTransparency(1, true, 1.0 - value);
 | 
			
		||||
    m_pdfWidget->getDrawWidgetProxy()->setGroupTransparency(2, false, value);
 | 
			
		||||
    m_pdfWidget->update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<pdf::PDFDocument> MainWindow::openDocument()
 | 
			
		||||
{
 | 
			
		||||
    QString fileName = QFileDialog::getOpenFileName(this, tr("Select PDF document"), m_settings.directory, tr("PDF document (*.pdf)"));
 | 
			
		||||
 
 | 
			
		||||
@@ -114,6 +114,7 @@ private:
 | 
			
		||||
    void updateFilteredResult();
 | 
			
		||||
    void updateViewDocument();
 | 
			
		||||
    void updateCustomPageLayout();
 | 
			
		||||
    void updateOverlayTransparency();
 | 
			
		||||
 | 
			
		||||
    std::optional<pdf::PDFDocument> openDocument();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,8 @@ SettingsDockWidget::SettingsDockWidget(Settings* settings, QWidget* parent) :
 | 
			
		||||
 | 
			
		||||
        connect(comboBox, &QComboBox::editTextChanged, this, &SettingsDockWidget::onEditColorChanged);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    connect(ui->transparencySlider, &QSlider::valueChanged, this, &SettingsDockWidget::transparencySliderChanged);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SettingsDockWidget::~SettingsDockWidget()
 | 
			
		||||
@@ -101,6 +103,11 @@ void SettingsDockWidget::loadColors()
 | 
			
		||||
    loadColor(ui->moveColorCombo, m_settings->colorPageMove);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SettingsDockWidget::getTransparencySliderValue() const
 | 
			
		||||
{
 | 
			
		||||
    return ui->transparencySlider->value();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QIcon SettingsDockWidget::getIconForColor(QColor color) const
 | 
			
		||||
{
 | 
			
		||||
    QIcon icon;
 | 
			
		||||
 
 | 
			
		||||
@@ -52,8 +52,11 @@ public:
 | 
			
		||||
    void loadColors();
 | 
			
		||||
    void saveColors();
 | 
			
		||||
 | 
			
		||||
    int getTransparencySliderValue() const;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
    void colorsChanged();
 | 
			
		||||
    void transparencySliderChanged(int value);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QIcon getIconForColor(QColor color) const;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    <x>0</x>
 | 
			
		||||
    <y>0</y>
 | 
			
		||||
    <width>548</width>
 | 
			
		||||
    <height>417</height>
 | 
			
		||||
    <height>511</height>
 | 
			
		||||
   </rect>
 | 
			
		||||
  </property>
 | 
			
		||||
  <property name="allowedAreas">
 | 
			
		||||
@@ -79,6 +79,31 @@
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item>
 | 
			
		||||
     <widget class="QGroupBox" name="overlayGroupBox">
 | 
			
		||||
      <property name="title">
 | 
			
		||||
       <string>Transparency | Overlay View</string>
 | 
			
		||||
      </property>
 | 
			
		||||
      <layout class="QVBoxLayout" name="verticalLayout_3">
 | 
			
		||||
       <item>
 | 
			
		||||
        <widget class="QSlider" name="transparencySlider">
 | 
			
		||||
         <property name="maximum">
 | 
			
		||||
          <number>100</number>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="value">
 | 
			
		||||
          <number>50</number>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="orientation">
 | 
			
		||||
          <enum>Qt::Horizontal</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
         <property name="tickPosition">
 | 
			
		||||
          <enum>QSlider::TicksAbove</enum>
 | 
			
		||||
         </property>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
     </widget>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item>
 | 
			
		||||
     <widget class="QGroupBox" name="colorsGroupBox">
 | 
			
		||||
      <property name="title">
 | 
			
		||||
 
 | 
			
		||||
@@ -16,8 +16,10 @@
 | 
			
		||||
//    along with PDF4QT.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include "pdfutils.h"
 | 
			
		||||
#include "pdfwidgetutils.h"
 | 
			
		||||
#include "pdfpainterutils.h"
 | 
			
		||||
#include "pdfdocumentbuilder.h"
 | 
			
		||||
 | 
			
		||||
#include <QPainter>
 | 
			
		||||
 | 
			
		||||
@@ -87,7 +89,7 @@ void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
 | 
			
		||||
                {
 | 
			
		||||
                    QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
 | 
			
		||||
                    QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    m_layout.emplace_back(0, i, rect);
 | 
			
		||||
                    m_layout.emplace_back(0, i, -1, rect);
 | 
			
		||||
                    yPos += pageSize.height() + 5;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -102,7 +104,7 @@ void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
 | 
			
		||||
 | 
			
		||||
                    QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
 | 
			
		||||
                    QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    m_layout.emplace_back(0, item.leftPage, rect);
 | 
			
		||||
                    m_layout.emplace_back(0, item.leftPage, -1, rect);
 | 
			
		||||
                    yPos += pageSize.height() + 5;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -126,7 +128,7 @@ void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
 | 
			
		||||
                {
 | 
			
		||||
                    QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
 | 
			
		||||
                    QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    m_layout.emplace_back(0, i, rect);
 | 
			
		||||
                    m_layout.emplace_back(0, i, -1, rect);
 | 
			
		||||
                    yPos += pageSize.height() + 5;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -141,7 +143,7 @@ void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
 | 
			
		||||
 | 
			
		||||
                    QSizeF pageSize = catalog->getPage(item.rightPage)->getRotatedMediaBoxMM().size();
 | 
			
		||||
                    QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    m_layout.emplace_back(0, item.rightPage, rect);
 | 
			
		||||
                    m_layout.emplace_back(0, item.rightPage, -1, rect);
 | 
			
		||||
                    yPos += pageSize.height() + 5;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
@@ -164,15 +166,20 @@ void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
 | 
			
		||||
                {
 | 
			
		||||
                    QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
 | 
			
		||||
                    QRectF rect;
 | 
			
		||||
                    pdf::PDFInteger groupIndex = -1;
 | 
			
		||||
                    if (mode == ComparedDocumentMapper::Mode::Combined)
 | 
			
		||||
                    {
 | 
			
		||||
                        rect = QRectF(-pageSize.width() - 5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if (item.rightPage != -1)
 | 
			
		||||
                        {
 | 
			
		||||
                            groupIndex = 1;
 | 
			
		||||
                        }
 | 
			
		||||
                        rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    }
 | 
			
		||||
                    m_layout.emplace_back(0, item.leftPage, rect);
 | 
			
		||||
                    m_layout.emplace_back(0, item.leftPage, groupIndex, rect);
 | 
			
		||||
                    yAdvance = pageSize.height() + 5;
 | 
			
		||||
                    m_leftPageIndices[item.leftPage] = item.leftPage;
 | 
			
		||||
                }
 | 
			
		||||
@@ -182,15 +189,20 @@ void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
 | 
			
		||||
                    pdf::PDFInteger rightPageIndex = item.rightPage + offset;
 | 
			
		||||
                    QSizeF pageSize = catalog->getPage(rightPageIndex)->getRotatedMediaBoxMM().size();
 | 
			
		||||
                    QRectF rect;
 | 
			
		||||
                    pdf::PDFInteger groupIndex = -1;
 | 
			
		||||
                    if (mode == ComparedDocumentMapper::Mode::Combined)
 | 
			
		||||
                    {
 | 
			
		||||
                        rect = QRectF(5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        if (item.leftPage != -1)
 | 
			
		||||
                        {
 | 
			
		||||
                            groupIndex = 2;
 | 
			
		||||
                        }
 | 
			
		||||
                        rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                    }
 | 
			
		||||
                    m_layout.emplace_back(0, rightPageIndex, rect);
 | 
			
		||||
                    m_layout.emplace_back(0, rightPageIndex, groupIndex, rect);
 | 
			
		||||
                    yAdvance = qMax(yAdvance, pageSize.height() + 5);
 | 
			
		||||
                    m_rightPageIndices[rightPageIndex] = item.rightPage;
 | 
			
		||||
                }
 | 
			
		||||
@@ -414,6 +426,69 @@ void DifferencesDrawInterface::drawPostRendering(QPainter* painter, QRect rect)
 | 
			
		||||
    Q_UNUSED(rect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DifferencesDrawInterface::drawAnnotations(const pdf::PDFDocument* document,
 | 
			
		||||
                                               pdf::PDFDocumentBuilder* builder)
 | 
			
		||||
{
 | 
			
		||||
    pdf::PDFInteger pageCount = document->getCatalog()->getPageCount();
 | 
			
		||||
 | 
			
		||||
    QString title = pdf::PDFSysUtils::getUserName();
 | 
			
		||||
    QString subject = tr("Difference");
 | 
			
		||||
 | 
			
		||||
    for (pdf::PDFInteger pageIndex = 0; pageIndex < pageCount; ++pageIndex)
 | 
			
		||||
    {
 | 
			
		||||
        const size_t differencesCount = m_diffResult->getDifferencesCount();
 | 
			
		||||
        const pdf::PDFInteger leftPageIndex = m_mapper->getLeftPageIndex(pageIndex);
 | 
			
		||||
        const pdf::PDFInteger rightPageIndex = m_mapper->getRightPageIndex(pageIndex);
 | 
			
		||||
 | 
			
		||||
        const pdf::PDFPage* page = document->getCatalog()->getPage(pageIndex);
 | 
			
		||||
        pdf::PDFObjectReference reference = page->getPageReference();
 | 
			
		||||
 | 
			
		||||
        if (leftPageIndex != -1)
 | 
			
		||||
        {
 | 
			
		||||
            for (size_t i = 0; i < differencesCount; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                auto leftRectangles = m_diffResult->getLeftRectangles(i);
 | 
			
		||||
                for (auto it = leftRectangles.first; it != leftRectangles.second; ++it)
 | 
			
		||||
                {
 | 
			
		||||
                    const auto& item = *it;
 | 
			
		||||
                    if (item.first == leftPageIndex)
 | 
			
		||||
                    {
 | 
			
		||||
                        QColor color = getColorForIndex(i);
 | 
			
		||||
                        const QRectF& rect = item.second;
 | 
			
		||||
                        QPolygonF polygon;
 | 
			
		||||
                        polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
 | 
			
		||||
                        pdf::PDFObjectReference annotation = builder->createAnnotationPolygon(reference, polygon, 1.0, color, color, title, subject, m_diffResult->getMessage(i));
 | 
			
		||||
                        builder->setAnnotationOpacity(annotation, 0.3);
 | 
			
		||||
                        builder->updateAnnotationAppearanceStreams(annotation);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (rightPageIndex != -1)
 | 
			
		||||
        {
 | 
			
		||||
            for (size_t i = 0; i < differencesCount; ++i)
 | 
			
		||||
            {
 | 
			
		||||
                auto rightRectangles = m_diffResult->getRightRectangles(i);
 | 
			
		||||
                for (auto it = rightRectangles.first; it != rightRectangles.second; ++it)
 | 
			
		||||
                {
 | 
			
		||||
                    const auto& item = *it;
 | 
			
		||||
                    if (item.first == rightPageIndex)
 | 
			
		||||
                    {
 | 
			
		||||
                        QColor color = getColorForIndex(i);
 | 
			
		||||
                        const QRectF& rect = item.second;
 | 
			
		||||
                        QPolygonF polygon;
 | 
			
		||||
                        polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
 | 
			
		||||
                        pdf::PDFObjectReference annotation = builder->createAnnotationPolygon(reference, polygon, 1.0, color, color, title, subject, m_diffResult->getMessage(i));
 | 
			
		||||
                        builder->setAnnotationOpacity(annotation, 0.3);
 | 
			
		||||
                        builder->updateAnnotationAppearanceStreams(annotation);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DifferencesDrawInterface::drawRectangle(QPainter* painter,
 | 
			
		||||
                                             const QMatrix& pagePointToDevicePointMatrix,
 | 
			
		||||
                                             const QRectF& rect,
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,13 @@
 | 
			
		||||
#include "pdfdrawspacecontroller.h"
 | 
			
		||||
#include "pdfdocumentdrawinterface.h"
 | 
			
		||||
 | 
			
		||||
#include <QtCore>
 | 
			
		||||
 | 
			
		||||
namespace pdf
 | 
			
		||||
{
 | 
			
		||||
class PDFDocumentBuilder;
 | 
			
		||||
}   // namespace pdf
 | 
			
		||||
 | 
			
		||||
namespace pdfdocdiff
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@@ -77,6 +84,8 @@ private:
 | 
			
		||||
 | 
			
		||||
class DifferencesDrawInterface : public pdf::IDocumentDrawInterface
 | 
			
		||||
{
 | 
			
		||||
    Q_DECLARE_TR_FUNCTIONS(pdfdocdiff::DifferencesDrawInterface)
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit DifferencesDrawInterface(const Settings* settings,
 | 
			
		||||
                                      const ComparedDocumentMapper* mapper,
 | 
			
		||||
@@ -87,8 +96,14 @@ public:
 | 
			
		||||
                          pdf::PDFTextLayoutGetter& layoutGetter,
 | 
			
		||||
                          const QMatrix& pagePointToDevicePointMatrix,
 | 
			
		||||
                          QList<pdf::PDFRenderError>& errors) const override;
 | 
			
		||||
 | 
			
		||||
    virtual void drawPostRendering(QPainter* painter, QRect rect) const override;
 | 
			
		||||
 | 
			
		||||
    /// Draw annotations for differences
 | 
			
		||||
    /// \param document Document
 | 
			
		||||
    /// \param builder Builder
 | 
			
		||||
    void drawAnnotations(const pdf::PDFDocument* document, pdf::PDFDocumentBuilder* builder);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void drawRectangle(QPainter* painter,
 | 
			
		||||
                       const QMatrix& pagePointToDevicePointMatrix,
 | 
			
		||||
 
 | 
			
		||||
@@ -195,7 +195,7 @@ void PDFDrawSpaceController::recalculate()
 | 
			
		||||
            QSizeF pageSize = PDFPage::getRotatedBox(catalog->getPage(leftIndex)->getRotatedMediaBoxMM(), m_pageRotation).size();
 | 
			
		||||
            PDFReal xPos = -pageSize.width() - m_horizontalSpacingMM * 0.5;
 | 
			
		||||
            QRectF rect(xPos, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
            m_layoutItems.emplace_back(blockIndex, leftIndex, rect);
 | 
			
		||||
            m_layoutItems.emplace_back(blockIndex, leftIndex, -1, rect);
 | 
			
		||||
            yPosAdvance = qMax(yPosAdvance, pageSize.height());
 | 
			
		||||
            boundingRect = boundingRect.united(rect);
 | 
			
		||||
        }
 | 
			
		||||
@@ -205,7 +205,7 @@ void PDFDrawSpaceController::recalculate()
 | 
			
		||||
            QSizeF pageSize = PDFPage::getRotatedBox(catalog->getPage(rightIndex)->getRotatedMediaBoxMM(), m_pageRotation).size();
 | 
			
		||||
            PDFReal xPos = m_horizontalSpacingMM * 0.5;
 | 
			
		||||
            QRectF rect(xPos, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
            m_layoutItems.emplace_back(blockIndex, rightIndex, rect);
 | 
			
		||||
            m_layoutItems.emplace_back(blockIndex, rightIndex, -1, rect);
 | 
			
		||||
            yPosAdvance = qMax(yPosAdvance, pageSize.height());
 | 
			
		||||
            boundingRect = boundingRect.united(rect);
 | 
			
		||||
        }
 | 
			
		||||
@@ -267,7 +267,7 @@ void PDFDrawSpaceController::recalculate()
 | 
			
		||||
            {
 | 
			
		||||
                QSizeF pageSize = PDFPage::getRotatedBox(catalog->getPage(i)->getRotatedMediaBoxMM(), m_pageRotation).size();
 | 
			
		||||
                QRectF rect(-pageSize.width() * 0.5, -pageSize.height() * 0.5, pageSize.width(), pageSize.height());
 | 
			
		||||
                m_layoutItems.emplace_back(i, i, rect);
 | 
			
		||||
                m_layoutItems.emplace_back(i, i, -1, rect);
 | 
			
		||||
                m_blockItems.emplace_back(rect);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -288,7 +288,7 @@ void PDFDrawSpaceController::recalculate()
 | 
			
		||||
                // Top of current page is at yPos.
 | 
			
		||||
                QSizeF pageSize = PDFPage::getRotatedBox(catalog->getPage(i)->getRotatedMediaBoxMM(), m_pageRotation).size();
 | 
			
		||||
                QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
 | 
			
		||||
                m_layoutItems.emplace_back(0, i, rect);
 | 
			
		||||
                m_layoutItems.emplace_back(0, i, -1, rect);
 | 
			
		||||
                yPos += pageSize.height() + m_verticalSpacingMM;
 | 
			
		||||
                boundingRectangle = boundingRectangle.united(rect);
 | 
			
		||||
            }
 | 
			
		||||
@@ -382,10 +382,10 @@ void PDFDrawSpaceController::recalculate()
 | 
			
		||||
            // We do not support page rotation for custom layout
 | 
			
		||||
            Q_ASSERT(m_pageRotation == PageRotation::None);
 | 
			
		||||
 | 
			
		||||
            // Assure, that layout items are sorted by block
 | 
			
		||||
            // Assure, that layout items are sorted by block and page group
 | 
			
		||||
            auto comparator = [](const LayoutItem& l, const LayoutItem& r)
 | 
			
		||||
            {
 | 
			
		||||
                return l.blockIndex < r.blockIndex;
 | 
			
		||||
                return std::tie(l.blockIndex, l.groupIndex) < std::tie(r.blockIndex, r.groupIndex);
 | 
			
		||||
            };
 | 
			
		||||
            std::stable_sort(m_layoutItems.begin(), m_layoutItems.end(), comparator);
 | 
			
		||||
 | 
			
		||||
@@ -566,7 +566,7 @@ void PDFDrawWidgetProxy::update()
 | 
			
		||||
        m_layout.items.reserve(items.size());
 | 
			
		||||
        for (const PDFDrawSpaceController::LayoutItem& item : items)
 | 
			
		||||
        {
 | 
			
		||||
            m_layout.items.emplace_back(item.pageIndex, fromDeviceSpace(item.pageRectMM).toRect());
 | 
			
		||||
            m_layout.items.emplace_back(item.pageIndex, item.groupIndex, fromDeviceSpace(item.pageRectMM).toRect());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        m_layout.blockRect = fromDeviceSpace(rectangle).toRect();
 | 
			
		||||
@@ -762,8 +762,13 @@ void PDFDrawWidgetProxy::drawPages(QPainter* painter, QRect rect, PDFRenderer::F
 | 
			
		||||
        QRect placedRect = item.pageRect.translated(m_horizontalOffset - m_layout.blockRect.left(), m_verticalOffset - m_layout.blockRect.top());
 | 
			
		||||
        if (placedRect.intersects(rect))
 | 
			
		||||
        {
 | 
			
		||||
            GroupInfo groupInfo = getGroupInfo(item.groupIndex);
 | 
			
		||||
 | 
			
		||||
            // Clear the page space by paper color
 | 
			
		||||
            painter->fillRect(placedRect, paperColor);
 | 
			
		||||
            if (groupInfo.drawPaper)
 | 
			
		||||
            {
 | 
			
		||||
                painter->fillRect(placedRect, paperColor);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const PDFPrecompiledPage* compiledPage = m_compiler->getCompiledPage(item.pageIndex, true);
 | 
			
		||||
            if (compiledPage && compiledPage->isValid())
 | 
			
		||||
@@ -773,7 +778,7 @@ void PDFDrawWidgetProxy::drawPages(QPainter* painter, QRect rect, PDFRenderer::F
 | 
			
		||||
 | 
			
		||||
                const PDFPage* page = m_controller->getDocument()->getCatalog()->getPage(item.pageIndex);
 | 
			
		||||
                QMatrix matrix = createPagePointToDevicePointMatrix(page, placedRect) * baseMatrix;
 | 
			
		||||
                compiledPage->draw(painter, page->getCropBox(), matrix, features);
 | 
			
		||||
                compiledPage->draw(painter, page->getCropBox(), matrix, features, groupInfo.transparency);
 | 
			
		||||
                PDFTextLayoutGetter layoutGetter = m_textLayoutCompiler->getTextLayoutLazy(item.pageIndex);
 | 
			
		||||
 | 
			
		||||
                // Draw text blocks/text lines, if it is enabled
 | 
			
		||||
@@ -1001,6 +1006,22 @@ PDFWidgetSnapshot PDFDrawWidgetProxy::getSnapshot() const
 | 
			
		||||
    return snapshot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PDFDrawWidgetProxy::setGroupTransparency(PDFInteger groupIndex, bool drawPaper, PDFReal transparency)
 | 
			
		||||
{
 | 
			
		||||
    GroupInfo groupInfo;
 | 
			
		||||
    groupInfo.drawPaper = drawPaper;
 | 
			
		||||
    groupInfo.transparency = transparency;
 | 
			
		||||
 | 
			
		||||
    if (groupInfo == GroupInfo())
 | 
			
		||||
    {
 | 
			
		||||
        m_groupInfos.erase(groupIndex);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_groupInfos[groupIndex] = std::move(groupInfo);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QRect PDFDrawWidgetProxy::getPagesIntersectingRectBoundingBox(QRect rect) const
 | 
			
		||||
{
 | 
			
		||||
    QRect resultRect;
 | 
			
		||||
@@ -1385,6 +1406,17 @@ void PDFDrawWidgetProxy::updateVerticalScrollbarFromOffset()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PDFDrawWidgetProxy::GroupInfo PDFDrawWidgetProxy::getGroupInfo(int groupIndex) const
 | 
			
		||||
{
 | 
			
		||||
    auto it = m_groupInfos.find(groupIndex);
 | 
			
		||||
    if (it != m_groupInfos.cend())
 | 
			
		||||
    {
 | 
			
		||||
        return it->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return GroupInfo();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PDFWidgetAnnotationManager* PDFDrawWidgetProxy::getAnnotationManager() const
 | 
			
		||||
{
 | 
			
		||||
    return m_widget->getAnnotationManager();
 | 
			
		||||
 
 | 
			
		||||
@@ -77,9 +77,9 @@ public:
 | 
			
		||||
    /// page and page rectangle, in which the page is contained.
 | 
			
		||||
    struct LayoutItem
 | 
			
		||||
    {
 | 
			
		||||
        constexpr inline explicit LayoutItem() : blockIndex(-1), pageIndex(-1) { }
 | 
			
		||||
        constexpr inline explicit LayoutItem(PDFInteger blockIndex, PDFInteger pageIndex, const QRectF& pageRectMM) :
 | 
			
		||||
            blockIndex(blockIndex), pageIndex(pageIndex), pageRectMM(pageRectMM) { }
 | 
			
		||||
        constexpr inline explicit LayoutItem() : blockIndex(-1), pageIndex(-1), groupIndex(-1) { }
 | 
			
		||||
        constexpr inline explicit LayoutItem(PDFInteger blockIndex, PDFInteger pageIndex, PDFInteger groupIndex, const QRectF& pageRectMM) :
 | 
			
		||||
            blockIndex(blockIndex), pageIndex(pageIndex), groupIndex(groupIndex), pageRectMM(pageRectMM) { }
 | 
			
		||||
 | 
			
		||||
        bool operator ==(const LayoutItem&) const = default;
 | 
			
		||||
 | 
			
		||||
@@ -87,6 +87,7 @@ public:
 | 
			
		||||
 | 
			
		||||
        PDFInteger blockIndex;
 | 
			
		||||
        PDFInteger pageIndex;
 | 
			
		||||
        PDFInteger groupIndex; ///< Page group index
 | 
			
		||||
        QRectF pageRectMM;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -371,6 +372,13 @@ public:
 | 
			
		||||
 | 
			
		||||
    /// Returns snapshot of current view area
 | 
			
		||||
    PDFWidgetSnapshot getSnapshot() const;
 | 
			
		||||
 | 
			
		||||
    /// Sets page group transparency settings. All pages with a given group index
 | 
			
		||||
    /// will be displayed with this transparency settings.
 | 
			
		||||
    /// \param groupIndex Group index
 | 
			
		||||
    /// \param drawPaper Draw background paper
 | 
			
		||||
    /// \param transparency Page graphics transparency
 | 
			
		||||
    void setGroupTransparency(PDFInteger groupIndex, bool drawPaper = true, PDFReal transparency = 1.0);
 | 
			
		||||
    
 | 
			
		||||
    PDFWidgetAnnotationManager* getAnnotationManager() const;
 | 
			
		||||
 | 
			
		||||
@@ -385,12 +393,13 @@ signals:
 | 
			
		||||
private:
 | 
			
		||||
    struct LayoutItem
 | 
			
		||||
    {
 | 
			
		||||
        constexpr inline explicit LayoutItem() : pageIndex(-1) { }
 | 
			
		||||
        constexpr inline explicit LayoutItem(PDFInteger pageIndex, const QRect& pageRect) :
 | 
			
		||||
            pageIndex(pageIndex), pageRect(pageRect) { }
 | 
			
		||||
        constexpr inline explicit LayoutItem() : pageIndex(-1), groupIndex(-1) { }
 | 
			
		||||
        constexpr inline explicit LayoutItem(PDFInteger pageIndex, PDFInteger groupIndex, const QRect& pageRect) :
 | 
			
		||||
            pageIndex(pageIndex), groupIndex(groupIndex), pageRect(pageRect) { }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        PDFInteger pageIndex;
 | 
			
		||||
        PDFInteger groupIndex; ///< Used to create group of pages (for transparency and overlay)
 | 
			
		||||
        QRect pageRect;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -406,6 +415,14 @@ private:
 | 
			
		||||
        QRect blockRect;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    struct GroupInfo
 | 
			
		||||
    {
 | 
			
		||||
        bool operator==(const GroupInfo&) const = default;
 | 
			
		||||
 | 
			
		||||
        bool drawPaper = true;
 | 
			
		||||
        PDFReal transparency = 1.0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t INVALID_BLOCK_INDEX = std::numeric_limits<size_t>::max();
 | 
			
		||||
 | 
			
		||||
    // Minimal/maximal zoom is from 8% to 6400 %, according to the PDF 1.7 Reference,
 | 
			
		||||
@@ -430,6 +447,8 @@ private:
 | 
			
		||||
    void updateHorizontalScrollbarFromOffset();
 | 
			
		||||
    void updateVerticalScrollbarFromOffset();
 | 
			
		||||
 | 
			
		||||
    GroupInfo getGroupInfo(int groupIndex) const;
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    struct Range
 | 
			
		||||
    {
 | 
			
		||||
@@ -518,6 +537,11 @@ private:
 | 
			
		||||
 | 
			
		||||
    /// Surface format for OpenGL
 | 
			
		||||
    QSurfaceFormat m_surfaceFormat;
 | 
			
		||||
 | 
			
		||||
    /// Page group info for rendering. Group of pages
 | 
			
		||||
    /// can be rendered with transparency or without paper
 | 
			
		||||
    /// as overlay.
 | 
			
		||||
    std::map<PDFInteger, GroupInfo> m_groupInfos;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}   // namespace pdf
 | 
			
		||||
 
 | 
			
		||||
@@ -501,13 +501,18 @@ void PDFPrecompiledPageGenerator::setCompositionMode(QPainter::CompositionMode m
 | 
			
		||||
    m_precompiledPage->addSetCompositionMode(mode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PDFPrecompiledPage::draw(QPainter* painter, const QRectF& cropBox, const QMatrix& pagePointToDevicePointMatrix, PDFRenderer::Features features) const
 | 
			
		||||
void PDFPrecompiledPage::draw(QPainter* painter,
 | 
			
		||||
                              const QRectF& cropBox,
 | 
			
		||||
                              const QMatrix& pagePointToDevicePointMatrix,
 | 
			
		||||
                              PDFRenderer::Features features,
 | 
			
		||||
                              PDFReal opacity) const
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(painter);
 | 
			
		||||
    Q_ASSERT(pagePointToDevicePointMatrix.isInvertible());
 | 
			
		||||
 | 
			
		||||
    painter->save();
 | 
			
		||||
    painter->setWorldMatrix(QMatrix());
 | 
			
		||||
    painter->setOpacity(opacity);
 | 
			
		||||
 | 
			
		||||
    if (features.testFlag(PDFRenderer::ClipToCropBox))
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -187,7 +187,12 @@ public:
 | 
			
		||||
    /// \param cropBox Page's crop box
 | 
			
		||||
    /// \param pagePointToDevicePointMatrix Page point to device point transformation matrix
 | 
			
		||||
    /// \param features Renderer features
 | 
			
		||||
    void draw(QPainter* painter, const QRectF& cropBox, const QMatrix& pagePointToDevicePointMatrix, PDFRenderer::Features features) const;
 | 
			
		||||
    /// \param opacity Opacity of page graphics
 | 
			
		||||
    void draw(QPainter* painter,
 | 
			
		||||
              const QRectF& cropBox,
 | 
			
		||||
              const QMatrix& pagePointToDevicePointMatrix,
 | 
			
		||||
              PDFRenderer::Features features,
 | 
			
		||||
              PDFReal opacity) const;
 | 
			
		||||
 | 
			
		||||
    /// Redact path - remove all content intersecting given path,
 | 
			
		||||
    /// and fill redact path with given color.
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,7 @@ PDFDocument PDFRedact::perform(Options options)
 | 
			
		||||
 | 
			
		||||
        QPainter* painter = contentStreamBuilder.begin(newPageReference);
 | 
			
		||||
        compiledPage.redact(redactPath, matrix, m_redactFillColor);
 | 
			
		||||
        compiledPage.draw(painter, QRectF(), matrix, PDFRenderer::None);
 | 
			
		||||
        compiledPage.draw(painter, QRectF(), matrix, PDFRenderer::None, 1.0);
 | 
			
		||||
        contentStreamBuilder.end(painter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -244,7 +244,7 @@ QImage PDFRasterizer::render(PDFInteger pageIndex,
 | 
			
		||||
                    QOpenGLPaintDevice device(size);
 | 
			
		||||
                    QPainter painter(&device);
 | 
			
		||||
                    painter.fillRect(QRect(QPoint(0, 0), size), compiledPage->getPaperColor());
 | 
			
		||||
                    compiledPage->draw(&painter, page->getCropBox(), matrix, features);
 | 
			
		||||
                    compiledPage->draw(&painter, page->getCropBox(), matrix, features, 1.0);
 | 
			
		||||
 | 
			
		||||
                    if (annotationManager)
 | 
			
		||||
                    {
 | 
			
		||||
@@ -276,7 +276,7 @@ QImage PDFRasterizer::render(PDFInteger pageIndex,
 | 
			
		||||
        image.fill(Qt::white);
 | 
			
		||||
 | 
			
		||||
        QPainter painter(&image);
 | 
			
		||||
        compiledPage->draw(&painter, page->getCropBox(), matrix, features);
 | 
			
		||||
        compiledPage->draw(&painter, page->getCropBox(), matrix, features, 1.0);
 | 
			
		||||
 | 
			
		||||
        if (annotationManager)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user