diff options
Diffstat (limited to 'src/printsupport/platform/windows/qprintengine_win.cpp')
-rw-r--r-- | src/printsupport/platform/windows/qprintengine_win.cpp | 171 |
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 ®ion); 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 |