Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qprintengine_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtPrintSupport/qtprintsupportglobal.h>
5
6#ifndef QT_NO_PRINTER
7
9
10#include <limits.h>
11
12#include <private/qprinter_p.h>
13#include <private/qfont_p.h>
14#include <private/qfontengine_p.h>
15#include <private/qpainter_p.h>
16#if QT_CONFIG(directwrite)
17# include <private/qwindowsfontenginedirectwrite_p.h>
18#endif
19
20#include <qpa/qplatformprintplugin.h>
21#include <qpa/qplatformprintersupport.h>
22
23#include <qbitmap.h>
24#include <qdebug.h>
25#include <qlist.h>
26#include <qpicture.h>
27#include <qpa/qplatformpixmap.h>
28#include <private/qpicture_p.h>
29#include <private/qpixmap_raster_p.h>
30#include <QtCore/QMetaType>
31#include <QtCore/qt_windows.h>
32#include <QtGui/qpagelayout.h>
33#include <QtGui/private/qpixmap_win_p.h>
34
36
37extern QPainterPath qt_regionToPath(const QRegion &region);
38extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits);
39
40// #define QT_DEBUG_DRAW
41// #define QT_DEBUG_METRICS
42
43static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc,
44 const QTransform &xform, const QPointF &topLeft);
45
48 PaintEngineFeatures(PrimitiveTransform
49 | PixmapTransform
50 | PerspectiveTransform
51 | PainterPaths
52 | Antialiasing
53 | PaintOutsidePaintEvent))
54{
56 d->mode = mode;
58 if (ps)
59 d->m_printDevice = ps->createPrintDevice(deviceId.isEmpty() ? ps->defaultPrintDeviceId() : deviceId);
60 d->m_pageLayout.setPageSize(d->m_printDevice.defaultPageSize());
61 d->initialize();
62}
63
64static QByteArray msgBeginFailed(const char *function, const DOCINFO &d)
65{
68 str << "QWin32PrintEngine::begin: " << function << " failed";
69 if (d.lpszDocName && d.lpszDocName[0])
70 str << ", document \"" << QString::fromWCharArray(d.lpszDocName) << '"';
71 if (d.lpszOutput && d.lpszOutput[0])
72 str << ", file \"" << QString::fromWCharArray(d.lpszOutput) << '"';
73 return std::move(result).toLocal8Bit();
74}
75
77{
79
81 if (!continueCall())
82 return true;
83
84 if (d->reinit) {
85 d->resetDC();
86 d->reinit = false;
87 }
88
89 // ### set default colors and stuff...
90
91 bool ok = d->state == QPrinter::Idle;
92
93 if (!d->hdc)
94 return false;
95
96 d->devMode->dmCopies = d->num_copies;
97
98 DOCINFO di;
99 memset(&di, 0, sizeof(DOCINFO));
100 di.cbSize = sizeof(DOCINFO);
101 if (d->docName.isEmpty())
102 di.lpszDocName = L"document1";
103 else
104 di.lpszDocName = reinterpret_cast<const wchar_t *>(d->docName.utf16());
105 if (d->printToFile && !d->fileName.isEmpty())
106 di.lpszOutput = reinterpret_cast<const wchar_t *>(d->fileName.utf16());
107 if (d->printToFile)
108 di.lpszOutput = d->fileName.isEmpty() ? L"FILE:" : reinterpret_cast<const wchar_t *>(d->fileName.utf16());
109 if (ok && StartDoc(d->hdc, &di) == SP_ERROR) {
110 qErrnoWarning(msgBeginFailed("StartDoc", di));
111 ok = false;
112 }
113
114 if (StartPage(d->hdc) <= 0) {
115 qErrnoWarning(msgBeginFailed("StartPage", di));
116 ok = false;
117 }
118
119 if (!ok) {
120 d->state = QPrinter::Idle;
121 } else {
122 d->state = QPrinter::Active;
123 }
124
125 d->matrix = QTransform();
126 d->has_pen = true;
127 d->pen = QColor(Qt::black);
128 d->has_brush = false;
129
130 d->complex_xform = false;
131
132 updateMatrix(d->matrix);
133
134 if (!ok)
135 cleanUp();
136
137#ifdef QT_DEBUG_METRICS
138 qDebug("QWin32PrintEngine::begin()");
139 d->debugMetrics();
140#endif // QT_DEBUG_METRICS
141
142 return ok;
143}
144
146{
148
149 if (d->hdc) {
150 if (d->state == QPrinter::Aborted) {
151 cleanUp();
152 AbortDoc(d->hdc);
153 return true;
154 }
155 }
156
158 if (!continueCall())
159 return true;
160
161 if (d->hdc) {
162 if (EndPage(d->hdc) <= 0) // end; printing done
163 qErrnoWarning("QWin32PrintEngine::end: EndPage failed (%p)", d->hdc);
164 if (EndDoc(d->hdc) <= 0)
165 qErrnoWarning("QWin32PrintEngine::end: EndDoc failed");
166 }
167
168 d->state = QPrinter::Idle;
169 d->reinit = true;
170 return true;
171}
172
174{
177
178 Q_ASSERT(d->hdc);
179
180 flushAndInit();
181
182 bool transparent = GetBkMode(d->hdc) == TRANSPARENT;
183
184 if (EndPage(d->hdc) <= 0) {
185 qErrnoWarning("QWin32PrintEngine::newPage: EndPage failed");
186 return false;
187 }
188
189 if (d->reinit) {
190 if (!d->resetDC())
191 return false;
192 d->reinit = false;
193 }
194
195 if (StartPage(d->hdc) <= 0) {
196 qErrnoWarning("Win32PrintEngine::newPage: StartPage failed");
197 return false;
198 }
199
200 SetTextAlign(d->hdc, TA_BASELINE);
201 if (transparent)
202 SetBkMode(d->hdc, TRANSPARENT);
203
204#ifdef QT_DEBUG_METRICS
205 qDebug("QWin32PrintEngine::newPage()");
206 d->debugMetrics();
207#endif // QT_DEBUG_METRICS
208
209 // ###
210 return true;
211
212 bool success = false;
213 if (d->hdc && d->state == QPrinter::Active) {
214 if (EndPage(d->hdc) > 0) {
215 // reinitialize the DC before StartPage if needed,
216 // because resetdc is disabled between calls to the StartPage and EndPage functions
217 // (see StartPage documentation in the Platform SDK:Windows GDI)
218// state = PST_ACTIVEDOC;
219// reinit();
220// state = PST_ACTIVE;
221 // start the new page now
222 if (d->reinit) {
223 if (!d->resetDC())
224 qErrnoWarning("QWin32PrintEngine::newPage(), ResetDC failed (2)");
225 d->reinit = false;
226 }
227 success = (StartPage(d->hdc) > 0);
228 if (!success)
229 qErrnoWarning("Win32PrintEngine::newPage: StartPage failed (2)");
230 }
231 if (!success) {
232 d->state = QPrinter::Aborted;
233 return false;
234 }
235 }
236 return true;
237}
238
240{
241 // do nothing loop.
242 return false;
243}
244
246{
247 Q_D(const QWin32PrintEngine);
248
250 if (!continueCall())
251 return;
252
253 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
254 QRgb brushColor = state->pen().brush().color().rgb();
255 bool fallBack = state->pen().brush().style() != Qt::SolidPattern
256 || qAlpha(brushColor) != 0xff
257 || d->txop >= QTransform::TxProject
258 || !d->embed_fonts;
259
260 if (!fallBack) {
261 bool deleteFont = false;
262 HFONT hfont = NULL;
263 if (ti.fontEngine->type() == QFontEngine::Win) {
264 hfont = static_cast<HFONT>(ti.fontEngine->handle());
265 }
266#if QT_CONFIG(directwrite)
267 else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
269 hfont = fedw->createHFONT();
270 if (hfont)
271 deleteFont = true;
272 }
273#endif
274
275 if (hfont) {
276 // Try selecting the font to see if we get a substitution font
277 SelectObject(d->hdc, hfont);
278 if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) {
279 LOGFONT logFont;
280 GetObject(hfont, sizeof(LOGFONT), &logFont);
281
282 wchar_t n[64];
283 GetTextFace(d->hdc, 64, n);
284 fallBack = QString::fromWCharArray(n)
285 != QString::fromWCharArray(logFont.lfFaceName);
286
287 if (deleteFont)
288 DeleteObject(hfont);
289 }
290 } else {
291 fallBack = true;
292 }
293 }
294
295
296 if (fallBack) {
297 QPaintEngine::drawTextItem(p, textItem);
298 return ;
299 }
300
301 COLORREF cf = RGB(qRed(brushColor), qGreen(brushColor), qBlue(brushColor));
302 SelectObject(d->hdc, CreateSolidBrush(cf));
303 SelectObject(d->hdc, CreatePen(PS_SOLID, 1, cf));
304 SetTextColor(d->hdc, cf);
305
306 draw_text_item_win(p, ti, d->hdc, d->matrix, QPointF(0.0, 0.0));
307 DeleteObject(SelectObject(d->hdc,GetStockObject(HOLLOW_BRUSH)));
308 DeleteObject(SelectObject(d->hdc,GetStockObject(BLACK_PEN)));
309}
310
312{
313 Q_D(const QWin32PrintEngine);
314
315 if (!d->hdc)
316 return 0;
317
318 int val;
319 int res = d->resolution;
320
321 switch (m) {
323 val = d->m_paintRectPixels.width();
324#ifdef QT_DEBUG_METRICS
325 qDebug() << "QWin32PrintEngine::metric(PdmWidth) = " << val;
326 d->debugMetrics();
327#endif // QT_DEBUG_METRICS
328 break;
330 val = d->m_paintRectPixels.height();
331#ifdef QT_DEBUG_METRICS
332 qDebug() << "QWin32PrintEngine::metric(PdmHeight) = " << val;
333 d->debugMetrics();
334#endif // QT_DEBUG_METRICS
335 break;
337 val = res;
338 break;
340 val = res;
341 break;
343 val = GetDeviceCaps(d->hdc, LOGPIXELSX);
344 break;
346 val = GetDeviceCaps(d->hdc, LOGPIXELSY);
347 break;
349 val = d->m_paintSizeMM.width();
350#ifdef QT_DEBUG_METRICS
351 qDebug() << "QWin32PrintEngine::metric(PdmWidthMM) = " << val;
352 d->debugMetrics();
353#endif // QT_DEBUG_METRICS
354 break;
356 val = d->m_paintSizeMM.height();
357#ifdef QT_DEBUG_METRICS
358 qDebug() << "QWin32PrintEngine::metric(PdmHeightMM) = " << val;
359 d->debugMetrics();
360#endif // QT_DEBUG_METRICS
361 break;
363 {
364 int bpp = GetDeviceCaps(d->hdc, BITSPIXEL);
365 if (bpp==32)
366 val = INT_MAX;
367 else if (bpp<=8)
368 val = GetDeviceCaps(d->hdc, NUMCOLORS);
369 else
370 val = 1 << (bpp * GetDeviceCaps(d->hdc, PLANES));
371 }
372 break;
374 val = GetDeviceCaps(d->hdc, PLANES);
375 break;
377 val = 1;
378 break;
381 break;
382 default:
383 qWarning("QPrinter::metric: Invalid metric command");
384 return 0;
385 }
386 return val;
387}
388
390{
392
394 if (!continueCall())
395 return;
396
397 if (state.state() & DirtyTransform) {
399 }
400
401 if (state.state() & DirtyPen) {
402 d->pen = state.pen();
403 d->has_pen = d->pen.style() != Qt::NoPen && d->pen.isSolid();
404 }
405
406 if (state.state() & DirtyBrush) {
408 d->has_brush = brush.style() == Qt::SolidPattern;
409 d->brush_color = brush.color();
410 }
411
412 if (state.state() & DirtyClipEnabled) {
413 if (state.isClipEnabled())
414 updateClipPath(painter()->clipPath(), Qt::ReplaceClip);
415 else
417 }
418
419 if (state.state() & DirtyClipPath) {
421 }
422
423 if (state.state() & DirtyClipRegion) {
424 QRegion clipRegion = state.clipRegion();
425 QPainterPath clipPath = qt_regionToPath(clipRegion);
427 }
428}
429
431{
433
434 bool doclip = true;
435 if (op == Qt::NoClip) {
436 SelectClipRgn(d->hdc, 0);
437 doclip = false;
438 }
439
440 if (doclip) {
441 QPainterPath xformed = clipPath * d->matrix;
442
443 if (xformed.isEmpty()) {
444// QRegion empty(-0x1000000, -0x1000000, 1, 1);
445 HRGN empty = CreateRectRgn(-0x1000000, -0x1000000, -0x0fffffff, -0x0ffffff);
446 SelectClipRgn(d->hdc, empty);
447 DeleteObject(empty);
448 } else {
449 d->composeGdiPath(xformed);
450 const int ops[] = {
451 -1, // Qt::NoClip, covered above
452 RGN_COPY, // Qt::ReplaceClip
453 RGN_AND, // Qt::IntersectClip
454 RGN_OR // Qt::UniteClip
455 };
456 Q_ASSERT(op > 0 && unsigned(op) <= sizeof(ops) / sizeof(int));
457 SelectClipPath(d->hdc, ops[op]);
458 }
459 }
460
462 if (!aclip.isEmpty()) {
463 QTransform tx(d->stretch_x, 0, 0, d->stretch_y, d->origin_x, d->origin_y);
464 d->composeGdiPath(tx.map(aclip));
465 SelectClipPath(d->hdc, RGN_DIFF);
466 }
467}
468
470{
472
473 QTransform stretch(d->stretch_x, 0, 0, d->stretch_y, d->origin_x, d->origin_y);
474 d->painterMatrix = m;
475 d->matrix = d->painterMatrix * stretch;
476 d->txop = d->matrix.type();
477 d->complex_xform = (d->txop > QTransform::TxScale);
478}
479
481{
486
488 const QPixmap &originalPixmap,
489 const QRectF &sourceRect)
490{
492
493 QAlphaPaintEngine::drawPixmap(targetRect, originalPixmap, sourceRect);
494 if (!continueCall())
495 return;
496
497 const int tileSize = 2048;
498
499 QRectF r = targetRect;
500 QRectF sr = sourceRect;
501
502 QPixmap pixmap = originalPixmap;
503 if (sr.size() != pixmap.size()) {
504 pixmap = pixmap.copy(sr.toRect());
505 }
506
507 qreal scaleX = 1.0f;
508 qreal scaleY = 1.0f;
509
510 QTransform scaleMatrix = QTransform::fromScale(r.width() / pixmap.width(), r.height() / pixmap.height());
511 QTransform adapted = QPixmap::trueMatrix(d->painterMatrix * scaleMatrix,
512 pixmap.width(), pixmap.height());
513
514 qreal xform_offset_x = adapted.dx();
515 qreal xform_offset_y = adapted.dy();
516
517 if (d->complex_xform) {
518 pixmap = pixmap.transformed(adapted);
519 scaleX = d->stretch_x;
520 scaleY = d->stretch_y;
521 } else {
522 scaleX = d->stretch_x * (r.width() / pixmap.width()) * d->painterMatrix.m11();
523 scaleY = d->stretch_y * (r.height() / pixmap.height()) * d->painterMatrix.m22();
524 }
525
526 QPointF topLeft = r.topLeft() * d->painterMatrix;
527 int tx = int(topLeft.x() * d->stretch_x + d->origin_x);
528 int ty = int(topLeft.y() * d->stretch_y + d->origin_y);
529 int tw = qAbs(int(pixmap.width() * scaleX));
530 int th = qAbs(int(pixmap.height() * scaleY));
531
532 xform_offset_x *= d->stretch_x;
533 xform_offset_y *= d->stretch_y;
534
535 int dc_state = SaveDC(d->hdc);
536
537 int tilesw = pixmap.width() / tileSize;
538 int tilesh = pixmap.height() / tileSize;
539 ++tilesw;
540 ++tilesh;
541
542 int txinc = tileSize*scaleX;
543 int tyinc = tileSize*scaleY;
544
545 for (int y = 0; y < tilesh; ++y) {
546 int tposy = ty + (y * tyinc);
547 int imgh = tileSize;
548 int height = tyinc;
549 if (y == (tilesh - 1)) {
550 imgh = pixmap.height() - (y * tileSize);
551 height = (th - (y * tyinc));
552 }
553 for (int x = 0; x < tilesw; ++x) {
554 int tposx = tx + (x * txinc);
555 int imgw = tileSize;
556 int width = txinc;
557 if (x == (tilesw - 1)) {
558 imgw = pixmap.width() - (x * tileSize);
559 width = (tw - (x * txinc));
560 }
561
562
563 QImage img(QSize(imgw, imgh), QImage::Format_RGB32);
564 img.setDevicePixelRatio(pixmap.devicePixelRatio());
565 img.fill(Qt::white);
567 painter.drawPixmap(0,0, pixmap, tileSize * x, tileSize * y, imgw, imgh);
569
570 HBITMAP hbitmap = qt_pixmapToWinHBITMAP(p, HBitmapNoAlpha);
571 HDC hbitmap_hdc = CreateCompatibleDC(d->hdc);
572 HGDIOBJ null_bitmap = SelectObject(hbitmap_hdc, hbitmap);
573
574 if (!StretchBlt(d->hdc, qRound(tposx - xform_offset_x), qRound(tposy - xform_offset_y), width, height,
575 hbitmap_hdc, 0, 0, p.width(), p.height(), SRCCOPY))
576 qErrnoWarning("QWin32PrintEngine::drawPixmap, StretchBlt failed");
577
578 SelectObject(hbitmap_hdc, null_bitmap);
579 DeleteObject(hbitmap);
580 DeleteDC(hbitmap_hdc);
581 }
582 }
583
584 RestoreDC(d->hdc, dc_state);
585}
586
587
589{
591
593 if (!continueCall())
594 return;
595
596 if (d->complex_xform || !pos.isNull()) {
598 } else {
599 int dc_state = SaveDC(d->hdc);
600
601 HBITMAP hbitmap = qt_pixmapToWinHBITMAP(pm, HBitmapNoAlpha);
602 HDC hbitmap_hdc = CreateCompatibleDC(d->hdc);
603 HGDIOBJ null_bitmap = SelectObject(hbitmap_hdc, hbitmap);
604
605 QRectF trect = d->painterMatrix.mapRect(r);
606 int tx = int(trect.left() * d->stretch_x + d->origin_x);
607 int ty = int(trect.top() * d->stretch_y + d->origin_y);
608
609 int xtiles = int(trect.width() / pm.width()) + 1;
610 int ytiles = int(trect.height() / pm.height()) + 1;
611 int xinc = int(pm.width() * d->stretch_x);
612 int yinc = int(pm.height() * d->stretch_y);
613
614 for (int y = 0; y < ytiles; ++y) {
615 int ity = ty + (yinc * y);
616 int ith = pm.height();
617 if (y == (ytiles - 1)) {
618 ith = int(trect.height() - (pm.height() * y));
619 }
620
621 for (int x = 0; x < xtiles; ++x) {
622 int itx = tx + (xinc * x);
623 int itw = pm.width();
624 if (x == (xtiles - 1)) {
625 itw = int(trect.width() - (pm.width() * x));
626 }
627
628 if (!StretchBlt(d->hdc, itx, ity, int(itw * d->stretch_x), int(ith * d->stretch_y),
629 hbitmap_hdc, 0, 0, itw, ith, SRCCOPY))
630 qErrnoWarning("QWin32PrintEngine::drawPixmap, StretchBlt failed");
631
632 }
633 }
634
635 SelectObject(hbitmap_hdc, null_bitmap);
636 DeleteObject(hbitmap);
637 DeleteDC(hbitmap_hdc);
638
639 RestoreDC(d->hdc, dc_state);
640 }
641}
642
643
645{
646 if (!BeginPath(hdc))
647 qErrnoWarning("QWin32PrintEnginePrivate::drawPath: BeginPath failed");
648
649 // Drawing the subpaths
650 int start = -1;
651 for (int i=0; i<path.elementCount(); ++i) {
652 const QPainterPath::Element &elm = path.elementAt(i);
653 switch (elm.type) {
655 if (start >= 0
656 && path.elementAt(start).x == path.elementAt(i-1).x
657 && path.elementAt(start).y == path.elementAt(i-1).y)
658 CloseFigure(hdc);
659 start = i;
660 MoveToEx(hdc, qRound(elm.x), qRound(elm.y), 0);
661 break;
663 LineTo(hdc, qRound(elm.x), qRound(elm.y));
664 break;
666 POINT pts[3] = {
667 { qRound(elm.x), qRound(elm.y) },
668 { qRound(path.elementAt(i+1).x), qRound(path.elementAt(i+1).y) },
669 { qRound(path.elementAt(i+2).x), qRound(path.elementAt(i+2).y) }
670 };
671 i+=2;
672 PolyBezierTo(hdc, pts, 3);
673 break;
674 }
675 default:
676 qFatal("QWin32PaintEngine::drawPath: Unhandled type: %d", elm.type);
677 }
678 }
679
680 if (start >= 0
681 && path.elementAt(start).x == path.elementAt(path.elementCount()-1).x
682 && path.elementAt(start).y == path.elementAt(path.elementCount()-1).y)
683 CloseFigure(hdc);
684
685 if (!EndPath(hdc))
686 qErrnoWarning("QWin32PaintEngine::drawPath: EndPath failed");
687
688 SetPolyFillMode(hdc, path.fillRule() == Qt::WindingFill ? WINDING : ALTERNATE);
689}
690
691
693{
694#ifdef QT_DEBUG_DRAW
695 qDebug() << " --- QWin32PrintEnginePrivate::fillPath() bound:" << path.boundingRect() << color;
696#endif
697
699
700 HBRUSH brush = CreateSolidBrush(RGB(color.red(), color.green(), color.blue()));
701 HGDIOBJ old_brush = SelectObject(hdc, brush);
702 FillPath(hdc);
703 DeleteObject(SelectObject(hdc, old_brush));
704}
705
707{
709 LOGBRUSH brush;
710 brush.lbStyle = BS_SOLID;
711 brush.lbColor = RGB(color.red(), color.green(), color.blue());
712 DWORD capStyle = PS_ENDCAP_SQUARE;
713 DWORD joinStyle = PS_JOIN_BEVEL;
714 if (pen.capStyle() == Qt::FlatCap)
715 capStyle = PS_ENDCAP_FLAT;
716 else if (pen.capStyle() == Qt::RoundCap)
717 capStyle = PS_ENDCAP_ROUND;
718
719 if (pen.joinStyle() == Qt::MiterJoin)
720 joinStyle = PS_JOIN_MITER;
721 else if (pen.joinStyle() == Qt::RoundJoin)
722 joinStyle = PS_JOIN_ROUND;
723
724 HPEN pen = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | capStyle | joinStyle,
725 (penWidth == 0) ? 1 : penWidth, &brush, 0, 0);
726
727 HGDIOBJ old_pen = SelectObject(hdc, pen);
728 StrokePath(hdc);
729 DeleteObject(SelectObject(hdc, old_pen));
730}
731
732
734{
736}
737
739{
740 QPainterPathStroker stroker;
741 if (pen.style() == Qt::CustomDashLine) {
742 stroker.setDashPattern(pen.dashPattern());
743 stroker.setDashOffset(pen.dashOffset());
744 } else {
745 stroker.setDashPattern(pen.style());
746 }
747 stroker.setCapStyle(pen.capStyle());
748 stroker.setJoinStyle(pen.joinStyle());
749 stroker.setMiterLimit(pen.miterLimit());
750
751 QPainterPath stroke;
752 qreal width = pen.widthF();
753 bool cosmetic = pen.isCosmetic();
754 if (pen.style() == Qt::SolidLine && (cosmetic || matrix.type() < QTransform::TxScale)) {
756 } else {
757 stroker.setWidth(width);
758 if (cosmetic) {
759 stroke = stroker.createStroke(path * matrix);
760 } else {
761 stroke = stroker.createStroke(path) * painterMatrix;
763 stroke = stroke * stretch;
764 }
765
766 if (stroke.isEmpty())
767 return;
768
769 fillPath_dev(stroke, color);
770 }
771}
772
773
775{
776#ifdef QT_DEBUG_DRAW
777 qDebug() << " - QWin32PrintEngine::drawPath(), bounds: " << path.boundingRect();
778#endif
779
781
783 if (!continueCall())
784 return;
785
786 if (d->has_brush)
787 d->fillPath(path, d->brush_color);
788
789 if (d->has_pen)
790 d->strokePath(path, d->pen.color());
791}
792
793
795{
796#ifdef QT_DEBUG_DRAW
797 qDebug() << " - QWin32PrintEngine::drawPolygon(), pointCount: " << pointCount;
798#endif
799
801 if (!continueCall())
802 return;
803
804 Q_ASSERT(pointCount > 1);
805
807
808 for (int i=1; i<pointCount; ++i) {
809 path.lineTo(points[i]);
810 }
811
813
814 bool has_brush = d->has_brush;
815
816 if (mode == PolylineMode)
817 d->has_brush = false; // No brush for polylines
818 else
819 path.closeSubpath(); // polygons are should always be closed.
820
821 drawPath(path);
822 d->has_brush = has_brush;
823}
824
826{
827 release();
828}
829
831{
832 release();
833
835 Q_ASSERT(!hdc);
837 Q_ASSERT(!pInfo);
838
839 if (!m_printDevice.isValid())
840 return;
841
843
844 QString printerName = m_printDevice.id();
845 bool ok = OpenPrinter((LPWSTR)printerName.utf16(), (LPHANDLE)&hPrinter, 0);
846 if (!ok) {
847 qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed");
848 return;
849 }
850
851 // Fetch the PRINTER_INFO_2 with DEVMODE data containing the
852 // printer settings.
853 DWORD infoSize, numBytes;
854 GetPrinter(hPrinter, 2, NULL, 0, &infoSize);
855 hMem = GlobalAlloc(GHND, infoSize);
856 pInfo = (PRINTER_INFO_2*) GlobalLock(hMem);
857 ok = GetPrinter(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes);
858
859 if (!ok) {
860 qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed");
861 release();
862 return;
863 }
864
865 devMode = pInfo->pDevMode;
866
867 if (!devMode) {
868 // pInfo->pDevMode == NULL for some printers and passing NULL
869 // into CreateDC leads to the printer doing nothing. In addition,
870 // the framework assumes that devMode isn't NULL, such as in
871 // QWin32PrintEngine::begin() and QPageSetupDialog::exec()
872 // Attempt to get the DEVMODE a different way.
873
874 // Allocate the required buffer
875 LONG result = DocumentProperties(NULL, hPrinter, (LPWSTR)printerName.utf16(),
876 NULL, NULL, 0);
877 devMode = (DEVMODE *) malloc(result);
878 ownsDevMode = true;
879
880 // Get the default DevMode
881 result = DocumentProperties(NULL, hPrinter, (LPWSTR)printerName.utf16(),
882 devMode, NULL, DM_OUT_BUFFER);
883 if (result != IDOK) {
884 qErrnoWarning("QWin32PrintEngine::initialize: Failed to obtain devMode");
885 free(devMode);
886 devMode = NULL;
887 ownsDevMode = false;
888 }
889 }
890
891 hdc = CreateDC(NULL, (LPCWSTR)printerName.utf16(), 0, devMode);
892
893 if (!hdc) {
894 qErrnoWarning("QWin32PrintEngine::initialize: CreateDC failed");
895 release();
896 return;
897 }
898
901
902 initHDC();
903
904 if (devMode) {
905 num_copies = devMode->dmCopies;
906 devMode->dmCollate = DMCOLLATE_TRUE;
908 }
909
910#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS
911 qDebug("QWin32PrintEngine::initialize()");
912 debugMetrics();
913#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS
914}
915
917{
918 Q_ASSERT(hdc);
919
920 HDC display_dc = GetDC(0);
921 dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
922 dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
923 dpi_display = GetDeviceCaps(display_dc, LOGPIXELSY);
924 ReleaseDC(0, display_dc);
925 if (dpi_display == 0) {
926 qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
927 "might be a driver problem");
928 dpi_display = 96; // Reasonable default
929 }
930
931 switch(mode) {
934 stretch_x = dpi_x / double(dpi_display);
935 stretch_y = dpi_y / double(dpi_display);
936 break;
940 stretch_x = 1;
941 stretch_y = 1;
942 break;
943 default:
944 break;
945 }
946
948}
949
951{
952 if (globalDevMode) { // Devmode comes from print dialog
953 GlobalUnlock(globalDevMode);
954 } else if (hMem) {
955 GlobalUnlock(hMem);
956 GlobalFree(hMem);
957 }
958 if (hPrinter)
959 ClosePrinter(hPrinter);
960 if (hdc)
961 DeleteDC(hdc);
962
963 // Check if devMode was allocated separately from pInfo / hMem.
964 if (ownsDevMode)
965 free(devMode);
966
967 hdc = 0;
968 hPrinter = 0;
969 pInfo = 0;
970 hMem = 0;
971 devMode = 0;
972 ownsDevMode = false;
973}
974
976{
977 if (state == QPrinter::Active) {
978 reinit = true;
979 } else {
980 resetDC();
981 reinit = false;
982 }
983}
984
986{
987 if (!hdc) {
988 qWarning("ResetDC() called with null hdc.");
989 return false;
990 }
991 const HDC oldHdc = hdc;
992 const HDC hdc = ResetDC(oldHdc, devMode);
993 if (!hdc) {
994 const int lastError = GetLastError();
995 qErrnoWarning(lastError, "ResetDC() on %p failed (%d)", oldHdc, lastError);
996 }
997 return hdc != 0;
998}
999
1001{
1002 for (int i = 0; i < inputSlots.size(); ++i) {
1003 if (inputSlots.at(i).id == id)
1004 return i;
1005 }
1006 return -1;
1007}
1008
1009static int indexOfWindowsId(const QList<QPrint::InputSlot> &inputSlots, int windowsId)
1010{
1011 for (int i = 0; i < inputSlots.size(); ++i) {
1012 if (inputSlots.at(i).windowsId == windowsId)
1013 return i;
1014 }
1015 return -1;
1016}
1017
1019{
1020 Q_D(QWin32PrintEngine);
1021 switch (key) {
1022
1023 // The following keys are properties or derived values and so cannot be set
1024 case PPK_PageRect:
1025 break;
1026 case PPK_PaperRect:
1027 break;
1028 case PPK_PaperSources:
1029 break;
1031 break;
1033 break;
1034
1035 // The following keys are settings that are unsupported by the Windows PrintEngine
1036 case PPK_CustomBase:
1037 break;
1038 case PPK_PageOrder:
1039 break;
1040 case PPK_PrinterProgram:
1041 break;
1043 break;
1044
1045 // The following keys are properties and settings that are supported by the Windows PrintEngine
1046 case PPK_FontEmbedding:
1047 d->embed_fonts = value.toBool();
1048 break;
1049
1050 case PPK_CollateCopies:
1051 {
1052 if (!d->devMode)
1053 break;
1054 d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
1055 d->doReinit();
1056 }
1057 break;
1058
1059 case PPK_ColorMode:
1060 {
1061 if (!d->devMode)
1062 break;
1063 d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
1064 d->doReinit();
1065 }
1066 break;
1067
1068 case PPK_Creator:
1069 d->m_creator = value.toString();
1070 break;
1071
1072 case PPK_DocumentName:
1073 if (isActive()) {
1074 qWarning("QWin32PrintEngine: Cannot change document name while printing is active");
1075 return;
1076 }
1077 d->docName = value.toString();
1078 break;
1079
1080 case PPK_Duplex: {
1081 if (!d->devMode)
1082 break;
1084 if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice.supportedDuplexModes().contains(mode))
1085 break;
1086 switch (mode) {
1087 case QPrint::DuplexNone:
1088 d->devMode->dmDuplex = DMDUP_SIMPLEX;
1089 break;
1090 case QPrint::DuplexAuto:
1091 d->devMode->dmDuplex = d->m_pageLayout.orientation() == QPageLayout::Landscape ? DMDUP_HORIZONTAL : DMDUP_VERTICAL;
1092 break;
1094 d->devMode->dmDuplex = DMDUP_VERTICAL;
1095 break;
1097 d->devMode->dmDuplex = DMDUP_HORIZONTAL;
1098 break;
1099 default:
1100 // Don't change
1101 break;
1102 }
1103 d->doReinit();
1104 break;
1105 }
1106
1107 case PPK_FullPage:
1108 if (value.toBool())
1109 d->m_pageLayout.setMode(QPageLayout::FullPageMode);
1110 else
1111 d->m_pageLayout.setMode(QPageLayout::StandardMode);
1112 d->updateMetrics();
1113#ifdef QT_DEBUG_METRICS
1114 qDebug() << "QWin32PrintEngine::setProperty(PPK_FullPage," << value.toBool() << + ")";
1115 d->debugMetrics();
1116#endif // QT_DEBUG_METRICS
1117 break;
1118
1119 case PPK_CopyCount:
1120 case PPK_NumberOfCopies:
1121 if (!d->devMode)
1122 break;
1123 d->num_copies = value.toInt();
1124 d->devMode->dmCopies = d->num_copies;
1125 d->doReinit();
1126 break;
1127
1128 case PPK_Orientation: {
1129 if (!d->devMode)
1130 break;
1132 d->devMode->dmOrientation = orientation == QPageLayout::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
1133 d->m_pageLayout.setOrientation(orientation);
1134 d->updateMetrics();
1135 d->doReinit();
1136#ifdef QT_DEBUG_METRICS
1137 qDebug() << "QWin32PrintEngine::setProperty(PPK_Orientation," << orientation << ')';
1138 d->debugMetrics();
1139#endif // QT_DEBUG_METRICS
1140 break;
1141 }
1142
1143 case PPK_OutputFileName:
1144 if (isActive()) {
1145 qWarning("QWin32PrintEngine: Cannot change filename while printing");
1146 } else {
1147 d->fileName = value.toString();
1148 d->printToFile = !value.toString().isEmpty();
1149 }
1150 break;
1151
1152 case PPK_PageSize: {
1153 if (!d->devMode)
1154 break;
1155 const QPageSize pageSize = QPageSize(QPageSize::PageSizeId(value.toInt()));
1156 if (pageSize.isValid()) {
1157 d->setPageSize(pageSize);
1158 d->doReinit();
1159#ifdef QT_DEBUG_METRICS
1160 qDebug() << "QWin32PrintEngine::setProperty(PPK_PageSize," << value.toInt() << ')';
1161 d->debugMetrics();
1162#endif // QT_DEBUG_METRICS
1163 }
1164 break;
1165 }
1166
1167 case PPK_PaperName: {
1168 if (!d->devMode)
1169 break;
1170 // Get the named page size from the printer if supported
1171 const QPageSize pageSize = d->m_printDevice.supportedPageSize(value.toString());
1172 if (pageSize.isValid()) {
1173 d->setPageSize(pageSize);
1174 d->doReinit();
1175#ifdef QT_DEBUG_METRICS
1176 qDebug() << "QWin32PrintEngine::setProperty(PPK_PaperName," << value.toString() << ')';
1177 d->debugMetrics();
1178#endif // QT_DEBUG_METRICS
1179 }
1180 break;
1181 }
1182
1183 case PPK_PaperSource: {
1184 if (!d->devMode)
1185 break;
1186 const auto inputSlots = d->m_printDevice.supportedInputSlots();
1187 const int paperSource = value.toInt();
1188 const int index = paperSource >= DMBIN_USER ?
1189 indexOfWindowsId(inputSlots, paperSource) : indexOfId(inputSlots, QPrint::InputSlotId(paperSource));
1190 d->devMode->dmDefaultSource = index >= 0 ? inputSlots.at(index).windowsId : DMBIN_AUTO;
1191 d->doReinit();
1192 break;
1193 }
1194
1195 case PPK_PrinterName: {
1196 QString id = value.toString();
1198 if (!ps)
1199 return;
1200
1201 QVariant pageSize = QVariant::fromValue(d->m_pageLayout.pageSize());
1202 const bool isFullPage = (d->m_pageLayout.mode() == QPageLayout::FullPageMode);
1203 QVariant orientation = QVariant::fromValue(d->m_pageLayout.orientation());
1204 QVariant margins = QVariant::fromValue(
1205 QPair<QMarginsF, QPageLayout::Unit>(d->m_pageLayout.margins(), d->m_pageLayout.units()));
1206 QPrintDevice printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id);
1207 if (printDevice.isValid()) {
1208 d->m_printDevice = printDevice;
1209 d->initialize();
1210 if (d->m_printDevice.supportedPageSize(pageSize.value<QPageSize>()).isValid())
1211 setProperty(PPK_QPageSize, pageSize);
1212 else
1214 setProperty(PPK_FullPage, QVariant(isFullPage));
1215 setProperty(PPK_Orientation, orientation);
1216 setProperty(PPK_QPageMargins, margins);
1217 }
1218 break;
1219 }
1220
1221 case PPK_Resolution: {
1222 d->resolution = value.toInt();
1223 d->stretch_x = d->dpi_x / double(d->resolution);
1224 d->stretch_y = d->dpi_y / double(d->resolution);
1225 d->updateMetrics();
1226#ifdef QT_DEBUG_METRICS
1227 qDebug() << "QWin32PrintEngine::setProperty(PPK_Resolution," << value.toInt() << ')';
1228 d->debugMetrics();
1229#endif // QT_DEBUG_METRICS
1230 break;
1231 }
1232
1233 case PPK_WindowsPageSize: {
1234 if (!d->devMode)
1235 break;
1236 const QPageSize pageSize = QPageSize(QPageSize::id(value.toInt()));
1237 if (pageSize.isValid()) {
1238 d->setPageSize(pageSize);
1239 d->doReinit();
1240#ifdef QT_DEBUG_METRICS
1241 qDebug() << "QWin32PrintEngine::setProperty(PPK_WindowsPageSize," << value.toInt() << ')';
1242 d->debugMetrics();
1243#endif // QT_DEBUG_METRICS
1244 break;
1245 }
1246 break;
1247 }
1248
1249 case PPK_CustomPaperSize: {
1250 if (!d->devMode)
1251 break;
1252 const QPageSize pageSize = QPageSize(value.toSizeF(), QPageSize::Point);
1253 if (pageSize.isValid()) {
1254 d->setPageSize(pageSize);
1255 d->doReinit();
1256#ifdef QT_DEBUG_METRICS
1257 qDebug() << "QWin32PrintEngine::setProperty(PPK_CustomPaperSize," << value.toSizeF() << ')';
1258 d->debugMetrics();
1259#endif // QT_DEBUG_METRICS
1260 }
1261 break;
1262 }
1263
1264 case PPK_PageMargins: {
1265 QList<QVariant> margins(value.toList());
1266 Q_ASSERT(margins.size() == 4);
1267 d->m_pageLayout.setUnits(QPageLayout::Point);
1268 d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(),
1269 margins.at(2).toReal(), margins.at(3).toReal()));
1270 d->updateMetrics();
1271#ifdef QT_DEBUG_METRICS
1272 qDebug() << "QWin32PrintEngine::setProperty(PPK_PageMargins," << margins << ')';
1273 d->debugMetrics();
1274#endif // QT_DEBUG_METRICS
1275 break;
1276 }
1277
1278 case PPK_QPageSize: {
1279 if (!d->devMode)
1280 break;
1281 // Get the page size from the printer if supported
1282 const QPageSize pageSize = value.value<QPageSize>();
1283 if (pageSize.isValid()) {
1284 d->setPageSize(pageSize);
1285 d->doReinit();
1286#ifdef QT_DEBUG_METRICS
1287 qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageSize," << pageSize << ')';
1288 d->debugMetrics();
1289#endif // QT_DEBUG_METRICS
1290 }
1291 break;
1292 }
1293
1294 case PPK_QPageMargins: {
1296 d->m_pageLayout.setUnits(pair.second);
1297 d->m_pageLayout.setMargins(pair.first);
1298 d->updateMetrics();
1299#ifdef QT_DEBUG_METRICS
1300 qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageMargins," << pair.first << pair.second << ')';
1301 d->debugMetrics();
1302#endif // QT_DEBUG_METRICS
1303 break;
1304 }
1305
1306 case PPK_QPageLayout: {
1307 QPageLayout pageLayout = value.value<QPageLayout>();
1308 if (pageLayout.isValid() && d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)) {
1312 d->m_pageLayout.setUnits(pageLayout.units());
1313 d->m_pageLayout.setMargins(pageLayout.margins());
1314 d->updateMetrics();
1315#ifdef QT_DEBUG_METRICS
1316 qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageLayout," << pageLayout << ')';
1317 d->debugMetrics();
1318#endif // QT_DEBUG_METRICS
1319 }
1320 break;
1321 }
1322
1323 // No default so that compiler will complain if new keys added and not handled in this engine
1324 }
1325}
1326
1328{
1329 Q_D(const QWin32PrintEngine);
1331 switch (key) {
1332
1333 // The following keys are settings that are unsupported by the Windows PrintEngine
1334 // Return sensible default values to ensure consistent behavior across platforms
1335 case PPK_PageOrder:
1337 break;
1338 case PPK_PrinterProgram:
1339 value = QString();
1340 break;
1342 value = QString();
1343 break;
1344
1345 // The following keys are properties and settings that are supported by the Windows PrintEngine
1346 case PPK_FontEmbedding:
1347 value = d->embed_fonts;
1348 break;
1349
1350 case PPK_CollateCopies:
1351 if (!d->devMode)
1352 value = false;
1353 else
1354 value = d->devMode->dmCollate == DMCOLLATE_TRUE;
1355 break;
1356
1357 case PPK_ColorMode:
1358 {
1359 if (!d->devMode) {
1361 } else {
1362 value = (d->devMode->dmColor == DMCOLOR_COLOR) ? QPrinter::Color : QPrinter::GrayScale;
1363 }
1364 }
1365 break;
1366
1367 case PPK_Creator:
1368 value = d->m_creator;
1369 break;
1370
1371 case PPK_DocumentName:
1372 value = d->docName;
1373 break;
1374
1375 case PPK_Duplex: {
1376 if (!d->devMode) {
1378 } else {
1379 switch (d->devMode->dmDuplex) {
1380 case DMDUP_VERTICAL:
1382 break;
1383 case DMDUP_HORIZONTAL:
1385 break;
1386 case DMDUP_SIMPLEX:
1387 default:
1389 break;
1390 }
1391 }
1392 break;
1393 }
1394
1395 case PPK_FullPage:
1396 value = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
1397 break;
1398
1399 case PPK_CopyCount:
1400 value = d->num_copies;
1401 break;
1402
1404 value = true;
1405 break;
1406
1407 case PPK_NumberOfCopies:
1408 value = 1;
1409 break;
1410
1411 case PPK_Orientation:
1412 value = d->m_pageLayout.orientation();
1413 break;
1414
1415 case PPK_OutputFileName:
1416 value = d->fileName;
1417 break;
1418
1419 case PPK_PageRect:
1420 // PageRect is returned in device pixels
1421 value = d->m_pageLayout.paintRectPixels(d->resolution);
1422 break;
1423
1424 case PPK_PageSize:
1425 value = d->m_pageLayout.pageSize().id();
1426 break;
1427
1428 case PPK_PaperRect:
1429 // PaperRect is returned in device pixels
1430 value = d->m_pageLayout.fullRectPixels(d->resolution);
1431 break;
1432
1433 case PPK_PaperName:
1434 value = d->m_pageLayout.pageSize().name();
1435 break;
1436
1437 case PPK_PaperSource:
1438 if (!d->devMode) {
1439 value = d->m_printDevice.defaultInputSlot().id;
1440 } else {
1441 if (d->devMode->dmDefaultSource >= DMBIN_USER) {
1442 value = int(d->devMode->dmDefaultSource);
1443 } else {
1444 const auto inputSlots = d->m_printDevice.supportedInputSlots();
1445 const int index = indexOfWindowsId(inputSlots, d->devMode->dmDefaultSource);
1446 value = index >= 0 ? inputSlots.at(index).id : QPrint::Auto;
1447 }
1448 }
1449 break;
1450
1451 case PPK_PrinterName:
1452 value = d->m_printDevice.id();
1453 break;
1454
1455 case PPK_Resolution:
1456 if (d->resolution || d->m_printDevice.isValid())
1457 value = d->resolution;
1458 break;
1459
1462 const auto resolutions = d->m_printDevice.supportedResolutions();
1463 list.reserve(resolutions.size());
1464 for (int resolution : resolutions)
1465 list << resolution;
1466 value = list;
1467 break;
1468 }
1469
1471 value = d->m_pageLayout.pageSize().windowsId();
1472 break;
1473
1474 case PPK_PaperSources: {
1476 const auto inputSlots = d->m_printDevice.supportedInputSlots();
1477 out.reserve(inputSlots.size());
1478 for (const QPrint::InputSlot &inputSlot : inputSlots)
1479 out << QVariant(inputSlot.id == QPrint::CustomInputSlot ? inputSlot.windowsId : int(inputSlot.id));
1480 value = out;
1481 break;
1482 }
1483
1485 value = d->m_pageLayout.fullRectPoints().size();
1486 break;
1487
1488 case PPK_PageMargins: {
1490 QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point);
1491 list << margins.left() << margins.top() << margins.right() << margins.bottom();
1492 value = list;
1493 break;
1494 }
1495
1496 case PPK_QPageSize:
1497 value.setValue(d->m_pageLayout.pageSize());
1498 break;
1499
1500 case PPK_QPageMargins: {
1501 QPair<QMarginsF, QPageLayout::Unit> pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units());
1502 value.setValue(pair);
1503 break;
1504 }
1505
1506 case PPK_QPageLayout:
1507 value.setValue(d->m_pageLayout);
1508 break;
1509
1510 case PPK_CustomBase:
1511 break;
1512
1513 // No default so that compiler will complain if new keys added and not handled in this engine
1514 }
1515 return value;
1516}
1517
1519{
1520 return d_func()->state;
1521}
1522
1524{
1525 return d_func()->hdc;
1526}
1527
1529{
1530
1531}
1532
1534{
1535 Q_D(QWin32PrintEngine);
1536
1537 const size_t size = sizeof(DEVNAMES) + d->m_printDevice.id().length() * 2 + 2;
1538 auto hGlobal = reinterpret_cast<HGLOBAL *>(GlobalAlloc(GMEM_MOVEABLE, size));
1539 auto dn = reinterpret_cast<DEVNAMES*>(GlobalLock(hGlobal));
1540
1541 dn->wDriverOffset = 0;
1542 dn->wDeviceOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
1543 dn->wOutputOffset = 0;
1544
1545 memcpy(reinterpret_cast<ushort*>(dn) + dn->wDeviceOffset,
1546 d->m_printDevice.id().utf16(), d->m_printDevice.id().length() * 2 + 2);
1547 dn->wDefault = 0;
1548
1549 GlobalUnlock(hGlobal);
1550 return hGlobal;
1551}
1552
1553void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode)
1554{
1555 Q_D(QWin32PrintEngine);
1556 if (globalDevNames) {
1557 auto dn = reinterpret_cast<DEVNAMES*>(GlobalLock(globalDevNames));
1558 const QString id =
1559 QString::fromWCharArray(reinterpret_cast<const wchar_t*>(dn) + dn->wDeviceOffset);
1561 if (ps)
1562 d->m_printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id);
1563 GlobalUnlock(globalDevNames);
1564 }
1565
1566 if (globalDevMode) {
1567 auto dm = reinterpret_cast<DEVMODE*>(GlobalLock(globalDevMode));
1568 d->release();
1569 d->globalDevMode = globalDevMode;
1570 if (d->ownsDevMode) {
1571 free(d->devMode);
1572 d->ownsDevMode = false;
1573 }
1574 d->devMode = dm;
1575 d->hdc = CreateDC(NULL, reinterpret_cast<const wchar_t *>(d->m_printDevice.id().utf16()), 0, dm);
1576
1577 d->num_copies = d->devMode->dmCopies;
1578 d->updatePageLayout();
1579
1580 if (!OpenPrinter((wchar_t*)d->m_printDevice.id().utf16(), &d->hPrinter, 0))
1581 qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
1582 }
1583
1584 if (d->hdc)
1585 d->initHDC();
1586
1587#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS
1588 qDebug("QWin32PrintEngine::setGlobalDevMode()");
1589 d->debugMetrics();
1590#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS
1591}
1592
1594{
1595 Q_D(QWin32PrintEngine);
1596 return d->globalDevMode;
1597}
1598
1600{
1601 if (!pageSize.isValid())
1602 return;
1603
1605
1606 // Use the printer page size if supported
1607 const QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize);
1608 const QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
1609
1612
1613 // Setup if Windows custom size, i.e. not a known Windows ID
1614 if (printerPageSize.isValid()) {
1615 has_custom_paper_size = false;
1616 devMode->dmPaperSize = m_pageLayout.pageSize().windowsId();
1617 devMode->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
1618 devMode->dmPaperWidth = 0;
1619 devMode->dmPaperLength = 0;
1620 } else {
1621 devMode->dmPaperSize = DMPAPER_USER;
1622 devMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH;
1623 // Size in tenths of a millimeter
1625 devMode->dmPaperWidth = qRound(sizeMM.width() * 10.0);
1626 devMode->dmPaperLength = qRound(sizeMM.height() * 10.0);
1627 }
1628 updateMetrics();
1629}
1630
1631// Update the page layout after any changes made to devMode
1633{
1635
1636 // Update orientation first as is needed to obtain printable margins when changing page size
1637 m_pageLayout.setOrientation(devMode->dmOrientation == DMORIENT_LANDSCAPE ? QPageLayout::Landscape : QPageLayout::Portrait);
1638 if (devMode->dmPaperSize >= DMPAPER_LAST) {
1639 // Is a custom size
1640 // Check if it is using the Postscript Custom Size first
1641 bool hasCustom = false;
1642 int feature = PSIDENT_GDICENTRIC;
1643 if (ExtEscape(hdc, POSTSCRIPT_IDENTIFY,
1644 sizeof(DWORD), reinterpret_cast<LPCSTR>(&feature), 0, 0) >= 0) {
1645 PSFEATURE_CUSTPAPER custPaper;
1646 feature = FEATURESETTING_CUSTPAPER;
1647 if (ExtEscape(hdc, GET_PS_FEATURESETTING, sizeof(INT), reinterpret_cast<LPCSTR>(&feature),
1648 sizeof(custPaper), reinterpret_cast<LPSTR>(&custPaper)) > 0) {
1649 // If orientation is 1 and width/height is 0 then it's not really custom
1650 if (!(custPaper.lOrientation == 1 && custPaper.lWidth == 0 && custPaper.lHeight == 0)) {
1651 if (custPaper.lOrientation == 0 || custPaper.lOrientation == 2)
1653 else
1655 QPageSize pageSize = QPageSize(QSizeF(custPaper.lWidth, custPaper.lHeight),
1657 setPageSize(pageSize);
1658 hasCustom = true;
1659 }
1660 }
1661 }
1662 if (!hasCustom) {
1663 QPageSize pageSize = QPageSize(QSizeF(devMode->dmPaperWidth / 10.0f, devMode->dmPaperLength / 10.0f),
1665 setPageSize(pageSize);
1666 }
1667 } else {
1668 // Is a supported size
1670 }
1671 updateMetrics();
1672}
1673
1674// Update the cached page paint metrics whenever page layout is changed
1676{
1678 // Some print devices allow scaling, so that "virtual" page size != current paper size
1679 const int devWidth = GetDeviceCaps(hdc, PHYSICALWIDTH);
1680 const int devHeight = GetDeviceCaps(hdc, PHYSICALHEIGHT);
1681 const int pageWidth = m_pageLayout.fullRectPixels(dpi_x).width();
1682 const int pageHeight = m_pageLayout.fullRectPixels(dpi_y).height();
1683 const qreal pageScaleX = (devWidth && pageWidth) ? qreal(devWidth) / pageWidth : 1;
1684 const qreal pageScaleY = (devHeight && pageHeight) ? qreal(devHeight) / pageHeight : 1;
1686
1688 m_paintSizeMM = QSize(qRound(sizeMM.width()), qRound(sizeMM.height()));
1689 // Calculate the origin using the physical device pixels, not our paint pixels
1690 // Origin is defined as User Margins - Device Margins
1692 origin_x = qRound(pageScaleX * margins.left() * dpi_x) - GetDeviceCaps(hdc, PHYSICALOFFSETX);
1693 origin_y = qRound(pageScaleY * margins.top() * dpi_y) - GetDeviceCaps(hdc, PHYSICALOFFSETY);
1694}
1695
1697{
1698 qDebug() << " " << "m_pageLayout = " << m_pageLayout;
1699 qDebug() << " " << "m_paintRectPixels = " << m_paintRectPixels;
1700 qDebug() << " " << "m_paintSizeMM = " << m_paintSizeMM;
1701 qDebug() << " " << "resolution = " << resolution;
1702 qDebug() << " " << "stretch = " << stretch_x << stretch_y;
1703 qDebug() << " " << "origin = " << origin_x << origin_y;
1704 qDebug() << " " << "dpi = " << dpi_x << dpi_y;
1705 qDebug() << "";
1706}
1707
1708static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc,
1709 const QTransform &xform, const QPointF &topLeft)
1710{
1711 QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft);
1712
1713 SetTextAlign(hdc, TA_BASELINE);
1714 SetBkMode(hdc, TRANSPARENT);
1715
1716 const bool has_kerning = ti.f && ti.f->kerning();
1717
1718 HFONT hfont = 0;
1719 bool deleteFont = false;
1720
1721 if (ti.fontEngine->type() == QFontEngine::Win) {
1722 if (ti.fontEngine->supportsTransformation(QTransform::fromScale(0.5, 0.5))) // is TrueType font?
1723 hfont = static_cast<HFONT>(ti.fontEngine->handle());
1724 }
1725#if QT_CONFIG(directwrite)
1726 else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
1728 hfont = fedw->createHFONT();
1729 if (hfont)
1730 deleteFont = true;
1731 }
1732#endif
1733
1734 if (!hfont)
1735 hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
1736
1737 HGDIOBJ old_font = SelectObject(hdc, hfont);
1738 unsigned int options = ETO_GLYPH_INDEX;
1739 QGlyphLayout glyphs = ti.glyphs;
1740
1741 bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
1742 for (int i = 0; fast && i < glyphs.numGlyphs; i++) {
1743 if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0
1744 || glyphs.attributes[i].dontPrint) {
1745 fast = false;
1746 break;
1747 }
1748 }
1749
1750 // Scale, rotate and translate here.
1751 XFORM win_xform;
1752 win_xform.eM11 = xform.m11();
1753 win_xform.eM12 = xform.m12();
1754 win_xform.eM21 = xform.m21();
1755 win_xform.eM22 = xform.m22();
1756 win_xform.eDx = xform.dx();
1757 win_xform.eDy = xform.dy();
1758
1759 SetGraphicsMode(hdc, GM_ADVANCED);
1760 SetWorldTransform(hdc, &win_xform);
1761
1762 if (fast) {
1763 // fast path
1765 for (int i = 0; i < glyphs.numGlyphs; ++i)
1766 g[i] = glyphs.glyphs[i];
1767 ExtTextOut(hdc,
1768 qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
1769 qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
1770 options, 0, g.constData(), glyphs.numGlyphs, 0);
1771 } else {
1774
1775 QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y());
1777 _glyphs, positions);
1778 if (_glyphs.isEmpty()) {
1779 SelectObject(hdc, old_font);
1780 return;
1781 }
1782
1783 options |= ETO_PDY;
1784 QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
1785 QVarLengthArray<wchar_t> g(_glyphs.size());
1786 const int lastGlyph = _glyphs.size() - 1;
1787 for (int i = 0; i < lastGlyph; ++i) {
1788 glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
1789 glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
1790 g[i] = _glyphs[i];
1791 }
1792 glyphDistances[lastGlyph * 2] = 0;
1793 glyphDistances[lastGlyph * 2 + 1] = 0;
1794 g[lastGlyph] = _glyphs[lastGlyph];
1795 ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, nullptr,
1796 g.constData(), _glyphs.size(),
1797 glyphDistances.data());
1798 }
1799
1800 win_xform.eM11 = win_xform.eM22 = 1.0;
1801 win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0;
1802 SetWorldTransform(hdc, &win_xform);
1803
1804 SelectObject(hdc, old_font);
1805
1806 if (deleteFont)
1807 DeleteObject(hfont);
1808}
1809
1811
1812#endif // QT_NO_PRINTER
QRegion alphaClipping() const
void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override
Reimplement this function to draw the part of the pm specified by the sr rectangle in the given r.
bool end() override
Reimplement this function to finish painting on the current paint device.
void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) override
Reimplement this virtual function to draw the polygon defined by the pointCount first points in point...
void drawTextItem(const QPointF &p, const QTextItem &textItem) override
This function draws the text item textItem at position p.
bool begin(QPaintDevice *pdev) override
Reimplement this function to initialise your paint engine when painting is to start on the paint devi...
void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) override
Reimplement this function to draw the pixmap in the given rect, starting at the given p.
void updateState(const QPaintEngineState &state) override
Reimplement this function to update the state of a paint engine.
void drawPath(const QPainterPath &path) override
The default implementation ignores the path and does nothing.
void flushAndInit(bool init=true)
\inmodule QtGui
Definition qbrush.h:30
const QColor & color() const
Returns the brush color.
Definition qbrush.h:121
Qt::BrushStyle style() const
Returns the brush style.
Definition qbrush.h:120
\inmodule QtCore
Definition qbytearray.h:57
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
QRgb rgb() const noexcept
Returns the RGB value of the color.
Definition qcolor.cpp:1439
virtual Qt::HANDLE handle() const
Type type() const
void getGlyphPositions(const QGlyphLayout &glyphs, const QTransform &matrix, QTextItem::RenderFlags flags, QVarLengthArray< glyph_t > &glyphs_out, QVarLengthArray< QFixedPoint > &positions)
virtual bool supportsTransformation(const QTransform &transform) const
bool kerning() const
Returns true if kerning should be used when drawing text with this font.
Definition qfont.cpp:1344
\inmodule QtGui
Definition qimage.h:37
@ Format_RGB32
Definition qimage.h:46
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void reserve(qsizetype size)
Definition qlist.h:746
\inmodule QtCore
Definition qmargins.h:274
constexpr qreal right() const noexcept
Returns the right margin.
Definition qmargins.h:370
constexpr qreal left() const noexcept
Returns the left margin.
Definition qmargins.h:364
constexpr qreal top() const noexcept
Returns the top margin.
Definition qmargins.h:367
constexpr qreal bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:373
\inmodule QtGui
Definition qpagelayout.h:20
void setOrientation(Orientation orientation)
Sets the page orientation of the page layout to orientation.
Mode mode() const
Returns the page layout mode.
Unit units() const
Returns the units the page layout is currently defined in.
bool isValid() const
Returns true if this page layout is valid.
QRectF paintRect() const
Returns the page rectangle in the current layout units.
Unit
This enum type is used to specify the measurement unit for page layout and margins.
Definition qpagelayout.h:24
QMarginsF margins() const
Returns the margins of the page layout using the currently set units.
Orientation orientation() const
Returns the page orientation of the page layout.
QRect paintRectPixels(int resolution) const
Returns the paintable rectangle in rounded device pixels for the given resolution.
void setPageSize(const QPageSize &pageSize, const QMarginsF &minMargins=QMarginsF(0, 0, 0, 0))
Sets the page size of the page layout to pageSize.
Orientation
This enum type defines the page orientation.
Definition qpagelayout.h:33
QRect fullRectPixels(int resolution) const
Returns the full page rectangle in device pixels for the given resolution.
QPageSize pageSize() const
Returns the page size of the page layout.
\inmodule QtGui
Definition qpagesize.h:22
bool isValid() const
Returns true if this page size is valid.
int windowsId() const
Returns the Windows DMPAPER enum value for the page size.
QSizeF size(Unit units) const
Returns the size of the page in the required units.
PageSizeId id() const
Returns the standard QPageSize::PageSizeId of the page, or QPageSize::Custom.
PageSizeId
This enum type lists the available page sizes as defined in the Postscript PPD standard.
Definition qpagesize.h:25
@ PdmDevicePixelRatioScaled
static qreal devicePixelRatioFScale()
The QPaintEngineState class provides information about the active paint engine's current state....
QTransform transform() const
QPainterPath clipPath() const
Returns the clip path in the current paint engine state.
Qt::ClipOperation clipOperation() const
Returns the clip operation in the current paint engine state.
bool isClipEnabled() const
Returns whether clipping is enabled or not in the current paint engine state.
QBrush brush() const
Returns the brush in the current paint engine state.
QRegion clipRegion() const
Returns the clip region in the current paint engine state.
QPen pen() const
Returns the pen in the current paint engine state.
QPaintEngine::DirtyFlags state() const
Returns a combination of flags identifying the set of properties that need to be updated when updatin...
virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)
Reimplement this function to draw the pixmap in the given rect, starting at the given p.
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem)
This function draws the text item textItem at position p.
PolygonDrawMode
\value OddEvenMode The polygon should be drawn using OddEven fill rule.
QPainter * painter() const
Returns the paint engine's painter.
QPaintEngineState * state
bool isActive() const
Returns true if the paint engine is actively drawing; otherwise returns false.
The QPainterPathStroker class is used to generate fillable outlines for a given painter path.
void setDashPattern(Qt::PenStyle)
Sets the dash pattern for the generated outlines to style.
void setDashOffset(qreal offset)
Sets the dash offset for the generated outlines to offset.
void setCapStyle(Qt::PenCapStyle style)
Sets the cap style of the generated outlines to style.
void setWidth(qreal width)
Sets the width of the generated outline painter path to width.
QPainterPath createStroke(const QPainterPath &path) const
Generates a new path that is a fillable area representing the outline of the given path.
void setJoinStyle(Qt::PenJoinStyle style)
Sets the join style of the generated outlines to style.
void setMiterLimit(qreal length)
Sets the miter limit of the generated outlines to limit.
\inmodule QtGui
\inmodule QtGui
bool isEmpty() const
Returns true if either there are no elements in this path, or if the only element is a MoveToElement;...
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device.
qreal widthF() const
Returns the pen width with floating point precision.
Definition qpen.cpp:598
QList< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition qpen.cpp:420
bool isCosmetic() const
Returns true if the pen is cosmetic; otherwise returns false.
Definition qpen.cpp:783
Qt::PenCapStyle capStyle() const
Returns the pen's cap style.
Definition qpen.cpp:662
Qt::PenJoinStyle joinStyle() const
Returns the pen's join style.
Definition qpen.cpp:689
qreal miterLimit() const
Returns the miter limit of the pen.
Definition qpen.cpp:548
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
Definition qpen.cpp:741
qreal dashOffset() const
Returns the dash offset for the pen.
Definition qpen.cpp:506
Qt::PenStyle style() const
Returns the pen style.
Definition qpen.cpp:385
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
int height() const
Returns the height of the pixmap.
Definition qpixmap.cpp:484
static QTransform trueMatrix(const QTransform &m, int w, int h)
Returns the actual matrix used for transforming a pixmap with the given width, height and matrix.
Definition qpixmap.cpp:436
int width() const
Returns the width of the pixmap.
Definition qpixmap.cpp:472
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition qpixmap.cpp:1445
static QPlatformPrinterSupport * get()
The QPlatformPrinterSupport class provides an abstraction for print support.
virtual QString defaultPrintDeviceId() const
virtual QPrintDevice createPrintDevice(const QString &id)
\inmodule QtCore\reentrant
Definition qpoint.h:214
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
QPageSize supportedPageSize(const QPageSize &pageSize) const
bool isValid() const
QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, int resolution) const
QString id() const
PrintEnginePropertyKey
This enum is used to communicate properties between the print engine and QPrinter.
@ PPK_SupportedResolutions
@ PPK_SupportsMultipleCopies
@ DuplexLongSide
Definition qprinter.h:87
@ DuplexNone
Definition qprinter.h:85
@ DuplexShortSide
Definition qprinter.h:88
@ GrayScale
Definition qprinter.h:42
PrinterMode
This enum describes the mode the printer should work in.
Definition qprinter.h:31
@ ScreenResolution
Definition qprinter.h:31
@ HighResolution
Definition qprinter.h:31
@ PrinterResolution
Definition qprinter.h:31
PrinterState
\value Idle \value Active \value Aborted \value Error
Definition qprinter.h:64
@ Aborted
Definition qprinter.h:66
@ FirstPageFirst
Definition qprinter.h:39
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr qreal height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:718
constexpr qreal width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:715
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:496
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:721
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:845
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:497
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:238
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:235
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
\inmodule QtCore
Definition qsize.h:207
constexpr qreal width() const noexcept
Returns the width.
Definition qsize.h:321
constexpr qreal height() const noexcept
Returns the height.
Definition qsize.h:324
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6737
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QByteArray toLocal8Bit() const &
Definition qstring.h:567
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1164
Internal QTextItem.
RenderFlags flags
QGlyphLayout glyphs
const QFont * f
QFontEngine * fontEngine
\inmodule QtGui
\inmodule QtCore
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
qreal m21() const
Returns the horizontal shearing factor.
Definition qtransform.h:211
static QTransform fromScale(qreal dx, qreal dy)
Creates a matrix which corresponds to a scaling of sx horizontally and sy vertically.
qreal m12() const
Returns the vertical shearing factor.
Definition qtransform.h:203
qreal dx() const
Returns the horizontal translation factor.
Definition qtransform.h:235
QPoint map(const QPoint &p) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qreal m11() const
Returns the horizontal scaling factor.
Definition qtransform.h:199
static QTransform fromTranslate(qreal dx, qreal dy)
Creates a matrix which corresponds to a translation of dx along the x axis and dy along the y axis.
QTransform inverted(bool *invertible=nullptr) const
Returns an inverted copy of this matrix.
qreal m22() const
Returns the vertical scaling factor.
Definition qtransform.h:215
QRect mapRect(const QRect &) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qreal dy() const
Returns the vertical translation factor.
Definition qtransform.h:239
constexpr size_type size() const noexcept
bool isEmpty() const
T * data() noexcept
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
QPrinter::PrinterState state
void fillPath_dev(const QPainterPath &path, const QColor &color)
void strokePath_dev(const QPainterPath &path, const QColor &color, qreal width)
void composeGdiPath(const QPainterPath &path)
void strokePath(const QPainterPath &path, const QColor &color)
void setPageSize(const QPageSize &pageSize)
void fillPath(const QPainterPath &path, const QColor &color)
void setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode)
void updateClipPath(const QPainterPath &clip, Qt::ClipOperation op)
void updateState(const QPaintEngineState &state) override
Reimplement this function to update the state of a paint engine.
void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &p) override
Reimplement this function to draw the pixmap in the given rect, starting at the given p.
QWin32PrintEngine(QPrinter::PrinterMode mode, const QString &deviceId)
void updateMatrix(const QTransform &matrix)
void drawPath(const QPainterPath &path) override
The default implementation ignores the path and does nothing.
bool begin(QPaintDevice *dev) override
Reimplement this function to initialise your paint engine when painting is to start on the paint devi...
QVariant property(PrintEnginePropertyKey key) const override
Returns the print engine's property specified by key.
void drawTextItem(const QPointF &p, const QTextItem &textItem) override
This function draws the text item textItem at position p.
QPrinter::PrinterState printerState() const override
Returns the current state of the printer being used by the print engine.
bool end() override
Reimplement this function to finish painting on the current paint device.
void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) override
Reimplement this virtual function to draw the polygon defined by the pointCount first points in point...
bool newPage() override
Instructs the print engine to start a new page.
void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override
Reimplement this function to draw the part of the pm specified by the sr rectangle in the given r.
bool abort() override
Instructs the print engine to abort the printing process.
int metric(QPaintDevice::PaintDeviceMetric) const override
Returns the metric for the given id.
void releaseDC(HDC) const
void setProperty(PrintEnginePropertyKey key, const QVariant &value) override
Sets the print engine's property specified by key to the given value.
HGLOBAL * createGlobalDevNames()
Windows font engine using Direct Write.
QString str
[2]
else opt state
[0]
void qErrnoWarning(const char *msg,...)
DuplexMode
Definition qprint_p.h:64
@ DuplexLongSide
Definition qprint_p.h:67
@ DuplexShortSide
Definition qprint_p.h:68
@ DuplexNone
Definition qprint_p.h:65
@ DuplexAuto
Definition qprint_p.h:66
InputSlotId
Definition qprint_p.h:78
@ CustomInputSlot
Definition qprint_p.h:93
@ Auto
Definition qprint_p.h:85
Combined button and popup list for selecting options.
ClipOperation
@ ReplaceClip
@ NoClip
@ white
Definition qnamespace.h:30
@ black
Definition qnamespace.h:29
@ CustomDashLine
@ SolidLine
@ NoPen
@ MiterJoin
@ RoundJoin
@ SolidPattern
@ WindingFill
@ RoundCap
@ FlatCap
Definition brush.cpp:5
std::pair< T1, T2 > QPair
static const QCssKnownValue positions[NumKnownPositionModes - 1]
static const short indexOfId[NumKnownValues]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
#define qFatal
Definition qlogging.h:164
static QT_BEGIN_NAMESPACE const int tileSize
Definition qmemrotate.cpp:9
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLint GLint GLint GLint GLint x
[0]
GLenum mode
const GLfloat * m
GLuint64 key
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLenum GLuint id
[7]
GLint GLsizei width
GLuint start
GLboolean GLboolean g
GLfloat n
GLint y
GLfixed GLfixed GLint GLint GLfixed points
GLuint res
GLuint GLfloat * val
GLint void * img
Definition qopenglext.h:233
GLuint GLenum matrix
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLbyte ty
Q_GUI_EXPORT QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
@ DMPAPER_USER
@ DMPAPER_LAST
QPainterPath qt_regionToPath(const QRegion &region)
Definition qregion.cpp:1007
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
HBitmapFormat
@ HBitmapNoAlpha
HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat)
#define DMBIN_AUTO
Definition qprint_p.h:43
#define DMBIN_USER
Definition qprint_p.h:50
QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits)
static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc, const QTransform &xform, const QPointF &topLeft)
@ HBitmapAlpha
@ HBitmapPremultipliedAlpha
@ HBitmapNoAlpha
static int indexOfWindowsId(const QList< QPrint::InputSlot > &inputSlots, int windowsId)
QT_BEGIN_NAMESPACE QPainterPath qt_regionToPath(const QRegion &region)
Definition qregion.cpp:1007
static QByteArray msgBeginFailed(const char *function, const DOCINFO &d)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
#define ETO_PDY
Definition qt_windows.h:83
unsigned short ushort
Definition qtypes.h:28
double qreal
Definition qtypes.h:92
static int toInt(const QChar &qc, int R)
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
QTextStream out(stdout)
[7]
widget render & pixmap
QFixed y
Definition qfixed_p.h:163
QFixed x
Definition qfixed_p.h:162
constexpr qreal toReal() const
Definition qfixed_p.h:42
QGlyphJustification * justifications
QGlyphAttributes * attributes
glyph_t * glyphs
QFixedPoint * offsets