| /**************************************************************************** |
| ** |
| ** Copyright (C) 2014 John Layt <jlayt@kde.org> |
| ** Copyright (C) 2018 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the plugins 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$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qwindowsprintdevice.h" |
| |
| #include <qdebug.h> |
| |
| #ifndef DC_COLLATE |
| # define DC_COLLATE 22 |
| #endif |
| |
| QT_BEGIN_NAMESPACE |
| |
| QT_WARNING_DISABLE_GCC("-Wsign-compare") |
| typedef QVector<QWindowsPrinterInfo> WindowsPrinterLookup; |
| Q_GLOBAL_STATIC(WindowsPrinterLookup, windowsDeviceLookup); |
| |
| extern qreal qt_pointMultiplier(QPageLayout::Unit unit); |
| |
| static inline uint qwcsnlen(const wchar_t *str, uint maxlen) |
| { |
| uint length = 0; |
| if (str) { |
| while (length < maxlen && *str++) |
| length++; |
| } |
| return length; |
| } |
| |
| static QPrint::InputSlot paperBinToInputSlot(int windowsId, const QString &name) |
| { |
| QPrint::InputSlot slot; |
| slot.name = name; |
| int i; |
| for (i = 0; inputSlotMap[i].id != QPrint::CustomInputSlot; ++i) { |
| if (inputSlotMap[i].windowsId == windowsId) { |
| slot.key = inputSlotMap[i].key; |
| slot.id = inputSlotMap[i].id; |
| slot.windowsId = inputSlotMap[i].windowsId; |
| return slot; |
| } |
| } |
| slot.key = inputSlotMap[i].key; |
| slot.id = inputSlotMap[i].id; |
| slot.windowsId = windowsId; |
| return slot; |
| } |
| |
| static LPDEVMODE getDevmode(HANDLE hPrinter, const QString &printerId) |
| { |
| LPWSTR printerIdUtf16 = const_cast<LPWSTR>(reinterpret_cast<LPCWSTR>(printerId.utf16())); |
| // Allocate the required DEVMODE buffer |
| LONG dmSize = DocumentProperties(NULL, hPrinter, printerIdUtf16, NULL, NULL, 0); |
| if (dmSize <= 0) |
| return nullptr; |
| LPDEVMODE pDevMode = reinterpret_cast<LPDEVMODE>(malloc(dmSize)); |
| // Get the default DevMode |
| LONG result = DocumentProperties(NULL, hPrinter, printerIdUtf16, pDevMode, NULL, DM_OUT_BUFFER); |
| if (result != IDOK) { |
| free(pDevMode); |
| pDevMode = nullptr; |
| } |
| return pDevMode; |
| } |
| |
| QWindowsPrintDevice::QWindowsPrintDevice() |
| : QPlatformPrintDevice(), |
| m_hPrinter(0) |
| { |
| } |
| |
| QWindowsPrintDevice::QWindowsPrintDevice(const QString &id) |
| : QPlatformPrintDevice(id), |
| m_hPrinter(0) |
| { |
| // First do a fast lookup to see if printer exists, if it does then open it |
| if (!id.isEmpty() && QWindowsPrintDevice::availablePrintDeviceIds().contains(id)) { |
| if (OpenPrinter(const_cast<LPWSTR>(wcharId()), &m_hPrinter, nullptr)) { |
| DWORD needed = 0; |
| GetPrinter(m_hPrinter, 2, 0, 0, &needed); |
| QScopedArrayPointer<BYTE> buffer(new BYTE[needed]); |
| if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { |
| PPRINTER_INFO_2 info = reinterpret_cast<PPRINTER_INFO_2>(buffer.data()); |
| m_name = QString::fromWCharArray(info->pPrinterName); |
| m_location = QString::fromWCharArray(info->pLocation); |
| m_makeAndModel = QString::fromWCharArray(info->pDriverName); // TODO Check is not available elsewhere |
| m_isRemote = info->Attributes & PRINTER_ATTRIBUTE_NETWORK; |
| } |
| QWindowsPrinterInfo m_info; |
| m_info.m_id = m_id; |
| m_info.m_name = m_name; |
| m_info.m_location = m_location; |
| m_info.m_makeAndModel = m_makeAndModel; |
| m_info.m_isRemote = m_isRemote; |
| m_infoIndex = windowsDeviceLookup()->indexOf(m_info); |
| if (m_infoIndex != -1) { |
| m_info = windowsDeviceLookup()->at(m_infoIndex); |
| m_havePageSizes = m_info.m_havePageSizes; |
| m_pageSizes = m_info.m_pageSizes; |
| m_haveResolutions = m_info.m_haveResolutions; |
| m_resolutions = m_info.m_resolutions; |
| m_haveCopies = m_info.m_haveCopies; |
| m_supportsMultipleCopies = m_info.m_supportsMultipleCopies; |
| m_supportsCollateCopies = m_info.m_supportsCollateCopies; |
| m_haveMinMaxPageSizes = m_info.m_haveMinMaxPageSizes; |
| m_minimumPhysicalPageSize = m_info.m_minimumPhysicalPageSize; |
| m_maximumPhysicalPageSize = m_info.m_maximumPhysicalPageSize; |
| m_supportsCustomPageSizes = m_info.m_supportsCustomPageSizes; |
| m_haveInputSlots = m_info.m_haveInputSlots; |
| m_inputSlots = m_info.m_inputSlots; |
| m_haveOutputBins = m_info.m_haveOutputBins; |
| m_outputBins = m_info.m_outputBins; |
| m_haveDuplexModes = m_info.m_haveDuplexModes; |
| m_duplexModes = m_info.m_duplexModes; |
| m_haveColorModes = m_info.m_haveColorModes; |
| m_colorModes = m_info.m_colorModes; |
| m_infoIndex = windowsDeviceLookup()->indexOf(m_info); |
| } else { |
| windowsDeviceLookup()->append(m_info); |
| m_infoIndex = windowsDeviceLookup()->count() - 1; |
| } |
| } |
| } |
| } |
| |
| QWindowsPrintDevice::~QWindowsPrintDevice() |
| { |
| ClosePrinter(m_hPrinter); |
| } |
| |
| bool QWindowsPrintDevice::isValid() const |
| { |
| return m_hPrinter; |
| } |
| |
| bool QWindowsPrintDevice::isDefault() const |
| { |
| return m_id == defaultPrintDeviceId(); |
| } |
| |
| QPrint::DeviceState QWindowsPrintDevice::state() const |
| { |
| DWORD needed = 0; |
| GetPrinter(m_hPrinter, 6, 0, 0, &needed); |
| QScopedArrayPointer<BYTE> buffer(new BYTE[needed]); |
| |
| if (GetPrinter(m_hPrinter, 6, buffer.data(), needed, &needed)) { |
| PPRINTER_INFO_6 info = reinterpret_cast<PPRINTER_INFO_6>(buffer.data()); |
| // TODO Check mapping |
| if (info->dwStatus == 0 |
| || (info->dwStatus & PRINTER_STATUS_WAITING) == PRINTER_STATUS_WAITING |
| || (info->dwStatus & PRINTER_STATUS_POWER_SAVE) == PRINTER_STATUS_POWER_SAVE) { |
| return QPrint::Idle; |
| } else if ((info->dwStatus & PRINTER_STATUS_PRINTING) == PRINTER_STATUS_PRINTING |
| || (info->dwStatus & PRINTER_STATUS_BUSY) == PRINTER_STATUS_BUSY |
| || (info->dwStatus & PRINTER_STATUS_INITIALIZING) == PRINTER_STATUS_INITIALIZING |
| || (info->dwStatus & PRINTER_STATUS_IO_ACTIVE) == PRINTER_STATUS_IO_ACTIVE |
| || (info->dwStatus & PRINTER_STATUS_PROCESSING) == PRINTER_STATUS_PROCESSING |
| || (info->dwStatus & PRINTER_STATUS_WARMING_UP) == PRINTER_STATUS_WARMING_UP) { |
| return QPrint::Active; |
| } |
| } |
| |
| return QPrint::Error; |
| } |
| |
| void QWindowsPrintDevice::loadPageSizes() const |
| { |
| // Get the number of paper sizes and check all 3 attributes have same count |
| DWORD paperCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERNAMES, NULL, NULL); |
| if (int(paperCount) > 0 |
| && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERSIZE, NULL, NULL) == paperCount |
| && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, NULL, NULL) == paperCount) { |
| |
| QScopedArrayPointer<wchar_t> paperNames(new wchar_t[paperCount*64]); |
| QScopedArrayPointer<POINT> winSizes(new POINT[paperCount]); |
| QScopedArrayPointer<wchar_t> papers(new wchar_t[paperCount]); |
| |
| // Get the details and match the default paper size |
| if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERNAMES, paperNames.data(), NULL) == paperCount |
| && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERSIZE, (wchar_t *)winSizes.data(), NULL) == paperCount |
| && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, papers.data(), NULL) == paperCount) { |
| |
| // Returned size is in tenths of a millimeter |
| const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter); |
| for (int i = 0; i < int(paperCount); ++i) { |
| QSize size = QSize(qRound((winSizes[i].x / 10.0) * multiplier), qRound((winSizes[i].y / 10.0) * multiplier)); |
| wchar_t *paper = paperNames.data() + (i * 64); |
| QString name = QString::fromWCharArray(paper, qwcsnlen(paper, 64)); |
| m_pageSizes.append(createPageSize(papers[i], size, name)); |
| } |
| |
| } |
| } |
| |
| m_havePageSizes = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_havePageSizes = true; |
| info[m_infoIndex].m_pageSizes = m_pageSizes; |
| } |
| |
| QPageSize QWindowsPrintDevice::defaultPageSize() const |
| { |
| if (!m_havePageSizes) |
| loadPageSizes(); |
| |
| QPageSize pageSize; |
| |
| if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { |
| // Get the default paper size |
| if (pDevMode->dmFields & DM_PAPERSIZE) { |
| // Find the supported page size that matches, in theory default should be one of them |
| foreach (const QPageSize &ps, m_pageSizes) { |
| if (ps.windowsId() == pDevMode->dmPaperSize) { |
| pageSize = ps; |
| break; |
| } |
| } |
| } |
| // Clean-up |
| free(pDevMode); |
| } |
| |
| return pageSize; |
| } |
| |
| QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize, |
| QPageLayout::Orientation orientation, |
| int resolution) const |
| { |
| // TODO This is slow, need to cache values or find better way! |
| // Modify the DevMode to get the DC printable margins in device pixels |
| QMarginsF margins = QMarginsF(0, 0, 0, 0); |
| DWORD needed = 0; |
| GetPrinter(m_hPrinter, 2, 0, 0, &needed); |
| QScopedArrayPointer<BYTE> buffer(new BYTE[needed]); |
| if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) { |
| PPRINTER_INFO_2 info = reinterpret_cast<PPRINTER_INFO_2>(buffer.data()); |
| LPDEVMODE devMode = info->pDevMode; |
| bool separateDevMode = false; |
| if (!devMode) { |
| // GetPrinter() didn't include the DEVMODE. Get it a different way. |
| devMode = getDevmode(m_hPrinter, m_id); |
| if (!devMode) |
| return margins; |
| separateDevMode = true; |
| } |
| |
| HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode); |
| if (pageSize.id() == QPageSize::Custom || pageSize.windowsId() <= 0 || pageSize.windowsId() > DMPAPER_LAST) { |
| devMode->dmPaperSize = 0; |
| devMode->dmPaperWidth = pageSize.size(QPageSize::Millimeter).width() * 10.0; |
| devMode->dmPaperLength = pageSize.size(QPageSize::Millimeter).height() * 10.0; |
| } else { |
| devMode->dmPaperSize = pageSize.windowsId(); |
| } |
| devMode->dmPrintQuality = resolution; |
| devMode->dmOrientation = orientation == QPageLayout::Portrait ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE; |
| ResetDC(pDC, devMode); |
| const int dpiWidth = GetDeviceCaps(pDC, LOGPIXELSX); |
| const int dpiHeight = GetDeviceCaps(pDC, LOGPIXELSY); |
| const qreal wMult = 72.0 / dpiWidth; |
| const qreal hMult = 72.0 / dpiHeight; |
| const qreal physicalWidth = GetDeviceCaps(pDC, PHYSICALWIDTH) * wMult; |
| const qreal physicalHeight = GetDeviceCaps(pDC, PHYSICALHEIGHT) * hMult; |
| const qreal printableWidth = GetDeviceCaps(pDC, HORZRES) * wMult; |
| const qreal printableHeight = GetDeviceCaps(pDC, VERTRES) * hMult; |
| const qreal leftMargin = GetDeviceCaps(pDC, PHYSICALOFFSETX)* wMult; |
| const qreal topMargin = GetDeviceCaps(pDC, PHYSICALOFFSETY) * hMult; |
| const qreal rightMargin = physicalWidth - leftMargin - printableWidth; |
| const qreal bottomMargin = physicalHeight - topMargin - printableHeight; |
| margins = QMarginsF(leftMargin, topMargin, rightMargin, bottomMargin); |
| if (separateDevMode) |
| free(devMode); |
| DeleteDC(pDC); |
| } |
| return margins; |
| } |
| |
| void QWindowsPrintDevice::loadResolutions() const |
| { |
| DWORD resCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, NULL, NULL); |
| if (int(resCount) > 0) { |
| QScopedArrayPointer<LONG> resolutions(new LONG[resCount*2]); |
| // Get the details and match the default paper size |
| if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_ENUMRESOLUTIONS, (LPWSTR)resolutions.data(), NULL) == resCount) { |
| for (int i = 0; i < int(resCount * 2); i += 2) |
| m_resolutions.append(resolutions[i+1]); |
| } |
| } |
| m_haveResolutions = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveResolutions = true; |
| info[m_infoIndex].m_resolutions = m_resolutions; |
| } |
| |
| int QWindowsPrintDevice::defaultResolution() const |
| { |
| int resolution = 72; // TODO Set a sensible default? |
| |
| if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { |
| // Get the default resolution |
| if (pDevMode->dmFields & DM_YRESOLUTION) { |
| if (pDevMode->dmPrintQuality > 0) |
| resolution = pDevMode->dmPrintQuality; |
| else |
| resolution = pDevMode->dmYResolution; |
| } |
| // Clean-up |
| free(pDevMode); |
| } |
| return resolution; |
| } |
| |
| void QWindowsPrintDevice::loadInputSlots() const |
| { |
| const auto printerId = wcharId(); |
| DWORD binCount = DeviceCapabilities(printerId, nullptr, DC_BINS, nullptr, nullptr); |
| if (int(binCount) > 0 |
| && DeviceCapabilities(printerId, nullptr, DC_BINNAMES, nullptr, nullptr) == binCount) { |
| |
| QScopedArrayPointer<WORD> bins(new WORD[binCount]); |
| QScopedArrayPointer<wchar_t> binNames(new wchar_t[binCount*24]); |
| |
| // Get the details and match the default paper size |
| if (DeviceCapabilities(printerId, nullptr, DC_BINS, |
| reinterpret_cast<LPWSTR>(bins.data()), nullptr) == binCount |
| && DeviceCapabilities(printerId, nullptr, DC_BINNAMES, binNames.data(), |
| nullptr) == binCount) { |
| |
| for (int i = 0; i < int(binCount); ++i) { |
| wchar_t *binName = binNames.data() + (i * 24); |
| QString name = QString::fromWCharArray(binName, qwcsnlen(binName, 24)); |
| m_inputSlots.append(paperBinToInputSlot(bins[i], name)); |
| } |
| |
| } |
| } |
| |
| m_haveInputSlots = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveInputSlots = true; |
| info[m_infoIndex].m_inputSlots = m_inputSlots; |
| } |
| |
| QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot() const |
| { |
| QPrint::InputSlot inputSlot = QPlatformPrintDevice::defaultInputSlot();; |
| |
| if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { |
| // Get the default input slot |
| if (pDevMode->dmFields & DM_DEFAULTSOURCE) { |
| QPrint::InputSlot tempSlot = paperBinToInputSlot(pDevMode->dmDefaultSource, QString()); |
| foreach (const QPrint::InputSlot &slot, supportedInputSlots()) { |
| if (slot.key == tempSlot.key) { |
| inputSlot = slot; |
| break; |
| } |
| } |
| } |
| // Clean-up |
| free(pDevMode); |
| } |
| return inputSlot; |
| } |
| |
| void QWindowsPrintDevice::loadOutputBins() const |
| { |
| m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); |
| m_haveOutputBins = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveOutputBins = true; |
| info[m_infoIndex].m_outputBins = m_outputBins; |
| } |
| |
| void QWindowsPrintDevice::loadDuplexModes() const |
| { |
| m_duplexModes.append(QPrint::DuplexNone); |
| DWORD duplex = DeviceCapabilities(wcharId(), nullptr, DC_DUPLEX, nullptr, nullptr); |
| if (int(duplex) == 1) { |
| // TODO Assume if duplex flag supports both modes |
| m_duplexModes.append(QPrint::DuplexAuto); |
| m_duplexModes.append(QPrint::DuplexLongSide); |
| m_duplexModes.append(QPrint::DuplexShortSide); |
| } |
| m_haveDuplexModes = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveDuplexModes = true; |
| info[m_infoIndex].m_duplexModes = m_duplexModes; |
| } |
| |
| QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const |
| { |
| QPrint::DuplexMode duplexMode = QPrint::DuplexNone; |
| |
| if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { |
| // Get the default duplex mode |
| if (pDevMode->dmFields & DM_DUPLEX) { |
| if (pDevMode->dmDuplex == DMDUP_VERTICAL) |
| duplexMode = QPrint::DuplexLongSide; |
| else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL) |
| duplexMode = QPrint::DuplexShortSide; |
| } |
| // Clean-up |
| free(pDevMode); |
| } |
| return duplexMode; |
| } |
| |
| void QWindowsPrintDevice::loadColorModes() const |
| { |
| m_colorModes.append(QPrint::GrayScale); |
| DWORD color = DeviceCapabilities(wcharId(), nullptr, DC_COLORDEVICE, nullptr, nullptr); |
| if (int(color) == 1) |
| m_colorModes.append(QPrint::Color); |
| m_haveColorModes = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveColorModes = true; |
| info[m_infoIndex].m_colorModes = m_colorModes; |
| } |
| |
| QPrint::ColorMode QWindowsPrintDevice::defaultColorMode() const |
| { |
| if (!m_haveColorModes) |
| loadColorModes(); |
| if (!m_colorModes.contains(QPrint::Color)) |
| return QPrint::GrayScale; |
| |
| QPrint::ColorMode colorMode = QPrint::GrayScale; |
| |
| if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) { |
| // Get the default color mode |
| if (pDevMode->dmFields & DM_COLOR && pDevMode->dmColor == DMCOLOR_COLOR) |
| colorMode = QPrint::Color; |
| // Clean-up |
| free(pDevMode); |
| } |
| return colorMode; |
| } |
| |
| QStringList QWindowsPrintDevice::availablePrintDeviceIds() |
| { |
| QStringList list; |
| DWORD needed = 0; |
| DWORD returned = 0; |
| if ((!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) |
| || !needed) { |
| return list; |
| } |
| QScopedArrayPointer<BYTE> buffer(new BYTE[needed]); |
| if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, buffer.data(), needed, &needed, &returned)) |
| return list; |
| PPRINTER_INFO_4 infoList = reinterpret_cast<PPRINTER_INFO_4>(buffer.data()); |
| for (uint i = 0; i < returned; ++i) |
| list.append(QString::fromWCharArray(infoList[i].pPrinterName)); |
| return list; |
| } |
| |
| QString QWindowsPrintDevice::defaultPrintDeviceId() |
| { |
| DWORD size = 0; |
| if (GetDefaultPrinter(NULL, &size) == ERROR_FILE_NOT_FOUND) |
| return QString(); |
| |
| QScopedArrayPointer<wchar_t> name(new wchar_t[size]); |
| GetDefaultPrinter(name.data(), &size); |
| return QString::fromWCharArray(name.data()); |
| } |
| |
| void QWindowsPrintDevice::loadCopiesSupport() const |
| { |
| auto printerId = wcharId(); |
| m_supportsMultipleCopies = (DeviceCapabilities(printerId, NULL, DC_COPIES, NULL, NULL) > 1); |
| m_supportsCollateCopies = DeviceCapabilities(printerId, NULL, DC_COLLATE, NULL, NULL); |
| m_haveCopies = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveCopies = true; |
| info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies; |
| info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies; |
| } |
| |
| bool QWindowsPrintDevice::supportsCollateCopies() const |
| { |
| if (!m_haveCopies) |
| loadCopiesSupport(); |
| return m_supportsCollateCopies; |
| } |
| |
| bool QWindowsPrintDevice::supportsMultipleCopies() const |
| { |
| if (!m_haveCopies) |
| loadCopiesSupport(); |
| return m_supportsMultipleCopies; |
| } |
| |
| bool QWindowsPrintDevice::supportsCustomPageSizes() const |
| { |
| if (!m_haveMinMaxPageSizes) |
| loadMinMaxPageSizes(); |
| return m_supportsCustomPageSizes; |
| } |
| |
| QSize QWindowsPrintDevice::minimumPhysicalPageSize() const |
| { |
| if (!m_haveMinMaxPageSizes) |
| loadMinMaxPageSizes(); |
| return m_minimumPhysicalPageSize; |
| } |
| |
| QSize QWindowsPrintDevice::maximumPhysicalPageSize() const |
| { |
| if (!m_haveMinMaxPageSizes) |
| loadMinMaxPageSizes(); |
| return m_maximumPhysicalPageSize; |
| } |
| |
| void QWindowsPrintDevice::loadMinMaxPageSizes() const |
| { |
| // Min/Max custom size is in tenths of a millimeter |
| const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter); |
| auto printerId = wcharId(); |
| DWORD min = DeviceCapabilities(printerId, NULL, DC_MINEXTENT, NULL, NULL); |
| m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier); |
| DWORD max = DeviceCapabilities(printerId, NULL, DC_MAXEXTENT, NULL, NULL); |
| m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier); |
| m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0); |
| m_haveMinMaxPageSizes = true; |
| QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); |
| info[m_infoIndex].m_haveCopies = true; |
| info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies; |
| info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies; |
| } |
| |
| QT_END_NAMESPACE |