Introduce a paged paintdevice and use it

Introduce a QPagedPaintDevice class that has a
newPage() method and page dimensions. QPdfWriter
and QPrinter inherit from it.
Add a bit of API to QPdfWriter.

Change-Id: Ibf23e7fe741f3a5ed854faf5d249a272acc75f35
Reviewed-on: http://codereview.qt.nokia.com/3206
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
This commit is contained in:
Lars Knoll 2011-08-17 11:26:51 +02:00
parent 64f94fa373
commit 9ebdc333a6
13 changed files with 409 additions and 89 deletions

View File

@ -11,6 +11,7 @@ HEADERS += \
painting/qmatrix.h \
painting/qmemrotate_p.h \
painting/qoutlinemapper_p.h \
painting/qpagedpaintdevice.h \
painting/qpaintdevice.h \
painting/qpaintengine.h \
painting/qpaintengine_p.h \
@ -50,6 +51,7 @@ SOURCES += \
painting/qmatrix.cpp \
painting/qmemrotate.cpp \
painting/qoutlinemapper.cpp \
painting/qpagedpaintdevice.cpp \
painting/qpaintdevice.cpp \
painting/qpaintdevice_qpa.cpp \
painting/qpaintengine.cpp \

View File

@ -0,0 +1,203 @@
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qpagedpaintdevice.h>
class QPagedPaintDevicePrivate
{
public:
QPagedPaintDevice::PageSize pageSize;
QSizeF pageSizeMM;
};
static const struct {
float width;
float height;
} pageSizes[] = {
{210, 297}, // A4
{176, 250}, // B5
{215.9f, 279.4f}, // Letter
{215.9f, 355.6f}, // Legal
{190.5f, 254}, // Executive
{841, 1189}, // A0
{594, 841}, // A1
{420, 594}, // A2
{297, 420}, // A3
{148, 210}, // A5
{105, 148}, // A6
{74, 105}, // A7
{52, 74}, // A8
{37, 52}, // A8
{1000, 1414}, // B0
{707, 1000}, // B1
{31, 44}, // B10
{500, 707}, // B2
{353, 500}, // B3
{250, 353}, // B4
{125, 176}, // B6
{88, 125}, // B7
{62, 88}, // B8
{33, 62}, // B9
{163, 229}, // C5E
{105, 241}, // US Common
{110, 220}, // DLE
{210, 330}, // Folio
{431.8f, 279.4f}, // Ledger
{279.4f, 431.8f} // Tabloid
};
/*!
\class QPagedPaintDevice
\brief The QPagedPaintDevice class is a represents a paintdevice that supports
multiple pages.
\ingroup painting
Paged paint devices are used to generate output for printing or for formats like PDF.
QPdfWriter and QPrinter inherit from it.
*/
/*!
Constructs a new paged paint device.
*/
QPagedPaintDevice::QPagedPaintDevice()
: d(new QPagedPaintDevicePrivate)
{
setPageSize(A4);
}
/*!
Destroys the object.
*/
QPagedPaintDevice::~QPagedPaintDevice()
{
delete d;
}
/*!
\enum QPagedPaintDevice::PageSize
This enum type specifies the page size of the paint device.
\value A0 841 x 1189 mm
\value A1 594 x 841 mm
\value A2 420 x 594 mm
\value A3 297 x 420 mm
\value A4 210 x 297 mm, 8.26 x 11.69 inches
\value A5 148 x 210 mm
\value A6 105 x 148 mm
\value A7 74 x 105 mm
\value A8 52 x 74 mm
\value A9 37 x 52 mm
\value B0 1000 x 1414 mm
\value B1 707 x 1000 mm
\value B2 500 x 707 mm
\value B3 353 x 500 mm
\value B4 250 x 353 mm
\value B5 176 x 250 mm, 6.93 x 9.84 inches
\value B6 125 x 176 mm
\value B7 88 x 125 mm
\value B8 62 x 88 mm
\value B9 33 x 62 mm
\value B10 31 x 44 mm
\value C5E 163 x 229 mm
\value Comm10E 105 x 241 mm, U.S. Common 10 Envelope
\value DLE 110 x 220 mm
\value Executive 7.5 x 10 inches, 190.5 x 254 mm
\value Folio 210 x 330 mm
\value Ledger 431.8 x 279.4 mm
\value Legal 8.5 x 14 inches, 215.9 x 355.6 mm
\value Letter 8.5 x 11 inches, 215.9 x 279.4 mm
\value Tabloid 279.4 x 431.8 mm
\value Custom Unknown, or a user defined size.
\omitvalue NPageSize
The page size can also be specified in millimeters using setPageSizeMM(). In this case the
page size enum is set to Custom.
*/
/*!
\fn bool QPagedPaintDevice::newPage()
Starts a new page.
*/
/*!
Sets the size of the a page to \a size.
\sa setPageSizeMM
*/
void QPagedPaintDevice::setPageSize(PageSize size)
{
if (size >= Custom)
return;
d->pageSize = size;
d->pageSizeMM = QSizeF(pageSizes[A4].width, pageSizes[A4].height);
}
/*!
Returns the currently used page size.
*/
QPagedPaintDevice::PageSize QPagedPaintDevice::pageSize() const
{
return d->pageSize;
}
/*!
Sets the page size to \a size. \a size is specified in millimeters.
*/
void QPagedPaintDevice::setPageSizeMM(const QSizeF &size)
{
d->pageSize = Custom;
d->pageSizeMM = size;
}
/*!
Returns the page size in millimeters.
*/
QSizeF QPagedPaintDevice::pageSizeMM() const
{
return d->pageSizeMM;
}

View File

@ -0,0 +1,42 @@
#ifndef QPAGEDPAINTDEVICE_H
#define QPAGEDPAINTDEVICE_H
#include <QtGui/qpaintdevice.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
class QPagedPaintDevicePrivate;
class Q_GUI_EXPORT QPagedPaintDevice : public QPaintDevice
{
public:
QPagedPaintDevice();
~QPagedPaintDevice();
virtual bool newPage() = 0;
enum PageSize { A4, B5, Letter, Legal, Executive,
A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1,
B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E,
DLE, Folio, Ledger, Tabloid, Custom, NPageSize = Custom };
virtual void setPageSize(PageSize size);
PageSize pageSize() const;
virtual void setPageSizeMM(const QSizeF &size);
QSizeF pageSizeMM() const;
private:
QPagedPaintDevicePrivate *d;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View File

@ -1463,7 +1463,7 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
QPdfEnginePrivate::QPdfEnginePrivate()
: clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false),
outDevice(0), fd(-1),
outDevice(0), ownsDevice(false),
fullPage(false), embedFonts(true),
landscape(false),
grayscale(false),
@ -1497,6 +1497,7 @@ bool QPdfEngine::begin(QPaintDevice *pdev)
} else {
return false;
}
d->ownsDevice = true;
}
d->postscript = false;
@ -1543,15 +1544,8 @@ bool QPdfEngine::end()
delete d->currentPage;
d->currentPage = 0;
if (d->outDevice) {
if (d->outDevice && d->ownsDevice) {
d->outDevice->close();
if (d->fd >= 0)
#if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400
::_close(d->fd);
#else
::close(d->fd);
#endif
d->fd = -1;
delete d->outDevice;
d->outDevice = 0;
}

View File

@ -161,12 +161,13 @@ public:
private:
};
class QPdfWriter;
class QPdfEnginePrivate;
class QPdfEngine : public QPaintEngine
{
Q_DECLARE_PRIVATE(QPdfEngine)
friend class QPdfWriter;
public:
QPdfEngine();
QPdfEngine(QPdfEnginePrivate &d);
@ -266,7 +267,7 @@ public:
// the device the output is in the end streamed to.
QIODevice *outDevice;
int fd;
bool ownsDevice;
// printer options
QString outputFileName;

View File

@ -64,6 +64,21 @@ public:
QFile *output;
};
/*! \class QPdfWriter
\brief The QPdfWriter class is a class to generate PDFs
that can be used as a paint device.
\ingroup painting
QPdfWriter generates PDF out of a series of drawing commands using QPainter.
The newPage() method can be used to create several pages.
*/
/*!
Constructs a PDF writer that will write the pdf to \a filename.
*/
QPdfWriter::QPdfWriter(const QString &filename)
: QObject(*new QPdfWriterPrivate)
{
@ -72,20 +87,65 @@ QPdfWriter::QPdfWriter(const QString &filename)
d->engine->setOutputFilename(filename);
}
/*!
Constructs a PDF writer that will write the pdf to \a device.
*/
QPdfWriter::QPdfWriter(QIODevice *device)
: QObject(*new QPdfWriterPrivate)
{
Q_D(QPdfWriter);
// ####
// d->engine->setDevice(device);
d->engine->d_func()->outDevice = device;
}
/*!
Destroys the pdf writer.
*/
QPdfWriter::~QPdfWriter()
{
}
/*!
Returns the title of the document.
*/
QString QPdfWriter::title() const
{
Q_D(const QPdfWriter);
return d->engine->d_func()->title;
}
/*!
Sets the title of the document being created.
*/
void QPdfWriter::setTitle(const QString &title)
{
Q_D(QPdfWriter);
d->engine->d_func()->title = title;
}
/*!
Returns the creator of the document.
*/
QString QPdfWriter::creator() const
{
Q_D(const QPdfWriter);
return d->engine->d_func()->creator;
}
/*!
Sets the creator of the document.
*/
void QPdfWriter::setCreator(const QString &creator)
{
Q_D(QPdfWriter);
d->engine->d_func()->creator = creator;
}
/*!
\reimp
*/
QPaintEngine *QPdfWriter::paintEngine() const
{
Q_D(const QPdfWriter);
@ -93,6 +153,28 @@ QPaintEngine *QPdfWriter::paintEngine() const
return d->engine;
}
/*!
\reimp
*/
void QPdfWriter::setPageSize(PageSize size)
{
Q_D(const QPdfWriter);
QPagedPaintDevice::setPageSize(size);
d->engine->d_func()->paperSize = pageSizeMM() * 25.4/72.;
}
/*!
\reimp
*/
void QPdfWriter::setPageSizeMM(const QSizeF &size)
{
Q_D(const QPdfWriter);
QPagedPaintDevice::setPageSizeMM(size);
d->engine->d_func()->paperSize = pageSizeMM() * 25.4/72.;
}
/*!
\internal
@ -104,9 +186,12 @@ int QPdfWriter::metric(PaintDeviceMetric id) const
return d->engine->metric(id);
}
void QPdfWriter::newPage()
/*!
\reimp
*/
bool QPdfWriter::newPage()
{
Q_D(QPdfWriter);
d->engine->newPage();
return d->engine->newPage();
}

View File

@ -43,7 +43,7 @@
#define QPDFWRITER_H
#include <QtCore/qobject.h>
#include <QtCore/qiodevice.h>
#include <QtGui/qpagedpaintdevice.h>
QT_BEGIN_HEADER
@ -53,7 +53,7 @@ QT_MODULE(Gui)
class QPdfWriterPrivate;
class Q_GUI_EXPORT QPdfWriter : public QObject, public QPaintDevice
class Q_GUI_EXPORT QPdfWriter : public QObject, public QPagedPaintDevice
{
Q_OBJECT
public:
@ -61,7 +61,16 @@ public:
QPdfWriter(QIODevice *device);
~QPdfWriter();
void newPage();
QString title() const;
void setTitle(const QString &title);
QString creator() const;
void setCreator(const QString &creator);
bool newPage();
void setPageSize(PageSize size);
void setPageSizeMM(const QSizeF &size);
protected:
QPaintEngine *paintEngine() const;

View File

@ -67,7 +67,7 @@ extern QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size);
#define Q_MM(n) int((n * 720 + 127) / 254)
#define Q_IN(n) int(n * 72)
static const char * const psToStr[QPrinter::NPaperSize+1] =
static const char * const psToStr[QPrinter::NPageSize+1] =
{
"A4", "B5", "Letter", "Legal", "Executive",
"A0", "A1", "A2", "A3", "A5", "A6", "A7", "A8", "A9", "B0", "B1",
@ -526,6 +526,19 @@ bool QPdfPrintEnginePrivate::openPrintDevice()
void QPdfPrintEnginePrivate::closePrintDevice()
{
if (outDevice) {
outDevice->close();
if (fd >= 0)
#if defined(Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400
::_close(fd);
#else
::close(fd);
#endif
fd = -1;
delete outDevice;
outDevice = 0;
}
#if !defined(QT_NO_CUPS) && !defined(QT_NO_LIBRARY)
if (!cupsTempFile.isEmpty()) {
QString tempFile = cupsTempFile;
@ -615,7 +628,8 @@ QPdfPrintEnginePrivate::QPdfPrintEnginePrivate(QPrinter::PrinterMode m)
copies(1),
pageOrder(QPrinter::FirstPageFirst),
paperSource(QPrinter::Auto),
printerPaperSize(QPrinter::A4)
printerPaperSize(QPrinter::A4),
fd(-1)
{
resolution = 72;
if (m == QPrinter::HighResolution)

View File

@ -154,6 +154,8 @@ private:
QRect cupsPaperRect;
QRect cupsPageRect;
QSizeF customPaperSize; // in postscript points
int fd;
};
QT_END_NAMESPACE

View File

@ -392,47 +392,6 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
\value PrintPageRange
*/
/*!
\enum QPrinter::PageSize
\obsolete
Use QPrinter::PaperSize instead.
\value A0 841 x 1189 mm
\value A1 594 x 841 mm
\value A2 420 x 594 mm
\value A3 297 x 420 mm
\value A4 210 x 297 mm, 8.26 x 11.69 inches
\value A5 148 x 210 mm
\value A6 105 x 148 mm
\value A7 74 x 105 mm
\value A8 52 x 74 mm
\value A9 37 x 52 mm
\value B0 1030 x 1456 mm
\value B1 728 x 1030 mm
\value B10 32 x 45 mm
\value B2 515 x 728 mm
\value B3 364 x 515 mm
\value B4 257 x 364 mm
\value B5 182 x 257 mm, 7.17 x 10.13 inches
\value B6 128 x 182 mm
\value B7 91 x 128 mm
\value B8 64 x 91 mm
\value B9 45 x 64 mm
\value C5E 163 x 229 mm
\value Comm10E 105 x 241 mm, U.S. Common 10 Envelope
\value DLE 110 x 220 mm
\value Executive 7.5 x 10 inches, 191 x 254 mm
\value Folio 210 x 330 mm
\value Ledger 432 x 279 mm
\value Legal 8.5 x 14 inches, 216 x 356 mm
\value Letter 8.5 x 11 inches, 216 x 279 mm
\value Tabloid 279 x 432 mm
\value Custom Unknown, or a user defined size.
\omitvalue NPageSize
*/
/*!
\enum QPrinter::PaperSize
\since 4.4
@ -591,7 +550,7 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke
Creates a new printer object with the given \a mode.
*/
QPrinter::QPrinter(PrinterMode mode)
: QPaintDevice(),
: QPagedPaintDevice(),
d_ptr(new QPrinterPrivate(this))
{
init(mode);
@ -611,7 +570,7 @@ QPrinter::QPrinter(PrinterMode mode)
Creates a new printer object with the given \a printer and \a mode.
*/
QPrinter::QPrinter(const QPrinterInfo& printer, PrinterMode mode)
: QPaintDevice(),
: QPagedPaintDevice(),
d_ptr(new QPrinterPrivate(this))
{
init(mode);
@ -1082,16 +1041,7 @@ QPrinter::PaperSize QPrinter::paperSize() const
*/
void QPrinter::setPaperSize(PaperSize newPaperSize)
{
Q_D(QPrinter);
if (d->paintEngine->type() != QPaintEngine::Pdf)
ABORT_IF_ACTIVE("QPrinter::setPaperSize");
if (newPaperSize < 0 || newPaperSize >= NPaperSize) {
qWarning("QPrinter::setPaperSize: Illegal paper size %d", newPaperSize);
return;
}
d->printEngine->setProperty(QPrintEngine::PPK_PaperSize, newPaperSize);
d->addToManualSetList(QPrintEngine::PPK_PaperSize);
d->hasUserSetPageSize = true;
setPageSize(newPaperSize);
}
/*!
@ -1117,7 +1067,18 @@ QPrinter::PageSize QPrinter::pageSize() const
void QPrinter::setPageSize(PageSize newPageSize)
{
setPaperSize(newPageSize);
QPagedPaintDevice::setPageSize(newPageSize);
Q_D(QPrinter);
if (d->paintEngine->type() != QPaintEngine::Pdf)
ABORT_IF_ACTIVE("QPrinter::setPaperSize");
if (newPageSize < 0 || newPageSize >= NPageSize) {
qWarning("QPrinter::setPaperSize: Illegal paper size %d", newPageSize);
return;
}
d->printEngine->setProperty(QPrintEngine::PPK_PaperSize, newPageSize);
d->addToManualSetList(QPrintEngine::PPK_PaperSize);
d->hasUserSetPageSize = true;
}
/*!
@ -1134,8 +1095,21 @@ void QPrinter::setPaperSize(const QSizeF &paperSize, QPrinter::Unit unit)
if (d->paintEngine->type() != QPaintEngine::Pdf)
ABORT_IF_ACTIVE("QPrinter::setPaperSize");
const qreal multiplier = qt_multiplierForUnit(unit, resolution());
QSizeF size(paperSize.width() * multiplier, paperSize.height() * multiplier);
d->printEngine->setProperty(QPrintEngine::PPK_CustomPaperSize, size);
QSizeF size(paperSize.width() * multiplier * 25.4/72., paperSize.height() * multiplier * 25.4/72.);
setPageSizeMM(size);
}
/*!
\reimp
*/
void QPrinter::setPageSizeMM(const QSizeF &size)
{
Q_D(QPrinter);
QPagedPaintDevice::setPageSizeMM(size);
QSizeF s = size * 72./25.4;
d->printEngine->setProperty(QPrintEngine::PPK_CustomPaperSize, s);
d->addToManualSetList(QPrintEngine::PPK_CustomPaperSize);
d->hasUserSetPageSize = true;
}
@ -2263,7 +2237,7 @@ QSizeF qt_paperSizeToQSizeF(QPrinter::PaperSize size)
*/
QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size)
{
for (int i = 0; i < static_cast<int>(QPrinter::NPaperSize); ++i) {
for (int i = 0; i < static_cast<int>(QPrinter::NPageSize); ++i) {
if (qt_paperSizes[i][0] >= size.width() - 1 &&
qt_paperSizes[i][0] <= size.width() + 1 &&
qt_paperSizes[i][1] >= size.height() - 1 &&

View File

@ -44,7 +44,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qscopedpointer.h>
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpagedpaintdevice.h>
QT_BEGIN_HEADER
@ -63,7 +63,7 @@ class QPaintEngine;
class QPrintEngine;
class QPrinterInfo;
class Q_GUI_EXPORT QPrinter : public QPaintDevice
class Q_GUI_EXPORT QPrinter : public QPagedPaintDevice
{
Q_DECLARE_PRIVATE(QPrinter)
public:
@ -78,16 +78,8 @@ public:
enum Orientation { Portrait, Landscape };
#ifndef Q_QDOC
enum PageSize { A4, B5, Letter, Legal, Executive,
A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1,
B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E,
DLE, Folio, Ledger, Tabloid, Custom, NPageSize = Custom, NPaperSize = Custom };
typedef PageSize PaperSize;
#else
enum PageSize { A4, B5, Letter, Legal, Executive,
A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1,
B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E,
DLE, Folio, Ledger, Tabloid, Custom, NPageSize = Custom };
enum PaperSize { A4, B5, Letter, Legal, Executive,
A0, A1, A2, A3, A5, A6, A7, A8, A9, B0, B1,
B10, B2, B3, B4, B6, B7, B8, B9, C5E, Comm10E,
@ -169,6 +161,8 @@ public:
void setPageSize(PageSize);
PageSize pageSize() const;
void setPageSizeMM(const QSizeF &size);
void setPaperSize(PaperSize);
PaperSize paperSize() const;

View File

@ -367,7 +367,7 @@ void QPageSetupWidget::setupPrinter() const
QRect paperRect = m_cups->paperRect(cupsPageSize);
engine->setProperty(PPK_CupsPaperRect, paperRect);
for(ps = 0; ps < QPrinter::NPaperSize; ++ps) {
for(ps = 0; ps < QPrinter::NPageSize; ++ps) {
QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps));
if (size.width == paperRect.width() && size.height == paperRect.height())
break;

View File

@ -970,7 +970,7 @@ void QUnixPrintWidgetPrivate::setCupsProperties()
QRect paperRect = cups->paperRect(cupsPageSize);
engine->setProperty(PPK_CupsPaperRect, paperRect);
for (int ps = 0; ps < QPrinter::NPaperSize; ++ps) {
for (int ps = 0; ps < QPrinter::NPageSize; ++ps) {
QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps));
if (size.width == paperRect.width() && size.height == paperRect.height())
printer->setPaperSize(static_cast<QPrinter::PaperSize>(ps));