Subversion Repositories Scribus

Rev

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
}