Rev 22557 | Rev 23064 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4430 | cbradney | 1 | /* |
2 | For general Scribus (>=1.3.2) copyright and licensing information please refer |
||
3 | to the COPYING file provided with the program. Following this notice may exist |
||
4 | a copyright and/or license notice that predates the release of Scribus 1.3.2 |
||
5 | for which a new license (GPL+exception) is in place. |
||
6 | */ |
||
4360 | cbradney | 7 | #ifdef WIN32_LEAN_AND_MEAN |
8 | #undef WIN32_LEAN_AND_MEAN |
||
9 | #endif |
||
10 | |||
11 | #ifndef _WIN32 |
||
12 | #error "This file compiles on win32 platform only!" |
||
13 | #endif |
||
14 | |||
15 | #include <memory> |
||
16 | #include <valarray> |
||
17 | #include <windows.h> |
||
9535 | fschmid | 18 | #include <QByteArray> |
21488 | jghali | 19 | #include <QScopedPointer> |
4360 | cbradney | 20 | using namespace ::std; |
21 | |||
5659 | jghali | 22 | #include "scconfig.h" |
23 | |||
24 | #ifdef HAVE_ICM |
||
4360 | cbradney | 25 | #include <icm.h> |
5659 | jghali | 26 | #endif |
27 | |||
16731 | jghali | 28 | |
29 | #include "commonstrings.h" |
||
30 | #include "prefscontext.h" |
||
31 | #include "prefsfile.h" |
||
32 | #include "prefsmanager.h" |
||
16736 | jghali | 33 | #include "pslib.h" |
16731 | jghali | 34 | #include "scpage.h" |
4360 | cbradney | 35 | #include "scpageoutput.h" |
16731 | jghali | 36 | #include "scpaths.h" |
16736 | jghali | 37 | #include "scpainterex_cairo.h" |
38 | #include "scprintengine_gdi.h" |
||
39 | #include "scribus.h" |
||
4360 | cbradney | 40 | #include "scribusapp.h" |
5248 | mrdocs | 41 | #include "scribuscore.h" |
16736 | jghali | 42 | #include "scribusview.h" |
16731 | jghali | 43 | #include "util.h" |
44 | #include "util_ghostscript.h" |
||
13552 | cbradney | 45 | #include "ui/customfdialog.h" |
46 | #include "ui/multiprogressdialog.h" |
||
4360 | cbradney | 47 | |
11881 | jghali | 48 | #include <cairo.h> |
49 | #include <cairo-win32.h> |
||
50 | |||
4360 | cbradney | 51 | // Calculates fixed point from floating point. |
52 | #define __FXPTMANTISSA(d, f) ( (DWORD)d << f ) |
||
53 | #define __FXPTFRACTION(d, f) ( (DWORD)ldexp((d - (DWORD)d), f) ) |
||
54 | #define __FXPT32(d, f) ( __FXPTMANTISSA(d, f) | __FXPTFRACTION(d, f) ) |
||
55 | #define __FXPT2DOT30(d) __FXPT32(d, 30) |
||
56 | #define __FXPT16DOT16(d) __FXPT32(d, 16) |
||
57 | |||
58 | // Convenient structure for performing postscript passthrough |
||
59 | typedef struct |
||
60 | { |
||
61 | WORD numBytes; |
||
62 | BYTE data[32768]; |
||
63 | } sPSPassthrough; |
||
64 | |||
10967 | jghali | 65 | ScPrintEngine_GDI::ScPrintEngine_GDI(void) : ScPrintEngine() |
4360 | cbradney | 66 | { |
11045 | jghali | 67 | m_abort = false; |
68 | m_forceGDI = false; |
||
4360 | cbradney | 69 | } |
70 | |||
10967 | jghali | 71 | void ScPrintEngine_GDI::setForceGDI(bool force) |
4360 | cbradney | 72 | { |
10967 | jghali | 73 | m_forceGDI = force; |
74 | } |
||
75 | |||
76 | void ScPrintEngine_GDI::resetData(void) |
||
77 | { |
||
4360 | cbradney | 78 | m_abort = false; |
11033 | jghali | 79 | //m_forceGDI = false; |
4360 | cbradney | 80 | } |
81 | |||
20447 | jghali | 82 | bool ScPrintEngine_GDI::print(ScribusDoc& doc, PrintOptions& options) |
4360 | cbradney | 83 | { |
84 | bool toFile; |
||
85 | bool success; |
||
86 | HDC printerDC; |
||
87 | QString diaSelection, docDir, prefsDocDir; |
||
10304 | jghali | 88 | QString printerName = options.printer; |
10967 | jghali | 89 | QByteArray devMode = options.devMode; |
10304 | jghali | 90 | QString fileName; |
4360 | cbradney | 91 | |
20447 | jghali | 92 | if (options.toFile) |
4360 | cbradney | 93 | return false; |
94 | resetData(); |
||
95 | |||
20447 | jghali | 96 | toFile = printerUseFilePort(options.printer); |
97 | if (toFile) |
||
4360 | cbradney | 98 | { |
22833 | jghali | 99 | QString docName = doc.documentFileName(); |
100 | diaSelection = docName.right(docName.length() - docName.lastIndexOf("/") - 1); |
||
20447 | jghali | 101 | diaSelection = diaSelection.left(diaSelection.indexOf(".")); |
4360 | cbradney | 102 | diaSelection += ".prn"; |
103 | PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs"); |
||
104 | QString prefsDocDir = PrefsManager::instance()->documentDir(); |
||
105 | if (!prefsDocDir.isEmpty()) |
||
106 | docDir = dirs->get("winprn", prefsDocDir); |
||
107 | else |
||
108 | docDir = "."; |
||
20447 | jghali | 109 | CustomFDialog dia(doc.scMW()->view, docDir, QObject::tr("Save As"), "Spool Files (*.prn *.ps);;All Files (*)", fdNone); |
110 | dia.setSelection(diaSelection); |
||
4360 | cbradney | 111 | if (dia.exec() == QDialog::Accepted) |
112 | { |
||
113 | QString selectedFile = dia.selectedFile(); |
||
20447 | jghali | 114 | if (overwrite(doc.scMW()->view, selectedFile)) |
4360 | cbradney | 115 | { |
10427 | cbradney | 116 | dirs->set("winprn", selectedFile.left(selectedFile.lastIndexOf("/"))); |
20447 | jghali | 117 | fileName = QDir::toNativeSeparators(selectedFile); |
4360 | cbradney | 118 | } |
119 | } |
||
120 | else |
||
121 | return true; |
||
122 | } |
||
123 | |||
124 | // Set user options in the DEVmode structure |
||
20447 | jghali | 125 | setDeviceParams(&doc, options, (DEVMODEW*) devMode.data()); |
4360 | cbradney | 126 | |
127 | // Create the device context |
||
22519 | craig | 128 | printerDC = CreateDCW(nullptr, (LPCWSTR) printerName.utf16(), nullptr, (DEVMODEW*) devMode.data()); |
20447 | jghali | 129 | if (printerDC) |
4360 | cbradney | 130 | { |
20447 | jghali | 131 | success = printPages(&doc, options, printerDC, (DEVMODEW*) devMode.data(), fileName); |
132 | DeleteDC(printerDC); |
||
4360 | cbradney | 133 | } |
134 | else |
||
135 | { |
||
136 | qWarning("doPrintPages : the device context could not be created"); |
||
137 | success = false; |
||
138 | } |
||
139 | |||
140 | return success; |
||
141 | } |
||
142 | |||
20447 | jghali | 143 | bool ScPrintEngine_GDI::gdiPrintPreview(ScribusDoc* doc, ScPage* page, QImage* image, PrintOptions& options, double scale) |
4360 | cbradney | 144 | { |
145 | bool success = true; |
||
22519 | craig | 146 | HCOLORSPACE hColorSpace = nullptr; |
4360 | cbradney | 147 | int imagew, imageh; |
148 | double scalex = 1, scaley = 1; |
||
149 | bool rotate = false; |
||
150 | |||
20447 | jghali | 151 | if (!doc || !page || !image) |
4360 | cbradney | 152 | return false; |
153 | resetData(); |
||
154 | |||
155 | // Get page position |
||
156 | int clipx = static_cast<int>(page->xOffset()); |
||
157 | int clipy = static_cast<int>(page->yOffset()); |
||
158 | int clipw = qRound(page->width()); |
||
159 | int cliph = qRound(page->height()); |
||
160 | |||
161 | // Setup image |
||
162 | imagew = clipw * scale; |
||
163 | imageh = cliph * scale; |
||
20447 | jghali | 164 | *image = QImage(imagew, imageh, QImage::Format_ARGB32_Premultiplied); |
10723 | jghali | 165 | if (image->width() <= 0 || image->height() <= 0) |
4360 | cbradney | 166 | return false; |
167 | |||
168 | // Calculate scaling factors and offsets |
||
169 | scalex = options.mirrorH ? -1.0 : 1.0; |
||
170 | scaley = options.mirrorV ? -1.0 : 1.0; |
||
171 | double dx = - clipx * scalex; |
||
172 | double dy = - clipy * scaley; |
||
20447 | jghali | 173 | if (options.mirrorH) dx += clipw; |
174 | if (options.mirrorV) dy += cliph; |
||
11033 | jghali | 175 | |
176 | // Create the GDI painters |
||
11945 | jghali | 177 | ScPageOutput pageOutput(doc, false); |
20447 | jghali | 178 | QRect drawRect(0, 0, imagew, imageh); |
4360 | cbradney | 179 | |
11945 | jghali | 180 | cairo_surface_t* surface = cairo_image_surface_create_for_data(image->bits(), CAIRO_FORMAT_ARGB32, imagew, imageh, imagew*4); |
181 | if (!surface) |
||
182 | return false; |
||
183 | cairo_t* context = cairo_create(surface); |
||
184 | if (!context) |
||
11033 | jghali | 185 | { |
11945 | jghali | 186 | cairo_surface_destroy(surface); |
187 | return false; |
||
11033 | jghali | 188 | } |
20447 | jghali | 189 | ScPainterEx_Cairo painter(context, drawRect, doc, !options.useColor); |
11033 | jghali | 190 | |
4360 | cbradney | 191 | scalex *= scale; |
192 | scaley *= scale; |
||
193 | dx *= scale; |
||
194 | dy *= scale; |
||
195 | |||
196 | // Set the world transformation matrix |
||
20447 | jghali | 197 | QTransform matrix(scalex, 0.0, 0.0, scaley, dx, dy); |
198 | painter.setWorldMatrix(matrix); |
||
4360 | cbradney | 199 | |
20447 | jghali | 200 | image->fill(qRgba(255, 255, 255, 255)); |
11945 | jghali | 201 | pageOutput.drawPage(page, &painter); |
4360 | cbradney | 202 | |
203 | return success; |
||
204 | } |
||
205 | |||
20447 | jghali | 206 | bool ScPrintEngine_GDI::printPages(ScribusDoc* doc, PrintOptions& options, HDC printerDC, DEVMODEW* devMode, QString& fileName) |
4360 | cbradney | 207 | { |
11881 | jghali | 208 | int jobId; |
21488 | jghali | 209 | QScopedPointer<MultiProgressDialog> progress; |
22519 | craig | 210 | PrintPageFunc printPageFunc = nullptr; |
11881 | jghali | 211 | bool success = true; |
212 | WCHAR docName[512]; |
||
213 | DOCINFOW docInfo; |
||
16731 | jghali | 214 | ScPage* docPage; |
4360 | cbradney | 215 | |
216 | // Test printer for PostScript support and |
||
217 | // choose appropriate page printing function |
||
20447 | jghali | 218 | bool psPrint = isPostscriptPrinter(printerDC); |
10967 | jghali | 219 | bool useGDI = (!psPrint || m_forceGDI || (options.prnEngine == WindowsGDI)); |
11881 | jghali | 220 | printPageFunc = (useGDI) ? &ScPrintEngine_GDI::printPage_GDI : &ScPrintEngine_GDI::printPage_PS; |
4360 | cbradney | 221 | |
222 | // Setup document infos structure |
||
22833 | jghali | 223 | wcsncpy (docName, (const WCHAR*) doc->documentFileName().utf16(), 511); |
20447 | jghali | 224 | ZeroMemory(&docInfo, sizeof(docInfo)); |
4360 | cbradney | 225 | docInfo.cbSize = sizeof(docInfo); |
226 | docInfo.lpszDocName = docName; |
||
22519 | craig | 227 | docInfo.lpszOutput = (LPCWSTR) (fileName.length() > 0 ? fileName.utf16() : nullptr); |
228 | docInfo.lpszDatatype = nullptr; |
||
4360 | cbradney | 229 | docInfo.fwType = 0; |
230 | |||
22519 | craig | 231 | cairo_surface_t* prnSurface = nullptr; |
232 | cairo_t* context = nullptr; |
||
11945 | jghali | 233 | if (printPageFunc == &ScPrintEngine_GDI::printPage_GDI) |
11881 | jghali | 234 | { |
20447 | jghali | 235 | prnSurface = cairo_win32_printing_surface_create(printerDC); |
11881 | jghali | 236 | if (!prnSurface) |
237 | return false; |
||
238 | context = cairo_create(prnSurface); |
||
239 | if (!context) |
||
240 | { |
||
20447 | jghali | 241 | cairo_surface_destroy(prnSurface); |
11881 | jghali | 242 | return false; |
243 | } |
||
244 | } |
||
11985 | jghali | 245 | else if ((printPageFunc == &ScPrintEngine_GDI::printPage_PS) && options.outputSeparations) |
246 | printPageFunc = &ScPrintEngine_GDI::printPage_PS_Sep; |
||
11881 | jghali | 247 | |
20447 | jghali | 248 | jobId = StartDocW(printerDC, &docInfo); |
249 | if (jobId <= 0) |
||
4360 | cbradney | 250 | { |
20447 | jghali | 251 | AbortDoc(printerDC) ; |
4360 | cbradney | 252 | return false; |
253 | } |
||
254 | |||
5248 | mrdocs | 255 | bool usingGui = ScCore->usingGUI(); |
20447 | jghali | 256 | if (usingGui) |
4360 | cbradney | 257 | { |
20447 | jghali | 258 | progress.reset(new MultiProgressDialog(QObject::tr("Printing..."), CommonStrings::tr_Cancel, doc->scMW())); |
259 | progress->setOverallTotalSteps(options.pageNumbers.size()); |
||
4360 | cbradney | 260 | progress->setOverallProgress(0); |
21488 | jghali | 261 | connect(progress.data(), SIGNAL(canceled()), this, SLOT(cancelRequested())); |
4360 | cbradney | 262 | progress->show(); |
263 | } |
||
264 | |||
20447 | jghali | 265 | for (uint index = 0; index < options.pageNumbers.size(); index++) |
4360 | cbradney | 266 | { |
20447 | jghali | 267 | if (usingGui) |
4360 | cbradney | 268 | progress->setOverallProgress(index); |
20447 | jghali | 269 | docPage = doc->Pages->at(options.pageNumbers[index] - 1); |
270 | success = (this->*printPageFunc)(doc, docPage, options, printerDC, context); |
||
4360 | cbradney | 271 | ScQApp->processEvents(); |
20447 | jghali | 272 | if (!success || m_abort) |
4360 | cbradney | 273 | break; |
20447 | jghali | 274 | if (usingGui) |
4360 | cbradney | 275 | progress->setOverallProgress(index + 1); |
276 | } |
||
277 | |||
20447 | jghali | 278 | if (usingGui) |
4360 | cbradney | 279 | progress->close(); |
280 | |||
20447 | jghali | 281 | if (m_abort) |
282 | AbortDoc(printerDC) ; |
||
283 | EndDoc(printerDC); |
||
4360 | cbradney | 284 | |
20447 | jghali | 285 | cairo_destroy(context); |
286 | cairo_surface_destroy(prnSurface); |
||
11881 | jghali | 287 | |
4360 | cbradney | 288 | return success; |
289 | } |
||
290 | |||
20447 | jghali | 291 | bool ScPrintEngine_GDI::printPage_GDI(ScribusDoc* doc, ScPage* page, PrintOptions& options, HDC printerDC, cairo_t* context) |
4360 | cbradney | 292 | { |
293 | int logPixelsX; |
||
294 | int logPixelsY; |
||
295 | int physicalWidth; |
||
296 | int physicalHeight; |
||
297 | int physicalWidthP; |
||
298 | int physicalHeightP; |
||
299 | int physicalOffsetX; |
||
300 | int physicalOffsetY; |
||
301 | bool success = true; |
||
10304 | jghali | 302 | QString inputProfile; |
303 | QString printerProfile; |
||
22519 | craig | 304 | HCOLORSPACE hColorSpace = nullptr; |
4360 | cbradney | 305 | double scalex = 1, scaley = 1; |
306 | bool rotate = false; |
||
307 | |||
20447 | jghali | 308 | StartPage(printerDC); |
4360 | cbradney | 309 | |
5659 | jghali | 310 | #ifdef HAVE_ICM |
20447 | jghali | 311 | if (isPostscriptPrinter(printerDC)) |
4360 | cbradney | 312 | { |
313 | success = false; |
||
15005 | jghali | 314 | QString mProf = doc->prefsData().colorPrefs.DCMSset.DefaultSolidColorRGBProfile; |
315 | QString pProf = doc->prefsData().colorPrefs.DCMSset.DefaultPrinterProfile; |
||
20447 | jghali | 316 | if (ScCore->MonitorProfiles.contains(mProf) && ScCore->PrinterProfiles.contains(pProf)) |
4360 | cbradney | 317 | { |
16577 | craig | 318 | inputProfile = QDir::toNativeSeparators(ScCore->InputProfiles[mProf]); |
319 | printerProfile = QDir::toNativeSeparators(ScCore->PrinterProfiles[pProf]); |
||
4360 | cbradney | 320 | // Avoid color transform if input and output profile are the same |
20447 | jghali | 321 | if (inputProfile != printerProfile) |
4360 | cbradney | 322 | { |
323 | // Setup input color space |
||
10304 | jghali | 324 | LOGCOLORSPACEW logColorSpace; |
4360 | cbradney | 325 | logColorSpace.lcsSize = sizeof(logColorSpace); |
326 | logColorSpace.lcsVersion = 0x400; |
||
327 | logColorSpace.lcsSignature = LCS_SIGNATURE; |
||
328 | logColorSpace.lcsCSType = LCS_CALIBRATED_RGB; |
||
329 | logColorSpace.lcsIntent = LCS_GM_GRAPHICS; |
||
10304 | jghali | 330 | wcsncpy(logColorSpace.lcsFilename, (const wchar_t*) inputProfile.utf16(), MAX_PATH); |
4360 | cbradney | 331 | // MSDN recommend to setup reasonable values even if profile is specified |
332 | // so let's use sRGB colorspace values |
||
333 | logColorSpace.lcsEndpoints.ciexyzRed.ciexyzX = __FXPT2DOT30(0.64); |
||
334 | logColorSpace.lcsEndpoints.ciexyzRed.ciexyzY = __FXPT2DOT30(0.33); |
||
335 | logColorSpace.lcsEndpoints.ciexyzRed.ciexyzZ = __FXPT2DOT30(0.03); |
||
336 | logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzX = __FXPT2DOT30(0.3); |
||
337 | logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzY = __FXPT2DOT30(0.6); |
||
338 | logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzZ = __FXPT2DOT30(0.1); |
||
339 | logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzX = __FXPT2DOT30(0.15); |
||
340 | logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzY = __FXPT2DOT30(0.06); |
||
341 | logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzZ = __FXPT2DOT30(0.79); |
||
342 | logColorSpace.lcsGammaRed = __FXPT16DOT16(0.45); |
||
343 | logColorSpace.lcsGammaGreen = __FXPT16DOT16(0.45); |
||
344 | logColorSpace.lcsGammaBlue = __FXPT16DOT16(0.45); |
||
345 | // Create the color space handle |
||
20447 | jghali | 346 | hColorSpace = CreateColorSpaceW(&logColorSpace); |
347 | if (hColorSpace) |
||
4360 | cbradney | 348 | { |
349 | // Setup the input and output profiles for the device context |
||
20447 | jghali | 350 | if (SetColorSpace(printerDC, hColorSpace) && SetICMProfileW(printerDC, (LPWSTR) printerProfile.utf16())) |
4360 | cbradney | 351 | { |
20447 | jghali | 352 | int result = SetICMMode(printerDC, ICM_ON); |
353 | success = (result != 0); |
||
4360 | cbradney | 354 | } |
355 | } |
||
356 | } |
||
357 | else |
||
358 | success = true; |
||
359 | } |
||
360 | // Return if color managament could not be setup |
||
20447 | jghali | 361 | if (!success) |
4360 | cbradney | 362 | { |
20447 | jghali | 363 | EndPage(printerDC); |
364 | if (hColorSpace) |
||
365 | DeleteColorSpace(hColorSpace); |
||
4360 | cbradney | 366 | return false; |
367 | } |
||
368 | } |
||
5659 | jghali | 369 | #endif |
4360 | cbradney | 370 | |
371 | // Get page position |
||
372 | int clipx = static_cast<int>(page->xOffset()); |
||
373 | int clipy = static_cast<int>(page->yOffset()); |
||
374 | int clipw = qRound(page->width()); |
||
375 | int cliph = qRound(page->height()); |
||
376 | |||
377 | // Get horizontal and vertical resolution of printer |
||
20447 | jghali | 378 | logPixelsX = GetDeviceCaps(printerDC, LOGPIXELSX); |
379 | logPixelsY = GetDeviceCaps(printerDC, LOGPIXELSY); |
||
4360 | cbradney | 380 | |
20447 | jghali | 381 | // Get paper dimensions (in pixels and points) |
382 | physicalWidth = GetDeviceCaps(printerDC, PHYSICALWIDTH); |
||
383 | physicalHeight = GetDeviceCaps(printerDC, PHYSICALHEIGHT); |
||
11945 | jghali | 384 | physicalWidthP = physicalWidth / (double) logPixelsX * 72.0; |
4360 | cbradney | 385 | physicalHeightP = physicalHeight / (double) logPixelsY * 72.0; |
386 | |||
387 | // Get margins dimensions |
||
20447 | jghali | 388 | physicalOffsetX = GetDeviceCaps(printerDC, PHYSICALOFFSETX); |
389 | physicalOffsetY = GetDeviceCaps(printerDC, PHYSICALOFFSETY); |
||
4360 | cbradney | 390 | |
391 | // Calculate scaling factors and offsets |
||
392 | scalex = options.mirrorH ? -1.0 : 1.0; |
||
393 | scaley = options.mirrorV ? -1.0 : 1.0; |
||
20447 | jghali | 394 | double dx = (physicalWidthP - clipw) / 2.0 - clipx * scalex; |
395 | double dy = (physicalHeightP - cliph) / 2.0 - clipy * scaley; |
||
396 | if (options.mirrorH) dx += clipw; |
||
397 | if (options.mirrorV) dy += cliph; |
||
398 | dx -= (physicalOffsetX / (double) logPixelsX * 72.0); |
||
399 | dy -= (physicalOffsetY / (double) logPixelsY * 72.0); |
||
4360 | cbradney | 400 | |
401 | // Create the GDI painter |
||
7108 | jghali | 402 | MarksOptions marksOptions(options); |
20363 | jghali | 403 | ScPageOutput pageOutput(doc, true, 300, true); |
11945 | jghali | 404 | pageOutput.setMarksOptions(marksOptions); |
4360 | cbradney | 405 | |
20447 | jghali | 406 | QRect drawRect(0, 0, physicalWidth, physicalHeight); |
407 | ScPainterEx_Cairo painter(context, drawRect, doc, !options.useColor); |
||
11945 | jghali | 408 | painter.clear(); |
409 | |||
20447 | jghali | 410 | scalex *= (logPixelsX / 72.0); |
411 | scaley *= (logPixelsY / 72.0); |
||
412 | dx *= (logPixelsX / 72.0); |
||
413 | dy *= (logPixelsY / 72.0); |
||
414 | QTransform matrix(scalex, 0.0, 0.0, scaley, dx, dy); |
||
415 | painter.setWorldMatrix(matrix); |
||
4360 | cbradney | 416 | |
11945 | jghali | 417 | pageOutput.drawPage(page, &painter); |
4360 | cbradney | 418 | |
11945 | jghali | 419 | cairo_show_page(context); |
20447 | jghali | 420 | EndPage(printerDC); |
4360 | cbradney | 421 | |
422 | if (hColorSpace) |
||
20447 | jghali | 423 | DeleteColorSpace(hColorSpace); |
4360 | cbradney | 424 | |
425 | return success; |
||
426 | } |
||
427 | |||
20447 | jghali | 428 | bool ScPrintEngine_GDI::printPage_PS(ScribusDoc* doc, ScPage* page, PrintOptions& options, HDC printerDC, cairo_t* /*context*/) |
4360 | cbradney | 429 | { |
430 | bool succeed = false; |
||
431 | ColorList usedColors; |
||
6992 | jghali | 432 | PrintOptions options2 = options; |
5389 | cbradney | 433 | QMap<QString, QMap<uint, FPointArray> > usedFonts; |
4360 | cbradney | 434 | QString tempFilePath; |
435 | int ret = 0; |
||
436 | |||
5389 | cbradney | 437 | doc->getUsedFonts(usedFonts); |
4360 | cbradney | 438 | doc->getUsedColors(usedColors); |
6992 | jghali | 439 | options2.pageNumbers.clear(); |
20447 | jghali | 440 | options2.pageNumbers.push_back(page->pageNr() + 1); |
4360 | cbradney | 441 | |
442 | tempFilePath = PrefsManager::instance()->preferencesLocation() + "/tmp.ps"; |
||
20447 | jghali | 443 | PSLib *dd = new PSLib(options2, false, PrefsManager::instance()->appPrefs.fontPrefs.AvailFonts, usedFonts, usedColors, false, options2.useSpotColors); |
444 | dd->PS_set_file(tempFilePath); |
||
445 | ret = dd->CreatePS(doc, options2); |
||
4360 | cbradney | 446 | delete dd; |
11060 | jghali | 447 | if (ret != 0) return false; |
4360 | cbradney | 448 | |
20447 | jghali | 449 | if (options.prnEngine == PostScript1 || options.prnEngine == PostScript2) |
4360 | cbradney | 450 | { |
451 | QString tmp; |
||
452 | QStringList opts; |
||
453 | QString tempFilePath2 = PrefsManager::instance()->preferencesLocation() + "/tmp2.ps"; |
||
20447 | jghali | 454 | opts.append( QString("-dDEVICEWIDTHPOINTS=%1").arg(tmp.setNum(doc->pageWidth()))); |
455 | opts.append( QString("-dDEVICEHEIGHTPOINTS=%1").arg(tmp.setNum(doc->pageHeight()))); |
||
456 | if (QFile::exists(tempFilePath2)) |
||
457 | QFile::remove(tempFilePath2); |
||
10947 | jghali | 458 | ret = convertPS2PS(tempFilePath, tempFilePath2, opts, options.prnEngine); |
20447 | jghali | 459 | if (ret == 0) |
4360 | cbradney | 460 | { |
20447 | jghali | 461 | QFile::remove(tempFilePath); |
4360 | cbradney | 462 | tempFilePath = tempFilePath2; |
463 | } |
||
464 | else |
||
465 | { |
||
20447 | jghali | 466 | QFile::remove(tempFilePath2); |
4360 | cbradney | 467 | } |
468 | } |
||
469 | |||
20447 | jghali | 470 | if (ret == 0) |
4360 | cbradney | 471 | { |
19837 | jghali | 472 | double bleedH = options.bleeds.left() + options.bleeds.right(); |
473 | double bleedV = options.bleeds.top() + options.bleeds.bottom(); |
||
20447 | jghali | 474 | StartPage(printerDC); |
475 | succeed = sendPSFile(tempFilePath, printerDC, page->width() + bleedH, page->height() + bleedV, (page->orientation() == 1)); |
||
476 | EndPage(printerDC); |
||
4360 | cbradney | 477 | } |
478 | |||
20447 | jghali | 479 | QFile::remove(tempFilePath); |
4360 | cbradney | 480 | return succeed; |
481 | } |
||
482 | |||
20447 | jghali | 483 | bool ScPrintEngine_GDI::printPage_PS_Sep(ScribusDoc* doc, ScPage* page, PrintOptions& options, HDC printerDC, cairo_t* context) |
11985 | jghali | 484 | { |
485 | bool succeed = true; |
||
486 | QStringList separations; |
||
22557 | jghali | 487 | if (options.separationName != "All") |
20447 | jghali | 488 | separations.append(options.separationName); |
11985 | jghali | 489 | else |
490 | separations += options.allSeparations; |
||
491 | for (int i = 0; i < separations.count(); ++i) |
||
492 | { |
||
493 | PrintOptions tempOptions = options; |
||
494 | tempOptions.separationName = separations.at(i); |
||
495 | succeed &= printPage_PS(doc, page, tempOptions, printerDC, context); |
||
496 | if (!succeed) break; |
||
497 | } |
||
498 | return succeed; |
||
499 | } |
||
500 | |||
20447 | jghali | 501 | bool ScPrintEngine_GDI::sendPSFile(QString filePath, HDC printerDC, int pageWidth, int pageHeight, bool landscape) |
4360 | cbradney | 502 | { |
503 | int escape; |
||
504 | int logPixelsX; |
||
505 | int logPixelsY; |
||
506 | int physicalWidth; |
||
507 | int physicalHeight; |
||
508 | bool done = true; |
||
509 | sPSPassthrough sps; |
||
510 | double transx, transy; |
||
511 | double scalex, scaley; |
||
20447 | jghali | 512 | QFile file(filePath); |
4360 | cbradney | 513 | int fileSize = 0; |
514 | int br, bw; |
||
515 | |||
516 | if (!printerDC) |
||
517 | return false; |
||
20447 | jghali | 518 | escape = getPSPassthroughSupport(printerDC); |
4360 | cbradney | 519 | if (!escape) |
520 | return false; |
||
521 | |||
522 | // Get printer resolution |
||
523 | logPixelsX = GetDeviceCaps(printerDC, LOGPIXELSX); |
||
524 | logPixelsY = GetDeviceCaps(printerDC, LOGPIXELSY); |
||
525 | |||
20447 | jghali | 526 | // Get paper dimensions (in point units) |
527 | physicalWidth = GetDeviceCaps(printerDC, PHYSICALWIDTH) / (double) logPixelsX * 72.0; |
||
528 | physicalHeight = GetDeviceCaps(printerDC, PHYSICALHEIGHT) / (double) logPixelsY * 72.0; |
||
4360 | cbradney | 529 | |
530 | // Calculate and set scaling factor |
||
531 | scalex = logPixelsX / 72.0; |
||
532 | scaley = -logPixelsY / 72.0; |
||
20447 | jghali | 533 | sprintf((char*) sps.data, "%0.3f %0.3f scale\n", scalex, scaley); |
534 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 535 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
4360 | cbradney | 536 | return false; |
537 | |||
4751 | cbradney | 538 | // Set some necessary stuff for embedding ps into ps |
539 | QString eBegin = "/b4_Inc_state save def\n"; |
||
540 | eBegin += "/dict_count countdictstack def\n"; |
||
541 | eBegin += "/op_count count 1 sub def\n"; |
||
542 | eBegin += "userdict begin\n"; |
||
543 | eBegin += "/showpage { } def\n"; |
||
544 | eBegin += "0 setgray 0 setlinecap\n"; |
||
545 | eBegin += "1 setlinewidth 0 setlinejoin\n"; |
||
546 | eBegin += "10 setmiterlimit [ ] 0 setdash newpath\n"; |
||
547 | eBegin += "/languagelevel where\n"; |
||
548 | eBegin += "{pop languagelevel\n"; |
||
549 | eBegin += "1 ne\n"; |
||
550 | eBegin += "{false setstrokeadjust false setoverprint\n"; |
||
551 | eBegin += "} if } if\n"; |
||
20447 | jghali | 552 | sprintf((char*) sps.data, "%s", eBegin.toLatin1().data()); |
553 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 554 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
4751 | cbradney | 555 | return false; |
556 | |||
15005 | jghali | 557 | // Match Postscript and GDI coordinate system |
20447 | jghali | 558 | sprintf((char*) sps.data, "0 %0.3f neg translate\n", (double) physicalHeight); |
559 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 560 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
15005 | jghali | 561 | return false; |
562 | |||
563 | // In case of landscape printing, pslib will rotate the page |
||
564 | // we must take that into account |
||
15550 | jghali | 565 | /*if (landscape) |
15005 | jghali | 566 | { |
20447 | jghali | 567 | sprintf((char*) sps.data, "-90 rotate %0.3f %0.3f translate\n", (double) -pageHeight, 0.0); |
568 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 569 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
15005 | jghali | 570 | return false; |
20447 | jghali | 571 | transx = (physicalHeight - pageHeight) / -2.0; |
572 | transy = (physicalWidth - pageWidth) / 2.0; |
||
15005 | jghali | 573 | } |
15550 | jghali | 574 | else*/ |
15005 | jghali | 575 | { |
20447 | jghali | 576 | transx = (physicalWidth - pageWidth) / 2.0; |
577 | transy = (physicalHeight - pageHeight) / 2.0; |
||
15005 | jghali | 578 | } |
579 | |||
4360 | cbradney | 580 | // Center the printed page in paper zone |
20447 | jghali | 581 | sprintf((char*) sps.data, "%0.3f %0.3f translate\n", transx, transy); |
582 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 583 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
4360 | cbradney | 584 | return false; |
585 | |||
20447 | jghali | 586 | sprintf((char*) sps.data, "%s: %s\n", "%%BeginDocument", file.fileName().toLocal8Bit().data()); |
587 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 588 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
11945 | jghali | 589 | return false; |
590 | |||
20447 | jghali | 591 | if (!file.open(QIODevice::ReadOnly)) |
4360 | cbradney | 592 | return false; |
593 | fileSize = file.size(); |
||
594 | bw = 0; // bytes written |
||
20447 | jghali | 595 | br = file.read((char*) sps.data, sizeof(sps.data)); |
596 | while (br > 0) |
||
4360 | cbradney | 597 | { |
598 | sps.numBytes = br; |
||
22519 | craig | 599 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
4360 | cbradney | 600 | break; |
11945 | jghali | 601 | bw += br; |
20447 | jghali | 602 | br = file.read((char*) sps.data, sizeof(sps.data)); |
4360 | cbradney | 603 | } |
604 | file.close(); |
||
605 | |||
20447 | jghali | 606 | sprintf((char*) sps.data, "%s", "\n%%EndDocument\n"); |
607 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 608 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
11945 | jghali | 609 | return false; |
610 | |||
4751 | cbradney | 611 | // Set some necessary stuff for embedding ps into ps |
612 | QString eEnd = "count op_count sub {pop} repeat\n"; |
||
613 | eEnd += "countdictstack dict_count sub {end} repeat\n"; |
||
614 | eEnd += "b4_Inc_state restore\n"; |
||
20447 | jghali | 615 | sprintf((char*) sps.data, "%s", eEnd.toLatin1().data()); |
616 | sps.numBytes = strlen((char*) sps.data); |
||
22519 | craig | 617 | if (ExtEscape(printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, nullptr) <= 0) |
4751 | cbradney | 618 | return false; |
619 | |||
20447 | jghali | 620 | return ((fileSize == bw) && (br >= 0)); |
4360 | cbradney | 621 | } |
622 | |||
20447 | jghali | 623 | void ScPrintEngine_GDI::setDeviceParams(ScribusDoc* doc, PrintOptions& options, DEVMODEW* devMode) |
4360 | cbradney | 624 | { |
625 | HANDLE handle; |
||
10304 | jghali | 626 | QString printer = options.printer; |
4360 | cbradney | 627 | |
628 | short nCopies = options.copies; |
||
20556 | jghali | 629 | devMode->dmCopies = nCopies; |
630 | devMode->dmFields |= DM_COPIES; |
||
4360 | cbradney | 631 | |
632 | bool greyscale = !options.useColor; |
||
20447 | jghali | 633 | if (greyscale) |
4360 | cbradney | 634 | { |
635 | devMode->dmDitherType = DMDITHER_GRAYSCALE; |
||
20556 | jghali | 636 | devMode->dmFields |= DM_DITHERTYPE; |
4360 | cbradney | 637 | } |
638 | |||
22519 | craig | 639 | OpenPrinterW((LPWSTR) printer.utf16(), &handle, nullptr); |
20447 | jghali | 640 | DocumentPropertiesW((HWND) doc->scMW()->winId(), handle, (LPWSTR) printer.utf16(), devMode, devMode, DM_IN_BUFFER | DM_OUT_BUFFER); |
641 | ClosePrinter(handle); |
||
4360 | cbradney | 642 | } |
643 | |||
20447 | jghali | 644 | QString ScPrintEngine_GDI::getDefaultPrinter(void) |
4360 | cbradney | 645 | { |
646 | QString defPrinter; |
||
647 | OSVERSIONINFO osvi; |
||
648 | DWORD returned, buffSize; |
||
10304 | jghali | 649 | WCHAR szPrinter[512] = { 0 }; |
650 | WCHAR* p; |
||
4360 | cbradney | 651 | |
10304 | jghali | 652 | buffSize = 512; |
4360 | cbradney | 653 | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
654 | GetVersionEx(&osvi); |
||
655 | |||
20447 | jghali | 656 | if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5) // Win2k and later |
4360 | cbradney | 657 | { |
20447 | jghali | 658 | if (GetDefaultPrinterW(szPrinter, &buffSize)) |
10304 | jghali | 659 | defPrinter = QString::fromUtf16((const ushort*) szPrinter); |
4360 | cbradney | 660 | } |
20447 | jghali | 661 | else if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion < 5) // NT4 or earlier |
4360 | cbradney | 662 | { |
20447 | jghali | 663 | if (GetProfileStringW(L"windows",L"device",L"", szPrinter, buffSize) < (buffSize - 1)) |
4360 | cbradney | 664 | { |
665 | p = szPrinter; |
||
666 | while (*p != 0 && *p != ',') |
||
667 | ++p; |
||
668 | *p = 0; |
||
10304 | jghali | 669 | defPrinter = QString::fromUtf16((const ushort*) szPrinter); |
4360 | cbradney | 670 | } |
671 | } |
||
672 | else |
||
673 | { |
||
674 | DWORD numPrinters; |
||
22519 | craig | 675 | PRINTER_INFO_2W* printerInfos = nullptr; |
676 | EnumPrintersW (PRINTER_ENUM_DEFAULT, nullptr, 2, nullptr, 0, &buffSize, &numPrinters); |
||
10304 | jghali | 677 | printerInfos = (PRINTER_INFO_2W*) malloc(buffSize); |
22519 | craig | 678 | if (EnumPrintersW (PRINTER_ENUM_LOCAL, nullptr, 2, (LPBYTE) printerInfos, buffSize, &buffSize, &returned)) |
4360 | cbradney | 679 | { |
20447 | jghali | 680 | if (returned > 0) |
4360 | cbradney | 681 | { |
10304 | jghali | 682 | defPrinter = QString::fromUtf16((const ushort*) printerInfos->pPrinterName); |
4360 | cbradney | 683 | } |
684 | } |
||
20447 | jghali | 685 | if (printerInfos) free(printerInfos); |
4360 | cbradney | 686 | } |
687 | return defPrinter; |
||
688 | } |
||
689 | |||
20447 | jghali | 690 | bool ScPrintEngine_GDI::isPostscriptPrinter(HDC dc) |
4360 | cbradney | 691 | { |
692 | int escapeCode; |
||
693 | char technology[MAX_PATH] = {0}; |
||
694 | |||
695 | if (!dc) |
||
696 | return false; |
||
697 | |||
698 | // Test printer support for the POSTSCRIPT_PASSTHROUGH escape (available since win2k) |
||
699 | escapeCode = POSTSCRIPT_PASSTHROUGH; |
||
22519 | craig | 700 | if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR) &escapeCode, 0, nullptr) > 0) |
4360 | cbradney | 701 | return true; |
702 | // Test printer support for the POSTSCRIPT_DATA escape (available since win95) |
||
703 | escapeCode = POSTSCRIPT_DATA; |
||
22519 | craig | 704 | if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR) &escapeCode, 0, nullptr) > 0) |
4360 | cbradney | 705 | return true; |
706 | // Test the printer technology |
||
707 | escapeCode = GETTECHNOLOGY; |
||
22519 | craig | 708 | if (ExtEscape(dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR) &escapeCode, 0, nullptr) > 0) |
4360 | cbradney | 709 | { |
710 | // If GETTECHNOLOGY is supported, then ... get technology |
||
22519 | craig | 711 | if (ExtEscape(dc, GETTECHNOLOGY, 0, nullptr, MAX_PATH, (LPSTR) technology) > 0) |
4360 | cbradney | 712 | { |
713 | // Check technology string for postscript word |
||
20447 | jghali | 714 | strupr(technology); |
715 | if (strstr(technology, "POSTSCRIPT")) |
||
4360 | cbradney | 716 | return true; |
717 | } |
||
718 | } |
||
719 | return false; |
||
720 | } |
||
721 | |||
20447 | jghali | 722 | int ScPrintEngine_GDI::getPSPassthroughSupport(HDC printerDC) |
4360 | cbradney | 723 | { |
724 | int escapeCode; |
||
725 | char technology[MAX_PATH] = {0}; |
||
726 | if (!printerDC) |
||
727 | return 0; |
||
728 | // Test printer support for the POSTSCRIPT_PASSTHROUGH escape (available since win2k) |
||
729 | escapeCode = POSTSCRIPT_PASSTHROUGH; |
||
22519 | craig | 730 | if (ExtEscape(printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR) &escapeCode, 0, nullptr) > 0) |
4360 | cbradney | 731 | return POSTSCRIPT_PASSTHROUGH; |
732 | // Test printer support for the POSTSCRIPT_DATA escape (available since win95) |
||
733 | escapeCode = POSTSCRIPT_DATA; |
||
22519 | craig | 734 | if (ExtEscape(printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR) &escapeCode, 0, nullptr) > 0) |
4360 | cbradney | 735 | return POSTSCRIPT_DATA; |
736 | // Test printer support for the PASSTHROUGH escape |
||
737 | escapeCode = PASSTHROUGH; |
||
22519 | craig | 738 | if (ExtEscape(printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR) &escapeCode, 0, nullptr) > 0) |
4360 | cbradney | 739 | return PASSTHROUGH; |
740 | return 0; |
||
741 | } |
||
742 | |||
20447 | jghali | 743 | bool ScPrintEngine_GDI::printerUseFilePort(QString& printerName) |
4360 | cbradney | 744 | { |
745 | bool done; |
||
746 | bool toFile = false; |
||
747 | HANDLE prnHandle; |
||
748 | DWORD size = 0; |
||
749 | |||
22519 | craig | 750 | done = OpenPrinterW((LPWSTR) printerName.utf16(), &prnHandle, nullptr); |
20447 | jghali | 751 | if (!done) |
4360 | cbradney | 752 | return false; |
753 | |||
754 | // Get buffer size for the PRINTER_INFO_2 structure |
||
22519 | craig | 755 | GetPrinterW(prnHandle, 2, nullptr, 0, &size); |
20447 | jghali | 756 | if (size > 0) |
4360 | cbradney | 757 | { |
10304 | jghali | 758 | PRINTER_INFO_2W* pInfos = (PRINTER_INFO_2W*) malloc(size); |
20447 | jghali | 759 | if (pInfos) |
4360 | cbradney | 760 | { |
761 | // Get printer informations |
||
20447 | jghali | 762 | done = GetPrinterW(prnHandle, 2, (LPBYTE) pInfos, size, &size); |
763 | if (done) |
||
4360 | cbradney | 764 | { |
765 | // Get printer port |
||
10304 | jghali | 766 | WCHAR* pPortName = pInfos->pPortName; |
20447 | jghali | 767 | if (wcsstr(pPortName, L"FILE:")) |
4360 | cbradney | 768 | toFile = true; |
769 | } |
||
770 | free(pInfos); |
||
771 | } |
||
772 | } |
||
773 | |||
20447 | jghali | 774 | ClosePrinter(prnHandle); |
4360 | cbradney | 775 | return toFile; |
776 | } |