Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 = nullptr;
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) {
268 QWindowsFontEngineDirectWrite *fedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
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, nullptr);
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
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, nullptr);
726
727 HGDIOBJ old_pen = SelectObject(hdc, pen);
728 StrokePath(hdc);
729 DeleteObject(SelectObject(hdc, old_pen));
730}
731
732
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
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(reinterpret_cast<LPWSTR>(const_cast<ushort *>(printerName.utf16())),
846 reinterpret_cast<LPHANDLE>(&hPrinter), nullptr);
847 if (!ok) {
848 qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed");
849 return;
850 }
851
852 // Fetch the PRINTER_INFO_2 with DEVMODE data containing the
853 // printer settings.
854 DWORD infoSize, numBytes;
855 GetPrinter(hPrinter, 2, nullptr, 0, &infoSize);
856 hMem = GlobalAlloc(GHND, infoSize);
857 pInfo = reinterpret_cast<PRINTER_INFO_2*>(GlobalLock(hMem));
858 ok = GetPrinter(hPrinter, 2, reinterpret_cast<LPBYTE>(pInfo), infoSize, &numBytes);
859
860 if (!ok) {
861 qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed");
862 release();
863 return;
864 }
865
866 devMode = pInfo->pDevMode;
867
868 if (!devMode) {
869 // pInfo->pDevMode == NULL for some printers and passing NULL
870 // into CreateDC leads to the printer doing nothing. In addition,
871 // the framework assumes that devMode isn't NULL, such as in
872 // QWin32PrintEngine::begin() and QPageSetupDialog::exec()
873 // Attempt to get the DEVMODE a different way.
874
875 // Allocate the required buffer
876 auto *lpwPrinterName = reinterpret_cast<LPWSTR>(const_cast<ushort *>(printerName.utf16()));
877 LONG result = DocumentProperties(nullptr, hPrinter, lpwPrinterName,
878 nullptr, nullptr, 0);
879 devMode = reinterpret_cast<DEVMODE *>(malloc(result));
881 ownsDevMode = true;
882
883 // Get the default DevMode
884 result = DocumentProperties(nullptr, hPrinter, lpwPrinterName,
885 devMode, nullptr, DM_OUT_BUFFER);
886 if (result != IDOK) {
887 qErrnoWarning("QWin32PrintEngine::initialize: Failed to obtain devMode");
888 free(devMode);
889 devMode = nullptr;
890 ownsDevMode = false;
891 }
892 }
893
894 hdc = CreateDC(nullptr, reinterpret_cast<LPCWSTR>(printerName.utf16()),
895 nullptr, devMode);
896
897 if (!hdc) {
898 qErrnoWarning("QWin32PrintEngine::initialize: CreateDC failed");
899 release();
900 return;
901 }
902
905
906 initHDC();
907
908 if (devMode) {
909 num_copies = devMode->dmCopies;
910 devMode->dmCollate = DMCOLLATE_TRUE;
912 }
913
914#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS
915 qDebug("QWin32PrintEngine::initialize()");
916 debugMetrics();
917#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS
918}
919
921{
922 memset(devMode, 0, sizeof(DEVMODE));
923 devMode->dmSize = sizeof(DEVMODE);
924 devMode->dmSpecVersion = DM_SPECVERSION;
925}
926
928{
929 Q_ASSERT(hdc);
930
931 HDC display_dc = GetDC(nullptr);
932 dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
933 dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
934 dpi_display = GetDeviceCaps(display_dc, LOGPIXELSY);
935 ReleaseDC(nullptr, display_dc);
936 if (dpi_display == 0) {
937 qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
938 "might be a driver problem");
939 dpi_display = 96; // Reasonable default
940 }
941
942 switch(mode) {
945 stretch_x = dpi_x / double(dpi_display);
946 stretch_y = dpi_y / double(dpi_display);
947 break;
951 stretch_x = 1;
952 stretch_y = 1;
953 break;
954 default:
955 break;
956 }
957
959}
960
962{
963 if (globalDevMode) { // Devmode comes from print dialog
964 GlobalUnlock(globalDevMode);
965 } else if (hMem) {
966 GlobalUnlock(hMem);
967 GlobalFree(hMem);
968 }
969 if (hPrinter)
970 ClosePrinter(hPrinter);
971 if (hdc)
972 DeleteDC(hdc);
973
974 // Check if devMode was allocated separately from pInfo / hMem.
975 if (ownsDevMode)
976 free(devMode);
977
978 hdc = nullptr;
979 hPrinter = nullptr;
980 pInfo = nullptr;
981 hMem = nullptr;
982 devMode = nullptr;
983 ownsDevMode = false;
984}
985
987{
988 if (state == QPrinter::Active) {
989 reinit = true;
990 } else {
991 resetDC();
992 reinit = false;
993 }
994}
995
997{
998 if (!hdc) {
999 qWarning("ResetDC() called with null hdc.");
1000 return false;
1001 }
1002 const HDC oldHdc = hdc;
1003 const HDC hdc = ResetDC(oldHdc, devMode);
1004 if (!hdc) {
1005 const int lastError = GetLastError();
1006 qErrnoWarning(lastError, "ResetDC() on %p failed (%d)", oldHdc, lastError);
1007 }
1008 return hdc != 0;
1009}
1010
1011static int indexOfId(const QList<QPrint::InputSlot> &inputSlots, QPrint::InputSlotId id)
1012{
1013 for (int i = 0; i < inputSlots.size(); ++i) {
1014 if (inputSlots.at(i).id == id)
1015 return i;
1016 }
1017 return -1;
1018}
1019
1020static int indexOfWindowsId(const QList<QPrint::InputSlot> &inputSlots, int windowsId)
1021{
1022 for (int i = 0; i < inputSlots.size(); ++i) {
1023 if (inputSlots.at(i).windowsId == windowsId)
1024 return i;
1025 }
1026 return -1;
1027}
1028
1030{
1031 Q_D(QWin32PrintEngine);
1032 switch (key) {
1033
1034 // The following keys are properties or derived values and so cannot be set
1035 case PPK_PageRect:
1036 break;
1037 case PPK_PaperRect:
1038 break;
1039 case PPK_PaperSources:
1040 break;
1042 break;
1044 break;
1045
1046 // The following keys are settings that are unsupported by the Windows PrintEngine
1047 case PPK_CustomBase:
1048 break;
1049 case PPK_PageOrder:
1050 break;
1051 case PPK_PrinterProgram:
1052 break;
1054 break;
1055
1056 // The following keys are properties and settings that are supported by the Windows PrintEngine
1057 case PPK_FontEmbedding:
1058 d->embed_fonts = value.toBool();
1059 break;
1060
1061 case PPK_CollateCopies:
1062 {
1063 if (!d->devMode)
1064 break;
1065 d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
1066 d->devMode->dmFields |= DM_COLLATE;
1067 d->doReinit();
1068 }
1069 break;
1070
1071 case PPK_ColorMode:
1072 {
1073 if (!d->devMode)
1074 break;
1075 d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
1076 d->devMode->dmFields |= DM_COLOR;
1077 d->doReinit();
1078 }
1079 break;
1080
1081 case PPK_Creator:
1082 d->m_creator = value.toString();
1083 break;
1084
1085 case PPK_DocumentName:
1086 if (isActive()) {
1087 qWarning("QWin32PrintEngine: Cannot change document name while printing is active");
1088 return;
1089 }
1090 d->docName = value.toString();
1091 break;
1092
1093 case PPK_Duplex: {
1094 if (!d->devMode)
1095 break;
1097 if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice.supportedDuplexModes().contains(mode))
1098 break;
1099 switch (mode) {
1100 case QPrint::DuplexNone:
1101 d->devMode->dmDuplex = DMDUP_SIMPLEX;
1102 d->devMode->dmFields |= DM_DUPLEX;
1103 break;
1104 case QPrint::DuplexAuto:
1105 d->devMode->dmDuplex = d->m_pageLayout.orientation() == QPageLayout::Landscape ? DMDUP_HORIZONTAL : DMDUP_VERTICAL;
1106 d->devMode->dmFields |= DM_DUPLEX;
1107 break;
1109 d->devMode->dmDuplex = DMDUP_VERTICAL;
1110 d->devMode->dmFields |= DM_DUPLEX;
1111 break;
1113 d->devMode->dmDuplex = DMDUP_HORIZONTAL;
1114 d->devMode->dmFields |= DM_DUPLEX;
1115 break;
1116 default:
1117 // Don't change
1118 break;
1119 }
1120 d->doReinit();
1121 break;
1122 }
1123
1124 case PPK_FullPage:
1125 if (value.toBool())
1126 d->m_pageLayout.setMode(QPageLayout::FullPageMode);
1127 else
1128 d->m_pageLayout.setMode(QPageLayout::StandardMode);
1129 d->updateMetrics();
1130#ifdef QT_DEBUG_METRICS
1131 qDebug() << "QWin32PrintEngine::setProperty(PPK_FullPage," << value.toBool() << + ")";
1132 d->debugMetrics();
1133#endif // QT_DEBUG_METRICS
1134 break;
1135
1136 case PPK_CopyCount:
1137 case PPK_NumberOfCopies:
1138 if (!d->devMode)
1139 break;
1140 d->num_copies = value.toInt();
1141 d->devMode->dmCopies = d->num_copies;
1142 d->devMode->dmFields |= DM_COPIES;
1143 d->doReinit();
1144 break;
1145
1146 case PPK_Orientation: {
1147 if (!d->devMode)
1148 break;
1150 d->devMode->dmOrientation = orientation == QPageLayout::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
1151 d->devMode->dmFields |= DM_ORIENTATION;
1152 d->m_pageLayout.setOrientation(orientation);
1153 d->doReinit();
1154 d->updateMetrics();
1155#ifdef QT_DEBUG_METRICS
1156 qDebug() << "QWin32PrintEngine::setProperty(PPK_Orientation," << orientation << ')';
1157 d->debugMetrics();
1158#endif // QT_DEBUG_METRICS
1159 break;
1160 }
1161
1162 case PPK_OutputFileName:
1163 if (isActive()) {
1164 qWarning("QWin32PrintEngine: Cannot change filename while printing");
1165 } else {
1166 d->fileName = value.toString();
1167 d->printToFile = !value.toString().isEmpty();
1168 }
1169 break;
1170
1171 case PPK_PageSize: {
1172 if (!d->devMode)
1173 break;
1174 const QPageSize pageSize = QPageSize(QPageSize::PageSizeId(value.toInt()));
1175 if (pageSize.isValid()) {
1176 d->setPageSize(pageSize);
1177 d->doReinit();
1178#ifdef QT_DEBUG_METRICS
1179 qDebug() << "QWin32PrintEngine::setProperty(PPK_PageSize," << value.toInt() << ')';
1180 d->debugMetrics();
1181#endif // QT_DEBUG_METRICS
1182 }
1183 break;
1184 }
1185
1186 case PPK_PaperName: {
1187 if (!d->devMode)
1188 break;
1189 // Get the named page size from the printer if supported
1190 const QPageSize pageSize = d->m_printDevice.supportedPageSize(value.toString());
1191 if (pageSize.isValid()) {
1192 d->setPageSize(pageSize);
1193 d->doReinit();
1194#ifdef QT_DEBUG_METRICS
1195 qDebug() << "QWin32PrintEngine::setProperty(PPK_PaperName," << value.toString() << ')';
1196 d->debugMetrics();
1197#endif // QT_DEBUG_METRICS
1198 }
1199 break;
1200 }
1201
1202 case PPK_PaperSource: {
1203 if (!d->devMode)
1204 break;
1205 const auto inputSlots = d->m_printDevice.supportedInputSlots();
1206 const int paperSource = value.toInt();
1207 const int index = paperSource >= DMBIN_USER ?
1208 indexOfWindowsId(inputSlots, paperSource) : indexOfId(inputSlots, QPrint::InputSlotId(paperSource));
1209 d->devMode->dmDefaultSource = index >= 0 ? inputSlots.at(index).windowsId : DMBIN_AUTO;
1210 d->doReinit();
1211 break;
1212 }
1213
1214 case PPK_PrinterName: {
1215 QString id = value.toString();
1217 if (!ps)
1218 return;
1219
1220 QVariant pageSize = QVariant::fromValue(d->m_pageLayout.pageSize());
1221 const bool isFullPage = (d->m_pageLayout.mode() == QPageLayout::FullPageMode);
1222 QVariant orientation = QVariant::fromValue(d->m_pageLayout.orientation());
1223 QVariant margins = QVariant::fromValue(
1224 QPair<QMarginsF, QPageLayout::Unit>(d->m_pageLayout.margins(), d->m_pageLayout.units()));
1225 QPrintDevice printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id);
1226 if (printDevice.isValid()) {
1227 d->m_printDevice = printDevice;
1228 d->initialize();
1229 if (d->m_printDevice.supportedPageSize(pageSize.value<QPageSize>()).isValid())
1230 setProperty(PPK_QPageSize, pageSize);
1231 else
1233 setProperty(PPK_FullPage, QVariant(isFullPage));
1234 setProperty(PPK_Orientation, orientation);
1235 setProperty(PPK_QPageMargins, margins);
1236 }
1237 break;
1238 }
1239
1240 case PPK_Resolution: {
1241 d->resolution = value.toInt();
1242 d->stretch_x = d->dpi_x / double(d->resolution);
1243 d->stretch_y = d->dpi_y / double(d->resolution);
1244 d->updateMetrics();
1245#ifdef QT_DEBUG_METRICS
1246 qDebug() << "QWin32PrintEngine::setProperty(PPK_Resolution," << value.toInt() << ')';
1247 d->debugMetrics();
1248#endif // QT_DEBUG_METRICS
1249 break;
1250 }
1251
1252 case PPK_WindowsPageSize: {
1253 if (!d->devMode)
1254 break;
1255 const QPageSize pageSize = QPageSize(QPageSize::id(value.toInt()));
1256 if (pageSize.isValid()) {
1257 d->setPageSize(pageSize);
1258 d->doReinit();
1259#ifdef QT_DEBUG_METRICS
1260 qDebug() << "QWin32PrintEngine::setProperty(PPK_WindowsPageSize," << value.toInt() << ')';
1261 d->debugMetrics();
1262#endif // QT_DEBUG_METRICS
1263 break;
1264 }
1265 break;
1266 }
1267
1268 case PPK_CustomPaperSize: {
1269 if (!d->devMode)
1270 break;
1271 const QPageSize pageSize = QPageSize(value.toSizeF(), QPageSize::Point);
1272 if (pageSize.isValid()) {
1273 d->setPageSize(pageSize);
1274 d->doReinit();
1275#ifdef QT_DEBUG_METRICS
1276 qDebug() << "QWin32PrintEngine::setProperty(PPK_CustomPaperSize," << value.toSizeF() << ')';
1277 d->debugMetrics();
1278#endif // QT_DEBUG_METRICS
1279 }
1280 break;
1281 }
1282
1283 case PPK_PageMargins: {
1284 QList<QVariant> margins(value.toList());
1285 Q_ASSERT(margins.size() == 4);
1286 d->m_pageLayout.setUnits(QPageLayout::Point);
1287 d->m_pageLayout.setMargins(QMarginsF(margins.at(0).toReal(), margins.at(1).toReal(),
1288 margins.at(2).toReal(), margins.at(3).toReal()),
1290 d->updateMetrics();
1291#ifdef QT_DEBUG_METRICS
1292 qDebug() << "QWin32PrintEngine::setProperty(PPK_PageMargins," << margins << ')';
1293 d->debugMetrics();
1294#endif // QT_DEBUG_METRICS
1295 break;
1296 }
1297
1298 case PPK_QPageSize: {
1299 if (!d->devMode)
1300 break;
1301 // Get the page size from the printer if supported
1302 const QPageSize pageSize = value.value<QPageSize>();
1303 if (pageSize.isValid()) {
1304 d->setPageSize(pageSize);
1305 d->doReinit();
1306#ifdef QT_DEBUG_METRICS
1307 qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageSize," << pageSize << ')';
1308 d->debugMetrics();
1309#endif // QT_DEBUG_METRICS
1310 }
1311 break;
1312 }
1313
1314 case PPK_QPageMargins: {
1315 QPair<QMarginsF, QPageLayout::Unit> pair = value.value<QPair<QMarginsF, QPageLayout::Unit> >();
1316 d->m_pageLayout.setUnits(pair.second);
1317 d->m_pageLayout.setMargins(pair.first, QPageLayout::OutOfBoundsPolicy::Clamp);
1318 d->updateMetrics();
1319#ifdef QT_DEBUG_METRICS
1320 qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageMargins," << pair.first << pair.second << ')';
1321 d->debugMetrics();
1322#endif // QT_DEBUG_METRICS
1323 break;
1324 }
1325
1326 case PPK_QPageLayout: {
1327 QPageLayout pageLayout = value.value<QPageLayout>();
1328 if (pageLayout.isValid() && d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)) {
1332 d->m_pageLayout.setUnits(pageLayout.units());
1333 d->m_pageLayout.setMargins(pageLayout.margins(), QPageLayout::OutOfBoundsPolicy::Clamp);
1334 d->updateMetrics();
1335#ifdef QT_DEBUG_METRICS
1336 qDebug() << "QWin32PrintEngine::setProperty(PPK_QPageLayout," << pageLayout << ')';
1337 d->debugMetrics();
1338#endif // QT_DEBUG_METRICS
1339 }
1340 break;
1341 }
1342
1343 // No default so that compiler will complain if new keys added and not handled in this engine
1344 }
1345}
1346
1348{
1349 Q_D(const QWin32PrintEngine);
1351 switch (key) {
1352
1353 // The following keys are settings that are unsupported by the Windows PrintEngine
1354 // Return sensible default values to ensure consistent behavior across platforms
1355 case PPK_PageOrder:
1357 break;
1358 case PPK_PrinterProgram:
1359 value = QString();
1360 break;
1362 value = QString();
1363 break;
1364
1365 // The following keys are properties and settings that are supported by the Windows PrintEngine
1366 case PPK_FontEmbedding:
1367 value = d->embed_fonts;
1368 break;
1369
1370 case PPK_CollateCopies:
1371 if (!d->devMode)
1372 value = false;
1373 else
1374 value = d->devMode->dmCollate == DMCOLLATE_TRUE;
1375 break;
1376
1377 case PPK_ColorMode:
1378 {
1379 if (!d->devMode) {
1381 } else {
1382 value = (d->devMode->dmColor == DMCOLOR_COLOR) ? QPrinter::Color : QPrinter::GrayScale;
1383 }
1384 }
1385 break;
1386
1387 case PPK_Creator:
1388 value = d->m_creator;
1389 break;
1390
1391 case PPK_DocumentName:
1392 value = d->docName;
1393 break;
1394
1395 case PPK_Duplex: {
1396 if (!d->devMode) {
1398 } else {
1399 switch (d->devMode->dmDuplex) {
1400 case DMDUP_VERTICAL:
1402 break;
1403 case DMDUP_HORIZONTAL:
1405 break;
1406 case DMDUP_SIMPLEX:
1407 default:
1409 break;
1410 }
1411 }
1412 break;
1413 }
1414
1415 case PPK_FullPage:
1416 value = d->m_pageLayout.mode() == QPageLayout::FullPageMode;
1417 break;
1418
1419 case PPK_CopyCount:
1420 value = d->num_copies;
1421 break;
1422
1424 value = true;
1425 break;
1426
1427 case PPK_NumberOfCopies:
1428 value = 1;
1429 break;
1430
1431 case PPK_Orientation:
1432 value = d->m_pageLayout.orientation();
1433 break;
1434
1435 case PPK_OutputFileName:
1436 value = d->fileName;
1437 break;
1438
1439 case PPK_PageRect:
1440 // PageRect is returned in device pixels
1441 value = d->m_pageLayout.paintRectPixels(d->resolution);
1442 break;
1443
1444 case PPK_PageSize:
1445 value = d->m_pageLayout.pageSize().id();
1446 break;
1447
1448 case PPK_PaperRect:
1449 // PaperRect is returned in device pixels
1450 value = d->m_pageLayout.fullRectPixels(d->resolution);
1451 break;
1452
1453 case PPK_PaperName:
1454 value = d->m_pageLayout.pageSize().name();
1455 break;
1456
1457 case PPK_PaperSource:
1458 if (!d->devMode) {
1459 value = d->m_printDevice.defaultInputSlot().id;
1460 } else {
1461 if (d->devMode->dmDefaultSource >= DMBIN_USER) {
1462 value = int(d->devMode->dmDefaultSource);
1463 } else {
1464 const auto inputSlots = d->m_printDevice.supportedInputSlots();
1465 const int index = indexOfWindowsId(inputSlots, d->devMode->dmDefaultSource);
1466 value = index >= 0 ? inputSlots.at(index).id : QPrint::Auto;
1467 }
1468 }
1469 break;
1470
1471 case PPK_PrinterName:
1472 value = d->m_printDevice.id();
1473 break;
1474
1475 case PPK_Resolution:
1476 if (d->resolution || d->m_printDevice.isValid())
1477 value = d->resolution;
1478 break;
1479
1481 QList<QVariant> list;
1482 const auto resolutions = d->m_printDevice.supportedResolutions();
1483 list.reserve(resolutions.size());
1484 for (int resolution : resolutions)
1485 list << resolution;
1486 value = list;
1487 break;
1488 }
1489
1491 value = d->m_pageLayout.pageSize().windowsId();
1492 break;
1493
1494 case PPK_PaperSources: {
1495 QList<QVariant> out;
1496 const auto inputSlots = d->m_printDevice.supportedInputSlots();
1497 out.reserve(inputSlots.size());
1498 for (const QPrint::InputSlot &inputSlot : inputSlots)
1499 out << QVariant(inputSlot.id == QPrint::CustomInputSlot ? inputSlot.windowsId : int(inputSlot.id));
1500 value = out;
1501 break;
1502 }
1503
1505 value = d->m_pageLayout.fullRectPoints().size();
1506 break;
1507
1508 case PPK_PageMargins: {
1509 QList<QVariant> list;
1510 QMarginsF margins = d->m_pageLayout.margins(QPageLayout::Point);
1511 list << margins.left() << margins.top() << margins.right() << margins.bottom();
1512 value = list;
1513 break;
1514 }
1515
1516 case PPK_QPageSize:
1517 value.setValue(d->m_pageLayout.pageSize());
1518 break;
1519
1520 case PPK_QPageMargins: {
1521 QPair<QMarginsF, QPageLayout::Unit> pair = qMakePair(d->m_pageLayout.margins(), d->m_pageLayout.units());
1522 value.setValue(pair);
1523 break;
1524 }
1525
1526 case PPK_QPageLayout:
1527 value.setValue(d->m_pageLayout);
1528 break;
1529
1530 case PPK_CustomBase:
1531 break;
1532
1533 // No default so that compiler will complain if new keys added and not handled in this engine
1534 }
1535 return value;
1536}
1537
1539{
1540 return d_func()->state;
1541}
1542
1544{
1545 return d_func()->hdc;
1546}
1547
1549{
1550
1551}
1552
1554{
1555 Q_D(QWin32PrintEngine);
1556
1557 const size_t size = sizeof(DEVNAMES) + d->m_printDevice.id().length() * 2 + 2;
1558 auto hGlobal = reinterpret_cast<HGLOBAL *>(GlobalAlloc(GMEM_MOVEABLE, size));
1559 auto dn = reinterpret_cast<DEVNAMES*>(GlobalLock(hGlobal));
1560
1561 dn->wDriverOffset = 0;
1562 dn->wDeviceOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
1563 dn->wOutputOffset = 0;
1564
1565 memcpy(reinterpret_cast<ushort*>(dn) + dn->wDeviceOffset,
1566 d->m_printDevice.id().utf16(), d->m_printDevice.id().length() * 2 + 2);
1567 dn->wDefault = 0;
1568
1569 GlobalUnlock(hGlobal);
1570 return hGlobal;
1571}
1572
1573void QWin32PrintEngine::setGlobalDevMode(HGLOBAL globalDevNames, HGLOBAL globalDevMode)
1574{
1575 Q_D(QWin32PrintEngine);
1576 if (globalDevNames) {
1577 auto dn = reinterpret_cast<DEVNAMES*>(GlobalLock(globalDevNames));
1578 const QString id =
1579 QString::fromWCharArray(reinterpret_cast<const wchar_t*>(dn) + dn->wDeviceOffset);
1581 if (ps)
1582 d->m_printDevice = ps->createPrintDevice(id.isEmpty() ? ps->defaultPrintDeviceId() : id);
1583 GlobalUnlock(globalDevNames);
1584 }
1585
1586 if (globalDevMode) {
1587 auto dm = reinterpret_cast<DEVMODE*>(GlobalLock(globalDevMode));
1588 d->release();
1589 d->globalDevMode = globalDevMode;
1590 if (d->ownsDevMode) {
1591 free(d->devMode);
1592 d->ownsDevMode = false;
1593 }
1594 d->devMode = dm;
1595 d->hdc = CreateDC(nullptr, reinterpret_cast<LPCWSTR>(d->m_printDevice.id().utf16()), nullptr, dm);
1596
1597 d->num_copies = d->devMode->dmCopies;
1598 d->updatePageLayout();
1599
1600 if (!OpenPrinter((wchar_t*)d->m_printDevice.id().utf16(), &d->hPrinter, 0))
1601 qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
1602 }
1603
1604 if (d->hdc)
1605 d->initHDC();
1606
1607#if defined QT_DEBUG_DRAW || defined QT_DEBUG_METRICS
1608 qDebug("QWin32PrintEngine::setGlobalDevMode()");
1609 d->debugMetrics();
1610#endif // QT_DEBUG_DRAW || QT_DEBUG_METRICS
1611}
1612
1614{
1615 Q_D(QWin32PrintEngine);
1616 return d->globalDevMode;
1617}
1618
1620{
1621 if (!pageSize.isValid())
1622 return;
1623
1625
1626 // Use the printer page size if supported
1627 const QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize);
1628 const QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize;
1629
1632
1633 // Setup if Windows custom size, i.e. not a known Windows ID
1634 if (printerPageSize.isValid()) {
1635 has_custom_paper_size = false;
1636 devMode->dmPaperSize = m_pageLayout.pageSize().windowsId();
1637 devMode->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
1638 devMode->dmPaperWidth = 0;
1639 devMode->dmPaperLength = 0;
1640 } else {
1641 devMode->dmPaperSize = DMPAPER_USER;
1642 devMode->dmFields |= DM_PAPERLENGTH | DM_PAPERWIDTH;
1643 // Size in tenths of a millimeter
1645 devMode->dmPaperWidth = qRound(sizeMM.width() * 10.0);
1646 devMode->dmPaperLength = qRound(sizeMM.height() * 10.0);
1647 }
1648 updateMetrics();
1649}
1650
1651// Update the page layout after any changes made to devMode
1653{
1655
1656 // Update orientation first as is needed to obtain printable margins when changing page size
1657 m_pageLayout.setOrientation(devMode->dmOrientation == DMORIENT_LANDSCAPE ? QPageLayout::Landscape : QPageLayout::Portrait);
1658 if (devMode->dmPaperSize >= DMPAPER_LAST) {
1659 // Is a custom size
1660 // Check if it is using the Postscript Custom Size first
1661 bool hasCustom = false;
1662 int feature = PSIDENT_GDICENTRIC;
1663 if (ExtEscape(hdc, POSTSCRIPT_IDENTIFY,
1664 sizeof(DWORD), reinterpret_cast<LPCSTR>(&feature), 0, 0) >= 0) {
1665 PSFEATURE_CUSTPAPER custPaper;
1666 feature = FEATURESETTING_CUSTPAPER;
1667 if (ExtEscape(hdc, GET_PS_FEATURESETTING, sizeof(INT), reinterpret_cast<LPCSTR>(&feature),
1668 sizeof(custPaper), reinterpret_cast<LPSTR>(&custPaper)) > 0) {
1669 // If orientation is 1 and width/height is 0 then it's not really custom
1670 if (!(custPaper.lOrientation == 1 && custPaper.lWidth == 0 && custPaper.lHeight == 0)) {
1671 if (custPaper.lOrientation == 0 || custPaper.lOrientation == 2)
1673 else
1675 QPageSize pageSize = QPageSize(QSizeF(custPaper.lWidth, custPaper.lHeight),
1677 setPageSize(pageSize);
1678 hasCustom = true;
1679 }
1680 }
1681 }
1682 if (!hasCustom) {
1683 QPageSize pageSize = QPageSize(QSizeF(devMode->dmPaperWidth / 10.0f, devMode->dmPaperLength / 10.0f),
1685 setPageSize(pageSize);
1686 }
1687 } else {
1688 // Is a supported size
1690 }
1691 updateMetrics();
1692}
1693
1694// Update the cached page paint metrics whenever page layout is changed
1696{
1698 // Some print devices allow scaling, so that "virtual" page size != current paper size
1699 const int devWidth = GetDeviceCaps(hdc, PHYSICALWIDTH);
1700 const int devHeight = GetDeviceCaps(hdc, PHYSICALHEIGHT);
1701 const int pageWidth = m_pageLayout.fullRectPixels(dpi_x).width();
1702 const int pageHeight = m_pageLayout.fullRectPixels(dpi_y).height();
1703 const qreal pageScaleX = (devWidth && pageWidth) ? qreal(devWidth) / pageWidth : 1;
1704 const qreal pageScaleY = (devHeight && pageHeight) ? qreal(devHeight) / pageHeight : 1;
1705 m_paintRectPixels = QTransform::fromScale(pageScaleX, pageScaleY).mapRect(m_paintRectPixels);
1706
1708 m_paintSizeMM = QSize(qRound(sizeMM.width()), qRound(sizeMM.height()));
1709 // Calculate the origin using the physical device pixels, not our paint pixels
1710 // Origin is defined as User Margins - Device Margins
1711 const bool isFullPage = (m_pageLayout.mode() == QPageLayout::FullPageMode);
1712 const QMarginsF margins = isFullPage ? QMarginsF() : (m_pageLayout.margins(QPageLayout::Millimeter) / 25.4);
1713 origin_x = qRound(pageScaleX * margins.left() * dpi_x) - GetDeviceCaps(hdc, PHYSICALOFFSETX);
1714 origin_y = qRound(pageScaleY * margins.top() * dpi_y) - GetDeviceCaps(hdc, PHYSICALOFFSETY);
1715}
1716
1718{
1719 qDebug() << " " << "m_pageLayout = " << m_pageLayout;
1720 qDebug() << " " << "m_paintRectPixels = " << m_paintRectPixels;
1721 qDebug() << " " << "m_paintSizeMM = " << m_paintSizeMM;
1722 qDebug() << " " << "resolution = " << resolution;
1723 qDebug() << " " << "stretch = " << stretch_x << stretch_y;
1724 qDebug() << " " << "origin = " << origin_x << origin_y;
1725 qDebug() << " " << "dpi = " << dpi_x << dpi_y;
1726 qDebug() << "";
1727}
1728
1729static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc,
1730 const QTransform &xform, const QPointF &topLeft)
1731{
1732 QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft);
1733
1734 SetTextAlign(hdc, TA_BASELINE);
1735 SetBkMode(hdc, TRANSPARENT);
1736
1737 const bool has_kerning = ti.f && ti.f->kerning();
1738
1739 HFONT hfont = nullptr;
1740 bool deleteFont = false;
1741
1742 if (ti.fontEngine->type() == QFontEngine::Win) {
1743 if (ti.fontEngine->supportsTransformation(QTransform::fromScale(0.5, 0.5))) // is TrueType font?
1744 hfont = static_cast<HFONT>(ti.fontEngine->handle());
1745 }
1746#if QT_CONFIG(directwrite)
1747 else if (ti.fontEngine->type() == QFontEngine::DirectWrite) {
1748 QWindowsFontEngineDirectWrite *fedw = static_cast<QWindowsFontEngineDirectWrite *>(ti.fontEngine);
1749 hfont = fedw->createHFONT();
1750 if (hfont)
1751 deleteFont = true;
1752 }
1753#endif
1754
1755 if (!hfont)
1756 hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
1757
1758 HGDIOBJ old_font = SelectObject(hdc, hfont);
1759 unsigned int options = ETO_GLYPH_INDEX;
1760 QGlyphLayout glyphs = ti.glyphs;
1761
1762 bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
1763 for (int i = 0; fast && i < glyphs.numGlyphs; i++) {
1764 if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0
1765 || glyphs.attributes[i].dontPrint) {
1766 fast = false;
1767 break;
1768 }
1769 }
1770
1771 // Scale, rotate and translate here.
1772 XFORM win_xform;
1773 win_xform.eM11 = xform.m11();
1774 win_xform.eM12 = xform.m12();
1775 win_xform.eM21 = xform.m21();
1776 win_xform.eM22 = xform.m22();
1777 win_xform.eDx = xform.dx();
1778 win_xform.eDy = xform.dy();
1779
1780 SetGraphicsMode(hdc, GM_ADVANCED);
1781 SetWorldTransform(hdc, &win_xform);
1782
1783 if (fast) {
1784 // fast path
1785 QVarLengthArray<wchar_t> g(glyphs.numGlyphs);
1786 for (int i = 0; i < glyphs.numGlyphs; ++i)
1787 g[i] = glyphs.glyphs[i];
1788 ExtTextOut(hdc,
1789 qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
1790 qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
1791 options, 0, g.constData(), glyphs.numGlyphs, 0);
1792 } else {
1793 QVarLengthArray<QFixedPoint> positions;
1794 QVarLengthArray<glyph_t> _glyphs;
1795
1796 QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y());
1797 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
1798 _glyphs, positions);
1799 if (_glyphs.isEmpty()) {
1800 SelectObject(hdc, old_font);
1801 return;
1802 }
1803
1804 options |= ETO_PDY;
1805 QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
1806 QVarLengthArray<wchar_t> g(_glyphs.size());
1807 const int lastGlyph = _glyphs.size() - 1;
1808 for (int i = 0; i < lastGlyph; ++i) {
1809 glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
1810 glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
1811 g[i] = _glyphs[i];
1812 }
1813 glyphDistances[lastGlyph * 2] = 0;
1814 glyphDistances[lastGlyph * 2 + 1] = 0;
1815 g[lastGlyph] = _glyphs[lastGlyph];
1816 ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, nullptr,
1817 g.constData(), _glyphs.size(),
1818 glyphDistances.data());
1819 }
1820
1821 win_xform.eM11 = win_xform.eM22 = 1.0;
1822 win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0;
1823 SetWorldTransform(hdc, &win_xform);
1824
1825 SelectObject(hdc, old_font);
1826
1827 if (deleteFont)
1828 DeleteObject(hfont);
1829}
1830
1832
1833#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
\inmodule QtGui
Definition qimage.h:37
@ Format_RGB32
Definition qimage.h:46
void reserve(qsizetype size)
Definition qlist.h:753
\inmodule QtCore
Definition qmargins.h:270
constexpr qreal right() const noexcept
Returns the right margin.
Definition qmargins.h:383
constexpr qreal left() const noexcept
Returns the left margin.
Definition qmargins.h:377
constexpr qreal top() const noexcept
Returns the top margin.
Definition qmargins.h:380
constexpr qreal bottom() const noexcept
Returns the bottom margin.
Definition qmargins.h:386
\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:572
QList< qreal > dashPattern() const
Returns the dash pattern of this pen.
Definition qpen.cpp:400
bool isCosmetic() const
Returns true if the pen is cosmetic; otherwise returns false.
Definition qpen.cpp:757
Qt::PenCapStyle capStyle() const
Returns the pen's cap style.
Definition qpen.cpp:636
Qt::PenJoinStyle joinStyle() const
Returns the pen's join style.
Definition qpen.cpp:663
qreal miterLimit() const
Returns the miter limit of the pen.
Definition qpen.cpp:524
QBrush brush() const
Returns the brush used to fill strokes generated with this pen.
Definition qpen.cpp:715
qreal dashOffset() const
Returns the dash offset for the pen.
Definition qpen.cpp:484
Qt::PenStyle style() const
Returns the pen style.
Definition qpen.cpp:366
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:480
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:432
int width() const
Returns the width of the pixmap.
Definition qpixmap.cpp:468
QPixmap copy(int x, int y, int width, int height) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qpixmap.h:153
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:1437
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:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
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:484
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qsize.h:25
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
Definition qstring.cpp:6995
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
Internal QTextItem.
\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.
TransformationType type() const
Returns the transformation type of this matrix.
qreal m22() const
Returns the vertical scaling factor.
Definition qtransform.h:215
qreal dy() const
Returns the vertical translation factor.
Definition qtransform.h:239
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
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:536
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)
static void initializeDevMode(DEVMODE *)
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:79
@ CustomInputSlot
Definition qprint_p.h:94
@ Auto
Definition qprint_p.h:86
Combined button and popup list for selecting options.
ClipOperation
@ ReplaceClip
@ NoClip
@ white
Definition qnamespace.h:31
@ black
Definition qnamespace.h:30
@ CustomDashLine
@ SolidLine
@ NoPen
@ MiterJoin
@ RoundJoin
@ SolidPattern
@ WindingFill
@ RoundCap
@ FlatCap
Definition brush.cpp:5
static const QCssKnownValue positions[NumKnownPositionModes - 1]
static const short indexOfId[NumKnownValues]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
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 color
[2]
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
QT_BEGIN_NAMESPACE 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:33
double qreal
Definition qtypes.h:187
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
args<< 1<< 2;QJSValue threeAgain=fun.call(args);QString fileName="helloworld.qs";QFile scriptFile(fileName);if(!scriptFile.open(QIODevice::ReadOnly)) QTextStream stream(&scriptFile);QString contents=stream.readAll();scriptFile.close();myEngine.evaluate(contents, fileName);myEngine.globalObject().setProperty("myNumber", 123);...QJSValue myNumberPlusOne=myEngine.evaluate("myNumber + 1");QJSValue result=myEngine.evaluate(...);if(result.isError()) qDebug()<< "Uncaught exception at line"<< result.property("lineNumber").toInt()<< ":"<< result.toString();QPushButton *button=new QPushButton;QJSValue scriptButton=myEngine.newQObject(button);myEngine.globalObject().setProperty("button", scriptButton);myEngine.evaluate("button.checkable = true");qDebug()<< scriptButton.property("checkable").toBool();scriptButton.property("show").call();QJSEngine engine;QObject *myQObject=new QObject();myQObject- setProperty)("dynamicProperty", 3)
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