| 1 | /****************************************************************************
|
|---|
| 2 | **
|
|---|
| 3 | ** Copyright (C) 2009 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
|
|---|