summaryrefslogtreecommitdiff
path: root/src/core/printing/printer_worker.cpp
blob: da71656236d7ec625ac9ba47be321b2b4818ea4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#include "printer_worker.h"

#include "printing/pdfium_document_wrapper_qt.h"

#include <QPainter>
#include <QPagedPaintDevice>

namespace QtWebEngineCore {

PrinterWorker::PrinterWorker(QSharedPointer<QByteArray> data, QPagedPaintDevice *device)
    : m_data(data), m_device(device)
{
}

PrinterWorker::~PrinterWorker() { }

void PrinterWorker::print()
{
    if (!m_data->size()) {
        qWarning("Failed to print: Print result data is empty.");
        Q_EMIT resultReady(false);
        return;
    }

    PdfiumDocumentWrapperQt pdfiumWrapper(m_data->constData(), m_data->size());

    const QPageRanges ranges = m_device->pageRanges();
    int toPage = ranges.firstPage();
    int fromPage = ranges.lastPage();
    bool ascendingOrder = true;

    if (fromPage == 0 && toPage == 0) {
        fromPage = 1;
        toPage = pdfiumWrapper.pageCount();
    }
    fromPage = qMax(1, fromPage);
    toPage = qMin(pdfiumWrapper.pageCount(), toPage);

    if (!m_firstPageFirst) {
        qSwap(fromPage, toPage);
        ascendingOrder = false;
    }

    int pageCopies = 1;
    if (m_collateCopies) {
        pageCopies = m_documentCopies;
        m_documentCopies = 1;
    }

    qreal resolution = m_deviceResolution / 72.0; // pdfium uses points so 1/72 inch

    QPainter painter;

    for (int printedDocuments = 0; printedDocuments < m_documentCopies; printedDocuments++) {
        if (printedDocuments > 0)
            m_device->newPage();

        int currentPageIndex = fromPage;

        for (int i = 0; true; i++) {
            QSizeF documentSize = (pdfiumWrapper.pageSize(currentPageIndex - 1) * resolution);
            bool isLandscape = documentSize.width() > documentSize.height();
            m_device->setPageOrientation(isLandscape ? QPageLayout::Landscape
                                                      : QPageLayout::Portrait);
            QRectF paintRect = m_device->pageLayout().paintRectPixels(m_deviceResolution);
            documentSize = documentSize.scaled(paintRect.size(), Qt::KeepAspectRatio);

            // setPageOrientation has to be called before qpainter.begin() or before
            // qprinter.newPage() so correct metrics is used, therefore call begin now for only
            // first page
            if (!painter.isActive() && !painter.begin(m_device)) {
                qWarning("Failure to print on device: Could not open printer for painting.");
                Q_EMIT resultReady(false);
                return;
            }

            if (i > 0)
                m_device->newPage();

            for (int printedPages = 0; printedPages < pageCopies; printedPages++) {
                if (printedPages > 0)
                    m_device->newPage();

                QImage currentImage = pdfiumWrapper.pageAsQImage(
                        currentPageIndex - 1, documentSize.width(), documentSize.height());
                if (currentImage.isNull()) {
                    Q_EMIT resultReady(false);
                    return;
                }
                painter.drawImage(0, 0, currentImage);
            }

            if (currentPageIndex == toPage)
                break;

            if (ascendingOrder)
                currentPageIndex++;
            else
                currentPageIndex--;
        }
    }
    painter.end();

    Q_EMIT resultReady(true);
    return;
}

} // namespace QtWebEngineCore