summaryrefslogtreecommitdiffstats
path: root/src/printsupport/platform/windows/qprintengine_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/printsupport/platform/windows/qprintengine_win.cpp')
-rw-r--r--src/printsupport/platform/windows/qprintengine_win.cpp171
1 files changed, 100 insertions, 71 deletions
diff --git a/src/printsupport/platform/windows/qprintengine_win.cpp b/src/printsupport/platform/windows/qprintengine_win.cpp
index 454bcab069..fa8d03a615 100644
--- a/src/printsupport/platform/windows/qprintengine_win.cpp
+++ b/src/printsupport/platform/windows/qprintengine_win.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtPrintSupport module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 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 <QtPrintSupport/qtprintsupportglobal.h>
@@ -49,6 +13,9 @@
#include <private/qfont_p.h>
#include <private/qfontengine_p.h>
#include <private/qpainter_p.h>
+#if QT_CONFIG(directwrite)
+# include <private/qwindowsfontenginedirectwrite_p.h>
+#endif
#include <qpa/qplatformprintplugin.h>
#include <qpa/qplatformprintersupport.h>
@@ -63,10 +30,10 @@
#include <QtCore/QMetaType>
#include <QtCore/qt_windows.h>
#include <QtGui/qpagelayout.h>
+#include <QtGui/private/qpixmap_win_p.h>
QT_BEGIN_NAMESPACE
-Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
extern QPainterPath qt_regionToPath(const QRegion &region);
extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
@@ -290,8 +257,22 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
|| d->txop >= QTransform::TxProject
|| !d->embed_fonts;
- if (!fallBack && ti.fontEngine->type() == QFontEngine::Win) {
- if (HFONT hfont = static_cast<HFONT>(ti.fontEngine->handle())) {
+ if (!fallBack) {
+ bool deleteFont = false;
+ HFONT hfont = nullptr;
+ if (ti.fontEngine->type() == QFontEngine::Win) {
+ hfont = static_cast<HFONT>(ti.fontEngine->handle());
+ }
+#if QT_CONFIG(directwrite)
+ else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
+ QWindowsFontEngineDirectWrite *fedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
+ hfont = fedw->createHFONT();
+ if (hfont)
+ deleteFont = true;
+ }
+#endif
+
+ if (hfont) {
// Try selecting the font to see if we get a substitution font
SelectObject(d->hdc, hfont);
if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) {
@@ -302,7 +283,12 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
GetTextFace(d->hdc, 64, n);
fallBack = QString::fromWCharArray(n)
!= QString::fromWCharArray(logFont.lfFaceName);
+
+ if (deleteFont)
+ DeleteObject(hfont);
}
+ } else {
+ fallBack = true;
}
}
@@ -447,7 +433,7 @@ void QWin32PrintEngine::updateClipPath(const QPainterPath &clipPath, Qt::ClipOpe
bool doclip = true;
if (op == Qt::NoClip) {
- SelectClipRgn(d->hdc, 0);
+ SelectClipRgn(d->hdc, nullptr);
doclip = false;
}
@@ -575,6 +561,7 @@ void QWin32PrintEngine::drawPixmap(const QRectF &targetRect,
QImage img(QSize(imgw, imgh), QImage::Format_RGB32);
+ img.setDevicePixelRatio(pixmap.devicePixelRatio());
img.fill(Qt::white);
QPainter painter(&img);
painter.drawPixmap(0,0, pixmap, tileSize * x, tileSize * y, imgw, imgh);
@@ -735,7 +722,7 @@ void QWin32PrintEnginePrivate::strokePath_dev(const QPainterPath &path, const QC
joinStyle = PS_JOIN_ROUND;
HPEN pen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | capStyle | joinStyle,
- (penWidth == 0) ? 1 : penWidth, &brush, 0, 0);
+ (penWidth == 0) ? 1 : penWidth, &brush, 0, nullptr);
HGDIOBJ old_pen = SelectObject(hdc, pen);
StrokePath(hdc);
@@ -855,7 +842,8 @@ void QWin32PrintEnginePrivate::initialize()
txop = QTransform::TxNone;
QString printerName = m_printDevice.id();
- bool ok = OpenPrinter((LPWSTR)printerName.utf16(), (LPHANDLE)&hPrinter, 0);
+ bool ok = OpenPrinter(reinterpret_cast<LPWSTR>(const_cast<ushort *>(printerName.utf16())),
+ reinterpret_cast<LPHANDLE>(&hPrinter), nullptr);
if (!ok) {
qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed");
return;
@@ -864,10 +852,10 @@ void QWin32PrintEnginePrivate::initialize()
// Fetch the PRINTER_INFO_2 with DEVMODE data containing the
// printer settings.
DWORD infoSize, numBytes;
- GetPrinter(hPrinter, 2, NULL, 0, &infoSize);
+ GetPrinter(hPrinter, 2, nullptr, 0, &infoSize);
hMem = GlobalAlloc(GHND, infoSize);
- pInfo = (PRINTER_INFO_2*) GlobalLock(hMem);
- ok = GetPrinter(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes);
+ pInfo = reinterpret_cast<PRINTER_INFO_2*>(GlobalLock(hMem));
+ ok = GetPrinter(hPrinter, 2, reinterpret_cast<LPBYTE>(pInfo), infoSize, &numBytes);
if (!ok) {
qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed");
@@ -885,23 +873,26 @@ void QWin32PrintEnginePrivate::initialize()
// Attempt to get the DEVMODE a different way.
// Allocate the required buffer
- LONG result = DocumentProperties(NULL, hPrinter, (LPWSTR)printerName.utf16(),
- NULL, NULL, 0);
- devMode = (DEVMODE *) malloc(result);
+ auto *lpwPrinterName = reinterpret_cast<LPWSTR>(const_cast<ushort *>(printerName.utf16()));
+ LONG result = DocumentProperties(nullptr, hPrinter, lpwPrinterName,
+ nullptr, nullptr, 0);
+ devMode = reinterpret_cast<DEVMODE *>(malloc(result));
+ initializeDevMode(devMode);
ownsDevMode = true;
// Get the default DevMode
- result = DocumentProperties(NULL, hPrinter, (LPWSTR)printerName.utf16(),
- devMode, NULL, DM_OUT_BUFFER);
+ result = DocumentProperties(nullptr, hPrinter, lpwPrinterName,
+ devMode, nullptr, DM_OUT_BUFFER);
if (result != IDOK) {
qErrnoWarning("QWin32PrintEngine::initialize: Failed to obtain devMode");
free(devMode);
- devMode = NULL;
+ devMode = nullptr;
ownsDevMode = false;
}
}
- hdc = CreateDC(NULL, (LPCWSTR)printerName.utf16(), 0, devMode);
+ hdc = CreateDC(nullptr, reinterpret_cast<LPCWSTR>(printerName.utf16()),
+ nullptr, devMode);
if (!hdc) {
qErrnoWarning("QWin32PrintEngine::initialize: CreateDC failed");
@@ -926,15 +917,22 @@ void QWin32PrintEnginePrivate::initialize()
#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS
}
+void QWin32PrintEnginePrivate::initializeDevMode(DEVMODE *devMode)
+{
+ memset(devMode, 0, sizeof(DEVMODE));
+ devMode->dmSize = sizeof(DEVMODE);
+ devMode->dmSpecVersion = DM_SPECVERSION;
+}
+
void QWin32PrintEnginePrivate::initHDC()
{
Q_ASSERT(hdc);
- HDC display_dc = GetDC(0);
+ HDC display_dc = GetDC(nullptr);
dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
dpi_display = GetDeviceCaps(display_dc, LOGPIXELSY);
- ReleaseDC(0, display_dc);
+ ReleaseDC(nullptr, display_dc);
if (dpi_display == 0) {
qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
"might be a driver problem");
@@ -977,11 +975,11 @@ void QWin32PrintEnginePrivate::release()
if (ownsDevMode)
free(devMode);
- hdc = 0;
- hPrinter = 0;
- pInfo = 0;
- hMem = 0;
- devMode = 0;
+ hdc = nullptr;
+ hPrinter = nullptr;
+ pInfo = nullptr;
+ hMem = nullptr;
+ devMode = nullptr;
ownsDevMode = false;
}
@@ -1065,6 +1063,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
if (!d->devMode)
break;
d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
+ d->devMode->dmFields |= DM_COLLATE;
d->doReinit();
}
break;
@@ -1074,6 +1073,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
if (!d->devMode)
break;
d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
+ d->devMode->dmFields |= DM_COLOR;
d->doReinit();
}
break;
@@ -1099,15 +1099,19 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
switch (mode) {
case QPrint::DuplexNone:
d->devMode->dmDuplex = DMDUP_SIMPLEX;
+ d->devMode->dmFields |= DM_DUPLEX;
break;
case QPrint::DuplexAuto:
d->devMode->dmDuplex = d->m_pageLayout.orientation() == QPageLayout::Landscape ? DMDUP_HORIZONTAL : DMDUP_VERTICAL;
+ d->devMode->dmFields |= DM_DUPLEX;
break;
case QPrint::DuplexLongSide:
d->devMode->dmDuplex = DMDUP_VERTICAL;
+ d->devMode->dmFields |= DM_DUPLEX;
break;
case QPrint::DuplexShortSide:
d->devMode->dmDuplex = DMDUP_HORIZONTAL;
+ d->devMode->dmFields |= DM_DUPLEX;
break;
default:
// Don't change
@@ -1135,6 +1139,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
break;
d->num_copies = value.toInt();
d->devMode->dmCopies = d->num_copies;
+ d->devMode->dmFields |= DM_COPIES;
d->doReinit();
break;
@@ -1143,9 +1148,10 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
break;
QPageLayout::Orientation orientation = QPageLayout::Orientation(value.toInt());
d->devMode->dmOrientation = orientation == QPageLayout::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
+ d->devMode->dmFields |= DM_ORIENTATION;
d->m_pageLayout.setOrientation(orientation);
- d->updateMetrics();
d->doReinit();
+ d->updateMetrics();
#ifdef QT_DEBUG_METRICS
qDebug() << "QWin32PrintEngine::setProperty(PPK_Orientation," << orientation << ')';
d->debugMetrics();
@@ -1279,7 +1285,8 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
Q_ASSERT(margins.size() == 4);
d->m_pageLayout.setUnits(QPageLayout::Point);
d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(),
- margins.at(2).toReal(), margins.at(3).toReal()));
+ margins.at(2).toReal(), margins.at(3).toReal()),
+ QPageLayout::OutOfBoundsPolicy::Clamp);
d->updateMetrics();
#ifdef QT_DEBUG_METRICS
qDebug() << "QWin32PrintEngine::setProperty(PPK_PageMargins," << margins << ')';
@@ -1307,7 +1314,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
case PPK_QPageMargins: {
QPair<QMarginsF, QPageLayout::Unit> pair = value.value<QPair<QMarginsF, QPageLayout::Unit> >();
d->m_pageLayout.setUnits(pair.second);
- d->m_pageLayout.setMargins(pair.first);
+ d->m_pageLayout.setMargins(pair.first, QPageLayout::OutOfBoundsPolicy::Clamp);
d->updateMetrics();
#ifdef QT_DEBUG_METRICS
qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageMargins," << pair.first << pair.second << ')';
@@ -1323,7 +1330,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
setProperty(PPK_FullPage, pageLayout.mode() == QPageLayout::FullPageMode);
setProperty(PPK_Orientation, QVariant::fromValue(pageLayout.orientation()));
d->m_pageLayout.setUnits(pageLayout.units());
- d->m_pageLayout.setMargins(pageLayout.margins());
+ d->m_pageLayout.setMargins(pageLayout.margins(), QPageLayout::OutOfBoundsPolicy::Clamp);
d->updateMetrics();
#ifdef QT_DEBUG_METRICS
qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageLayout," << pageLayout << ')';
@@ -1585,7 +1592,7 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD
d->ownsDevMode = false;
}
d->devMode = dm;
- d->hdc = CreateDC(NULL, reinterpret_cast<const wchar_t *>(d->m_printDevice.id().utf16()), 0, dm);
+ d->hdc = CreateDC(nullptr, reinterpret_cast<LPCWSTR>(d->m_printDevice.id().utf16()), nullptr, dm);
d->num_copies = d->devMode->dmCopies;
d->updatePageLayout();
@@ -1599,7 +1606,7 @@ void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalD
#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS
qDebug("QWin32PrintEngine::setGlobalDevMode()");
- debugMetrics();
+ d->debugMetrics();
#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS
}
@@ -1688,13 +1695,23 @@ void QWin32PrintEnginePrivate::updatePageLayout()
void QWin32PrintEnginePrivate::updateMetrics()
{
m_paintRectPixels = m_pageLayout.paintRectPixels(resolution);
+ // Some print devices allow scaling, so that "virtual" page size != current paper size
+ const int devWidth = GetDeviceCaps(hdc, PHYSICALWIDTH);
+ const int devHeight = GetDeviceCaps(hdc, PHYSICALHEIGHT);
+ const int pageWidth = m_pageLayout.fullRectPixels(dpi_x).width();
+ const int pageHeight = m_pageLayout.fullRectPixels(dpi_y).height();
+ const qreal pageScaleX = (devWidth && pageWidth) ? qreal(devWidth) / pageWidth : 1;
+ const qreal pageScaleY = (devHeight && pageHeight) ? qreal(devHeight) / pageHeight : 1;
+ m_paintRectPixels = QTransform::fromScale(pageScaleX, pageScaleY).mapRect(m_paintRectPixels);
+
QSizeF sizeMM = m_pageLayout.paintRect(QPageLayout::Millimeter).size();
m_paintSizeMM = QSize(qRound(sizeMM.width()), qRound(sizeMM.height()));
// Calculate the origin using the physical device pixels, not our paint pixels
// Origin is defined as User Margins - Device Margins
- QMarginsF margins = m_pageLayout.margins(QPageLayout::Millimeter) / 25.4;
- origin_x = qRound(margins.left() * dpi_x) - GetDeviceCaps(hdc, PHYSICALOFFSETX);
- origin_y = qRound(margins.top() * dpi_y) - GetDeviceCaps(hdc, PHYSICALOFFSETY);
+ const bool isFullPage = (m_pageLayout.mode() == QPageLayout::FullPageMode);
+ const QMarginsF margins = isFullPage ? QMarginsF() : (m_pageLayout.margins(QPageLayout::Millimeter) / 25.4);
+ origin_x = qRound(pageScaleX * margins.left() * dpi_x) - GetDeviceCaps(hdc, PHYSICALOFFSETX);
+ origin_y = qRound(pageScaleY * margins.top() * dpi_y) - GetDeviceCaps(hdc, PHYSICALOFFSETY);
}
void QWin32PrintEnginePrivate::debugMetrics() const
@@ -1719,12 +1736,21 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
const bool has_kerning = ti.f && ti.f->kerning();
- HFONT hfont = 0;
+ HFONT hfont = nullptr;
+ bool deleteFont = false;
if (ti.fontEngine->type() == QFontEngine::Win) {
if (ti.fontEngine->supportsTransformation(QTransform::fromScale(0.5, 0.5))) // is TrueType font?
hfont = static_cast<HFONT>(ti.fontEngine->handle());
}
+#if QT_CONFIG(directwrite)
+ else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
+ QWindowsFontEngineDirectWrite *fedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
+ hfont = fedw->createHFONT();
+ if (hfont)
+ deleteFont = true;
+ }
+#endif
if (!hfont)
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
@@ -1797,6 +1823,9 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
SetWorldTransform(hdc, &win_xform);
SelectObject(hdc, old_font);
+
+ if (deleteFont)
+ DeleteObject(hfont);
}
QT_END_NAMESPACE