Improve PDF/A-1b support in QPdfWriter
Add new enum QPrinter::PdfVersion to switch QPdfWriter
into PDF/A-1b mode. In that mode
- meta data are embedded in XMP format
- a color profile for sRGB is embedded and an OutputIntent defined
- the ID key is added to the document trailer dictionary
- a CIDSet entry is added to the font descriptor
- transparency is removed from pens, brushes and images
Change-Id: Ia8a24d83609b239e716aefc1ba05f07320dbd290
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
bb10
parent
3398d9d40c
commit
6c32927f8c
|
|
@ -0,0 +1,10 @@
|
|||
For the file sRGB2014.icc:
|
||||
|
||||
Copyright International Color Consortium, 2015
|
||||
|
||||
This profile is made available by the International Color Consortium, and may be copied,
|
||||
distributed, embedded, made, used, and sold without restriction. Altered versions of this
|
||||
profile shall have the original identification and copyright information removed and
|
||||
shall not be misrepresented as the original profile.
|
||||
|
||||
(original source location: http://www.color.org/srgbprofiles.xalter)
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[
|
||||
{
|
||||
"Id": "icc-sRGB-color-profile",
|
||||
"Name": "sRGB color profile icc file",
|
||||
"QDocModule": "qtgui",
|
||||
"QtUsage": "Used in Qt Gui (Embedded into PDF/A-1b files generated by QPrinter/QPdfWriter).",
|
||||
"Files": "sRGB2014.icc",
|
||||
|
||||
"Description": "An ICC color profile for PDF/A-1b compatible PDF files.",
|
||||
"LicenseId": "ICC License",
|
||||
"License": "International Color Consortium License",
|
||||
"LicenseFile": "LICENSE.txt",
|
||||
"Copyright": "Copyright International Color Consortium, 2015"
|
||||
}
|
||||
]
|
||||
Binary file not shown.
|
|
@ -99,6 +99,9 @@ SOURCES += \
|
|||
painting/qplatformbackingstore.cpp \
|
||||
painting/qpathsimplifier.cpp
|
||||
|
||||
RESOURCES += \
|
||||
painting/qpdf.qrc
|
||||
|
||||
darwin {
|
||||
HEADERS += painting/qcoregraphics_p.h
|
||||
SOURCES += painting/qcoregraphics.mm
|
||||
|
|
|
|||
|
|
@ -243,6 +243,18 @@ QPagedPaintDevicePrivate *QPagedPaintDevice::dd()
|
|||
Starts a new page. Returns \c true on success.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QPagedPaintDevice::PdfVersion
|
||||
|
||||
The PdfVersion enum describes the version of the PDF file that
|
||||
is produced by QPrinter or QPdfWriter.
|
||||
|
||||
\value PdfFormat_1_4 A PDF 1.4 compatible document is produced.
|
||||
|
||||
\value PdfFormat_A1b A PDF/A-1b compatible document is produced.
|
||||
|
||||
\since 5.10
|
||||
*/
|
||||
|
||||
/*!
|
||||
Sets the size of the a page to \a size.
|
||||
|
|
|
|||
|
|
@ -213,6 +213,8 @@ public:
|
|||
Envelope10 = Comm10E
|
||||
};
|
||||
|
||||
enum PdfVersion { PdfVersion_1_4, PdfVersion_A1b };
|
||||
|
||||
// ### Qt6 Make these virtual
|
||||
bool setPageLayout(const QPageLayout &pageLayout);
|
||||
bool setPageSize(const QPageSize &pageSize);
|
||||
|
|
|
|||
|
|
@ -42,16 +42,20 @@
|
|||
#ifndef QT_NO_PDF
|
||||
|
||||
#include "qplatformdefs.h"
|
||||
#include <qdebug.h>
|
||||
#include <qfile.h>
|
||||
#include <qtemporaryfile.h>
|
||||
|
||||
#include <private/qfont_p.h>
|
||||
#include <private/qmath_p.h>
|
||||
#include <private/qpainter_p.h>
|
||||
#include <qnumeric.h>
|
||||
#include "private/qfont_p.h"
|
||||
|
||||
#include <qbuffer.h>
|
||||
#include <qcryptographichash.h>
|
||||
#include <qdatetime.h>
|
||||
#include <qdebug.h>
|
||||
#include <qfile.h>
|
||||
#include <qimagewriter.h>
|
||||
#include "qbuffer.h"
|
||||
#include "QtCore/qdatetime.h"
|
||||
#include <qnumeric.h>
|
||||
#include <qtemporaryfile.h>
|
||||
#include <quuid.h>
|
||||
|
||||
#ifndef QT_NO_COMPRESS
|
||||
#include <zlib.h>
|
||||
|
|
@ -79,6 +83,45 @@ inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
|
|||
return f;
|
||||
}
|
||||
|
||||
extern bool qt_isExtendedRadialGradient(const QBrush &brush);
|
||||
|
||||
// helper function to remove transparency from brush in PDF/A-1b mode
|
||||
static void removeTransparencyFromBrush(QBrush &brush)
|
||||
{
|
||||
if (brush.style() == Qt::SolidPattern) {
|
||||
QColor color = brush.color();
|
||||
if (color.alpha() != 255) {
|
||||
color.setAlpha(255);
|
||||
brush.setColor(color);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (qt_isExtendedRadialGradient(brush)) {
|
||||
brush = QBrush(Qt::black); // the safest we can do so far...
|
||||
return;
|
||||
}
|
||||
|
||||
if (brush.style() == Qt::LinearGradientPattern
|
||||
|| brush.style() == Qt::RadialGradientPattern
|
||||
|| brush.style() == Qt::ConicalGradientPattern) {
|
||||
|
||||
QGradientStops stops = brush.gradient()->stops();
|
||||
for (int i = 0; i < stops.size(); ++i) {
|
||||
if (stops[i].second.alpha() != 255)
|
||||
stops[i].second.setAlpha(255);
|
||||
}
|
||||
|
||||
const_cast<QGradient*>(brush.gradient())->setStops(stops);
|
||||
return;
|
||||
}
|
||||
|
||||
if (brush.style() == Qt::TexturePattern) {
|
||||
// handled inside QPdfEnginePrivate::addImage() already
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* also adds a space at the end of the number */
|
||||
|
|
@ -1042,7 +1085,22 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
|
|||
d->stroker.matrix = state.transform();
|
||||
|
||||
if (flags & DirtyPen) {
|
||||
d->pen = state.pen();
|
||||
if (d->pdfVersion == QPdfEngine::Version_A1b) {
|
||||
QPen pen = state.pen();
|
||||
|
||||
QColor penColor = pen.color();
|
||||
if (penColor.alpha() != 255)
|
||||
penColor.setAlpha(255);
|
||||
pen.setColor(penColor);
|
||||
|
||||
QBrush penBrush = pen.brush();
|
||||
removeTransparencyFromBrush(penBrush);
|
||||
pen.setBrush(penBrush);
|
||||
|
||||
d->pen = pen;
|
||||
} else {
|
||||
d->pen = state.pen();
|
||||
}
|
||||
d->hasPen = d->pen.style() != Qt::NoPen;
|
||||
d->stroker.setPen(d->pen, state.renderHints());
|
||||
QBrush penBrush = d->pen.brush();
|
||||
|
|
@ -1054,7 +1112,13 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
|
|||
d->stroker.setPen(d->pen, state.renderHints());
|
||||
}
|
||||
if (flags & DirtyBrush) {
|
||||
d->brush = state.brush();
|
||||
if (d->pdfVersion == QPdfEngine::Version_A1b) {
|
||||
QBrush brush = state.brush();
|
||||
removeTransparencyFromBrush(brush);
|
||||
d->brush = brush;
|
||||
} else {
|
||||
d->brush = state.brush();
|
||||
}
|
||||
if (d->brush.color().alpha() == 0 && d->brush.style() == Qt::SolidPattern)
|
||||
d->brush.setStyle(Qt::NoBrush);
|
||||
d->hasBrush = d->brush.style() != Qt::NoBrush;
|
||||
|
|
@ -1286,6 +1350,12 @@ int QPdfEngine::resolution() const
|
|||
return d->resolution;
|
||||
}
|
||||
|
||||
void QPdfEngine::setPdfVersion(PdfVersion version)
|
||||
{
|
||||
Q_D(QPdfEngine);
|
||||
d->pdfVersion = version;
|
||||
}
|
||||
|
||||
void QPdfEngine::setPageLayout(const QPageLayout &pageLayout)
|
||||
{
|
||||
Q_D(QPdfEngine);
|
||||
|
|
@ -1364,6 +1434,7 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
|
|||
|
||||
QPdfEnginePrivate::QPdfEnginePrivate()
|
||||
: clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false),
|
||||
pdfVersion(QPdfEngine::Version_1_4),
|
||||
outDevice(0), ownsDevice(false),
|
||||
embedFonts(true),
|
||||
grayscale(false),
|
||||
|
|
@ -1469,13 +1540,34 @@ void QPdfEnginePrivate::writeHeader()
|
|||
|
||||
writeInfo();
|
||||
|
||||
int metaDataObj = -1;
|
||||
int outputIntentObj = -1;
|
||||
if (pdfVersion == QPdfEngine::Version_A1b) {
|
||||
metaDataObj = writeXmpMetaData();
|
||||
outputIntentObj = writeOutputIntent();
|
||||
}
|
||||
|
||||
catalog = addXrefEntry(-1);
|
||||
pageRoot = requestObject();
|
||||
xprintf("<<\n"
|
||||
"/Type /Catalog\n"
|
||||
"/Pages %d 0 R\n"
|
||||
">>\n"
|
||||
"endobj\n", pageRoot);
|
||||
|
||||
// catalog
|
||||
{
|
||||
QByteArray catalog;
|
||||
QPdf::ByteStream s(&catalog);
|
||||
s << "<<\n"
|
||||
<< "/Type /Catalog\n"
|
||||
<< "/Pages " << pageRoot << "0 R\n";
|
||||
|
||||
if (pdfVersion == QPdfEngine::Version_A1b) {
|
||||
s << "/OutputIntents [" << outputIntentObj << "0 R]\n";
|
||||
s << "/Metadata " << metaDataObj << "0 R\n";
|
||||
}
|
||||
|
||||
s << ">>\n"
|
||||
<< "endobj\n";
|
||||
|
||||
write(catalog);
|
||||
}
|
||||
|
||||
// graphics state
|
||||
graphicsState = addXrefEntry(-1);
|
||||
|
|
@ -1528,6 +1620,95 @@ void QPdfEnginePrivate::writeInfo()
|
|||
"endobj\n");
|
||||
}
|
||||
|
||||
int QPdfEnginePrivate::writeXmpMetaData()
|
||||
{
|
||||
const int metaDataObj = addXrefEntry(-1);
|
||||
|
||||
const QString producer(QString::fromLatin1("Qt " QT_VERSION_STR));
|
||||
|
||||
const QDateTime now = QDateTime::currentDateTime();
|
||||
const QDate date = now.date();
|
||||
const QTime time = now.time();
|
||||
|
||||
QString timeStr;
|
||||
timeStr.sprintf("%d-%02d-%02dT%02d:%02d:%02d", date.year(), date.month(), date.day(),
|
||||
time.hour(), time.minute(), time.second());
|
||||
|
||||
const int offset = now.offsetFromUtc();
|
||||
const int hours = (offset / 60) / 60;
|
||||
const int mins = (offset / 60) % 60;
|
||||
QString tzStr;
|
||||
if (offset < 0)
|
||||
tzStr.sprintf("-%02d:%02d", -hours, -mins);
|
||||
else if (offset > 0)
|
||||
tzStr.sprintf("+%02d:%02d", hours , mins);
|
||||
else
|
||||
tzStr = QLatin1String("Z");
|
||||
|
||||
const QString metaDataDate = timeStr + tzStr;
|
||||
|
||||
QFile metaDataFile(QLatin1String(":/qpdf/qpdfa_metadata.xml"));
|
||||
metaDataFile.open(QIODevice::ReadOnly);
|
||||
const QByteArray metaDataContent = QString::fromUtf8(metaDataFile.readAll()).arg(producer.toHtmlEscaped(),
|
||||
title.toHtmlEscaped(),
|
||||
creator.toHtmlEscaped(),
|
||||
metaDataDate).toUtf8();
|
||||
xprintf("<<\n"
|
||||
"/Type /Metadata /Subtype /XML\n"
|
||||
"/Length %d\n"
|
||||
">>\n"
|
||||
"stream\n", metaDataContent.size());
|
||||
write(metaDataContent);
|
||||
xprintf("\nendstream\n"
|
||||
"endobj\n");
|
||||
|
||||
return metaDataObj;
|
||||
}
|
||||
|
||||
int QPdfEnginePrivate::writeOutputIntent()
|
||||
{
|
||||
const int colorProfile = addXrefEntry(-1);
|
||||
{
|
||||
QFile colorProfileFile(QLatin1String(":/qpdf/sRGB2014.icc"));
|
||||
colorProfileFile.open(QIODevice::ReadOnly);
|
||||
const QByteArray colorProfileData = colorProfileFile.readAll();
|
||||
|
||||
QByteArray data;
|
||||
QPdf::ByteStream s(&data);
|
||||
int length_object = requestObject();
|
||||
|
||||
s << "<<\n";
|
||||
s << "/N 3\n";
|
||||
s << "/Alternate /DeviceRGB\n";
|
||||
s << "/Length " << length_object << "0 R\n";
|
||||
s << "/Filter /FlateDecode\n";
|
||||
s << ">>\n";
|
||||
s << "stream\n";
|
||||
write(data);
|
||||
const int len = writeCompressed(colorProfileData);
|
||||
write("\nendstream\n"
|
||||
"endobj\n");
|
||||
addXrefEntry(length_object);
|
||||
xprintf("%d\n"
|
||||
"endobj\n", len);
|
||||
}
|
||||
|
||||
const int outputIntent = addXrefEntry(-1);
|
||||
{
|
||||
xprintf("<<\n");
|
||||
xprintf("/Type /OutputIntent\n");
|
||||
xprintf("/S/GTS_PDFA1\n");
|
||||
xprintf("/OutputConditionIdentifier (sRGB_IEC61966-2-1_black_scaled)\n");
|
||||
xprintf("/DestOutputProfile %d 0 R\n", colorProfile);
|
||||
xprintf("/Info(sRGB IEC61966 v2.1 with black scaling)\n");
|
||||
xprintf("/RegistryName(http://www.color.org)\n");
|
||||
xprintf(">>\n");
|
||||
xprintf("endobj\n");
|
||||
}
|
||||
|
||||
return outputIntent;
|
||||
}
|
||||
|
||||
void QPdfEnginePrivate::writePageRoot()
|
||||
{
|
||||
addXrefEntry(pageRoot);
|
||||
|
|
@ -1569,6 +1750,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
|
|||
int fontstream = requestObject();
|
||||
int cidfont = requestObject();
|
||||
int toUnicode = requestObject();
|
||||
int cidset = requestObject();
|
||||
|
||||
QFontEngine::Properties properties = font->fontEngine->properties();
|
||||
QByteArray postscriptName = properties.postscriptName.replace(' ', '_');
|
||||
|
|
@ -1598,6 +1780,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
|
|||
"/CapHeight " << properties.capHeight.toReal()*scale << "\n"
|
||||
"/StemV " << properties.lineWidth.toReal()*scale << "\n"
|
||||
"/FontFile2 " << fontstream << "0 R\n"
|
||||
"/CIDSet " << cidset << "0 R\n"
|
||||
">>\nendobj\n";
|
||||
write(descriptor);
|
||||
}
|
||||
|
|
@ -1660,6 +1843,29 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
|
|||
"endobj\n";
|
||||
write(font);
|
||||
}
|
||||
{
|
||||
QByteArray cidSetStream(font->nGlyphs() / 8 + 1, 0);
|
||||
int byteCounter = 0;
|
||||
int bitCounter = 0;
|
||||
for (int i = 0; i < font->nGlyphs(); ++i) {
|
||||
cidSetStream.data()[byteCounter] |= (1 << (7 - bitCounter));
|
||||
|
||||
bitCounter++;
|
||||
if (bitCounter == 8) {
|
||||
bitCounter = 0;
|
||||
byteCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
addXrefEntry(cidset);
|
||||
xprintf("<<\n");
|
||||
xprintf("/Length %d\n", cidSetStream.size());
|
||||
xprintf(">>\n");
|
||||
xprintf("stream\n");
|
||||
write(cidSetStream);
|
||||
xprintf("\nendstream\n");
|
||||
xprintf("endobj\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1769,15 +1975,28 @@ void QPdfEnginePrivate::writeTail()
|
|||
for (int i = 1; i < xrefPositions.size()-1; ++i)
|
||||
xprintf("%010d 00000 n \n", xrefPositions[i]);
|
||||
|
||||
xprintf("trailer\n"
|
||||
"<<\n"
|
||||
"/Size %d\n"
|
||||
"/Info %d 0 R\n"
|
||||
"/Root %d 0 R\n"
|
||||
">>\n"
|
||||
"startxref\n%d\n"
|
||||
"%%%%EOF\n",
|
||||
xrefPositions.size()-1, info, catalog, xrefPositions.constLast());
|
||||
{
|
||||
QByteArray trailer;
|
||||
QPdf::ByteStream s(&trailer);
|
||||
|
||||
s << "trailer\n"
|
||||
<< "<<\n"
|
||||
<< "/Size " << xrefPositions.size() - 1 << "\n"
|
||||
<< "/Info " << info << "0 R\n"
|
||||
<< "/Root " << catalog << "0 R\n";
|
||||
|
||||
if (pdfVersion == QPdfEngine::Version_A1b) {
|
||||
const QString uniqueId = QUuid::createUuid().toString();
|
||||
const QByteArray fileIdentifier = QCryptographicHash::hash(uniqueId.toLatin1(), QCryptographicHash::Md5).toHex();
|
||||
s << "/ID [ <" << fileIdentifier << "> <" << fileIdentifier << "> ]\n";
|
||||
}
|
||||
|
||||
s << ">>\n"
|
||||
<< "startxref\n" << xrefPositions.constLast() << "\n"
|
||||
<< "%%EOF\n";
|
||||
|
||||
write(trailer);
|
||||
}
|
||||
}
|
||||
|
||||
int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
|
||||
|
|
@ -1983,7 +2202,7 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
|
|||
xprintf(">>\nstream\n");
|
||||
len = writeCompressed(data);
|
||||
}
|
||||
xprintf("endstream\n"
|
||||
xprintf("\nendstream\n"
|
||||
"endobj\n");
|
||||
addXrefEntry(lenobj);
|
||||
xprintf("%d\n"
|
||||
|
|
@ -2309,7 +2528,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QTransform &matrix,
|
|||
">>\n"
|
||||
"stream\n"
|
||||
<< content
|
||||
<< "endstream\n"
|
||||
<< "\nendstream\n"
|
||||
"endobj\n";
|
||||
|
||||
int softMaskFormObject = addXrefEntry(-1);
|
||||
|
|
@ -2418,7 +2637,7 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
|
|||
">>\n"
|
||||
"stream\n"
|
||||
<< pattern
|
||||
<< "endstream\n"
|
||||
<< "\nendstream\n"
|
||||
"endobj\n";
|
||||
|
||||
int patternObj = addXrefEntry(-1);
|
||||
|
|
@ -2449,6 +2668,23 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
|
|||
|
||||
QImage image = img;
|
||||
QImage::Format format = image.format();
|
||||
|
||||
if (pdfVersion == QPdfEngine::Version_A1b) {
|
||||
if (image.hasAlphaChannel()) {
|
||||
// transparent images are not allowed in PDF/A-1b, so we convert it to
|
||||
// a format without alpha channel first
|
||||
|
||||
QImage alphaLessImage(image.width(), image.height(), QImage::Format_RGB32);
|
||||
alphaLessImage.fill(Qt::white);
|
||||
|
||||
QPainter p(&alphaLessImage);
|
||||
p.drawImage(0, 0, image);
|
||||
|
||||
image = alphaLessImage;
|
||||
format = image.format();
|
||||
}
|
||||
}
|
||||
|
||||
if (image.depth() == 1 && *bitmap && is_monochrome(img.colorTable())) {
|
||||
if (format == QImage::Format_MonoLSB)
|
||||
image = image.convertToFormat(QImage::Format_Mono);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<!DOCTYPE RCC>
|
||||
<RCC version="1.0">
|
||||
<qresource prefix="qpdf/">
|
||||
<file>qpdfa_metadata.xml</file>
|
||||
<file alias="sRGB2014.icc">../../3rdparty/icc/sRGB2014.icc</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
@ -168,6 +168,12 @@ class Q_GUI_EXPORT QPdfEngine : public QPaintEngine
|
|||
Q_DECLARE_PRIVATE(QPdfEngine)
|
||||
friend class QPdfWriter;
|
||||
public:
|
||||
enum PdfVersion
|
||||
{
|
||||
Version_1_4,
|
||||
Version_A1b
|
||||
};
|
||||
|
||||
QPdfEngine();
|
||||
QPdfEngine(QPdfEnginePrivate &d);
|
||||
~QPdfEngine() {}
|
||||
|
|
@ -177,6 +183,8 @@ public:
|
|||
void setResolution(int resolution);
|
||||
int resolution() const;
|
||||
|
||||
void setPdfVersion(PdfVersion version);
|
||||
|
||||
// reimplementations QPaintEngine
|
||||
bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
|
||||
bool end() Q_DECL_OVERRIDE;
|
||||
|
|
@ -258,6 +266,7 @@ public:
|
|||
bool hasBrush;
|
||||
bool simplePen;
|
||||
qreal opacity;
|
||||
QPdfEngine::PdfVersion pdfVersion;
|
||||
|
||||
QHash<QFontEngine::FaceId, QFontSubset *> fonts;
|
||||
|
||||
|
|
@ -286,6 +295,8 @@ private:
|
|||
int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
|
||||
|
||||
void writeInfo();
|
||||
int writeXmpMetaData();
|
||||
int writeOutputIntent();
|
||||
void writePageRoot();
|
||||
void writeFonts();
|
||||
void embedFont(QFontSubset *font);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
|
||||
<x:xmpmeta xmlns:x="adobe:ns:meta/">
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
||||
<rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
|
||||
<dc:title>
|
||||
<rdf:Alt>
|
||||
<rdf:li xml:lang="x-default">%2</rdf:li>
|
||||
</rdf:Alt>
|
||||
</dc:title>
|
||||
</rdf:Description>
|
||||
<rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" rdf:about="" xmp:CreatorTool="%3" xmp:CreateDate="%4" xmp:ModifyDate="%4"/>
|
||||
<rdf:Description xmlns:pdf="http://ns.adobe.com/pdf/1.3/" rdf:about="" pdf:Producer="%1"/>
|
||||
<rdf:Description xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" rdf:about="" pdfaid:part="1" pdfaid:conformance="B"/>
|
||||
</rdf:RDF>
|
||||
</x:xmpmeta>
|
||||
<?xpacket end='w'?>
|
||||
|
|
@ -56,6 +56,7 @@ public:
|
|||
{
|
||||
engine = new QPdfEngine();
|
||||
output = 0;
|
||||
pdfVersion = QPdfWriter::PdfVersion_1_4;
|
||||
}
|
||||
~QPdfWriterPrivate()
|
||||
{
|
||||
|
|
@ -65,6 +66,7 @@ public:
|
|||
|
||||
QPdfEngine *engine;
|
||||
QFile *output;
|
||||
QPdfWriter::PdfVersion pdfVersion;
|
||||
};
|
||||
|
||||
class QPdfPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
|
||||
|
|
@ -176,6 +178,35 @@ QPdfWriter::~QPdfWriter()
|
|||
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.10
|
||||
|
||||
Sets the PDF version for this writer to \a version.
|
||||
|
||||
If \a version is the same value as currently set then no change will be made.
|
||||
*/
|
||||
void QPdfWriter::setPdfVersion(PdfVersion version)
|
||||
{
|
||||
Q_D(QPdfWriter);
|
||||
|
||||
if (d->pdfVersion == version)
|
||||
return;
|
||||
|
||||
d->pdfVersion = version;
|
||||
d->engine->setPdfVersion(d->pdfVersion == QPdfWriter::PdfVersion_1_4 ? QPdfEngine::Version_1_4 : QPdfEngine::Version_A1b);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.10
|
||||
|
||||
Returns the PDF version for this writer. The default is \c PdfVersion_1_4.
|
||||
*/
|
||||
QPdfWriter::PdfVersion QPdfWriter::pdfVersion() const
|
||||
{
|
||||
Q_D(const QPdfWriter);
|
||||
return d->pdfVersion;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the title of the document.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@ public:
|
|||
explicit QPdfWriter(QIODevice *device);
|
||||
~QPdfWriter();
|
||||
|
||||
void setPdfVersion(PdfVersion version);
|
||||
PdfVersion pdfVersion() const;
|
||||
|
||||
QString title() const;
|
||||
void setTitle(const QString &title);
|
||||
|
||||
|
|
|
|||
|
|
@ -58,10 +58,12 @@
|
|||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m)
|
||||
QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m, QPdfEngine::PdfVersion version)
|
||||
: QPdfEngine(*new QPdfPrintEnginePrivate(m))
|
||||
{
|
||||
state = QPrinter::Idle;
|
||||
|
||||
setPdfVersion(version);
|
||||
}
|
||||
|
||||
QPdfPrintEngine::QPdfPrintEngine(QPdfPrintEnginePrivate &p)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class Q_PRINTSUPPORT_EXPORT QPdfPrintEngine : public QPdfEngine, public QPrintEn
|
|||
{
|
||||
Q_DECLARE_PRIVATE(QPdfPrintEngine)
|
||||
public:
|
||||
QPdfPrintEngine(QPrinter::PrinterMode m);
|
||||
QPdfPrintEngine(QPrinter::PrinterMode m, QPdfEngine::PdfVersion version = QPdfEngine::Version_1_4);
|
||||
virtual ~QPdfPrintEngine();
|
||||
|
||||
// reimplementations QPaintEngine
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ void QPrinterPrivate::initEngines(QPrinter::OutputFormat format, const QPrinterI
|
|||
printEngine = ps->createNativePrintEngine(printerMode);
|
||||
paintEngine = ps->createPaintEngine(printEngine, printerMode);
|
||||
} else {
|
||||
QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode);
|
||||
const auto pdfEngineVersion = (pdfVersion == QPrinter::PdfVersion_1_4 ? QPdfEngine::Version_1_4 : QPdfEngine::Version_A1b);
|
||||
QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode, pdfEngineVersion);
|
||||
paintEngine = pdfEngine;
|
||||
printEngine = pdfEngine;
|
||||
}
|
||||
|
|
@ -685,7 +686,37 @@ QPrinter::OutputFormat QPrinter::outputFormat() const
|
|||
return d->outputFormat;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.10
|
||||
|
||||
Sets the PDF version for this printer to \a version.
|
||||
|
||||
If \a version is the same value as currently set then no change will be made.
|
||||
*/
|
||||
void QPrinter::setPdfVersion(PdfVersion version)
|
||||
{
|
||||
Q_D(QPrinter);
|
||||
|
||||
if (d->pdfVersion == version)
|
||||
return;
|
||||
|
||||
d->pdfVersion = version;
|
||||
|
||||
if (d->outputFormat == QPrinter::PdfFormat) {
|
||||
d->changeEngines(d->outputFormat, QPrinterInfo());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.10
|
||||
|
||||
Returns the PDF version for this printer. The default is \c PdfVersion_1_4.
|
||||
*/
|
||||
QPrinter::PdfVersion QPrinter::pdfVersion() const
|
||||
{
|
||||
Q_D(const QPrinter);
|
||||
return d->pdfVersion;
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ public:
|
|||
void setOutputFormat(OutputFormat format);
|
||||
OutputFormat outputFormat() const;
|
||||
|
||||
void setPdfVersion(PdfVersion version);
|
||||
PdfVersion pdfVersion() const;
|
||||
|
||||
void setPrinterName(const QString &);
|
||||
QString printerName() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ class Q_PRINTSUPPORT_EXPORT QPrinterPrivate
|
|||
Q_DECLARE_PUBLIC(QPrinter)
|
||||
public:
|
||||
QPrinterPrivate(QPrinter *printer)
|
||||
: printEngine(0),
|
||||
: pdfVersion(QPrinter::PdfVersion_1_4),
|
||||
printEngine(0),
|
||||
paintEngine(0),
|
||||
realPrintEngine(0),
|
||||
realPaintEngine(0),
|
||||
|
|
@ -107,6 +108,7 @@ public:
|
|||
|
||||
QPrinter::PrinterMode printerMode;
|
||||
QPrinter::OutputFormat outputFormat;
|
||||
QPrinter::PdfVersion pdfVersion;
|
||||
QPrintEngine *printEngine;
|
||||
QPaintEngine *paintEngine;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue