1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
---|
4 | ** All rights reserved.
|
---|
5 | ** Contact: Nokia Corporation ([email protected])
|
---|
6 | **
|
---|
7 | ** This file is part of the QtGui module of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
15 | **
|
---|
16 | ** GNU Lesser General Public License Usage
|
---|
17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
18 | ** General Public License version 2.1 as published by the Free Software
|
---|
19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
20 | ** packaging of this file. Please review the following information to
|
---|
21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
23 | **
|
---|
24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia 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 | d->devMode->dmCopies = d->num_copies;
|
---|
203 |
|
---|
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 | if (StartPage(d->hdc) <= 0) {
|
---|
216 | qErrnoWarning("QWin32PrintEngine::begin: StartPage failed");
|
---|
217 | ok = false;
|
---|
218 | }
|
---|
219 |
|
---|
220 | if (!ok) {
|
---|
221 | d->state = QPrinter::Idle;
|
---|
222 | } else {
|
---|
223 | d->state = QPrinter::Active;
|
---|
224 | }
|
---|
225 |
|
---|
226 | d->matrix = QTransform();
|
---|
227 | d->has_pen = true;
|
---|
228 | d->pen = QColor(Qt::black);
|
---|
229 | d->has_brush = false;
|
---|
230 |
|
---|
231 | d->complex_xform = false;
|
---|
232 |
|
---|
233 | updateMatrix(d->matrix);
|
---|
234 |
|
---|
235 | if (!ok)
|
---|
236 | cleanUp();
|
---|
237 |
|
---|
238 | return ok;
|
---|
239 | }
|
---|
240 |
|
---|
241 | bool QWin32PrintEngine::end()
|
---|
242 | {
|
---|
243 | Q_D(QWin32PrintEngine);
|
---|
244 |
|
---|
245 | if (d->hdc) {
|
---|
246 | if (d->state == QPrinter::Aborted) {
|
---|
247 | cleanUp();
|
---|
248 | AbortDoc(d->hdc);
|
---|
249 | return true;
|
---|
250 | }
|
---|
251 | }
|
---|
252 |
|
---|
253 | QAlphaPaintEngine::end();
|
---|
254 | if (!continueCall())
|
---|
255 | return true;
|
---|
256 |
|
---|
257 | if (d->hdc) {
|
---|
258 | EndPage(d->hdc); // end; printing done
|
---|
259 | EndDoc(d->hdc);
|
---|
260 | }
|
---|
261 |
|
---|
262 | d->state = QPrinter::Idle;
|
---|
263 | d->reinit = true;
|
---|
264 | return true;
|
---|
265 | }
|
---|
266 |
|
---|
267 | bool QWin32PrintEngine::newPage()
|
---|
268 | {
|
---|
269 | Q_D(QWin32PrintEngine);
|
---|
270 | Q_ASSERT(isActive());
|
---|
271 |
|
---|
272 | Q_ASSERT(d->hdc);
|
---|
273 |
|
---|
274 | flushAndInit();
|
---|
275 |
|
---|
276 | bool transparent = GetBkMode(d->hdc) == TRANSPARENT;
|
---|
277 |
|
---|
278 | if (!EndPage(d->hdc)) {
|
---|
279 | qErrnoWarning("QWin32PrintEngine::newPage: EndPage failed");
|
---|
280 | return false;
|
---|
281 | }
|
---|
282 |
|
---|
283 | if (d->reinit) {
|
---|
284 | if (!d->resetDC()) {
|
---|
285 | qErrnoWarning("QWin32PrintEngine::newPage: ResetDC failed");
|
---|
286 | return false;
|
---|
287 | }
|
---|
288 | d->reinit = false;
|
---|
289 | }
|
---|
290 |
|
---|
291 | if (!StartPage(d->hdc)) {
|
---|
292 | qErrnoWarning("Win32PrintEngine::newPage: StartPage failed");
|
---|
293 | return false;
|
---|
294 | }
|
---|
295 |
|
---|
296 | SetTextAlign(d->hdc, TA_BASELINE);
|
---|
297 | if (transparent)
|
---|
298 | SetBkMode(d->hdc, TRANSPARENT);
|
---|
299 |
|
---|
300 | // ###
|
---|
301 | return true;
|
---|
302 |
|
---|
303 | bool success = false;
|
---|
304 | if (d->hdc && d->state == QPrinter::Active) {
|
---|
305 | if (EndPage(d->hdc) != SP_ERROR) {
|
---|
306 | // reinitialize the DC before StartPage if needed,
|
---|
307 | // because resetdc is disabled between calls to the StartPage and EndPage functions
|
---|
308 | // (see StartPage documentation in the Platform SDK:Windows GDI)
|
---|
309 | // state = PST_ACTIVEDOC;
|
---|
310 | // reinit();
|
---|
311 | // state = PST_ACTIVE;
|
---|
312 | // start the new page now
|
---|
313 | if (d->reinit) {
|
---|
314 | if (!d->resetDC())
|
---|
315 | qErrnoWarning("QWin32PrintEngine::newPage(), ResetDC failed (2)");
|
---|
316 | d->reinit = false;
|
---|
317 | }
|
---|
318 | success = (StartPage(d->hdc) != SP_ERROR);
|
---|
319 | }
|
---|
320 | if (!success) {
|
---|
321 | d->state = QPrinter::Aborted;
|
---|
322 | return false;
|
---|
323 | }
|
---|
324 | }
|
---|
325 | return true;
|
---|
326 | }
|
---|
327 |
|
---|
328 | bool QWin32PrintEngine::abort()
|
---|
329 | {
|
---|
330 | // do nothing loop.
|
---|
331 | return false;
|
---|
332 | }
|
---|
333 |
|
---|
334 | void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
|
---|
335 | {
|
---|
336 | Q_D(const QWin32PrintEngine);
|
---|
337 |
|
---|
338 | QAlphaPaintEngine::drawTextItem(p, textItem);
|
---|
339 | if (!continueCall())
|
---|
340 | return;
|
---|
341 |
|
---|
342 | const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
|
---|
343 | QRgb brushColor = state->pen().brush().color().rgb();
|
---|
344 | bool fallBack = state->pen().brush().style() != Qt::SolidPattern
|
---|
345 | || qAlpha(brushColor) != 0xff
|
---|
346 | || d->txop >= QTransform::TxProject
|
---|
347 | || ti.fontEngine->type() != QFontEngine::Win;
|
---|
348 |
|
---|
349 |
|
---|
350 | if (!fallBack) {
|
---|
351 | QFontEngineWin *fe = static_cast<QFontEngineWin *>(ti.fontEngine);
|
---|
352 |
|
---|
353 | // Try selecting the font to see if we get a substitution font
|
---|
354 | SelectObject(d->hdc, fe->hfont);
|
---|
355 |
|
---|
356 | if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) {
|
---|
357 | wchar_t n[64];
|
---|
358 | GetTextFace(d->hdc, 64, n);
|
---|
359 | fallBack = QString::fromWCharArray(n)
|
---|
360 | != QString::fromWCharArray(fe->logfont.lfFaceName);
|
---|
361 | }
|
---|
362 | }
|
---|
363 |
|
---|
364 |
|
---|
365 | if (fallBack) {
|
---|
366 | QPaintEngine::drawTextItem(p, textItem);
|
---|
367 | return ;
|
---|
368 | }
|
---|
369 |
|
---|
370 | // We only want to convert the glyphs to text if the entire string is compatible with ASCII
|
---|
371 | bool convertToText = true;
|
---|
372 | for (int i=0; i < ti.num_chars; ++i) {
|
---|
373 | if (ti.chars[i].unicode() >= 0x80) {
|
---|
374 | convertToText = false;
|
---|
375 | break;
|
---|
376 | }
|
---|
377 |
|
---|
378 | if (ti.logClusters[i] != i) {
|
---|
379 | convertToText = false;
|
---|
380 | break;
|
---|
381 | }
|
---|
382 | }
|
---|
383 |
|
---|
384 | COLORREF cf = RGB(qRed(brushColor), qGreen(brushColor), qBlue(brushColor));
|
---|
385 | SelectObject(d->hdc, CreateSolidBrush(cf));
|
---|
386 | SelectObject(d->hdc, CreatePen(PS_SOLID, 1, cf));
|
---|
387 | SetTextColor(d->hdc, cf);
|
---|
388 |
|
---|
389 | draw_text_item_win(p, ti, d->hdc, convertToText, d->matrix, d->devPaperRect.topLeft());
|
---|
390 | DeleteObject(SelectObject(d->hdc,GetStockObject(HOLLOW_BRUSH)));
|
---|
391 | DeleteObject(SelectObject(d->hdc,GetStockObject(BLACK_PEN)));
|
---|
392 | }
|
---|
393 |
|
---|
394 | static inline qreal mmToInches(double mm)
|
---|
395 | {
|
---|
396 | return mm*0.039370147;
|
---|
397 | }
|
---|
398 |
|
---|
399 | static inline qreal inchesToMM(double in)
|
---|
400 | {
|
---|
401 | return in/0.039370147;
|
---|
402 | }
|
---|
403 |
|
---|
404 | int QWin32PrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
|
---|
405 | {
|
---|
406 | Q_D(const QWin32PrintEngine);
|
---|
407 |
|
---|
408 | if (!d->hdc)
|
---|
409 | return 0;
|
---|
410 |
|
---|
411 | int val;
|
---|
412 | int res = d->resolution;
|
---|
413 |
|
---|
414 | switch (m) {
|
---|
415 | case QPaintDevice::PdmWidth:
|
---|
416 | if (d->has_custom_paper_size) {
|
---|
417 | val = qRound(d->paper_size.width() * res / 72.0);
|
---|
418 | } else {
|
---|
419 | int logPixelsX = GetDeviceCaps(d->hdc, LOGPIXELSX);
|
---|
420 | if (logPixelsX == 0) {
|
---|
421 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
422 | "might be a driver problem");
|
---|
423 | logPixelsX = 600; // Reasonable default
|
---|
424 | }
|
---|
425 | val = res
|
---|
426 | * GetDeviceCaps(d->hdc, d->fullPage ? PHYSICALWIDTH : HORZRES)
|
---|
427 | / logPixelsX;
|
---|
428 | }
|
---|
429 | if (d->pageMarginsSet)
|
---|
430 | val -= int(mmToInches((d->previousDialogMargins.left() +
|
---|
431 | d->previousDialogMargins.width()) / 100.0) * res);
|
---|
432 | break;
|
---|
433 | case QPaintDevice::PdmHeight:
|
---|
434 | if (d->has_custom_paper_size) {
|
---|
435 | val = qRound(d->paper_size.height() * res / 72.0);
|
---|
436 | } else {
|
---|
437 | int logPixelsY = GetDeviceCaps(d->hdc, LOGPIXELSY);
|
---|
438 | if (logPixelsY == 0) {
|
---|
439 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
440 | "might be a driver problem");
|
---|
441 | logPixelsY = 600; // Reasonable default
|
---|
442 | }
|
---|
443 | val = res
|
---|
444 | * GetDeviceCaps(d->hdc, d->fullPage ? PHYSICALHEIGHT : VERTRES)
|
---|
445 | / logPixelsY;
|
---|
446 | }
|
---|
447 | if (d->pageMarginsSet)
|
---|
448 | val -= int(mmToInches((d->previousDialogMargins.top() +
|
---|
449 | d->previousDialogMargins.height()) / 100.0) * res);
|
---|
450 | break;
|
---|
451 | case QPaintDevice::PdmDpiX:
|
---|
452 | val = res;
|
---|
453 | break;
|
---|
454 | case QPaintDevice::PdmDpiY:
|
---|
455 | val = res;
|
---|
456 | break;
|
---|
457 | case QPaintDevice::PdmPhysicalDpiX:
|
---|
458 | val = GetDeviceCaps(d->hdc, LOGPIXELSX);
|
---|
459 | break;
|
---|
460 | case QPaintDevice::PdmPhysicalDpiY:
|
---|
461 | val = GetDeviceCaps(d->hdc, LOGPIXELSY);
|
---|
462 | break;
|
---|
463 | case QPaintDevice::PdmWidthMM:
|
---|
464 | if (d->has_custom_paper_size) {
|
---|
465 | val = qRound(d->paper_size.width()*25.4/72);
|
---|
466 | } else {
|
---|
467 | if (!d->fullPage) {
|
---|
468 | val = GetDeviceCaps(d->hdc, HORZSIZE);
|
---|
469 | } else {
|
---|
470 | float wi = 25.4 * GetDeviceCaps(d->hdc, PHYSICALWIDTH);
|
---|
471 | int logPixelsX = GetDeviceCaps(d->hdc, LOGPIXELSX);
|
---|
472 | if (logPixelsX == 0) {
|
---|
473 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
474 | "might be a driver problem");
|
---|
475 | logPixelsX = 600; // Reasonable default
|
---|
476 | }
|
---|
477 | val = qRound(wi / logPixelsX);
|
---|
478 | }
|
---|
479 | }
|
---|
480 | if (d->pageMarginsSet)
|
---|
481 | val -= (d->previousDialogMargins.left() +
|
---|
482 | d->previousDialogMargins.width()) / 100.0;
|
---|
483 | break;
|
---|
484 | case QPaintDevice::PdmHeightMM:
|
---|
485 | if (d->has_custom_paper_size) {
|
---|
486 | val = qRound(d->paper_size.height()*25.4/72);
|
---|
487 | } else {
|
---|
488 | if (!d->fullPage) {
|
---|
489 | val = GetDeviceCaps(d->hdc, VERTSIZE);
|
---|
490 | } else {
|
---|
491 | float hi = 25.4 * GetDeviceCaps(d->hdc, PHYSICALHEIGHT);
|
---|
492 | int logPixelsY = GetDeviceCaps(d->hdc, LOGPIXELSY);
|
---|
493 | if (logPixelsY == 0) {
|
---|
494 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
495 | "might be a driver problem");
|
---|
496 | logPixelsY = 600; // Reasonable default
|
---|
497 | }
|
---|
498 | val = qRound(hi / logPixelsY);
|
---|
499 | }
|
---|
500 | }
|
---|
501 | if (d->pageMarginsSet)
|
---|
502 | val -= (d->previousDialogMargins.top() +
|
---|
503 | d->previousDialogMargins.height()) / 100.0;
|
---|
504 | break;
|
---|
505 | case QPaintDevice::PdmNumColors:
|
---|
506 | {
|
---|
507 | int bpp = GetDeviceCaps(d->hdc, BITSPIXEL);
|
---|
508 | if(bpp==32)
|
---|
509 | val = INT_MAX;
|
---|
510 | else if(bpp<=8)
|
---|
511 | val = GetDeviceCaps(d->hdc, NUMCOLORS);
|
---|
512 | else
|
---|
513 | val = 1 << (bpp * GetDeviceCaps(d->hdc, PLANES));
|
---|
514 | }
|
---|
515 | break;
|
---|
516 | case QPaintDevice::PdmDepth:
|
---|
517 | val = GetDeviceCaps(d->hdc, PLANES);
|
---|
518 | break;
|
---|
519 | default:
|
---|
520 | qWarning("QPrinter::metric: Invalid metric command");
|
---|
521 | return 0;
|
---|
522 | }
|
---|
523 | return val;
|
---|
524 | }
|
---|
525 |
|
---|
526 | void QWin32PrintEngine::updateState(const QPaintEngineState &state)
|
---|
527 | {
|
---|
528 | Q_D(QWin32PrintEngine);
|
---|
529 |
|
---|
530 | QAlphaPaintEngine::updateState(state);
|
---|
531 | if (!continueCall())
|
---|
532 | return;
|
---|
533 |
|
---|
534 | if (state.state() & DirtyTransform) {
|
---|
535 | updateMatrix(state.transform());
|
---|
536 | }
|
---|
537 |
|
---|
538 | if (state.state() & DirtyPen) {
|
---|
539 | d->pen = state.pen();
|
---|
540 | d->has_pen = d->pen.style() != Qt::NoPen && d->pen.isSolid();
|
---|
541 | }
|
---|
542 |
|
---|
543 | if (state.state() & DirtyBrush) {
|
---|
544 | QBrush brush = state.brush();
|
---|
545 | d->has_brush = brush.style() == Qt::SolidPattern;
|
---|
546 | d->brush_color = brush.color();
|
---|
547 | }
|
---|
548 |
|
---|
549 | if (state.state() & DirtyClipEnabled) {
|
---|
550 | if (state.isClipEnabled())
|
---|
551 | updateClipPath(painter()->clipPath(), Qt::ReplaceClip);
|
---|
552 | else
|
---|
553 | updateClipPath(QPainterPath(), Qt::NoClip);
|
---|
554 | }
|
---|
555 |
|
---|
556 | if (state.state() & DirtyClipPath) {
|
---|
557 | updateClipPath(state.clipPath(), state.clipOperation());
|
---|
558 | }
|
---|
559 |
|
---|
560 | if (state.state() & DirtyClipRegion) {
|
---|
561 | QRegion clipRegion = state.clipRegion();
|
---|
562 | QPainterPath clipPath = qt_regionToPath(clipRegion);
|
---|
563 | updateClipPath(clipPath, state.clipOperation());
|
---|
564 | }
|
---|
565 | }
|
---|
566 |
|
---|
567 | void QWin32PrintEngine::updateClipPath(const QPainterPath &clipPath, Qt::ClipOperation op)
|
---|
568 | {
|
---|
569 | Q_D(QWin32PrintEngine);
|
---|
570 |
|
---|
571 | bool doclip = true;
|
---|
572 | if (op == Qt::NoClip) {
|
---|
573 | SelectClipRgn(d->hdc, 0);
|
---|
574 | doclip = false;
|
---|
575 | }
|
---|
576 |
|
---|
577 | if (doclip) {
|
---|
578 | QPainterPath xformed = clipPath * d->matrix;
|
---|
579 |
|
---|
580 | if (xformed.isEmpty()) {
|
---|
581 | QRegion empty(-0x1000000, -0x1000000, 1, 1);
|
---|
582 | SelectClipRgn(d->hdc, empty.handle());
|
---|
583 | } else {
|
---|
584 | d->composeGdiPath(xformed);
|
---|
585 | const int ops[] = {
|
---|
586 | -1, // Qt::NoClip, covered above
|
---|
587 | RGN_COPY, // Qt::ReplaceClip
|
---|
588 | RGN_AND, // Qt::IntersectClip
|
---|
589 | RGN_OR // Qt::UniteClip
|
---|
590 | };
|
---|
591 | Q_ASSERT(op > 0 && unsigned(op) <= sizeof(ops) / sizeof(int));
|
---|
592 | SelectClipPath(d->hdc, ops[op]);
|
---|
593 | }
|
---|
594 | }
|
---|
595 |
|
---|
596 | QPainterPath aclip = qt_regionToPath(alphaClipping());
|
---|
597 | if (!aclip.isEmpty()) {
|
---|
598 | QTransform tx(d->stretch_x, 0, 0, d->stretch_y, d->origin_x, d->origin_y);
|
---|
599 | d->composeGdiPath(tx.map(aclip));
|
---|
600 | SelectClipPath(d->hdc, RGN_DIFF);
|
---|
601 | }
|
---|
602 | }
|
---|
603 |
|
---|
604 | void QWin32PrintEngine::updateMatrix(const QTransform &m)
|
---|
605 | {
|
---|
606 | Q_D(QWin32PrintEngine);
|
---|
607 |
|
---|
608 | QTransform stretch(d->stretch_x, 0, 0, d->stretch_y, d->origin_x, d->origin_y);
|
---|
609 | d->painterMatrix = m;
|
---|
610 | d->matrix = d->painterMatrix * stretch;
|
---|
611 | d->txop = d->matrix.type();
|
---|
612 | d->complex_xform = (d->txop > QTransform::TxScale);
|
---|
613 | }
|
---|
614 |
|
---|
615 | void QWin32PrintEngine::drawPixmap(const QRectF &targetRect,
|
---|
616 | const QPixmap &originalPixmap,
|
---|
617 | const QRectF &sourceRect)
|
---|
618 | {
|
---|
619 | Q_D(QWin32PrintEngine);
|
---|
620 |
|
---|
621 | QAlphaPaintEngine::drawPixmap(targetRect, originalPixmap, sourceRect);
|
---|
622 | if (!continueCall())
|
---|
623 | return;
|
---|
624 |
|
---|
625 | const int tileSize = 2048;
|
---|
626 |
|
---|
627 | QRectF r = targetRect;
|
---|
628 | QRectF sr = sourceRect;
|
---|
629 |
|
---|
630 | QPixmap pixmap = originalPixmap;
|
---|
631 | if (sr.size() != pixmap.size()) {
|
---|
632 | pixmap = pixmap.copy(sr.toRect());
|
---|
633 | }
|
---|
634 |
|
---|
635 | qreal scaleX = 1.0f;
|
---|
636 | qreal scaleY = 1.0f;
|
---|
637 |
|
---|
638 | QTransform scaleMatrix = QTransform::fromScale(r.width() / pixmap.width(), r.height() / pixmap.height());
|
---|
639 | QTransform adapted = QPixmap::trueMatrix(d->painterMatrix * scaleMatrix,
|
---|
640 | pixmap.width(), pixmap.height());
|
---|
641 |
|
---|
642 | qreal xform_offset_x = adapted.dx();
|
---|
643 | qreal xform_offset_y = adapted.dy();
|
---|
644 |
|
---|
645 | if (d->complex_xform) {
|
---|
646 | pixmap = pixmap.transformed(adapted);
|
---|
647 | scaleX = d->stretch_x;
|
---|
648 | scaleY = d->stretch_y;
|
---|
649 | } else {
|
---|
650 | scaleX = d->stretch_x * (r.width() / pixmap.width()) * d->painterMatrix.m11();
|
---|
651 | scaleY = d->stretch_y * (r.height() / pixmap.height()) * d->painterMatrix.m22();
|
---|
652 | }
|
---|
653 |
|
---|
654 | QPointF topLeft = r.topLeft() * d->painterMatrix;
|
---|
655 | int tx = int(topLeft.x() * d->stretch_x + d->origin_x);
|
---|
656 | int ty = int(topLeft.y() * d->stretch_y + d->origin_y);
|
---|
657 | int tw = qAbs(int(pixmap.width() * scaleX));
|
---|
658 | int th = qAbs(int(pixmap.height() * scaleY));
|
---|
659 |
|
---|
660 | xform_offset_x *= d->stretch_x;
|
---|
661 | xform_offset_y *= d->stretch_y;
|
---|
662 |
|
---|
663 | int dc_state = SaveDC(d->hdc);
|
---|
664 |
|
---|
665 | int tilesw = pixmap.width() / tileSize;
|
---|
666 | int tilesh = pixmap.height() / tileSize;
|
---|
667 | ++tilesw;
|
---|
668 | ++tilesh;
|
---|
669 |
|
---|
670 | int txinc = tileSize*scaleX;
|
---|
671 | int tyinc = tileSize*scaleY;
|
---|
672 |
|
---|
673 | for (int y = 0; y < tilesh; ++y) {
|
---|
674 | int tposy = ty + (y * tyinc);
|
---|
675 | int imgh = tileSize;
|
---|
676 | int height = tyinc;
|
---|
677 | if (y == (tilesh - 1)) {
|
---|
678 | imgh = pixmap.height() - (y * tileSize);
|
---|
679 | height = (th - (y * tyinc));
|
---|
680 | }
|
---|
681 | for (int x = 0; x < tilesw; ++x) {
|
---|
682 | int tposx = tx + (x * txinc);
|
---|
683 | int imgw = tileSize;
|
---|
684 | int width = txinc;
|
---|
685 | if (x == (tilesw - 1)) {
|
---|
686 | imgw = pixmap.width() - (x * tileSize);
|
---|
687 | width = (tw - (x * txinc));
|
---|
688 | }
|
---|
689 |
|
---|
690 | QPixmap p = pixmap.copy(tileSize * x, tileSize * y, imgw, imgh);
|
---|
691 | HBITMAP hbitmap = p.toWinHBITMAP(QPixmap::NoAlpha);
|
---|
692 | HDC display_dc = GetDC(0);
|
---|
693 | HDC hbitmap_hdc = CreateCompatibleDC(display_dc);
|
---|
694 | HGDIOBJ null_bitmap = SelectObject(hbitmap_hdc, hbitmap);
|
---|
695 |
|
---|
696 | ReleaseDC(0, display_dc);
|
---|
697 |
|
---|
698 | if (!StretchBlt(d->hdc, qRound(tposx - xform_offset_x), qRound(tposy - xform_offset_y), width, height,
|
---|
699 | hbitmap_hdc, 0, 0, p.width(), p.height(), SRCCOPY))
|
---|
700 | qErrnoWarning("QWin32PrintEngine::drawPixmap, StretchBlt failed");
|
---|
701 |
|
---|
702 | SelectObject(hbitmap_hdc, null_bitmap);
|
---|
703 | DeleteObject(hbitmap);
|
---|
704 | DeleteDC(hbitmap_hdc);
|
---|
705 | }
|
---|
706 | }
|
---|
707 |
|
---|
708 | RestoreDC(d->hdc, dc_state);
|
---|
709 | }
|
---|
710 |
|
---|
711 |
|
---|
712 | void QWin32PrintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &pos)
|
---|
713 | {
|
---|
714 | Q_D(QWin32PrintEngine);
|
---|
715 |
|
---|
716 | QAlphaPaintEngine::drawTiledPixmap(r, pm, pos);
|
---|
717 | if (!continueCall())
|
---|
718 | return;
|
---|
719 |
|
---|
720 | if (d->complex_xform || !pos.isNull()) {
|
---|
721 | QPaintEngine::drawTiledPixmap(r, pm, pos);
|
---|
722 | } else {
|
---|
723 | int dc_state = SaveDC(d->hdc);
|
---|
724 |
|
---|
725 | HDC display_dc = GetDC(0);
|
---|
726 | HBITMAP hbitmap = pm.toWinHBITMAP(QPixmap::NoAlpha);
|
---|
727 | HDC hbitmap_hdc = CreateCompatibleDC(display_dc);
|
---|
728 | HGDIOBJ null_bitmap = SelectObject(hbitmap_hdc, hbitmap);
|
---|
729 |
|
---|
730 | ReleaseDC(0, display_dc);
|
---|
731 |
|
---|
732 | QRectF trect = d->painterMatrix.mapRect(r);
|
---|
733 | int tx = int(trect.left() * d->stretch_x + d->origin_x);
|
---|
734 | int ty = int(trect.top() * d->stretch_y + d->origin_y);
|
---|
735 |
|
---|
736 | int xtiles = int(trect.width() / pm.width()) + 1;
|
---|
737 | int ytiles = int(trect.height() / pm.height()) + 1;
|
---|
738 | int xinc = int(pm.width() * d->stretch_x);
|
---|
739 | int yinc = int(pm.height() * d->stretch_y);
|
---|
740 |
|
---|
741 | for (int y = 0; y < ytiles; ++y) {
|
---|
742 | int ity = ty + (yinc * y);
|
---|
743 | int ith = pm.height();
|
---|
744 | if (y == (ytiles - 1)) {
|
---|
745 | ith = int(trect.height() - (pm.height() * y));
|
---|
746 | }
|
---|
747 |
|
---|
748 | for (int x = 0; x < xtiles; ++x) {
|
---|
749 | int itx = tx + (xinc * x);
|
---|
750 | int itw = pm.width();
|
---|
751 | if (x == (xtiles - 1)) {
|
---|
752 | itw = int(trect.width() - (pm.width() * x));
|
---|
753 | }
|
---|
754 |
|
---|
755 | if (!StretchBlt(d->hdc, itx, ity, int(itw * d->stretch_x), int(ith * d->stretch_y),
|
---|
756 | hbitmap_hdc, 0, 0, itw, ith, SRCCOPY))
|
---|
757 | qErrnoWarning("QWin32PrintEngine::drawPixmap, StretchBlt failed");
|
---|
758 |
|
---|
759 | }
|
---|
760 | }
|
---|
761 |
|
---|
762 | SelectObject(hbitmap_hdc, null_bitmap);
|
---|
763 | DeleteObject(hbitmap);
|
---|
764 | DeleteDC(hbitmap_hdc);
|
---|
765 |
|
---|
766 | RestoreDC(d->hdc, dc_state);
|
---|
767 | }
|
---|
768 | }
|
---|
769 |
|
---|
770 |
|
---|
771 | void QWin32PrintEnginePrivate::composeGdiPath(const QPainterPath &path)
|
---|
772 | {
|
---|
773 | if (!BeginPath(hdc))
|
---|
774 | qErrnoWarning("QWin32PrintEnginePrivate::drawPath: BeginPath failed");
|
---|
775 |
|
---|
776 | // Drawing the subpaths
|
---|
777 | int start = -1;
|
---|
778 | for (int i=0; i<path.elementCount(); ++i) {
|
---|
779 | const QPainterPath::Element &elm = path.elementAt(i);
|
---|
780 | switch (elm.type) {
|
---|
781 | case QPainterPath::MoveToElement:
|
---|
782 | if (start >= 0
|
---|
783 | && path.elementAt(start).x == path.elementAt(i-1).x
|
---|
784 | && path.elementAt(start).y == path.elementAt(i-1).y)
|
---|
785 | CloseFigure(hdc);
|
---|
786 | start = i;
|
---|
787 | MoveToEx(hdc, qRound(elm.x), qRound(elm.y), 0);
|
---|
788 | break;
|
---|
789 | case QPainterPath::LineToElement:
|
---|
790 | LineTo(hdc, qRound(elm.x), qRound(elm.y));
|
---|
791 | break;
|
---|
792 | case QPainterPath::CurveToElement: {
|
---|
793 | POINT pts[3] = {
|
---|
794 | { qRound(elm.x), qRound(elm.y) },
|
---|
795 | { qRound(path.elementAt(i+1).x), qRound(path.elementAt(i+1).y) },
|
---|
796 | { qRound(path.elementAt(i+2).x), qRound(path.elementAt(i+2).y) }
|
---|
797 | };
|
---|
798 | i+=2;
|
---|
799 | PolyBezierTo(hdc, pts, 3);
|
---|
800 | break;
|
---|
801 | }
|
---|
802 | default:
|
---|
803 | qFatal("QWin32PaintEngine::drawPath: Unhandled type: %d", elm.type);
|
---|
804 | }
|
---|
805 | }
|
---|
806 |
|
---|
807 | if (start >= 0
|
---|
808 | && path.elementAt(start).x == path.elementAt(path.elementCount()-1).x
|
---|
809 | && path.elementAt(start).y == path.elementAt(path.elementCount()-1).y)
|
---|
810 | CloseFigure(hdc);
|
---|
811 |
|
---|
812 | if (!EndPath(hdc))
|
---|
813 | qErrnoWarning("QWin32PaintEngine::drawPath: EndPath failed");
|
---|
814 |
|
---|
815 | SetPolyFillMode(hdc, path.fillRule() == Qt::WindingFill ? WINDING : ALTERNATE);
|
---|
816 | }
|
---|
817 |
|
---|
818 |
|
---|
819 | void QWin32PrintEnginePrivate::fillPath_dev(const QPainterPath &path, const QColor &color)
|
---|
820 | {
|
---|
821 | #ifdef QT_DEBUG_DRAW
|
---|
822 | qDebug() << " --- QWin32PrintEnginePrivate::fillPath() bound:" << path.boundingRect() << color;
|
---|
823 | #endif
|
---|
824 |
|
---|
825 | composeGdiPath(path);
|
---|
826 |
|
---|
827 | HBRUSH brush = CreateSolidBrush(RGB(color.red(), color.green(), color.blue()));
|
---|
828 | HGDIOBJ old_brush = SelectObject(hdc, brush);
|
---|
829 | FillPath(hdc);
|
---|
830 | DeleteObject(SelectObject(hdc, old_brush));
|
---|
831 | }
|
---|
832 |
|
---|
833 | void QWin32PrintEnginePrivate::strokePath_dev(const QPainterPath &path, const QColor &color, qreal penWidth)
|
---|
834 | {
|
---|
835 | composeGdiPath(path);
|
---|
836 | LOGBRUSH brush;
|
---|
837 | brush.lbStyle = BS_SOLID;
|
---|
838 | brush.lbColor = RGB(color.red(), color.green(), color.blue());
|
---|
839 | DWORD capStyle = PS_ENDCAP_SQUARE;
|
---|
840 | DWORD joinStyle = PS_JOIN_BEVEL;
|
---|
841 | if (pen.capStyle() == Qt::FlatCap)
|
---|
842 | capStyle = PS_ENDCAP_FLAT;
|
---|
843 | else if (pen.capStyle() == Qt::RoundCap)
|
---|
844 | capStyle = PS_ENDCAP_ROUND;
|
---|
845 |
|
---|
846 | if (pen.joinStyle() == Qt::MiterJoin)
|
---|
847 | joinStyle = PS_JOIN_MITER;
|
---|
848 | else if (pen.joinStyle() == Qt::RoundJoin)
|
---|
849 | joinStyle = PS_JOIN_ROUND;
|
---|
850 |
|
---|
851 | HPEN pen = ExtCreatePen(((penWidth == 0) ? PS_COSMETIC : PS_GEOMETRIC)
|
---|
852 | | PS_SOLID | capStyle | joinStyle,
|
---|
853 | penWidth, &brush, 0, 0);
|
---|
854 |
|
---|
855 | HGDIOBJ old_pen = SelectObject(hdc, pen);
|
---|
856 | StrokePath(hdc);
|
---|
857 | DeleteObject(SelectObject(hdc, old_pen));
|
---|
858 | }
|
---|
859 |
|
---|
860 |
|
---|
861 | void QWin32PrintEnginePrivate::fillPath(const QPainterPath &path, const QColor &color)
|
---|
862 | {
|
---|
863 | fillPath_dev(path * matrix, color);
|
---|
864 | }
|
---|
865 |
|
---|
866 | void QWin32PrintEnginePrivate::strokePath(const QPainterPath &path, const QColor &color)
|
---|
867 | {
|
---|
868 | QPainterPathStroker stroker;
|
---|
869 | if (pen.style() == Qt::CustomDashLine) {
|
---|
870 | stroker.setDashPattern(pen.dashPattern());
|
---|
871 | stroker.setDashOffset(pen.dashOffset());
|
---|
872 | } else {
|
---|
873 | stroker.setDashPattern(pen.style());
|
---|
874 | }
|
---|
875 | stroker.setCapStyle(pen.capStyle());
|
---|
876 | stroker.setJoinStyle(pen.joinStyle());
|
---|
877 | stroker.setMiterLimit(pen.miterLimit());
|
---|
878 |
|
---|
879 | QPainterPath stroke;
|
---|
880 | qreal width = pen.widthF();
|
---|
881 | if (pen.style() == Qt::SolidLine && (pen.isCosmetic() || matrix.type() < QTransform::TxScale)) {
|
---|
882 | strokePath_dev(path * matrix, color, width);
|
---|
883 | } else {
|
---|
884 | stroker.setWidth(width);
|
---|
885 | if (pen.isCosmetic()) {
|
---|
886 | stroke = stroker.createStroke(path * matrix);
|
---|
887 | } else {
|
---|
888 | stroke = stroker.createStroke(path) * painterMatrix;
|
---|
889 | QTransform stretch(stretch_x, 0, 0, stretch_y, origin_x, origin_y);
|
---|
890 | stroke = stroke * stretch;
|
---|
891 | }
|
---|
892 |
|
---|
893 | if (stroke.isEmpty())
|
---|
894 | return;
|
---|
895 |
|
---|
896 | fillPath_dev(stroke, color);
|
---|
897 | }
|
---|
898 | }
|
---|
899 |
|
---|
900 |
|
---|
901 | void QWin32PrintEngine::drawPath(const QPainterPath &path)
|
---|
902 | {
|
---|
903 | #ifdef QT_DEBUG_DRAW
|
---|
904 | qDebug() << " - QWin32PrintEngine::drawPath(), bounds: " << path.boundingRect();
|
---|
905 | #endif
|
---|
906 |
|
---|
907 | Q_D(QWin32PrintEngine);
|
---|
908 |
|
---|
909 | QAlphaPaintEngine::drawPath(path);
|
---|
910 | if (!continueCall())
|
---|
911 | return;
|
---|
912 |
|
---|
913 | if (d->has_brush)
|
---|
914 | d->fillPath(path, d->brush_color);
|
---|
915 |
|
---|
916 | if (d->has_pen)
|
---|
917 | d->strokePath(path, d->pen.color());
|
---|
918 | }
|
---|
919 |
|
---|
920 |
|
---|
921 | void QWin32PrintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
|
---|
922 | {
|
---|
923 | #ifdef QT_DEBUG_DRAW
|
---|
924 | qDebug() << " - QWin32PrintEngine::drawPolygon(), pointCount: " << pointCount;
|
---|
925 | #endif
|
---|
926 |
|
---|
927 | QAlphaPaintEngine::drawPolygon(points, pointCount, mode);
|
---|
928 | if (!continueCall())
|
---|
929 | return;
|
---|
930 |
|
---|
931 | Q_ASSERT(pointCount > 1);
|
---|
932 |
|
---|
933 | QPainterPath path(points[0]);
|
---|
934 |
|
---|
935 | for (int i=1; i<pointCount; ++i) {
|
---|
936 | path.lineTo(points[i]);
|
---|
937 | }
|
---|
938 |
|
---|
939 | Q_D(QWin32PrintEngine);
|
---|
940 |
|
---|
941 | bool has_brush = d->has_brush;
|
---|
942 |
|
---|
943 | if (mode == PolylineMode)
|
---|
944 | d->has_brush = false; // No brush for polylines
|
---|
945 | else
|
---|
946 | path.closeSubpath(); // polygons are should always be closed.
|
---|
947 |
|
---|
948 | drawPath(path);
|
---|
949 | d->has_brush = has_brush;
|
---|
950 | }
|
---|
951 |
|
---|
952 | void QWin32PrintEnginePrivate::queryDefault()
|
---|
953 | {
|
---|
954 | /* Read the default printer name, driver and port with the intuitive function
|
---|
955 | * Strings "windows" and "device" are specified in the MSDN under EnumPrinters()
|
---|
956 | */
|
---|
957 | QString noPrinters(QLatin1String("qt_no_printers"));
|
---|
958 | wchar_t buffer[256];
|
---|
959 | GetProfileString(L"windows", L"device",
|
---|
960 | reinterpret_cast<const wchar_t *>(noPrinters.utf16()),
|
---|
961 | buffer, 256);
|
---|
962 | QString output = QString::fromWCharArray(buffer);
|
---|
963 | if (output.isEmpty() || output == noPrinters) // no printers
|
---|
964 | return;
|
---|
965 |
|
---|
966 | QStringList info = output.split(QLatin1Char(','));
|
---|
967 | if (info.size() > 0) {
|
---|
968 | if (name.isEmpty())
|
---|
969 | name = info.at(0);
|
---|
970 | if (program.isEmpty())
|
---|
971 | program = info.at(1);
|
---|
972 | if (port.isEmpty())
|
---|
973 | port = info.at(2);
|
---|
974 | }
|
---|
975 | }
|
---|
976 |
|
---|
977 | QWin32PrintEnginePrivate::~QWin32PrintEnginePrivate()
|
---|
978 | {
|
---|
979 | if (hdc)
|
---|
980 | release();
|
---|
981 | }
|
---|
982 |
|
---|
983 | void QWin32PrintEnginePrivate::initialize()
|
---|
984 | {
|
---|
985 | if (hdc)
|
---|
986 | release();
|
---|
987 | Q_ASSERT(!hPrinter);
|
---|
988 | Q_ASSERT(!hdc);
|
---|
989 | Q_ASSERT(!devMode);
|
---|
990 | Q_ASSERT(!pInfo);
|
---|
991 |
|
---|
992 | if (name.isEmpty())
|
---|
993 | return;
|
---|
994 |
|
---|
995 | txop = QTransform::TxNone;
|
---|
996 |
|
---|
997 | bool ok = OpenPrinter((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0);
|
---|
998 | if (!ok) {
|
---|
999 | qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed");
|
---|
1000 | return;
|
---|
1001 | }
|
---|
1002 |
|
---|
1003 | // Fetch the PRINTER_INFO_2 with DEVMODE data containing the
|
---|
1004 | // printer settings.
|
---|
1005 | DWORD infoSize, numBytes;
|
---|
1006 | GetPrinter(hPrinter, 2, NULL, 0, &infoSize);
|
---|
1007 | hMem = GlobalAlloc(GHND, infoSize);
|
---|
1008 | pInfo = (PRINTER_INFO_2*) GlobalLock(hMem);
|
---|
1009 | ok = GetPrinter(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes);
|
---|
1010 |
|
---|
1011 | if (!ok) {
|
---|
1012 | qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed");
|
---|
1013 | GlobalUnlock(pInfo);
|
---|
1014 | GlobalFree(hMem);
|
---|
1015 | ClosePrinter(hPrinter);
|
---|
1016 | pInfo = 0;
|
---|
1017 | hMem = 0;
|
---|
1018 | hPrinter = 0;
|
---|
1019 | return;
|
---|
1020 | }
|
---|
1021 |
|
---|
1022 | devMode = pInfo->pDevMode;
|
---|
1023 | hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
|
---|
1024 | reinterpret_cast<const wchar_t *>(name.utf16()), 0, devMode);
|
---|
1025 |
|
---|
1026 | Q_ASSERT(hPrinter);
|
---|
1027 | Q_ASSERT(pInfo);
|
---|
1028 |
|
---|
1029 | if (devMode) {
|
---|
1030 | num_copies = devMode->dmCopies;
|
---|
1031 | }
|
---|
1032 |
|
---|
1033 | initHDC();
|
---|
1034 |
|
---|
1035 | #ifdef QT_DEBUG_DRAW
|
---|
1036 | qDebug() << "QWin32PrintEngine::initialize()" << endl
|
---|
1037 | << " - paperRect" << devPaperRect << endl
|
---|
1038 | << " - pageRect" << devPageRect << endl
|
---|
1039 | << " - stretch_x" << stretch_x << endl
|
---|
1040 | << " - stretch_y" << stretch_y << endl
|
---|
1041 | << " - origin_x" << origin_x << endl
|
---|
1042 | << " - origin_y" << origin_y << endl;
|
---|
1043 | #endif
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | void QWin32PrintEnginePrivate::initHDC()
|
---|
1047 | {
|
---|
1048 | Q_ASSERT(hdc);
|
---|
1049 |
|
---|
1050 | HDC display_dc = GetDC(0);
|
---|
1051 | dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
|
---|
1052 | dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
|
---|
1053 | dpi_display = GetDeviceCaps(display_dc, LOGPIXELSY);
|
---|
1054 | ReleaseDC(0, display_dc);
|
---|
1055 | if (dpi_display == 0) {
|
---|
1056 | qWarning("QWin32PrintEngine::metric: GetDeviceCaps() failed, "
|
---|
1057 | "might be a driver problem");
|
---|
1058 | dpi_display = 96; // Reasonable default
|
---|
1059 | }
|
---|
1060 |
|
---|
1061 | switch(mode) {
|
---|
1062 | case QPrinter::ScreenResolution:
|
---|
1063 | resolution = dpi_display;
|
---|
1064 | stretch_x = dpi_x / double(dpi_display);
|
---|
1065 | stretch_y = dpi_y / double(dpi_display);
|
---|
1066 | break;
|
---|
1067 | case QPrinter::PrinterResolution:
|
---|
1068 | case QPrinter::HighResolution:
|
---|
1069 | resolution = dpi_y;
|
---|
1070 | stretch_x = 1;
|
---|
1071 | stretch_y = 1;
|
---|
1072 | break;
|
---|
1073 | default:
|
---|
1074 | break;
|
---|
1075 | }
|
---|
1076 |
|
---|
1077 | initDevRects();
|
---|
1078 | }
|
---|
1079 |
|
---|
1080 | void QWin32PrintEnginePrivate::initDevRects()
|
---|
1081 | {
|
---|
1082 | devPaperRect = QRect(0, 0,
|
---|
1083 | GetDeviceCaps(hdc, PHYSICALWIDTH),
|
---|
1084 | GetDeviceCaps(hdc, PHYSICALHEIGHT));
|
---|
1085 | devPhysicalPageRect = QRect(GetDeviceCaps(hdc, PHYSICALOFFSETX),
|
---|
1086 | GetDeviceCaps(hdc, PHYSICALOFFSETY),
|
---|
1087 | GetDeviceCaps(hdc, HORZRES),
|
---|
1088 | GetDeviceCaps(hdc, VERTRES));
|
---|
1089 | if (!pageMarginsSet)
|
---|
1090 | devPageRect = devPhysicalPageRect;
|
---|
1091 | else
|
---|
1092 | devPageRect = devPaperRect.adjusted(qRound(mmToInches(previousDialogMargins.left() / 100.0) * dpi_x),
|
---|
1093 | qRound(mmToInches(previousDialogMargins.top() / 100.0) * dpi_y),
|
---|
1094 | -qRound(mmToInches(previousDialogMargins.width() / 100.0) * dpi_x),
|
---|
1095 | -qRound(mmToInches(previousDialogMargins.height() / 100.0) * dpi_y));
|
---|
1096 | updateOrigin();
|
---|
1097 | }
|
---|
1098 |
|
---|
1099 | void QWin32PrintEnginePrivate::setPageMargins(int marginLeft, int marginTop, int marginRight, int marginBottom)
|
---|
1100 | {
|
---|
1101 | pageMarginsSet = true;
|
---|
1102 | previousDialogMargins = QRect(marginLeft, marginTop, marginRight, marginBottom);
|
---|
1103 |
|
---|
1104 | devPageRect = devPaperRect.adjusted(qRound(mmToInches(marginLeft / 100.0) * dpi_x),
|
---|
1105 | qRound(mmToInches(marginTop / 100.0) * dpi_y),
|
---|
1106 | - qRound(mmToInches(marginRight / 100.0) * dpi_x),
|
---|
1107 | - qRound(mmToInches(marginBottom / 100.0) * dpi_y));
|
---|
1108 | updateOrigin();
|
---|
1109 | }
|
---|
1110 |
|
---|
1111 | QRect QWin32PrintEnginePrivate::getPageMargins() const
|
---|
1112 | {
|
---|
1113 | if (pageMarginsSet)
|
---|
1114 | return previousDialogMargins;
|
---|
1115 | else
|
---|
1116 | return QRect(qRound(inchesToMM(devPhysicalPageRect.left()) * 100.0 / dpi_x),
|
---|
1117 | qRound(inchesToMM(devPhysicalPageRect.top()) * 100.0 / dpi_y),
|
---|
1118 | qRound(inchesToMM(devPaperRect.right() - devPhysicalPageRect.right()) * 100.0 / dpi_x),
|
---|
1119 | qRound(inchesToMM(devPaperRect.bottom() - devPhysicalPageRect.bottom()) * 100.0 / dpi_y));
|
---|
1120 | }
|
---|
1121 |
|
---|
1122 | void QWin32PrintEnginePrivate::release()
|
---|
1123 | {
|
---|
1124 | if (hdc == 0)
|
---|
1125 | return;
|
---|
1126 |
|
---|
1127 | if (globalDevMode) { // Devmode comes from print dialog
|
---|
1128 | GlobalUnlock(globalDevMode);
|
---|
1129 | } else { // Devmode comes from initialize...
|
---|
1130 | // devMode is a part of the same memory block as pInfo so one free is enough...
|
---|
1131 | GlobalUnlock(hMem);
|
---|
1132 | GlobalFree(hMem);
|
---|
1133 | }
|
---|
1134 | if (hPrinter)
|
---|
1135 | ClosePrinter(hPrinter);
|
---|
1136 | DeleteDC(hdc);
|
---|
1137 |
|
---|
1138 | hdc = 0;
|
---|
1139 | hPrinter = 0;
|
---|
1140 | pInfo = 0;
|
---|
1141 | hMem = 0;
|
---|
1142 | devMode = 0;
|
---|
1143 | }
|
---|
1144 |
|
---|
1145 | QList<QVariant> QWin32PrintEnginePrivate::queryResolutions() const
|
---|
1146 | {
|
---|
1147 | // Read the supported resolutions of the printer.
|
---|
1148 | QList<QVariant> list;
|
---|
1149 |
|
---|
1150 | DWORD numRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
|
---|
1151 | reinterpret_cast<const wchar_t *>(port.utf16()),
|
---|
1152 | DC_ENUMRESOLUTIONS, 0, 0);
|
---|
1153 | if (numRes == (DWORD)-1)
|
---|
1154 | return list;
|
---|
1155 |
|
---|
1156 | LONG *enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG));
|
---|
1157 | DWORD errRes = DeviceCapabilities(reinterpret_cast<const wchar_t *>(name.utf16()),
|
---|
1158 | reinterpret_cast<const wchar_t *>(port.utf16()),
|
---|
1159 | DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0);
|
---|
1160 |
|
---|
1161 | if (errRes == (DWORD)-1) {
|
---|
1162 | qErrnoWarning("QWin32PrintEngine::queryResolutions: DeviceCapabilities failed");
|
---|
1163 | return list;
|
---|
1164 | }
|
---|
1165 |
|
---|
1166 | for (uint i=0; i<numRes; ++i)
|
---|
1167 | list.append(int(enumRes[i * 2]));
|
---|
1168 |
|
---|
1169 | return list;
|
---|
1170 | }
|
---|
1171 |
|
---|
1172 | void QWin32PrintEnginePrivate::doReinit()
|
---|
1173 | {
|
---|
1174 | if (state == QPrinter::Active) {
|
---|
1175 | reinit = true;
|
---|
1176 | } else {
|
---|
1177 | resetDC();
|
---|
1178 | initDevRects();
|
---|
1179 | reinit = false;
|
---|
1180 | }
|
---|
1181 | }
|
---|
1182 |
|
---|
1183 | void QWin32PrintEnginePrivate::updateOrigin()
|
---|
1184 | {
|
---|
1185 | if (fullPage) {
|
---|
1186 | // subtract physical margins to make (0,0) absolute top corner of paper
|
---|
1187 | // then add user defined margins
|
---|
1188 | origin_x = -devPhysicalPageRect.x();
|
---|
1189 | origin_y = -devPhysicalPageRect.y();
|
---|
1190 | if (pageMarginsSet) {
|
---|
1191 | origin_x += devPageRect.left();
|
---|
1192 | origin_y += devPageRect.top();
|
---|
1193 | }
|
---|
1194 | } else {
|
---|
1195 | origin_x = 0;
|
---|
1196 | origin_y = 0;
|
---|
1197 | if (pageMarginsSet) {
|
---|
1198 | origin_x = devPageRect.left() - devPhysicalPageRect.x();
|
---|
1199 | origin_y = devPageRect.top() - devPhysicalPageRect.y();
|
---|
1200 | }
|
---|
1201 | }
|
---|
1202 | }
|
---|
1203 |
|
---|
1204 | void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &value)
|
---|
1205 | {
|
---|
1206 | Q_D(QWin32PrintEngine);
|
---|
1207 | switch (key) {
|
---|
1208 | case PPK_CollateCopies:
|
---|
1209 | {
|
---|
1210 | if (!d->devMode)
|
---|
1211 | break;
|
---|
1212 | d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE;
|
---|
1213 | d->doReinit();
|
---|
1214 | }
|
---|
1215 | break;
|
---|
1216 |
|
---|
1217 | case PPK_ColorMode:
|
---|
1218 | {
|
---|
1219 | if (!d->devMode)
|
---|
1220 | break;
|
---|
1221 | d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
|
---|
1222 | d->doReinit();
|
---|
1223 | }
|
---|
1224 | break;
|
---|
1225 |
|
---|
1226 | case PPK_Creator:
|
---|
1227 |
|
---|
1228 | break;
|
---|
1229 |
|
---|
1230 | case PPK_DocumentName:
|
---|
1231 | if (isActive()) {
|
---|
1232 | qWarning("QWin32PrintEngine: Cannot change document name while printing is active");
|
---|
1233 | return;
|
---|
1234 | }
|
---|
1235 | d->docName = value.toString();
|
---|
1236 | break;
|
---|
1237 |
|
---|
1238 | case PPK_FullPage:
|
---|
1239 | d->fullPage = value.toBool();
|
---|
1240 | d->updateOrigin();
|
---|
1241 | break;
|
---|
1242 |
|
---|
1243 | case PPK_NumberOfCopies:
|
---|
1244 | if (!d->devMode)
|
---|
1245 | break;
|
---|
1246 | d->num_copies = value.toInt();
|
---|
1247 | d->devMode->dmCopies = d->num_copies;
|
---|
1248 | d->doReinit();
|
---|
1249 | break;
|
---|
1250 |
|
---|
1251 | case PPK_Orientation:
|
---|
1252 | {
|
---|
1253 | if (!d->devMode)
|
---|
1254 | break;
|
---|
1255 | int orientation = value.toInt() == QPrinter::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
|
---|
1256 | int old_orientation = d->devMode->dmOrientation;
|
---|
1257 | d->devMode->dmOrientation = orientation;
|
---|
1258 | if (d->has_custom_paper_size && old_orientation != orientation)
|
---|
1259 | d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
|
---|
1260 | d->doReinit();
|
---|
1261 | }
|
---|
1262 | break;
|
---|
1263 |
|
---|
1264 | case PPK_OutputFileName:
|
---|
1265 | if (isActive()) {
|
---|
1266 | qWarning("QWin32PrintEngine: Cannot change filename while printing");
|
---|
1267 | } else {
|
---|
1268 | d->fileName = value.toString();
|
---|
1269 | d->printToFile = !value.toString().isEmpty();
|
---|
1270 | }
|
---|
1271 | break;
|
---|
1272 |
|
---|
1273 | case PPK_PaperSize:
|
---|
1274 | if (!d->devMode)
|
---|
1275 | break;
|
---|
1276 | d->devMode->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt()));
|
---|
1277 | d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom);
|
---|
1278 | d->doReinit();
|
---|
1279 | break;
|
---|
1280 |
|
---|
1281 | case PPK_PaperSource:
|
---|
1282 | {
|
---|
1283 | if (!d->devMode)
|
---|
1284 | break;
|
---|
1285 | int dmMapped = DMBIN_AUTO;
|
---|
1286 |
|
---|
1287 | QList<QVariant> v = property(PPK_PaperSources).toList();
|
---|
1288 | if (v.contains(value))
|
---|
1289 | dmMapped = mapPaperSourceDevmode(QPrinter::PaperSource(value.toInt()));
|
---|
1290 |
|
---|
1291 | d->devMode->dmDefaultSource = dmMapped;
|
---|
1292 | d->doReinit();
|
---|
1293 | }
|
---|
1294 | break;
|
---|
1295 |
|
---|
1296 | case PPK_PrinterName:
|
---|
1297 | d->name = value.toString();
|
---|
1298 | if(d->name.isEmpty())
|
---|
1299 | d->queryDefault();
|
---|
1300 | d->initialize();
|
---|
1301 | break;
|
---|
1302 |
|
---|
1303 | case PPK_Resolution:
|
---|
1304 | {
|
---|
1305 | d->resolution = value.toInt();
|
---|
1306 |
|
---|
1307 | d->stretch_x = d->dpi_x / double(d->resolution);
|
---|
1308 | d->stretch_y = d->dpi_y / double(d->resolution);
|
---|
1309 | }
|
---|
1310 | break;
|
---|
1311 |
|
---|
1312 | case PPK_SelectionOption:
|
---|
1313 |
|
---|
1314 | break;
|
---|
1315 |
|
---|
1316 | case PPK_SupportedResolutions:
|
---|
1317 |
|
---|
1318 | break;
|
---|
1319 |
|
---|
1320 |
|
---|
1321 | case PPK_WindowsPageSize:
|
---|
1322 | if (!d->devMode)
|
---|
1323 | break;
|
---|
1324 | d->has_custom_paper_size = false;
|
---|
1325 | d->devMode->dmPaperSize = value.toInt();
|
---|
1326 | d->doReinit();
|
---|
1327 | break;
|
---|
1328 |
|
---|
1329 | case PPK_CustomPaperSize:
|
---|
1330 | {
|
---|
1331 | d->has_custom_paper_size = true;
|
---|
1332 | d->paper_size = value.toSizeF();
|
---|
1333 | if (!d->devMode)
|
---|
1334 | break;
|
---|
1335 | int orientation = d->devMode->dmOrientation;
|
---|
1336 | DWORD needed = 0;
|
---|
1337 | DWORD returned = 0;
|
---|
1338 | if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) {
|
---|
1339 | BYTE *forms = (BYTE *) malloc(needed);
|
---|
1340 | if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) {
|
---|
1341 | for (DWORD i=0; i< returned; ++i) {
|
---|
1342 | FORM_INFO_1 *formArray = reinterpret_cast<FORM_INFO_1 *>(forms);
|
---|
1343 | // the form sizes are specified in 1000th of a mm,
|
---|
1344 | // convert the size to Points
|
---|
1345 | QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0,
|
---|
1346 | (formArray[i].Size.cy * 72/25.4)/1000.0);
|
---|
1347 | if (qAbs(d->paper_size.width() - size.width()) <= 2
|
---|
1348 | && qAbs(d->paper_size.height() - size.height()) <= 2)
|
---|
1349 | {
|
---|
1350 | d->devMode->dmPaperSize = i + 1;
|
---|
1351 | break;
|
---|
1352 | }
|
---|
1353 | }
|
---|
1354 | }
|
---|
1355 | free(forms);
|
---|
1356 | }
|
---|
1357 | if (orientation != DMORIENT_PORTRAIT)
|
---|
1358 | d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width());
|
---|
1359 | break;
|
---|
1360 | }
|
---|
1361 |
|
---|
1362 | case PPK_PageMargins:
|
---|
1363 | {
|
---|
1364 | QList<QVariant> margins(value.toList());
|
---|
1365 | Q_ASSERT(margins.size() == 4);
|
---|
1366 | int left, top, right, bottom;
|
---|
1367 | // specified in 1/100 mm
|
---|
1368 | left = (margins.at(0).toReal()*25.4/72.0) * 100;
|
---|
1369 | top = (margins.at(1).toReal()*25.4/72.0) * 100;
|
---|
1370 | right = (margins.at(2).toReal()*25.4/72.0) * 100;
|
---|
1371 | bottom = (margins.at(3).toReal()*25.4/72.0) * 100;
|
---|
1372 | d->setPageMargins(left, top, right, bottom);
|
---|
1373 | break;
|
---|
1374 | }
|
---|
1375 | default:
|
---|
1376 | // Do nothing
|
---|
1377 | break;
|
---|
1378 | }
|
---|
1379 | }
|
---|
1380 |
|
---|
1381 | QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const
|
---|
1382 | {
|
---|
1383 | Q_D(const QWin32PrintEngine);
|
---|
1384 | QVariant value;
|
---|
1385 | switch (key) {
|
---|
1386 |
|
---|
1387 | case PPK_CollateCopies:
|
---|
1388 | value = false;
|
---|
1389 | break;
|
---|
1390 |
|
---|
1391 | case PPK_ColorMode:
|
---|
1392 | {
|
---|
1393 | if (!d->devMode) {
|
---|
1394 | value = QPrinter::Color;
|
---|
1395 | } else {
|
---|
1396 | value = (d->devMode->dmColor == DMCOLOR_COLOR) ? QPrinter::Color : QPrinter::GrayScale;
|
---|
1397 | }
|
---|
1398 | }
|
---|
1399 | break;
|
---|
1400 |
|
---|
1401 | case PPK_DocumentName:
|
---|
1402 | value = d->docName;
|
---|
1403 | break;
|
---|
1404 |
|
---|
1405 | case PPK_FullPage:
|
---|
1406 | value = d->fullPage;
|
---|
1407 | break;
|
---|
1408 |
|
---|
1409 | case PPK_NumberOfCopies:
|
---|
1410 | value = 1;
|
---|
1411 | break;
|
---|
1412 |
|
---|
1413 | case PPK_Orientation:
|
---|
1414 | {
|
---|
1415 | if (!d->devMode) {
|
---|
1416 | value = QPrinter::Portrait;
|
---|
1417 | } else {
|
---|
1418 | value = (d->devMode->dmOrientation == DMORIENT_LANDSCAPE) ? QPrinter::Landscape : QPrinter::Portrait;
|
---|
1419 | }
|
---|
1420 | }
|
---|
1421 | break;
|
---|
1422 |
|
---|
1423 | case PPK_OutputFileName:
|
---|
1424 | value = d->fileName;
|
---|
1425 | break;
|
---|
1426 |
|
---|
1427 | case PPK_PageRect:
|
---|
1428 | if (d->has_custom_paper_size) {
|
---|
1429 | QRect rect(0, 0,
|
---|
1430 | qRound(d->paper_size.width() * d->resolution / 72.0),
|
---|
1431 | qRound(d->paper_size.height() * d->resolution / 72.0));
|
---|
1432 | if (d->pageMarginsSet) {
|
---|
1433 | rect = rect.adjusted(qRound(mmToInches(d->previousDialogMargins.left()/100.0) * d->resolution),
|
---|
1434 | qRound(mmToInches(d->previousDialogMargins.top()/100.0) * d->resolution),
|
---|
1435 | -qRound(mmToInches(d->previousDialogMargins.width()/100.0) * d->resolution),
|
---|
1436 | -qRound(mmToInches(d->previousDialogMargins.height()/100.0) * d->resolution));
|
---|
1437 | }
|
---|
1438 | value = rect;
|
---|
1439 | } else {
|
---|
1440 | value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0)
|
---|
1441 | .mapRect(d->fullPage ? d->devPhysicalPageRect : d->devPageRect);
|
---|
1442 | }
|
---|
1443 | break;
|
---|
1444 |
|
---|
1445 | case PPK_PaperSize:
|
---|
1446 | if (d->has_custom_paper_size) {
|
---|
1447 | value = QPrinter::Custom;
|
---|
1448 | } else {
|
---|
1449 | if (!d->devMode) {
|
---|
1450 | value = QPrinter::A4;
|
---|
1451 | } else {
|
---|
1452 | value = mapDevmodePaperSize(d->devMode->dmPaperSize);
|
---|
1453 | }
|
---|
1454 | }
|
---|
1455 | break;
|
---|
1456 |
|
---|
1457 | case PPK_PaperRect:
|
---|
1458 | if (d->has_custom_paper_size) {
|
---|
1459 | value = QRect(0, 0,
|
---|
1460 | qRound(d->paper_size.width() * d->resolution / 72.0),
|
---|
1461 | qRound(d->paper_size.height() * d->resolution / 72.0));
|
---|
1462 | } else {
|
---|
1463 | value = QTransform(1/d->stretch_x, 0, 0, 1/d->stretch_y, 0, 0).mapRect(d->devPaperRect);
|
---|
1464 | }
|
---|
1465 | break;
|
---|
1466 |
|
---|
1467 | case PPK_PaperSource:
|
---|
1468 | if (!d->devMode) {
|
---|
1469 | value = QPrinter::Auto;
|
---|
1470 | } else {
|
---|
1471 | value = mapDevmodePaperSource(d->devMode->dmDefaultSource);
|
---|
1472 | }
|
---|
1473 | break;
|
---|
1474 |
|
---|
1475 | case PPK_PrinterName:
|
---|
1476 | value = d->name;
|
---|
1477 | break;
|
---|
1478 |
|
---|
1479 | case PPK_Resolution:
|
---|
1480 | if (d->resolution || !d->name.isEmpty())
|
---|
1481 | value = d->resolution;
|
---|
1482 | break;
|
---|
1483 |
|
---|
1484 | case PPK_SupportedResolutions:
|
---|
1485 | value = d->queryResolutions();
|
---|
1486 | break;
|
---|
1487 |
|
---|
1488 | case PPK_WindowsPageSize:
|
---|
1489 | if (!d->devMode) {
|
---|
1490 | value = -1;
|
---|
1491 | } else {
|
---|
1492 | value = d->devMode->dmPaperSize;
|
---|
1493 | }
|
---|
1494 | break;
|
---|
1495 |
|
---|
1496 | case PPK_PaperSources:
|
---|
1497 | {
|
---|
1498 | int available = DeviceCapabilities((const wchar_t *)d->name.utf16(),
|
---|
1499 | (const wchar_t *)d->port.utf16(), DC_BINS, 0, d->devMode);
|
---|
1500 |
|
---|
1501 | if (available <= 0)
|
---|
1502 | break;
|
---|
1503 |
|
---|
1504 | wchar_t *data = new wchar_t[available];
|
---|
1505 | int count = DeviceCapabilities((const wchar_t *)d->name.utf16(),
|
---|
1506 | (const wchar_t *)d->port.utf16(), DC_BINS, data, d->devMode);
|
---|
1507 |
|
---|
1508 | QList<QVariant> out;
|
---|
1509 | for (int i=0; i<count; ++i) {
|
---|
1510 | QPrinter::PaperSource src = mapDevmodePaperSource(data[i]);
|
---|
1511 | if (src != -1)
|
---|
1512 | out << (int) src;
|
---|
1513 | }
|
---|
1514 | value = out;
|
---|
1515 |
|
---|
1516 | delete [] data;
|
---|
1517 | }
|
---|
1518 | break;
|
---|
1519 |
|
---|
1520 | case PPK_CustomPaperSize:
|
---|
1521 | value = d->paper_size;
|
---|
1522 | break;
|
---|
1523 |
|
---|
1524 | case PPK_PageMargins:
|
---|
1525 | {
|
---|
1526 | QList<QVariant> margins;
|
---|
1527 | QRect pageMargins(d->getPageMargins());
|
---|
1528 |
|
---|
1529 | // specified in 1/100 mm
|
---|
1530 | margins << (mmToInches(pageMargins.left()/100.0) * 72)
|
---|
1531 | << (mmToInches(pageMargins.top()/100.0) * 72)
|
---|
1532 | << (mmToInches(pageMargins.width()/100.0) * 72)
|
---|
1533 | << (mmToInches(pageMargins.height()/100.0) * 72);
|
---|
1534 | value = margins;
|
---|
1535 | break;
|
---|
1536 | }
|
---|
1537 | default:
|
---|
1538 | // Do nothing
|
---|
1539 | break;
|
---|
1540 | }
|
---|
1541 | return value;
|
---|
1542 | }
|
---|
1543 |
|
---|
1544 | QPrinter::PrinterState QWin32PrintEngine::printerState() const
|
---|
1545 | {
|
---|
1546 | return d_func()->state;
|
---|
1547 | }
|
---|
1548 |
|
---|
1549 | HDC QWin32PrintEngine::getDC() const
|
---|
1550 | {
|
---|
1551 | return d_func()->hdc;
|
---|
1552 | }
|
---|
1553 |
|
---|
1554 | void QWin32PrintEngine::releaseDC(HDC) const
|
---|
1555 | {
|
---|
1556 |
|
---|
1557 | }
|
---|
1558 |
|
---|
1559 | HGLOBAL *QWin32PrintEnginePrivate::createDevNames()
|
---|
1560 | {
|
---|
1561 | int size = sizeof(DEVNAMES)
|
---|
1562 | + program.length() * 2 + 2
|
---|
1563 | + name.length() * 2 + 2
|
---|
1564 | + port.length() * 2 + 2;
|
---|
1565 | HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size);
|
---|
1566 | DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal);
|
---|
1567 |
|
---|
1568 | dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
|
---|
1569 | dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1;
|
---|
1570 | dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1;
|
---|
1571 |
|
---|
1572 | memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2);
|
---|
1573 | memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2);
|
---|
1574 | memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2);
|
---|
1575 | dn->wDefault = 0;
|
---|
1576 |
|
---|
1577 | GlobalUnlock(hGlobal);
|
---|
1578 |
|
---|
1579 | // printf("QPrintDialogWinPrivate::createDevNames()\n"
|
---|
1580 | // " -> wDriverOffset: %d\n"
|
---|
1581 | // " -> wDeviceOffset: %d\n"
|
---|
1582 | // " -> wOutputOffset: %d\n",
|
---|
1583 | // dn->wDriverOffset,
|
---|
1584 | // dn->wDeviceOffset,
|
---|
1585 | // dn->wOutputOffset);
|
---|
1586 |
|
---|
1587 | // printf("QPrintDialogWinPrivate::createDevNames(): %s, %s, %s\n",
|
---|
1588 | // QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset).latin1(),
|
---|
1589 | // QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset).latin1(),
|
---|
1590 | // QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset).latin1());
|
---|
1591 |
|
---|
1592 | return hGlobal;
|
---|
1593 | }
|
---|
1594 |
|
---|
1595 | void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames)
|
---|
1596 | {
|
---|
1597 | if (globalDevnames) {
|
---|
1598 | DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames);
|
---|
1599 | name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset);
|
---|
1600 | port = QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset);
|
---|
1601 | program = QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset);
|
---|
1602 | GlobalUnlock(globalDevnames);
|
---|
1603 | }
|
---|
1604 | }
|
---|
1605 |
|
---|
1606 | void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode)
|
---|
1607 | {
|
---|
1608 | if (globalDevmode) {
|
---|
1609 | DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode);
|
---|
1610 | release();
|
---|
1611 | globalDevMode = globalDevmode;
|
---|
1612 | devMode = dm;
|
---|
1613 | hdc = CreateDC(reinterpret_cast<const wchar_t *>(program.utf16()),
|
---|
1614 | reinterpret_cast<const wchar_t *>(name.utf16()), 0, dm);
|
---|
1615 |
|
---|
1616 | num_copies = devMode->dmCopies;
|
---|
1617 | if (!OpenPrinter((wchar_t*)name.utf16(), &hPrinter, 0))
|
---|
1618 | qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE.");
|
---|
1619 | }
|
---|
1620 |
|
---|
1621 | if (hdc)
|
---|
1622 | initHDC();
|
---|
1623 | }
|
---|
1624 |
|
---|
1625 | static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc,
|
---|
1626 | bool convertToText, const QTransform &xform, const QPointF &topLeft)
|
---|
1627 | {
|
---|
1628 | QFontEngine *fe = ti.fontEngine;
|
---|
1629 | QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft);
|
---|
1630 |
|
---|
1631 | SetTextAlign(hdc, TA_BASELINE);
|
---|
1632 | SetBkMode(hdc, TRANSPARENT);
|
---|
1633 |
|
---|
1634 | bool has_kerning = ti.f && ti.f->kerning();
|
---|
1635 | QFontEngineWin *winfe = (fe->type() == QFontEngine::Win) ? static_cast<QFontEngineWin *>(fe) : 0;
|
---|
1636 |
|
---|
1637 | HFONT hfont;
|
---|
1638 | bool ttf = false;
|
---|
1639 |
|
---|
1640 | if (winfe) {
|
---|
1641 | hfont = winfe->hfont;
|
---|
1642 | ttf = winfe->ttf;
|
---|
1643 | } else {
|
---|
1644 | hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
---|
1645 | }
|
---|
1646 |
|
---|
1647 | HGDIOBJ old_font = SelectObject(hdc, hfont);
|
---|
1648 | unsigned int options = (ttf && !convertToText) ? ETO_GLYPH_INDEX : 0;
|
---|
1649 | wchar_t *convertedGlyphs = (wchar_t *)ti.chars;
|
---|
1650 | QGlyphLayout glyphs = ti.glyphs;
|
---|
1651 |
|
---|
1652 | bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
|
---|
1653 | for (int i = 0; fast && i < glyphs.numGlyphs; i++) {
|
---|
1654 | if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0
|
---|
1655 | || glyphs.attributes[i].dontPrint) {
|
---|
1656 | fast = false;
|
---|
1657 | break;
|
---|
1658 | }
|
---|
1659 | }
|
---|
1660 |
|
---|
1661 | #if !defined(Q_OS_WINCE)
|
---|
1662 | // Scale, rotate and translate here.
|
---|
1663 | XFORM win_xform;
|
---|
1664 | win_xform.eM11 = xform.m11();
|
---|
1665 | win_xform.eM12 = xform.m12();
|
---|
1666 | win_xform.eM21 = xform.m21();
|
---|
1667 | win_xform.eM22 = xform.m22();
|
---|
1668 | win_xform.eDx = xform.dx();
|
---|
1669 | win_xform.eDy = xform.dy();
|
---|
1670 |
|
---|
1671 | SetGraphicsMode(hdc, GM_ADVANCED);
|
---|
1672 | SetWorldTransform(hdc, &win_xform);
|
---|
1673 | #endif
|
---|
1674 |
|
---|
1675 | if (fast) {
|
---|
1676 | // fast path
|
---|
1677 | QVarLengthArray<wchar_t> g(glyphs.numGlyphs);
|
---|
1678 | for (int i = 0; i < glyphs.numGlyphs; ++i)
|
---|
1679 | g[i] = glyphs.glyphs[i];
|
---|
1680 | ExtTextOut(hdc,
|
---|
1681 | qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
|
---|
1682 | qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
|
---|
1683 | options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0);
|
---|
1684 | } else {
|
---|
1685 | QVarLengthArray<QFixedPoint> positions;
|
---|
1686 | QVarLengthArray<glyph_t> _glyphs;
|
---|
1687 |
|
---|
1688 | QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y());
|
---|
1689 | ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags,
|
---|
1690 | _glyphs, positions);
|
---|
1691 | if (_glyphs.size() == 0) {
|
---|
1692 | SelectObject(hdc, old_font);
|
---|
1693 | return;
|
---|
1694 | }
|
---|
1695 |
|
---|
1696 | convertToText = convertToText && glyphs.numGlyphs == _glyphs.size();
|
---|
1697 | bool outputEntireItem = _glyphs.size() > 0;
|
---|
1698 |
|
---|
1699 | if (outputEntireItem) {
|
---|
1700 | options |= ETO_PDY;
|
---|
1701 | QVarLengthArray<INT> glyphDistances(_glyphs.size() * 2);
|
---|
1702 | QVarLengthArray<wchar_t> g(_glyphs.size());
|
---|
1703 | for (int i=0; i<_glyphs.size() - 1; ++i) {
|
---|
1704 | glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x);
|
---|
1705 | glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y);
|
---|
1706 | g[i] = _glyphs[i];
|
---|
1707 | }
|
---|
1708 | glyphDistances[(_glyphs.size() - 1) * 2] = 0;
|
---|
1709 | glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
|
---|
1710 | g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
|
---|
1711 | ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
|
---|
1712 | convertToText ? convertedGlyphs : g.data(), _glyphs.size(),
|
---|
1713 | glyphDistances.data());
|
---|
1714 | } else {
|
---|
1715 | int i = 0;
|
---|
1716 | while(i < _glyphs.size()) {
|
---|
1717 | wchar_t g = _glyphs[i];
|
---|
1718 |
|
---|
1719 | ExtTextOut(hdc, qRound(positions[i].x),
|
---|
1720 | qRound(positions[i].y), options, 0,
|
---|
1721 | convertToText ? convertedGlyphs + i : &g, 1, 0);
|
---|
1722 | ++i;
|
---|
1723 | }
|
---|
1724 | }
|
---|
1725 | }
|
---|
1726 |
|
---|
1727 | #if !defined(Q_OS_WINCE)
|
---|
1728 | win_xform.eM11 = win_xform.eM22 = 1.0;
|
---|
1729 | win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0;
|
---|
1730 | SetWorldTransform(hdc, &win_xform);
|
---|
1731 | #endif
|
---|
1732 |
|
---|
1733 | SelectObject(hdc, old_font);
|
---|
1734 | }
|
---|
1735 |
|
---|
1736 |
|
---|
1737 | void QWin32PrintEnginePrivate::updateCustomPaperSize()
|
---|
1738 | {
|
---|
1739 | uint paperSize = devMode->dmPaperSize;
|
---|
1740 | if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) {
|
---|
1741 | has_custom_paper_size = true;
|
---|
1742 | DWORD needed = 0;
|
---|
1743 | DWORD returned = 0;
|
---|
1744 | if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) {
|
---|
1745 | BYTE *forms = (BYTE *) malloc(needed);
|
---|
1746 | if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) {
|
---|
1747 | if (paperSize <= returned) {
|
---|
1748 | FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms;
|
---|
1749 | int width = formArray[paperSize - 1].Size.cx; // 1/1000 of a mm
|
---|
1750 | int height = formArray[paperSize - 1].Size.cy; // 1/1000 of a mm
|
---|
1751 | paper_size = QSizeF((width * 72 /25.4) / 1000.0, (height * 72 / 25.4) / 1000.0);
|
---|
1752 | } else {
|
---|
1753 | has_custom_paper_size = false;
|
---|
1754 | }
|
---|
1755 | }
|
---|
1756 | free(forms);
|
---|
1757 | }
|
---|
1758 | } else {
|
---|
1759 | has_custom_paper_size = false;
|
---|
1760 | }
|
---|
1761 | }
|
---|
1762 |
|
---|
1763 | QT_END_NAMESPACE
|
---|
1764 |
|
---|
1765 | #endif // QT_NO_PRINTER
|
---|