Add CMYK support for pens/fills in the PDF engine
Insofar, painting with a CMYK color (pen/brush) was completely ignored by QPdfWriter, although the PDF format can faithfully represent CMYK colors. This commit adds support for CMYK colors in the PDF engine. The support is opt-in, in the name of backwards compatibility; an enumeration on QPdfWriter controls the output. QPrinter was using a hidden hook in QPdfEngine in order to do grayscale printing; this hook can now be made public API through the same enumeration. This work has been kindly sponsored by the QGIS project (https://qgis.org/). [ChangeLog][QtGui][QPdfWriter] QPdfWriter can now use CMYK colors directly, without converting them into RGB colors. Change-Id: Ia27c19ec81a58ab68ddc8b9c89c4e57d7d637301 Reviewed-by: Lars Knoll <lars@knoll.priv.no>
This commit is contained in:
parent
efc579145e
commit
0092f06a64
@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
|
||||
constexpr QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
|
||||
{
|
||||
QPaintEngine::PaintEngineFeatures f = QPaintEngine::AllFeatures;
|
||||
f &= ~(QPaintEngine::PorterDuff
|
||||
@ -1239,17 +1239,8 @@ void QPdfEngine::setPen()
|
||||
QBrush b = d->pen.brush();
|
||||
Q_ASSERT(b.style() == Qt::SolidPattern && b.isOpaque());
|
||||
|
||||
QColor rgba = b.color();
|
||||
if (d->grayscale) {
|
||||
qreal gray = qGray(rgba.rgba())/255.;
|
||||
*d->currentPage << gray << gray << gray;
|
||||
} else {
|
||||
*d->currentPage << rgba.redF()
|
||||
<< rgba.greenF()
|
||||
<< rgba.blueF();
|
||||
}
|
||||
d->writeColor(QPdfEnginePrivate::ColorDomain::Stroking, b.color());
|
||||
*d->currentPage << "SCN\n";
|
||||
|
||||
*d->currentPage << d->pen.widthF() << "w ";
|
||||
|
||||
int pdfCapStyle = 0;
|
||||
@ -1303,18 +1294,9 @@ void QPdfEngine::setBrush()
|
||||
if (!patternObject && !specifyColor)
|
||||
return;
|
||||
|
||||
*d->currentPage << (patternObject ? "/PCSp cs " : "/CSp cs ");
|
||||
if (specifyColor) {
|
||||
QColor rgba = d->brush.color();
|
||||
if (d->grayscale) {
|
||||
qreal gray = qGray(rgba.rgba())/255.;
|
||||
*d->currentPage << gray << gray << gray;
|
||||
} else {
|
||||
*d->currentPage << rgba.redF()
|
||||
<< rgba.greenF()
|
||||
<< rgba.blueF();
|
||||
}
|
||||
}
|
||||
const auto domain = patternObject ? QPdfEnginePrivate::ColorDomain::NonStrokingPattern
|
||||
: QPdfEnginePrivate::ColorDomain::NonStroking;
|
||||
d->writeColor(domain, specifyColor ? d->brush.color() : QColor());
|
||||
if (patternObject)
|
||||
*d->currentPage << "/Pat" << patternObject;
|
||||
*d->currentPage << "scn\n";
|
||||
@ -1454,9 +1436,9 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
|
||||
QPdfEnginePrivate::QPdfEnginePrivate()
|
||||
: clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false),
|
||||
needsTransform(false), pdfVersion(QPdfEngine::Version_1_4),
|
||||
colorModel(QPdfEngine::ColorModel::RGB),
|
||||
outDevice(nullptr), ownsDevice(false),
|
||||
embedFonts(true),
|
||||
grayscale(false),
|
||||
m_pageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF(10, 10, 10, 10))
|
||||
{
|
||||
initResources();
|
||||
@ -1511,7 +1493,9 @@ bool QPdfEngine::begin(QPaintDevice *pdev)
|
||||
d->catalog = 0;
|
||||
d->info = 0;
|
||||
d->graphicsState = 0;
|
||||
d->patternColorSpace = 0;
|
||||
d->patternColorSpaceRGB = 0;
|
||||
d->patternColorSpaceGrayscale = 0;
|
||||
d->patternColorSpaceCMYK = 0;
|
||||
d->simplePen = false;
|
||||
d->needsTransform = false;
|
||||
|
||||
@ -1629,10 +1613,99 @@ void QPdfEnginePrivate::writeHeader()
|
||||
">>\n"
|
||||
"endobj\n");
|
||||
|
||||
// color space for pattern
|
||||
patternColorSpace = addXrefEntry(-1);
|
||||
// color spaces for pattern
|
||||
patternColorSpaceRGB = addXrefEntry(-1);
|
||||
xprintf("[/Pattern /DeviceRGB]\n"
|
||||
"endobj\n");
|
||||
patternColorSpaceGrayscale = addXrefEntry(-1);
|
||||
xprintf("[/Pattern /DeviceGray]\n"
|
||||
"endobj\n");
|
||||
patternColorSpaceCMYK = addXrefEntry(-1);
|
||||
xprintf("[/Pattern /DeviceCMYK]\n"
|
||||
"endobj\n");
|
||||
}
|
||||
|
||||
QPdfEngine::ColorModel QPdfEnginePrivate::colorModelForColor(const QColor &color) const
|
||||
{
|
||||
switch (colorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
case QPdfEngine::ColorModel::Grayscale:
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
return colorModel;
|
||||
case QPdfEngine::ColorModel::Auto:
|
||||
switch (color.spec()) {
|
||||
case QColor::Invalid:
|
||||
case QColor::Rgb:
|
||||
case QColor::Hsv:
|
||||
case QColor::Hsl:
|
||||
case QColor::ExtendedRgb:
|
||||
return QPdfEngine::ColorModel::RGB;
|
||||
case QColor::Cmyk:
|
||||
return QPdfEngine::ColorModel::CMYK;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Q_UNREACHABLE_RETURN(QPdfEngine::ColorModel::RGB);
|
||||
}
|
||||
|
||||
void QPdfEnginePrivate::writeColor(ColorDomain domain, const QColor &color)
|
||||
{
|
||||
// Switch to the right colorspace.
|
||||
// For simplicity: do it even if it redundant (= already in that colorspace)
|
||||
const QPdfEngine::ColorModel actualColorModel = colorModelForColor(color);
|
||||
|
||||
switch (actualColorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
case QPdfEngine::ColorModel::Grayscale:
|
||||
switch (domain) {
|
||||
case ColorDomain::Stroking:
|
||||
*currentPage << "/CSp CS\n"; break;
|
||||
case ColorDomain::NonStroking:
|
||||
*currentPage << "/CSp cs\n"; break;
|
||||
case ColorDomain::NonStrokingPattern:
|
||||
*currentPage << "/PCSp cs\n"; break;
|
||||
}
|
||||
break;
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
switch (domain) {
|
||||
case ColorDomain::Stroking:
|
||||
*currentPage << "/CSpcmyk CS\n"; break;
|
||||
case ColorDomain::NonStroking:
|
||||
*currentPage << "/CSpcmyk cs\n"; break;
|
||||
case ColorDomain::NonStrokingPattern:
|
||||
*currentPage << "/PCSpcmyk cs\n"; break;
|
||||
}
|
||||
break;
|
||||
case QPdfEngine::ColorModel::Auto:
|
||||
Q_UNREACHABLE_RETURN();
|
||||
}
|
||||
|
||||
// If we also have a color specified, write it out.
|
||||
if (!color.isValid())
|
||||
return;
|
||||
|
||||
switch (actualColorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
*currentPage << color.redF()
|
||||
<< color.greenF()
|
||||
<< color.blueF();
|
||||
break;
|
||||
case QPdfEngine::ColorModel::Grayscale: {
|
||||
const qreal gray = qGray(color.rgba()) / 255.;
|
||||
*currentPage << gray << gray << gray;
|
||||
break;
|
||||
}
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
*currentPage << color.cyanF()
|
||||
<< color.magentaF()
|
||||
<< color.yellowF()
|
||||
<< color.blackF();
|
||||
break;
|
||||
case QPdfEngine::ColorModel::Auto:
|
||||
Q_UNREACHABLE_RETURN();
|
||||
}
|
||||
}
|
||||
|
||||
void QPdfEnginePrivate::writeInfo()
|
||||
@ -2078,12 +2151,18 @@ void QPdfEnginePrivate::writePage()
|
||||
xprintf("<<\n"
|
||||
"/ColorSpace <<\n"
|
||||
"/PCSp %d 0 R\n"
|
||||
"/PCSpg %d 0 R\n"
|
||||
"/PCSpcmyk %d 0 R\n"
|
||||
"/CSp /DeviceRGB\n"
|
||||
"/CSpg /DeviceGray\n"
|
||||
"/CSpcmyk /DeviceCMYK\n"
|
||||
">>\n"
|
||||
"/ExtGState <<\n"
|
||||
"/GSa %d 0 R\n",
|
||||
patternColorSpace, graphicsState);
|
||||
patternColorSpaceRGB,
|
||||
patternColorSpaceGrayscale,
|
||||
patternColorSpaceCMYK,
|
||||
graphicsState);
|
||||
|
||||
for (int i = 0; i < currentPage->graphicStates.size(); ++i)
|
||||
xprintf("/GState%d %d 0 R\n", currentPage->graphicStates.at(i), currentPage->graphicStates.at(i));
|
||||
@ -2396,7 +2475,22 @@ struct QGradientBound {
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(QGradientBound, Q_PRIMITIVE_TYPE);
|
||||
|
||||
int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha)
|
||||
void QPdfEnginePrivate::ShadingFunctionResult::writeColorSpace(QPdf::ByteStream *stream) const
|
||||
{
|
||||
*stream << "/ColorSpace ";
|
||||
switch (colorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
case QPdfEngine::ColorModel::Grayscale:
|
||||
*stream << "/DeviceRGB\n"; break;
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
*stream << "/DeviceCMYK\n"; break;
|
||||
case QPdfEngine::ColorModel::Auto:
|
||||
Q_UNREACHABLE(); break;
|
||||
}
|
||||
}
|
||||
|
||||
QPdfEnginePrivate::ShadingFunctionResult
|
||||
QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha)
|
||||
{
|
||||
QGradientStops stops = gradient->stops();
|
||||
if (stops.isEmpty()) {
|
||||
@ -2408,6 +2502,35 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from
|
||||
if (stops.at(stops.size() - 1).first < 1)
|
||||
stops.append(QGradientStop(1, stops.at(stops.size() - 1).second));
|
||||
|
||||
// Color to use which colorspace to use
|
||||
const QColor referenceColor = stops.constFirst().second;
|
||||
|
||||
switch (colorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
case QPdfEngine::ColorModel::Grayscale:
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
break;
|
||||
case QPdfEngine::ColorModel::Auto: {
|
||||
// Make sure that all the stops have the same color spec
|
||||
// (we don't support anything else)
|
||||
const QColor::Spec referenceSpec = referenceColor.spec();
|
||||
bool warned = false;
|
||||
for (QGradientStop &stop : stops) {
|
||||
if (stop.second.spec() != referenceSpec) {
|
||||
if (!warned) {
|
||||
qWarning("QPdfEngine: unable to create a gradient between colors of different spec");
|
||||
warned = true;
|
||||
}
|
||||
stop.second = stop.second.convertTo(referenceSpec);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ShadingFunctionResult result;
|
||||
result.colorModel = colorModelForColor(referenceColor);
|
||||
|
||||
QList<int> functions;
|
||||
const int numStops = stops.size();
|
||||
functions.reserve(numStops - 1);
|
||||
@ -2423,8 +2546,30 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from
|
||||
s << "/C0 [" << stops.at(i).second.alphaF() << "]\n"
|
||||
"/C1 [" << stops.at(i + 1).second.alphaF() << "]\n";
|
||||
} else {
|
||||
s << "/C0 [" << stops.at(i).second.redF() << stops.at(i).second.greenF() << stops.at(i).second.blueF() << "]\n"
|
||||
"/C1 [" << stops.at(i + 1).second.redF() << stops.at(i + 1).second.greenF() << stops.at(i + 1).second.blueF() << "]\n";
|
||||
switch (result.colorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
case QPdfEngine::ColorModel::Grayscale:
|
||||
// For backwards compatibility, Grayscale emits RGB colors
|
||||
s << "/C0 [" << stops.at(i).second.redF() << stops.at(i).second.greenF() << stops.at(i).second.blueF() << "]\n"
|
||||
"/C1 [" << stops.at(i + 1).second.redF() << stops.at(i + 1).second.greenF() << stops.at(i + 1).second.blueF() << "]\n";
|
||||
break;
|
||||
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
s << "/C0 [" << stops.at(i).second.cyanF()
|
||||
<< stops.at(i).second.magentaF()
|
||||
<< stops.at(i).second.yellowF()
|
||||
<< stops.at(i).second.blackF() << "]\n"
|
||||
"/C1 [" << stops.at(i + 1).second.cyanF()
|
||||
<< stops.at(i + 1).second.magentaF()
|
||||
<< stops.at(i + 1).second.yellowF()
|
||||
<< stops.at(i + 1).second.blackF() << "]\n";
|
||||
break;
|
||||
|
||||
case QPdfEngine::ColorModel::Auto:
|
||||
Q_UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
s << ">>\n"
|
||||
"endobj\n";
|
||||
@ -2492,7 +2637,8 @@ int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from
|
||||
} else {
|
||||
function = functions.at(0);
|
||||
}
|
||||
return function;
|
||||
result.function = function;
|
||||
return result;
|
||||
}
|
||||
|
||||
int QPdfEnginePrivate::generateLinearGradientShader(const QLinearGradient *gradient, const QTransform &matrix, bool alpha)
|
||||
@ -2538,17 +2684,22 @@ int QPdfEnginePrivate::generateLinearGradientShader(const QLinearGradient *gradi
|
||||
}
|
||||
}
|
||||
|
||||
int function = createShadingFunction(gradient, from, to, reflect, alpha);
|
||||
const auto shadingFunctionResult = createShadingFunction(gradient, from, to, reflect, alpha);
|
||||
|
||||
QByteArray shader;
|
||||
QPdf::ByteStream s(&shader);
|
||||
s << "<<\n"
|
||||
"/ShadingType 2\n"
|
||||
"/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
|
||||
"/AntiAlias true\n"
|
||||
"/ShadingType 2\n";
|
||||
|
||||
if (alpha)
|
||||
s << "/ColorSpace /DeviceGray\n";
|
||||
else
|
||||
shadingFunctionResult.writeColorSpace(&s);
|
||||
|
||||
s << "/AntiAlias true\n"
|
||||
"/Coords [" << start.x() << start.y() << stop.x() << stop.y() << "]\n"
|
||||
"/Extend [true true]\n"
|
||||
"/Function " << function << "0 R\n"
|
||||
"/Function " << shadingFunctionResult.function << "0 R\n"
|
||||
">>\n"
|
||||
"endobj\n";
|
||||
int shaderObject = addXrefEntry(-1);
|
||||
@ -2606,18 +2757,23 @@ int QPdfEnginePrivate::generateRadialGradientShader(const QRadialGradient *gradi
|
||||
}
|
||||
}
|
||||
|
||||
int function = createShadingFunction(gradient, from, to, reflect, alpha);
|
||||
const auto shadingFunctionResult = createShadingFunction(gradient, from, to, reflect, alpha);
|
||||
|
||||
QByteArray shader;
|
||||
QPdf::ByteStream s(&shader);
|
||||
s << "<<\n"
|
||||
"/ShadingType 3\n"
|
||||
"/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
|
||||
"/AntiAlias true\n"
|
||||
"/ShadingType 3\n";
|
||||
|
||||
if (alpha)
|
||||
s << "/ColorSpace /DeviceGray\n";
|
||||
else
|
||||
shadingFunctionResult.writeColorSpace(&s);
|
||||
|
||||
s << "/AntiAlias true\n"
|
||||
"/Domain [0 1]\n"
|
||||
"/Coords [" << p0.x() << p0.y() << r0 << p1.x() << p1.y() << r1 << "]\n"
|
||||
"/Extend [true true]\n"
|
||||
"/Function " << function << "0 R\n"
|
||||
"/Function " << shadingFunctionResult.function << "0 R\n"
|
||||
">>\n"
|
||||
"endobj\n";
|
||||
int shaderObject = addXrefEntry(-1);
|
||||
@ -2856,6 +3012,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, bool lossless,
|
||||
|
||||
QImage image = img;
|
||||
QImage::Format format = image.format();
|
||||
const bool grayscale = (colorModel == QPdfEngine::ColorModel::Grayscale);
|
||||
|
||||
if (pdfVersion == QPdfEngine::Version_A1b) {
|
||||
if (image.hasAlphaChannel()) {
|
||||
|
@ -142,7 +142,7 @@ public:
|
||||
};
|
||||
|
||||
QPdfEngine();
|
||||
QPdfEngine(QPdfEnginePrivate &d);
|
||||
explicit QPdfEngine(QPdfEnginePrivate &d);
|
||||
~QPdfEngine() {}
|
||||
|
||||
void setOutputFilename(const QString &filename);
|
||||
@ -157,6 +157,18 @@ public:
|
||||
|
||||
void addFileAttachment(const QString &fileName, const QByteArray &data, const QString &mimeType);
|
||||
|
||||
// keep in sync with QPdfWriter
|
||||
enum class ColorModel
|
||||
{
|
||||
RGB,
|
||||
Grayscale,
|
||||
CMYK,
|
||||
Auto,
|
||||
};
|
||||
|
||||
ColorModel colorModel() const;
|
||||
void setColorModel(ColorModel model);
|
||||
|
||||
// reimplementations QPaintEngine
|
||||
bool begin(QPaintDevice *pdev) override;
|
||||
bool end() override;
|
||||
@ -240,6 +252,7 @@ public:
|
||||
bool needsTransform;
|
||||
qreal opacity;
|
||||
QPdfEngine::PdfVersion pdfVersion;
|
||||
QPdfEngine::ColorModel colorModel;
|
||||
|
||||
QHash<QFontEngine::FaceId, QFontSubset *> fonts;
|
||||
|
||||
@ -255,7 +268,6 @@ public:
|
||||
QString creator;
|
||||
bool embedFonts;
|
||||
int resolution;
|
||||
bool grayscale;
|
||||
|
||||
// Page layout: size, orientation and margins
|
||||
QPageLayout m_pageLayout;
|
||||
@ -265,8 +277,22 @@ private:
|
||||
int generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha = false);
|
||||
int generateLinearGradientShader(const QLinearGradient *lg, const QTransform &matrix, bool alpha);
|
||||
int generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha);
|
||||
int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
|
||||
struct ShadingFunctionResult
|
||||
{
|
||||
int function;
|
||||
QPdfEngine::ColorModel colorModel;
|
||||
void writeColorSpace(QPdf::ByteStream *stream) const;
|
||||
};
|
||||
ShadingFunctionResult createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
|
||||
|
||||
enum class ColorDomain {
|
||||
Stroking,
|
||||
NonStroking,
|
||||
NonStrokingPattern,
|
||||
};
|
||||
|
||||
QPdfEngine::ColorModel colorModelForColor(const QColor &color) const;
|
||||
void writeColor(ColorDomain domain, const QColor &color);
|
||||
void writeInfo();
|
||||
int writeXmpDcumentMetaData();
|
||||
int writeOutputIntent();
|
||||
@ -316,7 +342,10 @@ private:
|
||||
|
||||
// various PDF objects
|
||||
int pageRoot, namesRoot, destsRoot, attachmentsRoot, catalog, info;
|
||||
int graphicsState, patternColorSpace;
|
||||
int graphicsState;
|
||||
int patternColorSpaceRGB;
|
||||
int patternColorSpaceGrayscale;
|
||||
int patternColorSpaceCMYK;
|
||||
QList<uint> pages;
|
||||
QHash<qint64, uint> imageCache;
|
||||
QHash<QPair<uint, uint>, uint > alphaCache;
|
||||
|
@ -295,6 +295,52 @@ bool QPdfWriter::newPage()
|
||||
return d->engine->newPage();
|
||||
}
|
||||
|
||||
/*!
|
||||
\enum QPdfWriter::ColorModel
|
||||
\since 6.8
|
||||
|
||||
This enumeration describes the way in which the PDF engine interprets
|
||||
stroking and filling colors, set as a QPainter's pen or brush (via
|
||||
QPen and QBrush).
|
||||
|
||||
\value RGB All colors are converted to RGB and saved as such in the
|
||||
PDF. This is the default.
|
||||
|
||||
\value Grayscale All colors are converted to grayscale. For backwards
|
||||
compatibility, they are emitted in the PDF output as RGB colors, with
|
||||
identical quantities of red, green and blue.
|
||||
|
||||
\value CMYK All colors are converted to CMYK and saved as such.
|
||||
|
||||
\value Auto RGB colors are emitted as RGB; CMYK colors are emitted as
|
||||
CMYK. Colors of any other color spec are converted to RGB.
|
||||
|
||||
\sa QColor, QGradient
|
||||
*/
|
||||
|
||||
/*!
|
||||
\since 6.8
|
||||
|
||||
Returns the color model used by this PDF writer.
|
||||
The default is QPdfWriter::ColorModel::RGB.
|
||||
*/
|
||||
QPdfWriter::ColorModel QPdfWriter::colorModel() const
|
||||
{
|
||||
Q_D(const QPdfWriter);
|
||||
return static_cast<ColorModel>(d->engine->d_func()->colorModel);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.8
|
||||
|
||||
Sets the color model used by this PDF writer to \a model.
|
||||
*/
|
||||
void QPdfWriter::setColorModel(ColorModel model)
|
||||
{
|
||||
Q_D(QPdfWriter);
|
||||
d->engine->d_func()->colorModel = static_cast<QPdfEngine::ColorModel>(model);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qpdfwriter.cpp"
|
||||
|
@ -44,6 +44,18 @@ public:
|
||||
|
||||
void addFileAttachment(const QString &fileName, const QByteArray &data, const QString &mimeType = QString());
|
||||
|
||||
enum class ColorModel
|
||||
{
|
||||
RGB,
|
||||
Grayscale,
|
||||
CMYK,
|
||||
Auto,
|
||||
};
|
||||
Q_ENUM(ColorModel)
|
||||
|
||||
ColorModel colorModel() const;
|
||||
void setColorModel(ColorModel model);
|
||||
|
||||
protected:
|
||||
QPaintEngine *paintEngine() const override;
|
||||
int metric(PaintDeviceMetric id) const override;
|
||||
|
@ -249,9 +249,12 @@ void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter)
|
||||
duplex = m_printDevice.defaultDuplexMode();
|
||||
duplexRequestedExplicitly = false;
|
||||
}
|
||||
QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color;
|
||||
if (!m_printDevice.supportedColorModes().contains(colorMode))
|
||||
grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale;
|
||||
QPrint::ColorMode colorMode = static_cast<QPrint::ColorMode>(printerColorMode());
|
||||
if (!m_printDevice.supportedColorModes().contains(colorMode)) {
|
||||
colorModel = (m_printDevice.defaultColorMode() == QPrint::GrayScale)
|
||||
? QPdfEngine::ColorModel::Grayscale
|
||||
: QPdfEngine::ColorModel::RGB;
|
||||
}
|
||||
|
||||
// Get the equivalent page size for this printer as supported names may be different
|
||||
if (m_printDevice.supportedPageSize(m_pageLayout.pageSize()).isValid())
|
||||
|
@ -68,6 +68,7 @@ namespace QPrint {
|
||||
DuplexShortSide
|
||||
};
|
||||
|
||||
// Note: Keep in sync with QPrinter::ColorMode
|
||||
enum ColorMode {
|
||||
GrayScale,
|
||||
Color
|
||||
|
@ -104,7 +104,14 @@ void QPdfPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
|
||||
d->collate = value.toBool();
|
||||
break;
|
||||
case PPK_ColorMode:
|
||||
d->grayscale = (QPrinter::ColorMode(value.toInt()) == QPrinter::GrayScale);
|
||||
switch (QPrinter::ColorMode(value.toInt())) {
|
||||
case QPrinter::GrayScale:
|
||||
d->colorModel = QPdfEngine::ColorModel::Grayscale;
|
||||
break;
|
||||
case QPrinter::Color:
|
||||
d->colorModel = QPdfEngine::ColorModel::RGB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPK_Creator:
|
||||
d->creator = value.toString();
|
||||
@ -221,7 +228,7 @@ QVariant QPdfPrintEngine::property(PrintEnginePropertyKey key) const
|
||||
ret = d->collate;
|
||||
break;
|
||||
case PPK_ColorMode:
|
||||
ret = d->grayscale ? QPrinter::GrayScale : QPrinter::Color;
|
||||
ret = d->printerColorMode();
|
||||
break;
|
||||
case PPK_Creator:
|
||||
ret = d->creator;
|
||||
@ -367,6 +374,22 @@ QPdfPrintEnginePrivate::~QPdfPrintEnginePrivate()
|
||||
{
|
||||
}
|
||||
|
||||
QPrinter::ColorMode QPdfPrintEnginePrivate::printerColorMode() const
|
||||
{
|
||||
switch (colorModel) {
|
||||
case QPdfEngine::ColorModel::RGB:
|
||||
case QPdfEngine::ColorModel::CMYK:
|
||||
case QPdfEngine::ColorModel::Auto:
|
||||
return QPrinter::Color;
|
||||
case QPdfEngine::ColorModel::Grayscale:
|
||||
return QPrinter::GrayScale;
|
||||
}
|
||||
|
||||
Q_UNREACHABLE();
|
||||
return QPrinter::Color;
|
||||
}
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_PRINTER
|
||||
|
@ -79,6 +79,8 @@ public:
|
||||
QPdfPrintEnginePrivate(QPrinter::PrinterMode m);
|
||||
~QPdfPrintEnginePrivate();
|
||||
|
||||
QPrinter::ColorMode printerColorMode() const;
|
||||
|
||||
virtual bool openPrintDevice();
|
||||
virtual void closePrintDevice();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user