summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@digia.com>2013-09-13 23:20:38 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-14 21:15:35 +0100
commit3396ba5612c1047d1b21a90c4996dff848c00114 (patch)
tree389849c5108de7ff946ba14ff28f0757a95af41f /src
parent127c18ff1100a9fb8559ca651dbc03ff1f8eabbd (diff)
Match up the specified paper size to an existing one if possible
When EnumForms was used then the dmPaperSize was not always correct for the custom paper sizes available on some printers. By using DeviceCapabilities we can be sure that the information is correct in this respect. This also fixes respecting of the custom paper size if one is given and there is no corresponding existing paper size for it. Task-number: QTBUG-34276 Change-Id: I9924d5be8527027fc434261e37f6c7aae66210c3 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp128
1 files changed, 82 insertions, 46 deletions
diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp
index acaa32304e..e2446c19b1 100644
--- a/src/printsupport/kernel/qprintengine_win.cpp
+++ b/src/printsupport/kernel/qprintengine_win.cpp
@@ -67,6 +67,8 @@ QT_BEGIN_NAMESPACE
Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
extern QPainterPath qt_regionToPath(const QRegion &region);
+Q_PRINTSUPPORT_EXPORT QSizeF qt_SizeFromUnitToMillimeter(const QSizeF &, QPrinter::Unit, double);
+Q_PRINTSUPPORT_EXPORT double qt_multiplierForUnit(QPrinter::Unit unit, int resolution);
// #define QT_DEBUG_DRAW
@@ -114,6 +116,52 @@ static const struct {
{ 0, QPrinter::Custom }
};
+// Return a list of printer paper sizes in millimeters with the corresponding dmPaperSize value
+static QList<QPair<QSizeF, int> > printerPaperSizes(const QString &printerName)
+{
+ QList<QPair<QSizeF, int> > result;
+ const wchar_t *name = reinterpret_cast<const wchar_t*>(printerName.utf16());
+ DWORD paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERS, NULL, NULL);
+ if ((int)paperNameCount > 0) {
+ // If they are not equal, then there seems to be a problem with the driver
+ if (paperNameCount != DeviceCapabilities(name, NULL, DC_PAPERSIZE, NULL, NULL))
+ return result;
+ QScopedArrayPointer<wchar_t> papersNames(new wchar_t[paperNameCount]);
+ paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERS, papersNames.data(), NULL);
+ result.reserve(paperNameCount);
+ QScopedArrayPointer<POINT> paperSizes(new POINT[paperNameCount]);
+ paperNameCount = DeviceCapabilities(name, NULL, DC_PAPERSIZE, (wchar_t *)paperSizes.data(), NULL);
+ for (int i=0; i <(int)paperNameCount; i++)
+ result.push_back(qMakePair(QSizeF(paperSizes[i].x / 10, paperSizes[i].y / 10), papersNames[i]));
+ }
+ return result;
+}
+
+// Find the best-matching printer paper for size in millimeters.
+static inline int findCustomPaperSize(const QSizeF &needlePt, const QString &printerName)
+{
+ const QList<QPair<QSizeF, int> > sizes = printerPaperSizes(printerName);
+ const qreal nw = needlePt.width();
+ const qreal nh = needlePt.height();
+ for (int i = 0; i < sizes.size(); ++i) {
+ if (qAbs(nw - sizes.at(i).first.width()) <= 1 && qAbs(nh - sizes.at(i).first.height()) <= 1)
+ return sizes.at(i).second;
+ }
+ return -1;
+}
+
+static inline void setDevModePaperFlags(DEVMODE *devMode, bool custom)
+{
+ if (custom) {
+ devMode->dmPaperSize = DMPAPER_USER;
+ devMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH;
+ } else {
+ devMode->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
+ devMode->dmPaperLength = 0;
+ devMode->dmPaperWidth = 0;
+ }
+}
+
QPrinter::PaperSize mapDevmodePaperSize(int s)
{
int i = 0;
@@ -1293,6 +1341,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
break;
d->devMode->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom);
+ setDevModePaperFlags(d->devMode, d->has_custom_paper_size);
d->doReinit();
break;
case PPK_PaperName:
@@ -1320,9 +1369,19 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
wchar_t *papers = new wchar_t[size];
size = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->name.utf16()),
NULL, DC_PAPERS, papers, NULL);
- d->has_custom_paper_size = false;
- d->devMode->dmPaperSize = papers[paperPos];
- d->doReinit();
+ QScopedArrayPointer<POINT> paperSizes(new POINT[size]);
+ DWORD paperNameCount = DeviceCapabilities(reinterpret_cast<const wchar_t*>(d->name.utf16()), NULL, DC_PAPERSIZE, (wchar_t *)paperSizes.data(), NULL);
+ if (paperNameCount == size) {
+ const double multiplier = qt_multiplierForUnit(QPrinter::Millimeter, d->resolution);
+ d->paper_size = QSizeF((paperSizes[paperPos].x / 10.0) * multiplier, (paperSizes[paperPos].y / 10.0) * multiplier);
+ // Our sizes may not match the paper name's size exactly
+ // So we treat it as custom so we know the paper size is correct
+ d->has_custom_paper_size = true;
+ d->devMode->dmPaperSize = papers[paperPos];
+ setDevModePaperFlags(d->devMode, false);
+ d->doReinit();
+ }
+
delete [] papers;
}
}
@@ -1373,6 +1432,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
break;
d->has_custom_paper_size = false;
d->devMode->dmPaperSize = value.toInt();
+ setDevModePaperFlags(d->devMode, d->has_custom_paper_size);
d->doReinit();
break;
@@ -1382,30 +1442,17 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &
d->paper_size = value.toSizeF();
if (!d->devMode)
break;
- int orientation = d->devMode->dmOrientation;
- DWORD needed = 0;
- DWORD returned = 0;
- if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) {
- BYTE *forms = (BYTE *) malloc(needed);
- if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) {
- for (DWORD i=0; i< returned; ++i) {
- FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms);
- // the form sizes are specified in 1000th of a mm,
- // convert the size to Points
- QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0,
- (formArray[i].Size.cy * 72/25.4)/1000.0);
- if (qAbs(d->paper_size.width() - size.width()) <= 2
- && qAbs(d->paper_size.height() - size.height()) <= 2)
- {
- d->devMode->dmPaperSize = i + 1;
- break;
- }
- }
- }
- free(forms);
+ const QSizeF sizeMM = qt_SizeFromUnitToMillimeter(d->paper_size, QPrinter::Point, d->resolution);
+ const int match = findCustomPaperSize(sizeMM, d->name);
+ setDevModePaperFlags(d->devMode, (match >= 0) ? false : true);
+ if (match >= 0) {
+ d->devMode->dmPaperSize = match;
+ if (d->devMode->dmOrientation != DMORIENT_PORTRAIT)
+ qSwap(d->paper_size.rwidth(), d->paper_size.rheight());
+ } else {
+ d->devMode->dmPaperLength = qRound(sizeMM.height() * 10.0);
+ d->devMode->dmPaperWidth = qRound(sizeMM.width() * 10.0);
}
- if (orientation != DMORIENT_PORTRAIT)
- d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
break;
}
@@ -1692,7 +1739,7 @@ QList<QPair<QString, QSizeF> > QWin32PrintEngine::supportedSizesWithNames(const
for (int i=0;i<(int)size;i++) {
wchar_t *paper = papers + (i * 64);
QString str = QString::fromWCharArray(paper, qwcsnlen(paper, 64));
- paperSizes << qMakePair(str, QSizeF(points[i].x / 10, points[i].y / 10));
+ paperSizes << qMakePair(str, QSizeF(points[i].x / 10.0, points[i].y / 10.0));
}
delete [] points;
}
@@ -1908,30 +1955,19 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
SelectObject(hdc, old_font);
}
-
void QWin32PrintEnginePrivate::updateCustomPaperSize()
{
- uint paperSize = devMode->dmPaperSize;
+ const uint paperSize = devMode->dmPaperSize;
+ has_custom_paper_size = true;
if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) {
- has_custom_paper_size = true;
- DWORD needed = 0;
- DWORD returned = 0;
- if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) {
- BYTE *forms = (BYTE *) malloc(needed);
- if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) {
- if (paperSize <= returned) {
- FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms;
- int width = formArray[paperSize - 1].Size.cx; // 1/1000 of a mm
- int height = formArray[paperSize - 1].Size.cy; // 1/1000 of a mm
- paper_size = QSizeF((width * 72 /25.4) / 1000.0, (height * 72 / 25.4) / 1000.0);
- } else {
- has_custom_paper_size = false;
- }
+ const QList<QPair<QSizeF, int> > paperSizes = printerPaperSizes(name);
+ for (int i=0; i<paperSizes.size(); i++) {
+ if ((uint)paperSizes.at(i).second == paperSize) {
+ paper_size = paperSizes.at(paperSize).first;
+ has_custom_paper_size = false;
+ break;
}
- free(forms);
}
- } else {
- has_custom_paper_size = false;
}
}