1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** Contact: Qt Software Information ([email protected])
|
---|
5 | **
|
---|
6 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
7 | **
|
---|
8 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
9 | ** Commercial Usage
|
---|
10 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
11 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
12 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
13 | ** a written agreement between you and Nokia.
|
---|
14 | **
|
---|
15 | ** GNU Lesser General Public License Usage
|
---|
16 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
17 | ** General Public License version 2.1 as published by the Free Software
|
---|
18 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
19 | ** packaging of this file. Please review the following information to
|
---|
20 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
21 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
22 | **
|
---|
23 | ** In addition, as a special exception, Nokia gives you certain
|
---|
24 | ** additional rights. These rights are described in the Nokia Qt LGPL
|
---|
25 | ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
|
---|
26 | ** package.
|
---|
27 | **
|
---|
28 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you are unsure which license is appropriate for your use, please
|
---|
37 | ** contact the sales department at [email protected].
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #ifndef QT_NO_PRINTER
|
---|
43 |
|
---|
44 | #include "qprinter_p.h"
|
---|
45 | #include "qprintengine_win_p.h"
|
---|
46 |
|
---|
47 | #include <limits.h>
|
---|
48 |
|
---|
49 | #include <private/qfont_p.h>
|
---|
50 | #include <private/qfontengine_p.h>
|
---|
51 | #include <private/qpainter_p.h>
|
---|
52 |
|
---|
53 | #include <qbitmap.h>
|
---|
54 | #include <qdebug.h>
|
---|
55 | #include <qvector.h>
|
---|
56 | #include <qpicture.h>
|
---|
57 | #include <private/qpicture_p.h>
|
---|
58 |
|
---|
59 | QT_BEGIN_NAMESPACE
|
---|
60 |
|
---|
61 | extern QPainterPath qt_regionToPath(const QRegion ®ion);
|
---|
62 |
|
---|
63 | // #define QT_DEBUG_DRAW
|
---|
64 |
|
---|
65 | static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc,
|
---|
66 | bool convertToText, const QTransform &xform, const QPointF &topLeft);
|
---|
67 |
|
---|
68 | static const struct {
|
---|
69 | int winSizeName;
|
---|
70 | QPrinter::PaperSize qtSizeName;
|
---|
71 | } dmMapping[] = {
|
---|
72 | { DMPAPER_LETTER, QPrinter::Letter },
|
---|
73 | { DMPAPER_LETTERSMALL, QPrinter::Letter },
|
---|
74 | { DMPAPER_TABLOID, QPrinter::Tabloid },
|
---|
75 | { DMPAPER_LEDGER, QPrinter::Ledger },
|
---|
76 | { DMPAPER_LEGAL, QPrinter::Legal },
|
---|
77 | { DMPAPER_EXECUTIVE, QPrinter::Executive },
|
---|
78 | { DMPAPER_A3, QPrinter::A3 },
|
---|
79 | { DMPAPER_A4, QPrinter::A4 },
|
---|
80 | { DMPAPER_A4SMALL, QPrinter::A4 },
|
---|
81 | { DMPAPER_A5, QPrinter::A5 },
|
---|
82 | { DMPAPER_B4, QPrinter::B4 },
|
---|
83 | { DMPAPER_B5, QPrinter::B5 },
|
---|
84 | { DMPAPER_FOLIO, QPrinter::Folio },
|
---|
85 | { DMPAPER_ENV_10, QPrinter::Comm10E },
|
---|
86 | { DMPAPER_ENV_DL, QPrinter::DLE },
|
---|
87 | { DMPAPER_ENV_C3, QPrinter::C5E },
|
---|
88 | { DMPAPER_LETTER_EXTRA, QPrinter::Letter },
|
---|
89 | { DMPAPER_LEGAL_EXTRA, QPrinter::Legal },
|
---|
90 | { DMPAPER_TABLOID_EXTRA, QPrinter::Tabloid },
|
---|
91 | { DMPAPER_A4_EXTRA, QPrinter::A4},
|
---|
92 | { DMPAPER_LETTER_TRANSVERSE, QPrinter::Letter},
|
---|
93 | { DMPAPER_A4_TRANSVERSE, QPrinter::A4},
|
---|
94 | { DMPAPER_LETTER_EXTRA_TRANSVERSE, QPrinter::Letter },
|
---|
95 | { DMPAPER_A_PLUS, QPrinter::A4 },
|
---|
96 | { DMPAPER_B_PLUS, QPrinter::A3 },
|
---|
97 | { DMPAPER_LETTER_PLUS, QPrinter::Letter },
|
---|
98 | { DMPAPER_A4_PLUS, QPrinter::A4 },
|
---|
99 | { DMPAPER_A5_TRANSVERSE, QPrinter::A5 },
|
---|
100 | { DMPAPER_B5_TRANSVERSE, QPrinter::B5 },
|
---|
101 | { DMPAPER_A3_EXTRA, QPrinter::A3 },
|
---|
102 | { DMPAPER_A5_EXTRA, QPrinter::A5 },
|
---|
103 | { DMPAPER_B5_EXTRA, QPrinter::B5 },
|
---|
104 | { DMPAPER_A2, QPrinter::A2 },
|
---|
105 | { DMPAPER_A3_TRANSVERSE, QPrinter::A3 },
|
---|
106 | { DMPAPER_A3_EXTRA_TRANSVERSE,QPrinter::A3 },
|
---|
107 | { 0, QPrinter::Custom }
|
---|
108 | };
|
---|
109 |
|
---|
110 | QPrinter::PaperSize mapDevmodePaperSize(int s)
|
---|
111 | {
|
---|
112 | int i = 0;
|
---|
113 | while ((dmMapping[i].winSizeName > 0) && (dmMapping[i].winSizeName != s))
|
---|
114 | i++;
|
---|
115 | return dmMapping[i].qtSizeName;
|
---|
116 | }
|
---|
117 |
|
---|
118 | static int mapPaperSizeDevmode(QPrinter::PaperSize s)
|
---|
119 | {
|
---|
120 | int i = 0;
|
---|
121 | while ((dmMapping[i].winSizeName > 0) && (dmMapping[i].qtSizeName != s))
|
---|
122 | i++;
|
---|
123 | return dmMapping[i].winSizeName;
|
---|
124 | }
|
---|
125 |
|
---|
126 | static const struct {
|
---|
127 | int winSourceName;
|
---|
128 | QPrinter::PaperSource qtSourceName;
|
---|
129 | } sources[] = {
|
---|
130 | { DMBIN_ONLYONE, QPrinter::OnlyOne },
|
---|
131 | { DMBIN_LOWER, QPrinter::Lower },
|
---|
132 | { DMBIN_MIDDLE, QPrinter::Middle },
|
---|
133 | { DMBIN_MANUAL, QPrinter::Manual },
|
---|
134 | { DMBIN_ENVELOPE, QPrinter::Envelope },
|
---|
135 | { DMBIN_ENVMANUAL, QPrinter::EnvelopeManual },
|
---|
136 | { DMBIN_AUTO, QPrinter::Auto },
|
---|
137 | { DMBIN_TRACTOR, QPrinter::Tractor },
|
---|
138 | { DMBIN_SMALLFMT, QPrinter::SmallFormat },
|
---|
139 | { DMBIN_LARGEFMT, QPrinter::LargeFormat },
|
---|
140 | { DMBIN_LARGECAPACITY, QPrinter::LargeCapacity },
|
---|
141 | { DMBIN_CASSETTE, QPrinter::Cassette },
|
---|
142 | { DMBIN_FORMSOURCE, QPrinter::FormSource },
|
---|
143 | { 0, (QPrinter::PaperSource) -1 }
|
---|
144 | };
|
---|
145 |
|
---|
146 | static QPrinter::PaperSource mapDevmodePaperSource(int s)
|
---|
147 | {
|
---|
148 | int i = 0;
|
---|
149 | while ((sources[i].winSourceName > 0) && (sources[i].winSourceName != s))
|
---|
150 | i++;
|
---|
151 | return sources[i].winSourceName ? sources[i].qtSourceName : (QPrinter::PaperSource) s;
|
---|
152 | }
|
---|
153 |
|
---|
154 | static int mapPaperSourceDevmode(QPrinter::PaperSource s)
|
---|
155 | {
|
---|
156 | int i = 0;
|
---|
157 | while ((sources[i].qtSourceName >= 0) && (sources[i].qtSourceName != s))
|
---|
158 | i++;
|
---|
159 | return sources[i].winSourceName ? sources[i].winSourceName : s;
|
---|
160 | }
|
---|
161 |
|
---|
162 | QWin32PrintEngine::QWin32PrintEngine(QPrinter::PrinterMode mode)
|
---|
163 | : QAlphaPaintEngine(*(new QWin32PrintEnginePrivate),
|
---|
164 | PaintEngineFeatures(PrimitiveTransform
|
---|
165 | | PixmapTransform
|
---|
166 | | PerspectiveTransform
|
---|
167 | | PainterPaths
|
---|
168 | | Antialiasing
|
---|
169 | | PaintOutsidePaintEvent))
|
---|
170 | {
|
---|
171 | Q_D(QWin32PrintEngine);
|
---|
172 | d->docName = QLatin1String("document1");
|
---|
173 | d->mode = mode;
|
---|
174 | d->queryDefault();
|
---|
175 | d->initialize();
|
---|
176 | }
|
---|
177 |
|
---|
178 | bool QWin32PrintEngine::begin(QPaintDevice *pdev)
|
---|
179 | {
|
---|
180 | Q_D(QWin32PrintEngine);
|
---|
181 |
|
---|
182 | QAlphaPaintEngine::begin(pdev);
|
---|
183 | if (!continueCall())
|
---|
184 | return true;
|
---|
185 |
|
---|
186 | if (d->reinit) {
|
---|
187 | d->resetDC();
|
---|
188 | d->reinit = false;
|
---|
189 | }
|
---|
190 |
|
---|
191 | // ### set default colors and stuff...
|
---|
192 |
|
---|
193 | bool ok = d->state == QPrinter::Idle;
|
---|
194 |
|
---|
195 | if (!d->hdc)
|
---|
196 | return false;
|
---|
197 |
|
---|
198 | // Assign the FILE: to get the query...
|
---|
199 | if (d->printToFile && d->fileName.isEmpty())
|
---|
200 | d->fileName = d->port;
|
---|
201 |
|
---|
202 | QT_WA({
|
---|
203 | d->devModeW()->dmCopies = d->num_copies;
|
---|
204 | DOCINFO di;
|
---|
205 | memset(&di, 0, sizeof(DOCINFO));
|
---|
206 | di.cbSize = sizeof(DOCINFO);
|
---|
207 | di.lpszDocName = reinterpret_cast<const wchar_t *>(d->docName.utf16());
|
---|
208 | if (d->printToFile && !d->fileName.isEmpty())
|
---|
209 | di.lpszOutput = reinterpret_cast<const wchar_t *>(d->fileName.utf16());
|
---|
210 | if (ok && StartDoc(d->hdc, &di) == SP_ERROR) {
|
---|
211 | qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed");
|
---|
212 | ok = false;
|
---|
213 | }
|
---|
214 | } , {
|
---|
215 | d->devModeA()->dmCopies = d->num_copies;
|
---|
216 | DOCINFOA di;
|
---|
217 | memset(&di, 0, sizeof(DOCINFOA));
|
---|
218 | di.cbSize = sizeof(DOCINFOA);
|
---|
219 | QByteArray docNameA = d->docName.toLocal8Bit();
|
---|
220 | di.lpszDocName = docNameA.data();
|
---|
221 | QByteArray outfileA = d->fileName.toLocal8Bit();
|
---|
222 | if (d->printToFile && !d->fileName.isEmpty())
|
---|
223 | di.lpszOutput = outfileA;
|
---|
224 | if (ok && StartDocA(d->hdc, &di) == SP_ERROR) {
|
---|
225 | qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed");
|
---|
226 | ok = false;
|
---|
227 | }
|
---|
228 | });
|
---|
229 |
|
---|
230 | if (StartPage(d->hdc) <= 0) {
|
---|
231 | qErrnoWarning("QWin32PrintEngine::begin: StartPage failed");
|
---|
232 | ok = false;
|
---|
233 | }
|
---|
234 |
|
---|
235 | if (!ok) {
|
---|
236 | d->state = QPrinter::Idle;
|
---|
237 | } else {
|
---|
238 | d->state = QPrinter::Active;
|
---|
239 | }
|
---|
240 |
|
---|
241 | d->matrix = QTransform();
|
---|
242 | d->has_pen = true;
|
---|
243 | d->pen = QColor(Qt::black);
|
---|
244 | d->has_brush = false;
|
---|
245 |
|
---|
246 | d->complex_xform = false;
|
---|
247 |
|
---|
248 | updateMatrix(d->matrix);
|
---|
249 |
|
---|
250 | if (!ok)
|
---|
251 | cleanUp();
|
---|
252 |
|
---|
253 | return ok;
|
---|
254 | }
|
---|
255 |
|
---|
256 | bool QWin32PrintEngine::end()
|
---|
257 | {
|
---|
258 | Q_D(QWin32PrintEngine);
|
---|
259 |
|
---|
260 | if (d->hdc) {
|
---|
261 | if (d->state == QPrinter::Aborted) {
|
---|
262 | cleanUp();
|
---|
263 | AbortDoc(d->hdc);
|
---|
264 | return true;
|
---|
265 | }
|
---|
266 | }
|
---|
267 |
|
---|
268 | QAlphaPaintEngine::end();
|
---|
269 | if (!continueCall())
|
---|
270 | return true;
|
---|
271 |
|
---|
272 | if (d->hdc) {
|
---|
273 | EndPage(d->hdc); // end; printing done
|
---|
274 | EndDoc(d->hdc);
|
---|
275 | }
|
---|
276 |
|
---|
277 | d->state = QPrinter::Idle;
|
---|
278 | d->reinit = true;
|
---|
279 | return true;
|
---|
280 | }
|
---|
281 |
|
---|
282 | bool QWin32PrintEngine::newPage()
|
---|
283 | {
|
---|
284 | Q_D(QWin32PrintEngine);
|
---|
285 | Q_ASSERT(isActive());
|
---|
286 |
|
---|
287 | Q_ASSERT(d->hdc);
|
---|
288 |
|
---|
289 | flushAndInit();
|
---|
290 |
|
---|
291 | bool transparent = GetBkMode(d->hdc) == TRANSPARENT;
|
---|
292 |
|
---|
293 | if (!EndPage(d->hdc)) {
|
---|
294 | qErrnoWarning("QWin32PrintEngine::newPage: EndPage failed");
|
---|
295 | return false;
|
---|
296 | }
|
---|
297 |
|
---|
298 | if (d->reinit) {
|
---|
299 | if (!d->resetDC()) {
|
---|
300 | qErrnoWarning("QWin32PrintEngine::newPage: ResetDC failed");
|
---|
301 | return false;
|
---|
302 | }
|
---|
303 | d->reinit = false;
|
---|
304 | }
|
---|
305 |
|
---|
306 | if (!StartPage(d->hdc)) {
|
---|
307 | qErrnoWarning("Win32PrintEngine::newPage: StartPage failed");
|
---|
308 | return false;
|
---|
309 | }
|
---|
310 |
|
---|
311 | SetTextAlign(d->hdc, TA_BASELINE);
|
---|
312 | if (transparent)
|
---|
313 | SetBkMode(d->hdc, TRANSPARENT);
|
---|
314 |
|
---|
315 | // ###
|
---|
316 | return true;
|
---|
317 |
|
---|
318 | bool success = false;
|
---|
319 | if (d->hdc && d->state == QPrinter::Active) {
|
---|
320 | // bool restorePainter = false;
|
---|
321 | // if ((qWinVersion()& Qt::WV_DOS_based) && painter && painter->isActive()) {
|
---|
322 | // painter->save(); // EndPage/StartPage ruins the DC
|
---|
323 | // restorePainter = true;
|
---|
324 | // }
|
---|
325 | if (EndPage(d->hdc) != SP_ERROR) {
|
---|
326 | // reinitialize the DC before StartPage if needed,
|
---|
327 | // because resetdc is disabled between calls to the StartPage and EndPage functions
|
---|
328 | // (see StartPage documentation in the Platform SDK:Windows GDI)
|
---|
329 | // state = PST_ACTIVEDOC;
|
---|
330 | // reinit();
|
---|
331 | // state = PST_ACTIVE;
|
---|
332 | // start the new page now
|
---|
333 | if (d->reinit) {
|
---|
334 | if (!d->resetDC())
|
---|
335 | qErrnoWarning("QWin32PrintEngine::newPage(), ResetDC failed (2)");
|
---|
336 | d->reinit = false;
|
---|
337 | }
|
---|
338 | success = (StartPage(d->hdc) != SP_ERROR);
|
---|
339 | }
|
---|
340 | if (!success)
|
---|
341 | d->state = QPrinter::Aborted;
|
---|
342 |
|
---|
343 | // if (qWinVersion() & Qt::WV_DOS_based)
|
---|
344 | // if (restorePainter) {
|
---|
345 | // painter->restore();
|
---|
346 | // }
|
---|
347 |
|
---|
348 | if (!success)
|
---|
349 | return false;
|
---|
350 | }
|
---|
351 | return true;
|
---|
352 | }
|
---|
353 |
|
---|
354 | bool QWin32PrintEngine::abort()
|
---|
355 | {
|
---|
356 | // do nothing loop.
|
---|
357 | return false;
|
---|
358 | }
|
---|
359 |
|
---|
360 | void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
|
---|
361 | {
|
---|
362 | Q_D(const QWin32PrintEngine);
|
---|
363 |
|
---|
364 | QAlphaPaintEngine::drawTextItem(p, textItem);
|
---|
365 | if (!continueCall())
|
---|
366 | return;
|
---|
367 |
|
---|
368 | const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
|
---|
369 | QRgb brushColor = state->pen().brush().color().rgb();
|
---|
370 | bool fallBack = state->pen().brush().style() != Qt::SolidPattern
|
---|
371 | || qAlpha(brushColor) != 0xff
|
---|
372 | || QT_WA_INLINE(d->txop >= QTransform::TxProject, d->txop >= QTransform::TxScale)
|
---|
373 | || ti.fontEngine->type() != QFontEngine::Win;
|
---|
374 |
|
---|
375 |
|
---|
376 | if (!fallBack) {
|
---|
377 | QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine);
|
---|
378 |
|
---|
379 | // Try selecting the font to see if we get a substitution font
|
---|
380 | SelectObject(d->hdc, fe->hfont);
|
---|
381 |
|
---|
382 | if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) {
|
---|
383 | QT_WA({
|
---|
384 | TCHAR n[64];
|
---|
385 | GetTextFaceW(d->hdc, 64, n);
|
---|
386 | fallBack = QString::fromUtf16((ushort *)n)
|
---|
387 | != QString::fromUtf16((ushort *)fe->logfont.lfFaceName);
|
---|
388 | } , {
|
---|
389 | char an[64];
|
---|
390 | GetTextFaceA(d->hdc, 64, an);
|
---|
391 | fallBack = QString::fromLocal8Bit(an)
|
---|
392 | != QString::fromLocal8Bit(((LOGFONTA*)(&fe->logfont))->lfFaceName);
|
---|
393 | });
|
---|
394 | }
|
---|
395 | }
|
---|
396 |
|
---|
397 |
|
---|
398 | if (fallBack) {
|
---|
399 | QPaintEngine::drawTextItem(p, textItem);
|
---|
400 | return ;
|
---|
401 | }
|
---|
402 |
|
---|
403 | // We only want to convert the glyphs to text if the entire string is latin1
|
---|
404 | bool latin1String = true;
|
---|
405 | for (int i=0; i < ti.num_chars; ++i) {
|
---|
406 | if (ti.chars[i].unicode() >= 0x100) {
|
---|
407 | latin1String = false;
|
---|
408 | break;
|
---|
409 | }
|
---|
410 | }
|
---|
411 |
|
---|
412 | COLORREF cf = RGB(qRed(brushColor), qGreen(brushColor), qBlue(brushColor));
|
---|
413 | SelectObject(d->hdc, CreateSolidBrush(cf));
|
---|
414 | SelectObject(d->hdc, CreatePen(PS_SOLID, 1, cf));
|
---|
415 | SetTextColor(d->hdc, cf);
|
---|
416 |
|
---|
417 | draw_text_item_win(p, ti, d->hdc, latin1String, d->matrix, d->devPaperRect.topLeft());
|
---|
418 | DeleteObject(SelectObject(d->hdc,GetStockObject(HOLLOW_BRUSH)));
|
---|
419 | DeleteObject(SelectObject(d->hdc,GetStockObject(BLACK_PEN)));
|
---|
420 | }
|
---|
421 |
|
---|
422 | static inline qreal mmToInches(double mm)
|
---|
423 | {
|
---|
424 | return mm*0.039370147;
|
---|
425 | }
|
---|
426 |
|
---|
427 | static inline qreal inchesToMM(double in)
|
---|
428 | {
|
---|
429 | return in/0.039370147;
|
---|
430 | }
|
---|
431 |
|
---|
432 | int QWin32PrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
|
---|
433 | {
|
---|
434 | Q_D(const QWin32PrintEngine);
|
---|
435 |
|
---|
436 | if (!d->hdc)
|
---|
437 | return 0;
|
---|
438 |
|
---|
439 | int val;
|
---|
440 | int res = d->resolution;
|
---|
441 |
|
---|
442 | switch (m) {
|
---|
443 | case QPaintDevice::PdmWidth:
|
---|
444 | if (d->has_custom_paper_size) {
|
---|
445 | val = qRound(d->paper_size.width() * res / 72.0);
|
---|
446 | } else {
|
---|
447 | int logPixelsX = GetDeviceCaps(d->hdc, LOGPIXELSX);
|
---|
448 | if (logPixelsX == 0) {
|
---|
449 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
450 | "might be a driver problem");
|
---|
451 | logPixelsX = 600; // Reasonable default
|
---|
452 | }
|
---|
453 | val = res
|
---|
454 | * GetDeviceCaps(d->hdc, d->fullPage ? PHYSICALWIDTH : HORZRES)
|
---|
455 | / logPixelsX;
|
---|
456 | }
|
---|
457 | if (d->pageMarginsSet)
|
---|
458 | val -= int(mmToInches((d->previousDialogMargins.left() +
|
---|
459 | d->previousDialogMargins.width()) / 100.0) * res);
|
---|
460 | break;
|
---|
461 | case QPaintDevice::PdmHeight:
|
---|
462 | if (d->has_custom_paper_size) {
|
---|
463 | val = qRound(d->paper_size.height() * res / 72.0);
|
---|
464 | } else {
|
---|
465 | int logPixelsY = GetDeviceCaps(d->hdc, LOGPIXELSY);
|
---|
466 | if (logPixelsY == 0) {
|
---|
467 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
468 | "might be a driver problem");
|
---|
469 | logPixelsY = 600; // Reasonable default
|
---|
470 | }
|
---|
471 | val = res
|
---|
472 | * GetDeviceCaps(d->hdc, d->fullPage ? PHYSICALHEIGHT : VERTRES)
|
---|
473 | / logPixelsY;
|
---|
474 | }
|
---|
475 | if (d->pageMarginsSet)
|
---|
476 | val -= int(mmToInches((d->previousDialogMargins.top() +
|
---|
477 | d->previousDialogMargins.height()) / 100.0) * res);
|
---|
478 | break;
|
---|
479 | case QPaintDevice::PdmDpiX:
|
---|
480 | val = res;
|
---|
481 | break;
|
---|
482 | case QPaintDevice::PdmDpiY:
|
---|
483 | val = res;
|
---|
484 | break;
|
---|
485 | case QPaintDevice::PdmPhysicalDpiX:
|
---|
486 | val = GetDeviceCaps(d->hdc, LOGPIXELSX);
|
---|
487 | break;
|
---|
488 | case QPaintDevice::PdmPhysicalDpiY:
|
---|
489 | val = GetDeviceCaps(d->hdc, LOGPIXELSY);
|
---|
490 | break;
|
---|
491 | case QPaintDevice::PdmWidthMM:
|
---|
492 | if (d->has_custom_paper_size) {
|
---|
493 | val = qRound(d->paper_size.width()*25.4/72);
|
---|
494 | } else {
|
---|
495 | if (!d->fullPage) {
|
---|
496 | val = GetDeviceCaps(d->hdc, HORZSIZE);
|
---|
497 | } else {
|
---|
498 | float wi = 25.4 * GetDeviceCaps(d->hdc, PHYSICALWIDTH);
|
---|
499 | int logPixelsX = GetDeviceCaps(d->hdc, LOGPIXELSX);
|
---|
500 | if (logPixelsX == 0) {
|
---|
501 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
502 | "might be a driver problem");
|
---|
503 | logPixelsX = 600; // Reasonable default
|
---|
504 | }
|
---|
505 | val = qRound(wi / logPixelsX);
|
---|
506 | }
|
---|
507 | }
|
---|
508 | if (d->pageMarginsSet)
|
---|
509 | val -= (d->previousDialogMargins.left() +
|
---|
510 | d->previousDialogMargins.width()) / 100.0;
|
---|
511 | break;
|
---|
512 | case QPaintDevice::PdmHeightMM:
|
---|
513 | if (d->has_custom_paper_size) {
|
---|
514 | val = qRound(d->paper_size.height()*25.4/72);
|
---|
515 | } else {
|
---|
516 | if (!d->fullPage) {
|
---|
517 | val = GetDeviceCaps(d->hdc, VERTSIZE);
|
---|
518 | } else {
|
---|
519 | float hi = 25.4 * GetDeviceCaps(d->hdc, PHYSICALHEIGHT);
|
---|
520 | int logPixelsY = GetDeviceCaps(d->hdc, LOGPIXELSY);
|
---|
521 | if (logPixelsY == 0) {
|
---|
522 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
523 | "might be a driver problem");
|
---|
524 | logPixelsY = 600; // Reasonable default
|
---|
525 | }
|
---|
526 | val = qRound(hi / logPixelsY);
|
---|
527 | }
|
---|
528 | }
|
---|
529 | if (d->pageMarginsSet)
|
---|
530 | val -= (d->previousDialogMargins.top() +
|
---|
531 | d->previousDialogMargins.height()) / 100.0;
|
---|
532 | break;
|
---|
533 | case QPaintDevice::PdmNumColors:
|
---|
534 | {
|
---|
535 | int bpp = GetDeviceCaps(d->hdc, BITSPIXEL);
|
---|
536 | if(bpp==32)
|
---|
537 | val = INT_MAX;
|
---|
538 | else if(bpp<=8)
|
---|
539 | val = GetDeviceCaps(d->hdc, NUMCOLORS);
|
---|
540 | else
|
---|
541 | val = 1 << (bpp * GetDeviceCaps(d->hdc, PLANES));
|
---|
542 | }
|
---|
543 | break;
|
---|
544 | case QPaintDevice::PdmDepth:
|
---|
545 | val = GetDeviceCaps(d->hdc, PLANES);
|
---|
546 | break;
|
---|
547 | default:
|
---|
548 | qWarning("QPrinter::metric: Invalid metric command");
|
---|
549 | return 0;
|
---|
550 | }
|
---|
551 | return val;
|
---|
552 | }
|
---|
553 |
|
---|
554 | void QWin32PrintEngine::updateState(const QPaintEngineState &state)
|
---|
555 | {
|
---|
556 | Q_D(QWin32PrintEngine);
|
---|
557 |
|
---|
558 | QAlphaPaintEngine::updateState(state);
|
---|
559 | if (!continueCall())
|
---|
560 | return;
|
---|
561 |
|
---|
562 | if (state.state() & DirtyTransform) {
|
---|
563 | updateMatrix(state.transform());
|
---|
564 | }
|
---|
565 |
|
---|
566 | if (state.state() & DirtyPen) {
|
---|
567 | d->pen = state.pen();
|
---|
568 | d->has_pen = d->pen.style() != Qt::NoPen && d->pen.isSolid();
|
---|
569 | }
|
---|
570 |
|
---|
571 | if (state.state() & DirtyBrush) {
|
---|
572 | QBrush brush = state.brush();
|
---|
573 | d->has_brush = brush.style() == Qt::SolidPattern;
|
---|
574 | d->brush_color = brush.color();
|
---|
575 | }
|
---|
576 |
|
---|
577 | if (state.state() & DirtyClipEnabled) {
|
---|
578 | if (state.isClipEnabled())
|
---|
579 | updateClipPath(painter()->clipPath(), Qt::ReplaceClip);
|
---|
580 | else
|
---|
581 | updateClipPath(QPainterPath(), Qt::NoClip);
|
---|
582 | }
|
---|
583 |
|
---|
584 | if (state.state() & DirtyClipPath) {
|
---|
585 | updateClipPath(state.clipPath(), state.clipOperation());
|
---|
586 | }
|
---|
587 |
|
---|
588 | if (state.state() & DirtyClipRegion) {
|
---|
589 | QRegion clipRegion = state.clipRegion();
|
---|
590 | QPainterPath clipPath = qt_regionToPath(clipRegion);
|
---|
591 | updateClipPath(clipPath, state.clipOperation());
|
---|
592 | }
|
---|
593 | }
|
---|
594 |
|
---|
595 | void QWin32PrintEngine::updateClipPath(const QPainterPath &clipPath, Qt::ClipOperation op)
|
---|
596 | {
|
---|
597 | Q_D(QWin32PrintEngine);
|
---|
598 |
|
---|
599 | bool doclip = true;
|
---|
600 | if (op == Qt::NoClip) {
|
---|
601 | SelectClipRgn(d->hdc, 0);
|
---|
602 | doclip = false;
|
---|
603 | }
|
---|
604 |
|
---|
605 | if (doclip) {
|
---|
606 | QPainterPath xformed = clipPath * d->matrix;
|
---|
607 |
|
---|
608 | if (xformed.isEmpty()) {
|
---|
609 | QRegion empty(-0x1000000, -0x1000000, 1, 1);
|
---|
610 | SelectClipRgn(d->hdc, empty.handle());
|
---|
611 | } else {
|
---|
612 | d->composeGdiPath(xformed);
|
---|
613 | const int ops[] = {
|
---|
614 | -1, // Qt::NoClip, covered above
|
---|
615 | RGN_COPY, // Qt::ReplaceClip
|
---|
616 | RGN_AND, // Qt::IntersectClip
|
---|
617 | RGN_OR // Qt::UniteClip
|
---|
618 | };
|
---|
619 | Q_ASSERT(op > 0 && unsigned(op) <= sizeof(ops) / sizeof(int));
|
---|
620 | SelectClipPath(d->hdc, ops[op]);
|
---|
621 | }
|
---|
622 | }
|
---|
623 |
|
---|
624 | QPainterPath aclip = qt_regionToPath(alphaClipping());
|
---|
625 | if (!aclip.isEmpty()) {
|
---|
626 | QTransform tx(d->stretch_x, 0, 0, d->stretch_y, d->origin_x, d->origin_y);
|
---|
627 | d->composeGdiPath(tx.map(aclip));
|
---|
628 | SelectClipPath(d->hdc, RGN_DIFF);
|
---|
629 | }
|
---|
630 | }
|
---|
631 |
|
---|
632 | void QWin32PrintEngine::updateMatrix(const QTransform &m)
|
---|
633 | {
|
---|
634 | Q_D(QWin32PrintEngine);
|
---|
635 |
|
---|
636 | QTransform stretch(d->stretch_x, 0, 0, d->stretch_y, d->origin_x, d->origin_y);
|
---|
637 | d->painterMatrix = m;
|
---|
638 | d->matrix = d->painterMatrix * stretch;
|
---|
639 | d->txop = d->matrix.type();
|
---|
640 | d->complex_xform = (d->txop > QTransform::TxScale);
|
---|
641 | }
|
---|
642 |
|
---|
643 | void QWin32PrintEngine::drawPixmap(const QRectF &targetRect,
|
---|
644 | const QPixmap &originalPixmap,
|
---|
645 | const QRectF &sourceRect)
|
---|
646 | {
|
---|
647 | Q_D(QWin32PrintEngine);
|
---|
648 |
|
---|
649 | QAlphaPaintEngine::drawPixmap(targetRect, originalPixmap, sourceRect);
|
---|
650 | if (!continueCall())
|
---|
651 | return;
|
---|
652 |
|
---|
653 | const int tileSize = 2048;
|
---|
654 |
|
---|
655 | QRectF r = targetRect;
|
---|
656 | QRectF sr = sourceRect;
|
---|
657 |
|
---|
658 | QPixmap pixmap = originalPixmap;
|
---|
659 | if (sr.size() != pixmap.size()) {
|
---|
660 | pixmap = pixmap.copy(sr.toRect());
|
---|
661 | }
|
---|
662 |
|
---|
663 | qreal scaleX = 1.0f;
|
---|
664 | qreal scaleY = 1.0f;
|
---|
665 |
|
---|
666 | QTransform scaleMatrix;
|
---|
667 | scaleMatrix.scale(r.width() / pixmap.width(), r.height() / pixmap.height());
|
---|
668 | QTransform adapted = QPixmap::trueMatrix(d->painterMatrix * scaleMatrix,
|
---|
669 | pixmap.width(), pixmap.height());
|
---|
670 |
|
---|
671 | qreal xform_offset_x = adapted.dx();
|
---|
672 | qreal xform_offset_y = adapted.dy();
|
---|
673 |
|
---|
674 | if (d->complex_xform) {
|
---|
675 | pixmap = pixmap.transformed(adapted);
|
---|
676 | scaleX = d->stretch_x;
|
---|
677 | scaleY = d->stretch_y;
|
---|
678 | } else {
|
---|
679 | scaleX = d->stretch_x * (r.width() / pixmap.width()) * d->painterMatrix.m11();
|
---|
680 | scaleY = d->stretch_y * (r.height() / pixmap.height()) * d->painterMatrix.m22();
|
---|
681 | }
|
---|
682 |
|
---|
683 | QPointF topLeft = r.topLeft() * d->painterMatrix;
|
---|
684 | int tx = int(topLeft.x() * d->stretch_x + d->origin_x);
|
---|
685 | int ty = int(topLeft.y() * d->stretch_y + d->origin_y);
|
---|
686 | int tw = qAbs(int(pixmap.width() * scaleX));
|
---|
687 | int th = qAbs(int(pixmap.height() * scaleY));
|
---|
688 |
|
---|
689 | xform_offset_x *= d->stretch_x;
|
---|
690 | xform_offset_y *= d->stretch_y;
|
---|
691 |
|
---|
692 | int dc_state = SaveDC(d->hdc);
|
---|
693 |
|
---|
694 | int tilesw = pixmap.width() / tileSize;
|
---|
695 | int tilesh = pixmap.height() / tileSize;
|
---|
696 | ++tilesw;
|
---|
697 | ++tilesh;
|
---|
698 |
|
---|
699 | int txinc = tileSize*scaleX;
|
---|
700 | int tyinc = tileSize*scaleY;
|
---|
701 |
|
---|
702 | for (int y = 0; y < tilesh; ++y) {
|
---|
703 | int tposy = ty + (y * tyinc);
|
---|
704 | int imgh = tileSize;
|
---|
705 | int height = tyinc;
|
---|
706 | if (y == (tilesh - 1)) {
|
---|
707 | imgh = pixmap.height() - (y * tileSize);
|
---|
708 | height = (th - (y * tyinc));
|
---|
709 | }
|
---|
710 | for (int x = 0; x < tilesw; ++x) {
|
---|
711 | int tposx = tx + (x * txinc);
|
---|
712 | int imgw = tileSize;
|
---|
713 | int width = txinc;
|
---|
714 | if (x == (tilesw - 1)) {
|
---|
715 | imgw = pixmap.width() - (x * tileSize);
|
---|
716 | width = (tw - (x * txinc));
|
---|
717 | }
|
---|
718 |
|
---|
719 | QPixmap p = pixmap.copy(tileSize * x, tileSize * y, imgw, imgh);
|
---|
720 | HBITMAP hbitmap = p.toWinHBITMAP(QPixmap::NoAlpha);
|
---|
721 | HDC display_dc = GetDC(0);
|
---|
722 | HDC hbitmap_hdc = CreateCompatibleDC(display_dc);
|
---|
723 | HGDIOBJ null_bitmap = SelectObject(hbitmap_hdc, hbitmap);
|
---|
724 |
|
---|
725 | ReleaseDC(0, display_dc);
|
---|
726 |
|
---|
727 | if (!StretchBlt(d->hdc, qRound(tposx - xform_offset_x), qRound(tposy - xform_offset_y), width, height,
|
---|
728 | hbitmap_hdc, 0, 0, p.width(), p.height(), SRCCOPY))
|
---|
729 | qErrnoWarning("QWin32PrintEngine::drawPixmap, StretchBlt failed");
|
---|
730 |
|
---|
731 | SelectObject(hbitmap_hdc, null_bitmap);
|
---|
732 | DeleteObject(hbitmap);
|
---|
733 | DeleteDC(hbitmap_hdc);
|
---|
734 | }
|
---|
735 | }
|
---|
736 |
|
---|
737 | RestoreDC(d->hdc, dc_state);
|
---|
738 | }
|
---|
739 |
|
---|
740 |
|
---|
741 | void QWin32PrintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &pos)
|
---|
742 | {
|
---|
743 | Q_D(QWin32PrintEngine);
|
---|
744 |
|
---|
745 | QAlphaPaintEngine::drawTiledPixmap(r, pm, pos);
|
---|
746 | if (!continueCall())
|
---|
747 | return;
|
---|
748 |
|
---|
749 | if (d->complex_xform || !pos.isNull()) {
|
---|
750 | QPaintEngine::drawTiledPixmap(r, pm, pos);
|
---|
751 | } else {
|
---|
752 | int dc_state = SaveDC(d->hdc);
|
---|
753 |
|
---|
754 | HDC display_dc = GetDC(0);
|
---|
755 | HBITMAP hbitmap = pm.toWinHBITMAP(QPixmap::NoAlpha);
|
---|
756 | HDC hbitmap_hdc = CreateCompatibleDC(display_dc);
|
---|
757 | HGDIOBJ null_bitmap = SelectObject(hbitmap_hdc, hbitmap);
|
---|
758 |
|
---|
759 | ReleaseDC(0, display_dc);
|
---|
760 |
|
---|
761 | QRectF trect = d->painterMatrix.mapRect(r);
|
---|
762 | int tx = int(trect.left() * d->stretch_x + d->origin_x);
|
---|
763 | int ty = int(trect.top() * d->stretch_y + d->origin_y);
|
---|
764 |
|
---|
765 | int xtiles = int(trect.width() / pm.width()) + 1;
|
---|
766 | int ytiles = int(trect.height() / pm.height()) + 1;
|
---|
767 | int xinc = int(pm.width() * d->stretch_x);
|
---|
768 | int yinc = int(pm.height() * d->stretch_y);
|
---|
769 |
|
---|
770 | for (int y = 0; y < ytiles; ++y) {
|
---|
771 | int ity = ty + (yinc * y);
|
---|
772 | int ith = pm.height();
|
---|
773 | if (y == (ytiles - 1)) {
|
---|
774 | ith = int(trect.height() - (pm.height() * y));
|
---|
775 | }
|
---|
776 |
|
---|
777 | for (int x = 0; x < xtiles; ++x) {
|
---|
778 | int itx = tx + (xinc * x);
|
---|
779 | int itw = pm.width();
|
---|
780 | if (x == (xtiles - 1)) {
|
---|
781 | itw = int(trect.width() - (pm.width() * x));
|
---|
782 | }
|
---|
783 |
|
---|
784 | if (!StretchBlt(d->hdc, itx, ity, int(itw * d->stretch_x), int(ith * d->stretch_y),
|
---|
785 | hbitmap_hdc, 0, 0, itw, ith, SRCCOPY))
|
---|
786 | qErrnoWarning("QWin32PrintEngine::drawPixmap, StretchBlt failed");
|
---|
787 |
|
---|
788 | }
|
---|
789 | }
|
---|
790 |
|
---|
791 | SelectObject(hbitmap_hdc, null_bitmap);
|
---|
792 | DeleteObject(hbitmap);
|
---|
793 | DeleteDC(hbitmap_hdc);
|
---|
794 |
|
---|
795 | RestoreDC(d->hdc, dc_state);
|
---|
796 | }
|
---|
797 | }
|
---|
798 |
|
---|
799 |
|
---|
800 | void QWin32PrintEnginePrivate::composeGdiPath(const QPainterPath &path)
|
---|
801 | {
|
---|
802 | if (!BeginPath(hdc))
|
---|
803 | qErrnoWarning("QWin32PrintEnginePrivate::drawPath: BeginPath failed");
|
---|
804 |
|
---|
805 | // Drawing the subpaths
|
---|
806 | int start = -1;
|
---|
807 | for (int i=0; i<path.elementCount(); ++i) {
|
---|
808 | const QPainterPath::Element &elm = path.elementAt(i);
|
---|
809 | switch (elm.type) {
|
---|
810 | case QPainterPath::MoveToElement:
|
---|
811 | if (start >= 0
|
---|
812 | && path.elementAt(start).x == path.elementAt(i-1).x
|
---|
813 | && path.elementAt(start).y == path.elementAt(i-1).y)
|
---|
814 | CloseFigure(hdc);
|
---|
815 | start = i;
|
---|
816 | MoveToEx(hdc, qRound(elm.x), qRound(elm.y), 0);
|
---|
817 | break;
|
---|
818 | case QPainterPath::LineToElement:
|
---|
819 | LineTo(hdc, qRound(elm.x), qRound(elm.y));
|
---|
820 | break;
|
---|
821 | case QPainterPath::CurveToElement: {
|
---|
822 | POINT pts[3] = {
|
---|
823 | { qRound(elm.x), qRound(elm.y) },
|
---|
824 | { qRound(path.elementAt(i+1).x), qRound(path.elementAt(i+1).y) },
|
---|
825 | { qRound(path.elementAt(i+2).x), qRound(path.elementAt(i+2).y) }
|
---|
826 | };
|
---|
827 | i+=2;
|
---|
828 | PolyBezierTo(hdc, pts, 3);
|
---|
829 | break;
|
---|
830 | }
|
---|
831 | default:
|
---|
832 | qFatal("QWin32PaintEngine::drawPath: Unhandled type: %d", elm.type);
|
---|
833 | }
|
---|
834 | }
|
---|
835 |
|
---|
836 | if (start >= 0
|
---|
837 | && path.elementAt(start).x == path.elementAt(path.elementCount()-1).x
|
---|
838 | && path.elementAt(start).y == path.elementAt(path.elementCount()-1).y)
|
---|
839 | CloseFigure(hdc);
|
---|
840 |
|
---|
841 | if (!EndPath(hdc))
|
---|
842 | qErrnoWarning("QWin32PaintEngine::drawPath: EndPath failed");
|
---|
843 |
|
---|
844 | SetPolyFillMode(hdc, path.fillRule() == Qt::WindingFill ? WINDING : ALTERNATE);
|
---|
845 | }
|
---|
846 |
|
---|
847 |
|
---|
848 | void QWin32PrintEnginePrivate::fillPath_dev(const QPainterPath &path, const QColor &color)
|
---|
849 | {
|
---|
850 | #ifdef QT_DEBUG_DRAW
|
---|
851 | qDebug() << " --- QWin32PrintEnginePrivate::fillPath() bound:" << path.boundingRect() << color;
|
---|
852 | #endif
|
---|
853 |
|
---|
854 | composeGdiPath(path);
|
---|
855 |
|
---|
856 | HBRUSH brush = CreateSolidBrush(RGB(color.red(), color.green(), color.blue()));
|
---|
857 | HGDIOBJ old_brush = SelectObject(hdc, brush);
|
---|
858 | FillPath(hdc);
|
---|
859 | DeleteObject(SelectObject(hdc, old_brush));
|
---|
860 | }
|
---|
861 |
|
---|
862 | void QWin32PrintEnginePrivate::strokePath_dev(const QPainterPath &path, const QColor &color, qreal penWidth)
|
---|
863 | {
|
---|
864 | composeGdiPath(path);
|
---|
865 | HPEN pen = CreatePen(PS_SOLID, qRound(penWidth), RGB(color.red(), color.green(), color.blue()));
|
---|
866 | HGDIOBJ old_pen = SelectObject(hdc, pen);
|
---|
867 | StrokePath(hdc);
|
---|
868 | DeleteObject(SelectObject(hdc, old_pen));
|
---|
869 | }
|
---|
870 |
|
---|
871 |
|
---|
872 | void QWin32PrintEnginePrivate::fillPath(const QPainterPath &path, const QColor &color)
|
---|
873 | {
|
---|
874 | fillPath_dev(path * matrix, color);
|
---|
875 | }
|
---|
876 |
|
---|
877 | void QWin32PrintEnginePrivate::strokePath(const QPainterPath &path, const QColor &color)
|
---|
878 | {
|
---|
879 | QPainterPathStroker stroker;
|
---|
880 | if (pen.style() == Qt::CustomDashLine) {
|
---|
881 | stroker.setDashPattern(pen.dashPattern());
|
---|
882 | stroker.setDashOffset(pen.dashOffset());
|
---|
883 | } else {
|
---|
884 | stroker.setDashPattern(pen.style());
|
---|
885 | }
|
---|
886 | stroker.setCapStyle(pen.capStyle());
|
---|
887 | stroker.setJoinStyle(pen.joinStyle());
|
---|
888 | stroker.setMiterLimit(pen.miterLimit());
|
---|
889 |
|
---|
890 | QPainterPath stroke;
|
---|
891 | qreal width = pen.widthF();
|
---|
892 | if (pen.style() == Qt::SolidLine && (pen.isCosmetic() || matrix.type() < QTransform::TxScale)) {
|
---|
893 | strokePath_dev(path * matrix, color, width);
|
---|
894 | } else {
|
---|
895 | stroker.setWidth(width);
|
---|
896 | if (pen.isCosmetic()) {
|
---|
897 | stroke = stroker.createStroke(path * matrix);
|
---|
898 | } else {
|
---|
899 | stroke = stroker.createStroke(path) * painterMatrix;
|
---|
900 | QTransform stretch(stretch_x, 0, 0, stretch_y, origin_x, origin_y);
|
---|
901 | stroke = stroke * stretch;
|
---|
902 | }
|
---|
903 |
|
---|
904 | if (stroke.isEmpty())
|
---|
905 | return;
|
---|
906 |
|
---|
907 | fillPath_dev(stroke, color);
|
---|
908 | }
|
---|
909 | }
|
---|
910 |
|
---|
911 |
|
---|
912 | void QWin32PrintEngine::drawPath(const QPainterPath &path)
|
---|
913 | {
|
---|
914 | #ifdef QT_DEBUG_DRAW
|
---|
915 | qDebug() << " - QWin32PrintEngine::drawPath(), bounds: " << path.boundingRect();
|
---|
916 | #endif
|
---|
917 |
|
---|
918 | Q_D(QWin32PrintEngine);
|
---|
919 |
|
---|
920 | QAlphaPaintEngine::drawPath(path);
|
---|
921 | if (!continueCall())
|
---|
922 | return;
|
---|
923 |
|
---|
924 | if (d->has_brush)
|
---|
925 | d->fillPath(path, d->brush_color);
|
---|
926 |
|
---|
927 | if (d->has_pen)
|
---|
928 | d->strokePath(path, d->pen.color());
|
---|
929 | }
|
---|
930 |
|
---|
931 |
|
---|
932 | void QWin32PrintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
|
---|
933 | {
|
---|
934 | #ifdef QT_DEBUG_DRAW
|
---|
935 | qDebug() << " - QWin32PrintEngine::drawPolygon(), pointCount: " << pointCount;
|
---|
936 | #endif
|
---|
937 |
|
---|
938 | QAlphaPaintEngine::drawPolygon(points, pointCount, mode);
|
---|
939 | if (!continueCall())
|
---|
940 | return;
|
---|
941 |
|
---|
942 | Q_ASSERT(pointCount > 1);
|
---|
943 |
|
---|
944 | QPainterPath path(points[0]);
|
---|
945 |
|
---|
946 | for (int i=1; i<pointCount; ++i) {
|
---|
947 | path.lineTo(points[i]);
|
---|
948 | }
|
---|
949 |
|
---|
950 | Q_D(QWin32PrintEngine);
|
---|
951 |
|
---|
952 | bool has_brush = d->has_brush;
|
---|
953 |
|
---|
954 | if (mode == PolylineMode)
|
---|
955 | d->has_brush = false; // No brush for polylines
|
---|
956 | else
|
---|
957 | path.closeSubpath(); // polygons are should always be closed.
|
---|
958 |
|
---|
959 | drawPath(path);
|
---|
960 | d->has_brush = has_brush;
|
---|
961 | }
|
---|
962 |
|
---|
963 | void QWin32PrintEnginePrivate::queryDefault()
|
---|
964 | {
|
---|
965 | /* Read the default printer name, driver and port with the intuitive function
|
---|
966 | * Strings "windows" and "device" are specified in the MSDN under EnumPrinters()
|
---|
967 | */
|
---|
968 | QString noPrinters(QLatin1String("qt_no_printers"));
|
---|
969 | QString output;
|
---|
970 | QT_WA({
|
---|
971 | ushort buffer[256];
|
---|
972 | GetProfileStringW(L"windows", L"device",
|
---|
973 | reinterpret_cast<const wchar_t *>(noPrinters.utf16()),
|
---|
974 | reinterpret_cast<wchar_t *>(buffer), 256);
|
---|
975 | output = QString::fromUtf16(buffer);
|
---|
976 | if (output.isEmpty() || output == noPrinters) // no printers
|
---|
977 | return;
|
---|
978 | }, {
|
---|
979 | char buffer[256];
|
---|
980 | GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256);
|
---|
981 | output = QString::fromLocal8Bit(buffer);
|
---|
982 | if (output.isEmpty() || output == noPrinters) // no printers
|
---|
983 | return;
|
---|
984 | });
|
---|
985 | QStringList info = output.split(QLatin1Char(','));
|
---|
986 | if (info.size() > 0) {
|
---|
987 | if (name.isEmpty())
|
---|
988 | name = info.at(0);
|
---|
989 | if (program.isEmpty())
|
---|
990 | program = info.at(1);
|
---|
991 | if (port.isEmpty())
|
---|
992 | port = info.at(2);
|
---|
993 | }
|
---|
994 | }
|
---|
995 |
|
---|
996 | QWin32PrintEnginePrivate::~QWin32PrintEnginePrivate()
|
---|
997 | {
|
---|
998 | if (hdc)
|
---|
999 | release();
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 | void QWin32PrintEnginePrivate::initialize()
|
---|
1003 | {
|
---|
1004 | if (hdc)
|
---|
1005 | release();
|
---|
1006 | Q_ASSERT(!hPrinter);
|
---|
1007 | Q_ASSERT(!hdc);
|
---|
1008 | Q_ASSERT(!devMode);
|
---|
1009 | Q_ASSERT(!pInfo);
|
---|
1010 |
|
---|
1011 | if (name.isEmpty())
|
---|
1012 | return;
|
---|
1013 |
|
---|
1014 | txop = QTransform::TxNone;
|
---|
1015 |
|
---|
1016 | bool ok;
|
---|
1017 | QT_WA( {
|
---|
1018 | ok = OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0);
|
---|
1019 | }, {
|
---|
1020 | ok = OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0);
|
---|
1021 | } );
|
---|
1022 |
|
---|
1023 | if (!ok) {
|
---|
1024 | qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed");
|
---|
1025 | return;
|
---|
1026 | }
|
---|
1027 |
|
---|
1028 | // Fetch the PRINTER_INFO_2 with DEVMODE data containing the
|
---|
1029 | // printer settings.
|
---|
1030 | DWORD infoSize, numBytes;
|
---|
1031 | ok = true;
|
---|
1032 | QT_WA( {
|
---|
1033 | GetPrinterW(hPrinter, 2, NULL, 0, &infoSize);
|
---|
1034 | hMem = GlobalAlloc(GHND, infoSize);
|
---|
1035 | pInfo = GlobalLock(hMem);
|
---|
1036 | if (!GetPrinterW(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) {
|
---|
1037 | ok = false;
|
---|
1038 | }
|
---|
1039 | }, {
|
---|
1040 | GetPrinterA(hPrinter, 2, NULL, 0, &infoSize);
|
---|
1041 | hMem = GlobalAlloc(GHND, infoSize);
|
---|
1042 | pInfo = GlobalLock(hMem);
|
---|
1043 | if (!GetPrinterA(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) {
|
---|
1044 | ok = false;
|
---|
1045 | }
|
---|
1046 | });
|
---|
1047 |
|
---|
1048 | if (!ok) {
|
---|
1049 | qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed");
|
---|
1050 | GlobalUnlock(pInfo);
|
---|
1051 | GlobalFree(hMem);
|
---|
1052 | ClosePrinter(hPrinter);
|
---|
1053 | pInfo = 0;
|
---|
1054 | hMem = 0;
|
---|
1055 | hPrinter = 0;
|
---|
1056 | return;
|
---|
1057 | }
|
---|
1058 |
|
---|
1059 | QT_WA( {
|
---|
1060 | devMode = pInfoW()->pDevMode;
|
---|
1061 | }, {
|
---|
1062 | devMode = pInfoA()->pDevMode;
|
---|
1063 | } );
|
---|
1064 |
|
---|
1065 | QT_WA( {
|
---|
1066 | hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
|
---|
1067 | reinterpret_cast<const wchar_t *>(name.utf16()), 0, devModeW());
|
---|
1068 | }, {
|
---|
1069 | hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, devModeA());
|
---|
1070 | } );
|
---|
1071 |
|
---|
1072 | Q_ASSERT(hPrinter);
|
---|
1073 | Q_ASSERT(pInfo);
|
---|
1074 |
|
---|
1075 | if (devMode) {
|
---|
1076 | QT_WA( {
|
---|
1077 | num_copies = devModeW()->dmCopies;
|
---|
1078 | }, {
|
---|
1079 | num_copies = devModeA()->dmCopies;
|
---|
1080 | } );
|
---|
1081 | }
|
---|
1082 |
|
---|
1083 | initHDC();
|
---|
1084 |
|
---|
1085 | #ifdef QT_DEBUG_DRAW
|
---|
1086 | qDebug() << "QWin32PrintEngine::initialize()" << endl
|
---|
1087 | << " - paperRect" << devPaperRect << endl
|
---|
1088 | << " - pageRect" << devPageRect << endl
|
---|
1089 | << " - stretch_x" << stretch_x << endl
|
---|
1090 | << " - stretch_y" << stretch_y << endl
|
---|
1091 | << " - origin_x" << origin_x << endl
|
---|
1092 | << " - origin_y" << origin_y << endl;
|
---|
1093 | #endif
|
---|
1094 | }
|
---|
1095 |
|
---|
1096 | void QWin32PrintEnginePrivate::initHDC()
|
---|
1097 | {
|
---|
1098 | Q_ASSERT(hdc);
|
---|
1099 |
|
---|
1100 | HDC display_dc = GetDC(0);
|
---|
1101 | dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
|
---|
1102 | dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
|
---|
1103 | dpi_display = GetDeviceCaps(display_dc, LOGPIXELSY);
|
---|
1104 | ReleaseDC(0, display_dc);
|
---|
1105 | if (dpi_display == 0) {
|
---|
1106 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
1107 | "might be a driver problem");
|
---|
1108 | dpi_display = 96; // Reasonable default
|
---|
1109 | }
|
---|
1110 |
|
---|
1111 | switch(mode) {
|
---|
1112 | case QPrinter::ScreenResolution:
|
---|
1113 | resolution = dpi_display;
|
---|
1114 | stretch_x = dpi_x / double(dpi_display);
|
---|
1115 | stretch_y = dpi_y / double(dpi_display);
|
---|
1116 | break;
|
---|
1117 | case QPrinter::PrinterResolution:
|
---|
1118 | case QPrinter::HighResolution:
|
---|
1119 | resolution = dpi_y;
|
---|
1120 | stretch_x = 1;
|
---|
1121 | stretch_y = 1;
|
---|
1122 | break;
|
---|
1123 | default:
|
---|
1124 | break;
|
---|
1125 | }
|
---|
1126 |
|
---|
1127 | initDevRects();
|
---|
1128 | }
|
---|
1129 |
|
---|
1130 | void QWin32PrintEnginePrivate::initDevRects()
|
---|
1131 | {
|
---|
1132 | devPaperRect = QRect(0, 0,
|
---|
1133 | GetDeviceCaps(hdc, PHYSICALWIDTH),
|
---|
1134 | GetDeviceCaps(hdc, PHYSICALHEIGHT));
|
---|
1135 | devPhysicalPageRect = QRect(GetDeviceCaps(hdc, PHYSICALOFFSETX),
|
---|
1136 | GetDeviceCaps(hdc, PHYSICALOFFSETY),
|
---|
1137 | GetDeviceCaps(hdc, HORZRES),
|
---|
1138 | GetDeviceCaps(hdc, VERTRES));
|
---|
1139 | if (!pageMarginsSet)
|
---|
1140 | devPageRect = devPhysicalPageRect;
|
---|
1141 | else
|
---|
1142 | devPageRect = devPaperRect.adjusted(qRound(mmToInches(previousDialogMargins.left() / 100.0) * dpi_x),
|
---|
1143 | qRound(mmToInches(previousDialogMargins.top() / 100.0) * dpi_y),
|
---|
1144 | -qRound(mmToInches(previousDialogMargins.width() / 100.0) * dpi_x),
|
---|
1145 | -qRound(mmToInches(previousDialogMargins.height() / 100.0) * dpi_y));
|
---|
1146 | updateOrigin();
|
---|
1147 | }
|
---|
1148 |
|
---|
1149 | void QWin32PrintEnginePrivate::setPageMargins(int marginLeft, int marginTop, int marginRight, int marginBottom)
|
---|
1150 | {
|
---|
1151 | pageMarginsSet = true;
|
---|
1152 | previousDialogMargins = QRect(marginLeft, marginTop, marginRight, marginBottom);
|
---|
1153 |
|
---|
1154 | devPageRect = devPaperRect.adjusted(qRound(mmToInches(marginLeft / 100.0) * dpi_x),
|
---|
1155 | qRound(mmToInches(marginTop / 100.0) * dpi_y),
|
---|
1156 | - qRound(mmToInches(marginRight / 100.0) * dpi_x),
|
---|
1157 | - qRound(mmToInches(marginBottom / 100.0) * dpi_y));
|
---|
1158 | updateOrigin();
|
---|
1159 | }
|
---|
1160 |
|
---|
1161 | QRect QWin32PrintEnginePrivate::getPageMargins() const
|
---|
1162 | {
|
---|
1163 | if (pageMarginsSet)
|
---|
1164 | return previousDialogMargins;
|
---|
1165 | else
|
---|
1166 | return QRect(qRound(inchesToMM(devPhysicalPageRect.left()) * 100.0 / dpi_x),
|
---|
1167 | qRound(inchesToMM(devPhysicalPageRect.top()) * 100.0 / dpi_y),
|
---|
1168 | qRound(inchesToMM(devPaperRect.right() - devPhysicalPageRect.right()) * 100.0 / dpi_x),
|
---|
1169 | qRound(inchesToMM(devPaperRect.bottom() - devPhysicalPageRect.bottom()) * 100.0 / dpi_y));
|
---|
1170 | }
|
---|
1171 |
|
---|
1172 | void QWin32PrintEnginePrivate::release()
|
---|
1173 | {
|
---|
1174 | if (hdc == 0)
|
---|
1175 | return;
|
---|
1176 |
|
---|
1177 | if (globalDevMode) { // Devmode comes from print dialog
|
---|
1178 | GlobalUnlock(globalDevMode);
|
---|
1179 | } else { // Devmode comes from initialize...
|
---|
1180 | // devMode is a part of the same memory block as pInfo so one free is enough...
|
---|
1181 | GlobalUnlock(hMem);
|
---|
1182 | GlobalFree(hMem);
|
---|
1183 | }
|
---|
1184 | if (hPrinter)
|
---|
1185 | ClosePrinter(hPrinter);
|
---|
1186 | DeleteDC(hdc);
|
---|
1187 |
|
---|
1188 | hdc = 0;
|
---|
1189 | hPrinter = 0;
|
---|
1190 | pInfo = 0;
|
---|
1191 | hMem = 0;
|
---|
1192 | devMode = 0;
|
---|
1193 | }
|
---|
1194 |
|
---|
1195 | QList<QVariant> QWin32PrintEnginePrivate::queryResolutions() const
|
---|
1196 | {
|
---|
1197 | // Read the supported resolutions of the printer.
|
---|
1198 | DWORD numRes;
|
---|
1199 | LONG *enumRes;
|
---|
1200 | DWORD errRes;
|
---|
1201 | QList<QVariant> list;
|
---|
1202 |
|
---|
1203 | QT_WA({
|
---|
1204 | numRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
|
---|
1205 | reinterpret_cast<const wchar_t *>(port.utf16()),
|
---|
1206 | DC_ENUMRESOLUTIONS, 0, 0);
|
---|
1207 | if (numRes == (DWORD)-1)
|
---|
1208 | return list;
|
---|
1209 | enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG));
|
---|
1210 | errRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
|
---|
1211 | reinterpret_cast<const wchar_t *>(port.utf16()),
|
---|
1212 | DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0);
|
---|
1213 | }, {
|
---|
1214 | numRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, 0, 0);
|
---|
1215 | if (numRes == (DWORD)-1)
|
---|
1216 | return list;
|
---|
1217 | enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG));
|
---|
1218 | errRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, (LPSTR)enumRes, 0);
|
---|
1219 | });
|
---|
1220 |
|
---|
1221 | if (errRes == (DWORD)-1) {
|
---|
1222 | qErrnoWarning("QWin32PrintEngine::queryResolutions: DeviceCapabilities failed");
|
---|
1223 | return list;
|
---|
1224 | }
|
---|
1225 |
|
---|
1226 | for (uint i=0; i<numRes; ++i)
|
---|
1227 | list.append(int(enumRes[i*2]));
|
---|
1228 | return list;
|
---|
1229 | }
|
---|
1230 |
|
---|
1231 | void QWin32PrintEnginePrivate::doReinit()
|
---|
1232 | {
|
---|
1233 | if (state == QPrinter::Active) {
|
---|
1234 | reinit = true;
|
---|
1235 | } else {
|
---|
1236 | resetDC();
|
---|
1237 | initDevRects();
|
---|
1238 | reinit = false;
|
---|
1239 | }
|
---|
1240 | }
|
---|
1241 |
|
---|
1242 | void QWin32PrintEnginePrivate::updateOrigin()
|
---|
1243 | {
|
---|
1244 | if (fullPage) {
|
---|
1245 | // subtract physical margins to make (0,0) absolute top corner of paper
|
---|
1246 | // then add user defined margins
|
---|
1247 | origin_x = -devPhysicalPageRect.x();
|
---|
1248 | origin_y = -devPhysicalPageRect.y();
|
---|
1249 | if (pageMarginsSet) {
|
---|
1250 | origin_x += devPageRect.left();
|
---|
1251 | origin_y += devPageRect.top();
|
---|
1252 | }
|
---|
1253 | } else {
|
---|
1254 | origin_x = 0;
|
---|
1255 | origin_y = 0;
|
---|
1256 | if (pageMarginsSet) {
|
---|
1257 | origin_x = devPageRect.left() - devPhysicalPageRect.x();
|
---|
1258 | origin_y = devPageRect.top() - devPhysicalPageRect.y();
|
---|
1259 | }
|
---|
1260 | }
|
---|
1261 | }
|
---|
1262 |
|
---|
1263 | void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
|
---|
1264 | {
|
---|
1265 | Q_D(QWin32PrintEngine);
|
---|
1266 | switch (key) {
|
---|
1267 | case PPK_CollateCopies:
|
---|
1268 | {
|
---|
1269 | if (!d->devMode)
|
---|
1270 | break;
|
---|
1271 | short collate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
|
---|
1272 | QT_WA( { d->devModeW()->dmCollate = collate; },
|
---|
1273 | { d->devModeA()->dmCollate = collate; } );
|
---|
1274 | d->doReinit();
|
---|
1275 | }
|
---|
1276 | break;
|
---|
1277 |
|
---|
1278 | case PPK_ColorMode:
|
---|
1279 | {
|
---|
1280 | if (!d->devMode)
|
---|
1281 | break;
|
---|
1282 | int cm = value.toInt() == QPrinter::Color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
|
---|
1283 | QT_WA( { d->devModeW()->dmColor = cm; }, { d->devModeA()->dmColor = cm; } );
|
---|
1284 | d->doReinit();
|
---|
1285 | }
|
---|
1286 | break;
|
---|
1287 |
|
---|
1288 | case PPK_Creator:
|
---|
1289 |
|
---|
1290 | break;
|
---|
1291 |
|
---|
1292 | case PPK_DocumentName:
|
---|
1293 | if (isActive()) {
|
---|
1294 | qWarning("QWin32PrintEngine: Cannot change document name while printing is active");
|
---|
1295 | return;
|
---|
1296 | }
|
---|
1297 | d->docName = value.toString();
|
---|
1298 | break;
|
---|
1299 |
|
---|
1300 | case PPK_FullPage:
|
---|
1301 | d->fullPage = value.toBool();
|
---|
1302 | d->updateOrigin();
|
---|
1303 | break;
|
---|
1304 |
|
---|
1305 | case PPK_NumberOfCopies:
|
---|
1306 | if (!d->devMode)
|
---|
1307 | break;
|
---|
1308 | d->num_copies = value.toInt();
|
---|
1309 | QT_WA( { d->devModeW()->dmCopies = d->num_copies; },
|
---|
1310 | { d->devModeA()->dmCopies = d->num_copies; });
|
---|
1311 | d->doReinit();
|
---|
1312 | break;
|
---|
1313 |
|
---|
1314 | case PPK_Orientation:
|
---|
1315 | {
|
---|
1316 | if (!d->devMode)
|
---|
1317 | break;
|
---|
1318 | int orientation = value.toInt() == QPrinter::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
|
---|
1319 | int old_orientation;
|
---|
1320 | QT_WA( {
|
---|
1321 | old_orientation = d->devModeW()->dmOrientation;
|
---|
1322 | d->devModeW()->dmOrientation = orientation;
|
---|
1323 | }, {
|
---|
1324 | old_orientation = d->devModeA()->dmOrientation;
|
---|
1325 | d->devModeA()->dmOrientation = orientation;
|
---|
1326 | } );
|
---|
1327 | if (d->has_custom_paper_size && old_orientation != orientation)
|
---|
1328 | d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
|
---|
1329 | d->doReinit();
|
---|
1330 | }
|
---|
1331 | break;
|
---|
1332 |
|
---|
1333 | case PPK_OutputFileName:
|
---|
1334 | if (isActive()) {
|
---|
1335 | qWarning("QWin32PrintEngine: Cannot change filename while printing");
|
---|
1336 | } else {
|
---|
1337 | d->fileName = value.toString();
|
---|
1338 | d->printToFile = !value.toString().isEmpty();
|
---|
1339 | }
|
---|
1340 | break;
|
---|
1341 |
|
---|
1342 | case PPK_PaperSize:
|
---|
1343 | if (!d->devMode)
|
---|
1344 | break;
|
---|
1345 | QT_WA( {
|
---|
1346 | d->devModeW()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
|
---|
1347 | }, {
|
---|
1348 | d->devModeA()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
|
---|
1349 | } );
|
---|
1350 | d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom);
|
---|
1351 | d->doReinit();
|
---|
1352 | break;
|
---|
1353 |
|
---|
1354 | case PPK_PaperSource:
|
---|
1355 | {
|
---|
1356 | if (!d->devMode)
|
---|
1357 | break;
|
---|
1358 | int dmMapped = DMBIN_AUTO;
|
---|
1359 |
|
---|
1360 | QList<QVariant> v = property(PPK_PaperSources).toList();
|
---|
1361 | if (v.contains(value))
|
---|
1362 | dmMapped = mapPaperSourceDevmode(QPrinter::PaperSource(value.toInt()));
|
---|
1363 |
|
---|
1364 | QT_WA( {
|
---|
1365 | d->devModeW()->dmDefaultSource = dmMapped;
|
---|
1366 | }, {
|
---|
1367 | d->devModeA()->dmDefaultSource = dmMapped;
|
---|
1368 | } );
|
---|
1369 | d->doReinit();
|
---|
1370 | }
|
---|
1371 | break;
|
---|
1372 |
|
---|
1373 | case PPK_PrinterName:
|
---|
1374 | d->name = value.toString();
|
---|
1375 | if(d->name.isEmpty())
|
---|
1376 | d->queryDefault();
|
---|
1377 | d->initialize();
|
---|
1378 | break;
|
---|
1379 |
|
---|
1380 | case PPK_Resolution:
|
---|
1381 | {
|
---|
1382 | d->resolution = value.toInt();
|
---|
1383 |
|
---|
1384 | d->stretch_x = d->dpi_x / double(d->resolution);
|
---|
1385 | d->stretch_y = d->dpi_y / double(d->resolution);
|
---|
1386 | }
|
---|
1387 | break;
|
---|
1388 |
|
---|
1389 | case PPK_SelectionOption:
|
---|
1390 |
|
---|
1391 | break;
|
---|
1392 |
|
---|
1393 | case PPK_SupportedResolutions:
|
---|
1394 |
|
---|
1395 | break;
|
---|
1396 |
|
---|
1397 |
|
---|
1398 | case PPK_WindowsPageSize:
|
---|
1399 | if (!d->devMode)
|
---|
1400 | break;
|
---|
1401 | d->has_custom_paper_size = false;
|
---|
1402 | QT_WA( {
|
---|
1403 | d->devModeW()->dmPaperSize = value.toInt();
|
---|
1404 | }, {
|
---|
1405 | d->devModeA()->dmPaperSize = value.toInt();
|
---|
1406 | } );
|
---|
1407 | d->doReinit();
|
---|
1408 | break;
|
---|
1409 |
|
---|
1410 | case PPK_CustomPaperSize:
|
---|
1411 | {
|
---|
1412 | d->has_custom_paper_size = true;
|
---|
1413 | d->paper_size = value.toSizeF();
|
---|
1414 | if (!d->devMode)
|
---|
1415 | break;
|
---|
1416 | int orientation;
|
---|
1417 | QT_WA( {
|
---|
1418 | orientation = d->devModeW()->dmOrientation;
|
---|
1419 | DWORD needed = 0;
|
---|
1420 | DWORD returned = 0;
|
---|
1421 | if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) {
|
---|
1422 | BYTE *forms = (BYTE *) malloc(needed);
|
---|
1423 | if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) {
|
---|
1424 | for (DWORD i=0; i< returned; ++i) {
|
---|
1425 | FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms);
|
---|
1426 | // the form sizes are specified in 1000th of a mm,
|
---|
1427 | // convert the size to Points
|
---|
1428 | QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0,
|
---|
1429 | (formArray[i].Size.cy * 72/25.4)/1000.0);
|
---|
1430 | if (qAbs(d->paper_size.width() - size.width()) <= 2
|
---|
1431 | && qAbs(d->paper_size.height() - size.height()) <= 2)
|
---|
1432 | {
|
---|
1433 | d->devModeW()->dmPaperSize = i+1;
|
---|
1434 | break;
|
---|
1435 | }
|
---|
1436 | }
|
---|
1437 | }
|
---|
1438 | free(forms);
|
---|
1439 | }
|
---|
1440 | }, {
|
---|
1441 | orientation = d->devModeA()->dmOrientation;
|
---|
1442 | } );
|
---|
1443 | if (orientation != DMORIENT_PORTRAIT)
|
---|
1444 | d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
|
---|
1445 | break;
|
---|
1446 | }
|
---|
1447 |
|
---|
1448 | case PPK_PageMargins:
|
---|
1449 | {
|
---|
1450 | QList<QVariant> margins(value.toList());
|
---|
1451 | Q_ASSERT(margins.size() == 4);
|
---|
1452 | int left, top, right, bottom;
|
---|
1453 | // specified in 1/100 mm
|
---|
1454 | left = (margins.at(0).toDouble()*25.4/72.0) * 100;
|
---|
1455 | top = (margins.at(1).toDouble()*25.4/72.0) * 100;
|
---|
1456 | right = (margins.at(2).toDouble()*25.4/72.0) * 100;
|
---|
1457 | bottom = (margins.at(3).toDouble()*25.4/72.0) * 100;
|
---|
1458 | d->setPageMargins(left, top, right, bottom);
|
---|
1459 | break;
|
---|
1460 | }
|
---|
1461 | default:
|
---|
1462 | // Do nothing
|
---|
1463 | break;
|
---|
1464 | }
|
---|
1465 | }
|
---|
1466 |
|
---|
1467 | QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
|
---|
1468 | {
|
---|
1469 | Q_D(const QWin32PrintEngine);
|
---|
1470 | QVariant value;
|
---|
1471 | switch (key) {
|
---|
1472 |
|
---|
1473 | case PPK_CollateCopies:
|
---|
1474 | value = false;
|
---|
1475 | break;
|
---|
1476 |
|
---|
1477 | case PPK_ColorMode:
|
---|
1478 | {
|
---|
1479 | if (!d->devMode) {
|
---|
1480 | value = QPrinter::Color;
|
---|
1481 | } else {
|
---|
1482 | int mode;
|
---|
1483 | QT_WA( {
|
---|
1484 | mode = d->devModeW()->dmColor;
|
---|
1485 | }, {
|
---|
1486 | mode = d->devModeA()->dmColor;
|
---|
1487 | } );
|
---|
1488 | value = mode == DMCOLOR_COLOR ? QPrinter::Color : QPrinter::GrayScale;
|
---|
1489 | }
|
---|
1490 | }
|
---|
1491 | break;
|
---|
1492 |
|
---|
1493 | case PPK_DocumentName:
|
---|
1494 | value = d->docName;
|
---|
1495 | break;
|
---|
1496 |
|
---|
1497 | case PPK_FullPage:
|
---|
1498 | value = d->fullPage;
|
---|
1499 | break;
|
---|
1500 |
|
---|
1501 | case PPK_NumberOfCopies:
|
---|
1502 | value = 1;
|
---|
1503 | break;
|
---|
1504 |
|
---|
1505 | case PPK_Orientation:
|
---|
1506 | {
|
---|
1507 | if (!d->devMode) {
|
---|
1508 | value = QPrinter::Portrait;
|
---|
1509 | } else {
|
---|
1510 | int o;
|
---|
1511 | QT_WA( { o = d->devModeW()->dmOrientation; }, { o = d->devModeA()->dmOrientation; } );
|
---|
1512 | value = o == DMORIENT_LANDSCAPE ? QPrinter::Landscape : QPrinter::Portrait;
|
---|
1513 | }
|
---|
1514 | }
|
---|
1515 | break;
|
---|
1516 |
|
---|
1517 | case PPK_OutputFileName:
|
---|
1518 | value = d->fileName;
|
---|
1519 | break;
|
---|
1520 |
|
---|
1521 | case PPK_PageRect:
|
---|
1522 | if (d->has_custom_paper_size) {
|
---|
1523 | QRect rect(0, 0,
|
---|
1524 | qRound(d->paper_size.width() * d->resolution / 72.0),
|
---|
1525 | qRound(d->paper_size.height() * d->resolution / 72.0));
|
---|
1526 | if (d->pageMarginsSet) {
|
---|
1527 | rect = rect.adjusted(qRound(mmToInches(d->previousDialogMargins.left()/100.0) * d->resolution),
|
---|
1528 | qRound(mmToInches(d->previousDialogMargins.top()/100.0) * d->resolution),
|
---|
1529 | -qRound(mmToInches(d->previousDialogMargins.width()/100.0) * d->resolution),
|
---|
1530 | -qRound(mmToInches(d->previousDialogMargins.height()/100.0) * d->resolution));
|
---|
1531 | }
|
---|
1532 | value = rect;
|
---|
1533 | } else {
|
---|
1534 | value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0)
|
---|
1535 | .mapRect(d->fullPage ? d->devPaperRect : d->devPageRect);
|
---|
1536 | }
|
---|
1537 | break;
|
---|
1538 |
|
---|
1539 | case PPK_PaperSize:
|
---|
1540 | if (d->has_custom_paper_size) {
|
---|
1541 | value = QPrinter::Custom;
|
---|
1542 | } else {
|
---|
1543 | if (!d->devMode) {
|
---|
1544 | value = QPrinter::A4;
|
---|
1545 | } else {
|
---|
1546 | QT_WA( {
|
---|
1547 | value = mapDevmodePaperSize(d->devModeW()->dmPaperSize);
|
---|
1548 | }, {
|
---|
1549 | value = mapDevmodePaperSize(d->devModeA()->dmPaperSize);
|
---|
1550 | } );
|
---|
1551 | }
|
---|
1552 | }
|
---|
1553 | break;
|
---|
1554 |
|
---|
1555 | case PPK_PaperRect:
|
---|
1556 | if (d->has_custom_paper_size) {
|
---|
1557 | value = QRect(0, 0,
|
---|
1558 | qRound(d->paper_size.width() * d->resolution / 72.0),
|
---|
1559 | qRound(d->paper_size.height() * d->resolution / 72.0));
|
---|
1560 | } else {
|
---|
1561 | value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0).mapRect(d->devPaperRect);
|
---|
1562 | }
|
---|
1563 | break;
|
---|
1564 |
|
---|
1565 | case PPK_PaperSource:
|
---|
1566 | if (!d->devMode) {
|
---|
1567 | value = QPrinter::Auto;
|
---|
1568 | } else {
|
---|
1569 | QT_WA( {
|
---|
1570 | value = mapDevmodePaperSource(d->devModeW()->dmDefaultSource);
|
---|
1571 | }, {
|
---|
1572 | value = mapDevmodePaperSource(d->devModeA()->dmDefaultSource);
|
---|
1573 | } );
|
---|
1574 | }
|
---|
1575 | break;
|
---|
1576 |
|
---|
1577 | case PPK_PrinterName:
|
---|
1578 | value = d->name;
|
---|
1579 | break;
|
---|
1580 |
|
---|
1581 | case PPK_Resolution:
|
---|
1582 | if (d->resolution || !d->name.isEmpty())
|
---|
1583 | value = d->resolution;
|
---|
1584 | break;
|
---|
1585 |
|
---|
1586 | case PPK_SupportedResolutions:
|
---|
1587 | value = d->queryResolutions();
|
---|
1588 | break;
|
---|
1589 |
|
---|
1590 | case PPK_WindowsPageSize:
|
---|
1591 | if (!d->devMode) {
|
---|
1592 | value = -1;
|
---|
1593 | } else {
|
---|
1594 | QT_WA( {
|
---|
1595 | value = d->devModeW()->dmPaperSize;
|
---|
1596 | }, {
|
---|
1597 | value = d->devModeA()->dmPaperSize;
|
---|
1598 | } );
|
---|
1599 | }
|
---|
1600 | break;
|
---|
1601 |
|
---|
1602 | case PPK_PaperSources:
|
---|
1603 | {
|
---|
1604 | int available, count;
|
---|
1605 | WORD *data;
|
---|
1606 |
|
---|
1607 | QT_WA({
|
---|
1608 | available = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, 0,
|
---|
1609 | d->devModeW());
|
---|
1610 | }, {
|
---|
1611 | available = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS, 0,
|
---|
1612 | d->devModeA());
|
---|
1613 | });
|
---|
1614 |
|
---|
1615 | if (available <= 0)
|
---|
1616 | break;
|
---|
1617 | data = (WORD *) malloc(available * sizeof(WORD));
|
---|
1618 |
|
---|
1619 | QT_WA({
|
---|
1620 | count = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, (WCHAR *)data,
|
---|
1621 | d->devModeW());
|
---|
1622 | }, {
|
---|
1623 | count = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS,
|
---|
1624 | (char *) data, d->devModeA());
|
---|
1625 | });
|
---|
1626 |
|
---|
1627 | QList<QVariant> out;
|
---|
1628 | for (int i=0; i<count; ++i) {
|
---|
1629 | QPrinter::PaperSource src = mapDevmodePaperSource(data[i]);
|
---|
1630 | if (src != -1)
|
---|
1631 | out << (int) src;
|
---|
1632 | }
|
---|
1633 | value = out;
|
---|
1634 | free(data);
|
---|
1635 | }
|
---|
1636 | break;
|
---|
1637 |
|
---|
1638 | case PPK_CustomPaperSize:
|
---|
1639 | value = d->paper_size;
|
---|
1640 | break;
|
---|
1641 |
|
---|
1642 | case PPK_PageMargins:
|
---|
1643 | {
|
---|
1644 | QList<QVariant> margins;
|
---|
1645 | QRect pageMargins(d->getPageMargins());
|
---|
1646 |
|
---|
1647 | // specified in 1/100 mm
|
---|
1648 | margins << (mmToInches(pageMargins.left()/100.0) * 72)
|
---|
1649 | << (mmToInches(pageMargins.top()/100.0) * 72)
|
---|
1650 | << (mmToInches(pageMargins.width()/100.0) * 72)
|
---|
1651 | << (mmToInches(pageMargins.height()/100.0) * 72);
|
---|
1652 | value = margins;
|
---|
1653 | break;
|
---|
1654 | }
|
---|
1655 | default:
|
---|
1656 | // Do nothing
|
---|
1657 | break;
|
---|
1658 | }
|
---|
1659 | return value;
|
---|
1660 | }
|
---|
1661 |
|
---|
1662 | QPrinter::PrinterState QWin32PrintEngine::printerState() const
|
---|
1663 | {
|
---|
1664 | return d_func()->state;
|
---|
1665 | }
|
---|
1666 |
|
---|
1667 | HDC QWin32PrintEngine::getDC() const
|
---|
1668 | {
|
---|
1669 | return d_func()->hdc;
|
---|
1670 | }
|
---|
1671 |
|
---|
1672 | void QWin32PrintEngine::releaseDC(HDC) const
|
---|
1673 | {
|
---|
1674 |
|
---|
1675 | }
|
---|
1676 |
|
---|
1677 | HGLOBAL *QWin32PrintEnginePrivate::createDevNames()
|
---|
1678 | {
|
---|
1679 | QT_WA( {
|
---|
1680 | int size = sizeof(DEVNAMES)
|
---|
1681 | + program.length() * 2 + 2
|
---|
1682 | + name.length() * 2 + 2
|
---|
1683 | + port.length() * 2 + 2;
|
---|
1684 | HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
|
---|
1685 | DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
|
---|
1686 |
|
---|
1687 | dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR);
|
---|
1688 | dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1;
|
---|
1689 | dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1;
|
---|
1690 |
|
---|
1691 | memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2);
|
---|
1692 | memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2);
|
---|
1693 | memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2);
|
---|
1694 | dn->wDefault = 0;
|
---|
1695 |
|
---|
1696 | GlobalUnlock(hGlobal);
|
---|
1697 |
|
---|
1698 | // printf("QPrintDialogWinPrivate::createDevNames()\n"
|
---|
1699 | // " -> wDriverOffset: %d\n"
|
---|
1700 | // " -> wDeviceOffset: %d\n"
|
---|
1701 | // " -> wOutputOffset: %d\n",
|
---|
1702 | // dn->wDriverOffset,
|
---|
1703 | // dn->wDeviceOffset,
|
---|
1704 | // dn->wOutputOffset);
|
---|
1705 |
|
---|
1706 | // printf("QPrintDialogWinPrivate::createDevNames(): %s, %s, %s\n",
|
---|
1707 | // QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset).latin1(),
|
---|
1708 | // QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset).latin1(),
|
---|
1709 | // QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset).latin1());
|
---|
1710 |
|
---|
1711 | return hGlobal;
|
---|
1712 | }, {
|
---|
1713 | int size = sizeof(DEVNAMES)
|
---|
1714 | + program.length() + 2
|
---|
1715 | + name.length() + 2
|
---|
1716 | + port.length() + 2;
|
---|
1717 | HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
|
---|
1718 | DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
|
---|
1719 |
|
---|
1720 | dn->wDriverOffset = sizeof(DEVNAMES);
|
---|
1721 | dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1;
|
---|
1722 | dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1;
|
---|
1723 |
|
---|
1724 | memcpy((char*)dn + dn->wDriverOffset, program.toLatin1(), program.length() + 2);
|
---|
1725 | memcpy((char*)dn + dn->wDeviceOffset, name.toLatin1(), name.length() + 2);
|
---|
1726 | memcpy((char*)dn + dn->wOutputOffset, port.toLatin1(), port.length() + 2);
|
---|
1727 | dn->wDefault = 0;
|
---|
1728 |
|
---|
1729 | GlobalUnlock(hGlobal);
|
---|
1730 | return hGlobal;
|
---|
1731 | } );
|
---|
1732 | }
|
---|
1733 |
|
---|
1734 | void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames)
|
---|
1735 | {
|
---|
1736 | if (globalDevnames) {
|
---|
1737 | QT_WA( {
|
---|
1738 | DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames);
|
---|
1739 | name = QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset);
|
---|
1740 | port = QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset);
|
---|
1741 | program = QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset);
|
---|
1742 | GlobalUnlock(globalDevnames);
|
---|
1743 | }, {
|
---|
1744 | DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames);
|
---|
1745 | name = QString::fromLatin1((char*)(dn) + dn->wDeviceOffset);
|
---|
1746 | port = QString::fromLatin1((char*)(dn) + dn->wOutputOffset);
|
---|
1747 | program = QString::fromLatin1((char*)(dn) + dn->wDriverOffset);
|
---|
1748 | GlobalUnlock(globalDevnames);
|
---|
1749 | } );
|
---|
1750 | }
|
---|
1751 | }
|
---|
1752 |
|
---|
1753 | void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode)
|
---|
1754 | {
|
---|
1755 | if (globalDevmode) {
|
---|
1756 | QT_WA( {
|
---|
1757 | DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode);
|
---|
1758 | release();
|
---|
1759 | globalDevMode = globalDevmode;
|
---|
1760 | devMode = dm;
|
---|
1761 | hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
|
---|
1762 | reinterpret_cast<const wchar_t *>(name.utf16()), 0, dm);
|
---|
1763 |
|
---|
1764 | num_copies = devModeW()->dmCopies;
|
---|
1765 | if (!OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0))
|
---|
1766 | qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
|
---|
1767 | }, {
|
---|
1768 | DEVMODEA *dm = (DEVMODEA*) GlobalLock(globalDevmode);
|
---|
1769 | release();
|
---|
1770 | globalDevMode = globalDevmode;
|
---|
1771 | devMode = dm;
|
---|
1772 | hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, dm);
|
---|
1773 |
|
---|
1774 | num_copies = devModeA()->dmCopies;
|
---|
1775 | if (!OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0))
|
---|
1776 | qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
|
---|
1777 | } );
|
---|
1778 | }
|
---|
1779 |
|
---|
1780 | if (hdc)
|
---|
1781 | initHDC();
|
---|
1782 | }
|
---|
1783 |
|
---|
1784 | static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc,
|
---|
1785 | bool convertToText, const QTransform &xform, const QPointF &topLeft)
|
---|
1786 | {
|
---|
1787 |
|
---|
1788 | // Make sure we translate for systems that can't handle world transforms
|
---|
1789 | QPointF pos(QT_WA_INLINE(_pos, _pos + QPointF(xform.dx(), xform.dy())));
|
---|
1790 | QFontEngine *fe = ti.fontEngine;
|
---|
1791 | QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft);
|
---|
1792 |
|
---|
1793 | SetTextAlign(hdc, TA_BASELINE);
|
---|
1794 | SetBkMode(hdc, TRANSPARENT);
|
---|
1795 |
|
---|
1796 | bool has_kerning = ti.f && ti.f->kerning();
|
---|
1797 | QFontEngineWin *winfe = (fe->type() == QFontEngine::Win) ? static_cast<QFontEngineWin *>(fe) : 0;
|
---|
1798 |
|
---|
1799 | HFONT hfont;
|
---|
1800 | bool ttf = false;
|
---|
1801 | bool useTextOutA = false;
|
---|
1802 |
|
---|
1803 | if (winfe) {
|
---|
1804 | hfont = winfe->hfont;
|
---|
1805 | ttf = winfe->ttf;
|
---|
1806 | useTextOutA = winfe->useTextOutA;
|
---|
1807 | } else {
|
---|
1808 | hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
---|
1809 | }
|
---|
1810 |
|
---|
1811 | HGDIOBJ old_font = SelectObject(hdc, hfont);
|
---|
1812 | unsigned int options = (ttf && !convertToText) ? ETO_GLYPH_INDEX : 0;
|
---|
1813 | wchar_t *convertedGlyphs = (wchar_t *)ti.chars;
|
---|
1814 | QGlyphLayout glyphs = ti.glyphs;
|
---|
1815 |
|
---|
1816 | if (!(ti.flags & QTextItem::RightToLeft) && useTextOutA) {
|
---|
1817 | qreal x = pos.x();
|
---|
1818 | qreal y = pos.y();
|
---|
1819 |
|
---|
1820 | // hack to get symbol fonts working on Win95. See also QFontEngine constructor
|
---|
1821 | // can only happen if !ttf
|
---|
1822 | for(int i = 0; i < glyphs.numGlyphs; i++) {
|
---|
1823 | QString str(QChar(glyphs.glyphs[i]));
|
---|
1824 | QT_WA({
|
---|
1825 | TextOutW(hdc, qRound(x + glyphs.offsets[i].x.toReal()),
|
---|
1826 | qRound(y + glyphs.offsets[i].y.toReal()),
|
---|
1827 | (LPWSTR)str.utf16(), str.length());
|
---|
1828 | } , {
|
---|
1829 | QByteArray cstr = str.toLocal8Bit();
|
---|
1830 | TextOutA(hdc, qRound(x + glyphs.offsets[i].x.toReal()),
|
---|
1831 | qRound(y + glyphs.offsets[i].y.toReal()),
|
---|
1832 | cstr.data(), cstr.length());
|
---|
1833 | });
|
---|
1834 | x += glyphs.effectiveAdvance(i).toReal();
|
---|
1835 | }
|
---|
1836 | } else {
|
---|
1837 | bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
|
---|
1838 | for(int i = 0; fast && i < glyphs.numGlyphs; i++) {
|
---|
1839 | if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0
|
---|
1840 | || glyphs.attributes[i].dontPrint) {
|
---|
1841 | fast = false;
|
---|
1842 | break;
|
---|
1843 | }
|
---|
1844 | }
|
---|
1845 |
|
---|
1846 | #if !defined(Q_OS_WINCE)
|
---|
1847 | // Scale, rotate and translate here. This is only valid for systems > Windows Me.
|
---|
1848 | // We should never get here on Windows Me or lower if the transformation specifies
|
---|
1849 | // scaling or rotation.
|
---|
1850 | QT_WA({
|
---|
1851 | XFORM win_xform;
|
---|
1852 | win_xform.eM11 = xform.m11();
|
---|
1853 | win_xform.eM12 = xform.m12();
|
---|
1854 | win_xform.eM21 = xform.m21();
|
---|
1855 | win_xform.eM22 = xform.m22();
|
---|
1856 | win_xform.eDx = xform.dx();
|
---|
1857 | win_xform.eDy = xform.dy();
|
---|
1858 | SetGraphicsMode(hdc, GM_ADVANCED);
|
---|
1859 | SetWorldTransform(hdc, &win_xform);
|
---|
1860 | }, {
|
---|
1861 | // nothing
|
---|
1862 | });
|
---|
1863 | #endif
|
---|
1864 |
|
---|
1865 | if (fast) {
|
---|
1866 | // fast path
|
---|
1867 | QVarLengthArray<wchar_t> g(glyphs.numGlyphs);
|
---|
1868 | for (int i = 0; i < glyphs.numGlyphs; ++i)
|
---|
1869 | g[i] = glyphs.glyphs[i];
|
---|
1870 | ExtTextOutW(hdc,
|
---|
1871 | qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
|
---|
1872 | qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
|
---|
1873 | options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0);
|
---|
1874 | } else {
|
---|
1875 | QVarLengthArray<QFixedPoint> positions;
|
---|
1876 | QVarLengthArray<glyph_t> _glyphs;
|
---|
1877 |
|
---|
1878 | QTransform matrix;
|
---|
1879 | matrix.translate(baseline_pos.x(), baseline_pos.y());
|
---|
1880 | ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
|
---|
1881 | _glyphs, positions);
|
---|
1882 | if (_glyphs.size() == 0) {
|
---|
1883 | SelectObject(hdc, old_font);
|
---|
1884 | return;
|
---|
1885 | }
|
---|
1886 |
|
---|
1887 | convertToText = convertToText && glyphs.numGlyphs == _glyphs.size();
|
---|
1888 |
|
---|
1889 | bool outputEntireItem = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)
|
---|
1890 | && QSysInfo::WindowsVersion != QSysInfo::WV_NT
|
---|
1891 | && _glyphs.size() > 0;
|
---|
1892 |
|
---|
1893 | if (outputEntireItem) {
|
---|
1894 | options |= ETO_PDY;
|
---|
1895 | QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
|
---|
1896 | QVarLengthArray<wchar_t> g(_glyphs.size());
|
---|
1897 | for (int i=0; i<_glyphs.size() - 1; ++i) {
|
---|
1898 | glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
|
---|
1899 | glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
|
---|
1900 | g[i] = _glyphs[i];
|
---|
1901 | }
|
---|
1902 | glyphDistances[(_glyphs.size() - 1) * 2] = 0;
|
---|
1903 | glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
|
---|
1904 | g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
|
---|
1905 | ExtTextOutW(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
|
---|
1906 | convertToText ? convertedGlyphs : g.data(), _glyphs.size(),
|
---|
1907 | glyphDistances.data());
|
---|
1908 | } else {
|
---|
1909 | int i = 0;
|
---|
1910 | while(i < _glyphs.size()) {
|
---|
1911 | wchar_t g = _glyphs[i];
|
---|
1912 |
|
---|
1913 | ExtTextOutW(hdc, qRound(positions[i].x),
|
---|
1914 | qRound(positions[i].y), options, 0,
|
---|
1915 | convertToText ? convertedGlyphs + i : &g, 1, 0);
|
---|
1916 | ++i;
|
---|
1917 | }
|
---|
1918 | }
|
---|
1919 | }
|
---|
1920 |
|
---|
1921 | #if !defined(Q_OS_WINCE)
|
---|
1922 | QT_WA({
|
---|
1923 | XFORM win_xform;
|
---|
1924 | win_xform.eM11 = win_xform.eM22 = 1.0;
|
---|
1925 | win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0;
|
---|
1926 | SetWorldTransform(hdc, &win_xform);
|
---|
1927 | }, {
|
---|
1928 | // nothing
|
---|
1929 | });
|
---|
1930 | #endif
|
---|
1931 | }
|
---|
1932 | SelectObject(hdc, old_font);
|
---|
1933 | }
|
---|
1934 |
|
---|
1935 |
|
---|
1936 | void QWin32PrintEnginePrivate::updateCustomPaperSize()
|
---|
1937 | {
|
---|
1938 | QT_WA( {
|
---|
1939 | uint paperSize = devModeW()->dmPaperSize;
|
---|
1940 | if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) {
|
---|
1941 | has_custom_paper_size = true;
|
---|
1942 | DWORD needed = 0;
|
---|
1943 | DWORD returned = 0;
|
---|
1944 | if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) {
|
---|
1945 | BYTE *forms = (BYTE *) malloc(needed);
|
---|
1946 | if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) {
|
---|
1947 | if (paperSize <= returned) {
|
---|
1948 | FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms;
|
---|
1949 | int width = formArray[paperSize-1].Size.cx; // 1/1000 of a mm
|
---|
1950 | int height = formArray[paperSize-1].Size.cy; // 1/1000 of a mm
|
---|
1951 | paper_size = QSizeF((width*72/25.4)/1000.0, (height*72/25.4)/1000.0);
|
---|
1952 | } else {
|
---|
1953 | has_custom_paper_size = false;
|
---|
1954 | }
|
---|
1955 | }
|
---|
1956 | free(forms);
|
---|
1957 | }
|
---|
1958 | } else {
|
---|
1959 | has_custom_paper_size = false;
|
---|
1960 | }
|
---|
1961 | }, {
|
---|
1962 | // Not supported under Win98
|
---|
1963 | } );
|
---|
1964 | }
|
---|
1965 |
|
---|
1966 | QT_END_NAMESPACE
|
---|
1967 |
|
---|
1968 | #endif // QT_NO_PRINTER
|
---|