| 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
|
|---|