diff options
| author | craig <craig@11d20701-8431-0410-a711-e3c959e3b870> | 2012-01-01 11:40:09 +0000 |
|---|---|---|
| committer | craig <craig@11d20701-8431-0410-a711-e3c959e3b870> | 2012-01-01 11:40:09 +0000 |
| commit | 7ed83b6c6666eb8b6b104c211ae7e52907350372 (patch) | |
| tree | 4430b556abac0ad660a0aacf1887d77f85d8be02 /scribus/scprintengine_gdi.cpp | |
| download | scribus-7ed83b6c6666eb8b6b104c211ae7e52907350372.tar.gz scribus-7ed83b6c6666eb8b6b104c211ae7e52907350372.tar.xz scribus-7ed83b6c6666eb8b6b104c211ae7e52907350372.zip | |
Branch 1.3.5 tree to 1.4.x tree, goodbye 1.3.x
git-svn-id: svn://scribus.net/branches/Version14x/Scribus@17163 11d20701-8431-0410-a711-e3c959e3b870
Diffstat (limited to 'scribus/scprintengine_gdi.cpp')
| -rw-r--r-- | scribus/scprintengine_gdi.cpp | 779 |
1 files changed, 779 insertions, 0 deletions
diff --git a/scribus/scprintengine_gdi.cpp b/scribus/scprintengine_gdi.cpp new file mode 100644 index 0000000..5db9a19 --- /dev/null +++ b/scribus/scprintengine_gdi.cpp @@ -0,0 +1,779 @@ +/* +For general Scribus (>=1.3.2) copyright and licensing information please refer +to the COPYING file provided with the program. Following this notice may exist +a copyright and/or license notice that predates the release of Scribus 1.3.2 +for which a new license (GPL+exception) is in place. +*/ +#ifdef WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#endif + +#ifndef _WIN32 +#error "This file compiles on win32 platform only!" +#endif + +#include <algorithm> +#include <memory> +#include <valarray> +#include <windows.h> +#include <QByteArray> +using namespace ::std; + +#include "scconfig.h" + +#ifdef HAVE_ICM +#include <icm.h> +#endif + +#include "util.h" +#include "util_ghostscript.h" +#include "scprintengine_gdi.h" +#include "scpainterex_cairo.h" + +#include "scpageoutput.h" +#include "scribusview.h" +#include "scribusapp.h" +#include "scribuscore.h" +#include "scribus.h" +#include "page.h" + +#include "prefsfile.h" +#include "prefscontext.h" +#include "prefsmanager.h" +#include "customfdialog.h" +#include "commonstrings.h" +#include "multiprogressdialog.h" +#include "scpaths.h" +#include "pslib.h" + +#include <cairo.h> +#include <cairo-win32.h> + +// Calculates fixed point from floating point. +#define __FXPTMANTISSA(d, f) ( (DWORD)d << f ) +#define __FXPTFRACTION(d, f) ( (DWORD)ldexp((d - (DWORD)d), f) ) +#define __FXPT32(d, f) ( __FXPTMANTISSA(d, f) | __FXPTFRACTION(d, f) ) +#define __FXPT2DOT30(d) __FXPT32(d, 30) +#define __FXPT16DOT16(d) __FXPT32(d, 16) + +// Convenient structure for performing postscript passthrough +typedef struct +{ + WORD numBytes; + BYTE data[32768]; +} sPSPassthrough; + +ScPrintEngine_GDI::ScPrintEngine_GDI(void) : ScPrintEngine() +{ + m_abort = false; + m_forceGDI = false; +} + +void ScPrintEngine_GDI::setForceGDI(bool force) +{ + m_forceGDI = force; +} + +void ScPrintEngine_GDI::resetData(void) +{ + m_abort = false; + //m_forceGDI = false; +} + +bool ScPrintEngine_GDI::print( ScribusDoc& doc, PrintOptions& options ) +{ + bool toFile; + bool success; + HDC printerDC; + QString diaSelection, docDir, prefsDocDir; + QString printerName = options.printer; + QByteArray devMode = options.devMode; + QString fileName; + + if( options.toFile ) + return false; + resetData(); + + toFile = printerUseFilePort( options.printer ); + if ( toFile ) + { + diaSelection = doc.DocName.right( doc.DocName.length() - doc.DocName.lastIndexOf("/") - 1 ); + diaSelection = diaSelection.left( diaSelection.indexOf(".") ); + diaSelection += ".prn"; + PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs"); + QString prefsDocDir = PrefsManager::instance()->documentDir(); + if (!prefsDocDir.isEmpty()) + docDir = dirs->get("winprn", prefsDocDir); + else + docDir = "."; + CustomFDialog dia( doc.scMW()->view, docDir, QObject::tr("Save As"), "Spool Files (*.prn *.ps);;All Files (*)", fdNone); + dia.setSelection( diaSelection ); + if (dia.exec() == QDialog::Accepted) + { + QString selectedFile = dia.selectedFile(); + if ( overwrite(doc.scMW()->view, selectedFile) ) + { + dirs->set("winprn", selectedFile.left(selectedFile.lastIndexOf("/"))); + fileName = QDir::toNativeSeparators( selectedFile ); + } + } + else + return true; + } + + // Set user options in the DEVmode structure + setDeviceParams( &doc, options, (DEVMODEW*) devMode.data() ); + + // Create the device context + printerDC = CreateDCW( NULL, (LPCWSTR) printerName.utf16(), NULL, (DEVMODEW*) devMode.data() ); + if( printerDC ) + { + success = printPages( &doc, options, printerDC, (DEVMODEW*) devMode.data(), fileName); + DeleteDC( printerDC ); + } + else + { + qWarning("doPrintPages : the device context could not be created"); + success = false; + } + + return success; +} + +bool ScPrintEngine_GDI::gdiPrintPreview( ScribusDoc* doc, Page* page, QImage* image, PrintOptions& options, double scale ) +{ + bool success = true; + HCOLORSPACE hColorSpace = NULL; + int imagew, imageh; + double scalex = 1, scaley = 1; + bool rotate = false; + + if ( !doc || !page || !image) + return false; + resetData(); + + // Get page position + int clipx = static_cast<int>(page->xOffset()); + int clipy = static_cast<int>(page->yOffset()); + int clipw = qRound(page->width()); + int cliph = qRound(page->height()); + + // Setup image + imagew = clipw * scale; + imageh = cliph * scale; + *image = QImage( imagew, imageh, QImage::Format_ARGB32 ); + if (image->width() <= 0 || image->height() <= 0) + return false; + + // Calculate scaling factors and offsets + scalex = options.mirrorH ? -1.0 : 1.0; + scaley = options.mirrorV ? -1.0 : 1.0; + double dx = - clipx * scalex; + double dy = - clipy * scaley; + if ( options.mirrorH ) dx += clipw; + if ( options.mirrorV ) dy += cliph; + + // Create the GDI painters + ScPageOutput pageOutput(doc, false); + QRect drawRect( 0, 0, imagew, imageh ); + + cairo_surface_t* surface = cairo_image_surface_create_for_data(image->bits(), CAIRO_FORMAT_ARGB32, imagew, imageh, imagew*4); + if (!surface) + return false; + cairo_t* context = cairo_create(surface); + if (!context) + { + cairo_surface_destroy(surface); + return false; + } + ScPainterEx_Cairo painter( context, drawRect, doc, !options.useColor ); + + scalex *= scale; + scaley *= scale; + dx *= scale; + dy *= scale; + + // Set the world transformation matrix + QMatrix matrix( scalex, 0.0, 0.0, scaley, dx, dy ); + painter.setWorldMatrix( matrix ); + + image->fill( qRgba(255, 255, 255, 255) ); + pageOutput.drawPage(page, &painter); + + return success; +} + +bool ScPrintEngine_GDI::printPages( ScribusDoc* doc, PrintOptions& options, HDC printerDC, DEVMODEW* devMode, QString& fileName ) +{ + int jobId; + auto_ptr<MultiProgressDialog> progress; + PrintPageFunc printPageFunc = NULL; + bool success = true; + WCHAR docName[512]; + DOCINFOW docInfo; + Page* docPage; + + // Test printer for PostScript support and + // choose appropriate page printing function + bool psPrint = isPostscriptPrinter( printerDC ); + bool useGDI = (!psPrint || m_forceGDI || (options.prnEngine == WindowsGDI)); + printPageFunc = (useGDI) ? &ScPrintEngine_GDI::printPage_GDI : &ScPrintEngine_GDI::printPage_PS; + + // Setup document infos structure + wcsncpy (docName, (const WCHAR*) doc->DocName.utf16(), 511); + ZeroMemory( &docInfo, sizeof(docInfo) ); + docInfo.cbSize = sizeof(docInfo); + docInfo.lpszDocName = docName; + docInfo.lpszOutput = (LPCWSTR) ( fileName.length() > 0 ? fileName.utf16() : NULL ); + docInfo.lpszDatatype = NULL; + docInfo.fwType = 0; + + cairo_surface_t* prnSurface = NULL; + cairo_t* context = NULL; + if (printPageFunc == &ScPrintEngine_GDI::printPage_GDI) + { + prnSurface = cairo_win32_printing_surface_create( printerDC ); + if (!prnSurface) + return false; + context = cairo_create(prnSurface); + if (!context) + { + cairo_surface_destroy( prnSurface ); + return false; + } + } + else if ((printPageFunc == &ScPrintEngine_GDI::printPage_PS) && options.outputSeparations) + printPageFunc = &ScPrintEngine_GDI::printPage_PS_Sep; + + jobId = StartDocW( printerDC, &docInfo ); + if ( jobId <= 0 ) + { + AbortDoc( printerDC ) ; + return false; + } + + bool usingGui = ScCore->usingGUI(); + if ( usingGui ) + { + progress.reset( new MultiProgressDialog( QObject::tr("Printing..."), CommonStrings::tr_Cancel, doc->scMW()) ); + progress->setOverallTotalSteps( options.pageNumbers.size() ); + progress->setOverallProgress(0); + connect(progress.get(), SIGNAL(canceled()), this, SLOT(cancelRequested())); + progress->show(); + } + + for ( uint index = 0; index < options.pageNumbers.size(); index++ ) + { + if( usingGui ) + progress->setOverallProgress(index); + docPage = doc->Pages->at( options.pageNumbers[index] - 1 ); + success = (this->*printPageFunc)( doc, docPage, options, printerDC, context ); + ScQApp->processEvents(); + if (!success || m_abort ) + break; + if ( usingGui ) + progress->setOverallProgress(index + 1); + } + + if ( usingGui ) + progress->close(); + + if( m_abort ) + AbortDoc( printerDC ) ; + EndDoc( printerDC ); + + cairo_destroy( context ); + cairo_surface_destroy( prnSurface ); + + return success; +} + +bool ScPrintEngine_GDI::printPage_GDI ( ScribusDoc* doc, Page* page, PrintOptions& options, HDC printerDC, cairo_t* context ) +{ + int logPixelsX; + int logPixelsY; + int physicalWidth; + int physicalHeight; + int physicalWidthP; + int physicalHeightP; + int physicalOffsetX; + int physicalOffsetY; + bool success = true; + QString inputProfile; + QString printerProfile; + HCOLORSPACE hColorSpace = NULL; + double scalex = 1, scaley = 1; + bool rotate = false; + + StartPage( printerDC ); + +#ifdef HAVE_ICM + if ( options.useICC && isPostscriptPrinter(printerDC) ) + { + success = false; + QString mProf = doc->CMSSettings.DefaultSolidColorRGBProfile; + QString pProf = doc->CMSSettings.DefaultPrinterProfile; + if ( ScCore->MonitorProfiles.contains(mProf) && ScCore->PrinterProfiles.contains(pProf) ) + { + inputProfile = QDir::toNativeSeparators(ScCore->InputProfiles[mProf]); + printerProfile = QDir::toNativeSeparators(ScCore->PrinterProfiles[pProf]); + // Avoid color transform if input and output profile are the same + if ( inputProfile != printerProfile ) + { + // Setup input color space + LOGCOLORSPACEW logColorSpace; + logColorSpace.lcsSize = sizeof(logColorSpace); + logColorSpace.lcsVersion = 0x400; + logColorSpace.lcsSignature = LCS_SIGNATURE; + logColorSpace.lcsCSType = LCS_CALIBRATED_RGB; + logColorSpace.lcsIntent = LCS_GM_GRAPHICS; + wcsncpy(logColorSpace.lcsFilename, (const wchar_t*) inputProfile.utf16(), MAX_PATH); + // MSDN recommend to setup reasonable values even if profile is specified + // so let's use sRGB colorspace values + logColorSpace.lcsEndpoints.ciexyzRed.ciexyzX = __FXPT2DOT30(0.64); + logColorSpace.lcsEndpoints.ciexyzRed.ciexyzY = __FXPT2DOT30(0.33); + logColorSpace.lcsEndpoints.ciexyzRed.ciexyzZ = __FXPT2DOT30(0.03); + logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzX = __FXPT2DOT30(0.3); + logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzY = __FXPT2DOT30(0.6); + logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzZ = __FXPT2DOT30(0.1); + logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzX = __FXPT2DOT30(0.15); + logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzY = __FXPT2DOT30(0.06); + logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzZ = __FXPT2DOT30(0.79); + logColorSpace.lcsGammaRed = __FXPT16DOT16(0.45); + logColorSpace.lcsGammaGreen = __FXPT16DOT16(0.45); + logColorSpace.lcsGammaBlue = __FXPT16DOT16(0.45); + // Create the color space handle + hColorSpace = CreateColorSpaceW( &logColorSpace ); + if ( hColorSpace ) + { + // Setup the input and output profiles for the device context + if ( SetColorSpace(printerDC, hColorSpace) && SetICMProfileW(printerDC, (LPWSTR) printerProfile.utf16()) ) + { + int result = SetICMMode( printerDC, ICM_ON ); + success = ( result != 0 ); + } + } + } + else + success = true; + } + // Return if color managament could not be setup + if ( !success ) + { + EndPage( printerDC ); + if ( hColorSpace ) + DeleteColorSpace( hColorSpace ); + return false; + } + } +#endif + + // Get page position + int clipx = static_cast<int>(page->xOffset()); + int clipy = static_cast<int>(page->yOffset()); + int clipw = qRound(page->width()); + int cliph = qRound(page->height()); + + // Get horizontal and vertical resolution of printer + logPixelsX = GetDeviceCaps( printerDC, LOGPIXELSX ); + logPixelsY = GetDeviceCaps( printerDC, LOGPIXELSY ); + + // Get paper dimensions ( in pixels and points) + physicalWidth = GetDeviceCaps( printerDC, PHYSICALWIDTH ); + physicalHeight = GetDeviceCaps( printerDC, PHYSICALHEIGHT ); + physicalWidthP = physicalWidth / (double) logPixelsX * 72.0; + physicalHeightP = physicalHeight / (double) logPixelsY * 72.0; + + // Get margins dimensions + physicalOffsetX = GetDeviceCaps( printerDC, PHYSICALOFFSETX ); + physicalOffsetY = GetDeviceCaps( printerDC, PHYSICALOFFSETY ); + + // Calculate scaling factors and offsets + scalex = options.mirrorH ? -1.0 : 1.0; + scaley = options.mirrorV ? -1.0 : 1.0; + double dx = ( physicalWidthP - clipw ) / 2.0 - clipx * scalex; + double dy = ( physicalHeightP - cliph ) / 2.0 - clipy * scaley; + if ( options.mirrorH ) dx += clipw; + if ( options.mirrorV ) dy += cliph; + dx -= ( physicalOffsetX / (double) logPixelsX * 72.0 ); + dy -= ( physicalOffsetY / (double) logPixelsY * 72.0 ); + + // Create the GDI painter + MarksOptions marksOptions(options); + ScPageOutput pageOutput(doc, true, 300, options.useICC); + pageOutput.setMarksOptions(marksOptions); + + QRect drawRect( 0, 0, physicalWidth, physicalHeight); + ScPainterEx_Cairo painter(context, drawRect, doc, !options.useColor ); + painter.clear(); + + scalex *= ( logPixelsX / 72.0 ); + scaley *= ( logPixelsY / 72.0 ); + dx *= ( logPixelsX / 72.0 ); + dy *= ( logPixelsY / 72.0 ); + QMatrix matrix( scalex, 0.0, 0.0, scaley, dx, dy ); + painter.setWorldMatrix( matrix ); + + pageOutput.drawPage(page, &painter); + + cairo_show_page(context); + EndPage( printerDC ); + + if (hColorSpace) + DeleteColorSpace( hColorSpace ); + + return success; +} + +bool ScPrintEngine_GDI::printPage_PS ( ScribusDoc* doc, Page* page, PrintOptions& options, HDC printerDC, cairo_t* /*context*/ ) +{ + bool succeed = false; + ColorList usedColors; + PrintOptions options2 = options; + QMap<QString, QMap<uint, FPointArray> > usedFonts; + QString tempFilePath; + int ret = 0; + + doc->getUsedFonts(usedFonts); + doc->getUsedColors(usedColors); + options2.pageNumbers.clear(); + options2.pageNumbers.push_back(page->pageNr() + 1 ); + + tempFilePath = PrefsManager::instance()->preferencesLocation() + "/tmp.ps"; + PSLib *dd = new PSLib(options2, false, PrefsManager::instance()->appPrefs.AvailFonts, usedFonts, usedColors, false, options2.useSpotColors ); + dd->PS_set_file( tempFilePath ); + ret = dd->CreatePS( doc, options2); + delete dd; + if (ret != 0) return false; + + if ( options.prnEngine == PostScript1 || options.prnEngine == PostScript2 ) + { + QString tmp; + QStringList opts; + QString tempFilePath2 = PrefsManager::instance()->preferencesLocation() + "/tmp2.ps"; + opts.append( QString("-dDEVICEWIDTHPOINTS=%1").arg(tmp.setNum(doc->pageWidth)) ); + opts.append( QString("-dDEVICEHEIGHTPOINTS=%1").arg(tmp.setNum(doc->pageHeight)) ); + if ( QFile::exists( tempFilePath2 ) ) + QFile::remove( tempFilePath2 ); + ret = convertPS2PS(tempFilePath, tempFilePath2, opts, options.prnEngine); + if ( ret == 0 ) + { + QFile::remove( tempFilePath ); + tempFilePath = tempFilePath2; + } + else + { + QFile::remove( tempFilePath2 ); + } + } + + if( ret == 0 ) + { + double bleedH = options.bleeds.Left + options.bleeds.Right; + double bleedV = options.bleeds.Top + options.bleeds.Bottom; + StartPage( printerDC ); + succeed = sendPSFile( tempFilePath, printerDC, page->width() + bleedH, page->height() + bleedV, (page->PageOri == 1)); + EndPage( printerDC ); + } + + QFile::remove( tempFilePath ); + return succeed; +} + +bool ScPrintEngine_GDI::printPage_PS_Sep( ScribusDoc* doc, Page* page, PrintOptions& options, HDC printerDC, cairo_t* context ) +{ + bool succeed = true; + QStringList separations; + if (options.separationName != QObject::tr("All")) + separations.append( options.separationName ); + else + separations += options.allSeparations; + for (int i = 0; i < separations.count(); ++i) + { + PrintOptions tempOptions = options; + tempOptions.separationName = separations.at(i); + succeed &= printPage_PS(doc, page, tempOptions, printerDC, context); + if (!succeed) break; + } + return succeed; +} + +bool ScPrintEngine_GDI::sendPSFile( QString filePath, HDC printerDC, int pageWidth, int pageHeight, bool landscape ) +{ + int escape; + int logPixelsX; + int logPixelsY; + int physicalWidth; + int physicalHeight; + bool done = true; + sPSPassthrough sps; + double transx, transy; + double scalex, scaley; + QFile file( filePath ); + int fileSize = 0; + int br, bw; + + if (!printerDC) + return false; + escape = getPSPassthroughSupport( printerDC ); + if (!escape) + return false; + + // Get printer resolution + logPixelsX = GetDeviceCaps(printerDC, LOGPIXELSX); + logPixelsY = GetDeviceCaps(printerDC, LOGPIXELSY); + + // Get paper dimensions ( in point units ) + physicalWidth = GetDeviceCaps( printerDC, PHYSICALWIDTH ) / (double) logPixelsX * 72.0; + physicalHeight = GetDeviceCaps( printerDC, PHYSICALHEIGHT ) / (double) logPixelsY * 72.0; + + // Calculate and set scaling factor + scalex = logPixelsX / 72.0; + scaley = -logPixelsY / 72.0; + sprintf( (char*) sps.data, "%0.3f %0.3f scale\n", scalex, scaley ); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + // Set some necessary stuff for embedding ps into ps + QString eBegin = "/b4_Inc_state save def\n"; + eBegin += "/dict_count countdictstack def\n"; + eBegin += "/op_count count 1 sub def\n"; + eBegin += "userdict begin\n"; + eBegin += "/showpage { } def\n"; + eBegin += "0 setgray 0 setlinecap\n"; + eBegin += "1 setlinewidth 0 setlinejoin\n"; + eBegin += "10 setmiterlimit [ ] 0 setdash newpath\n"; + eBegin += "/languagelevel where\n"; + eBegin += "{pop languagelevel\n"; + eBegin += "1 ne\n"; + eBegin += "{false setstrokeadjust false setoverprint\n"; + eBegin += "} if } if\n"; + sprintf( (char*) sps.data, "%s", eBegin.toLatin1().data() ); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + // Match Postscript and GDI coordinate system + sprintf( (char*) sps.data, "0 %0.3f neg translate\n", (double) physicalHeight ); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + // In case of landscape printing, pslib will rotate the page + // we must take that into account + /*if (landscape) + { + sprintf( (char*) sps.data, "-90 rotate %0.3f %0.3f translate\n", (double) -pageHeight, 0.0); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + transx = ( physicalHeight - pageHeight ) / -2.0; + transy = ( physicalWidth - pageWidth ) / 2.0; + } + else*/ + { + transx = ( physicalWidth - pageWidth ) / 2.0; + transy = ( physicalHeight - pageHeight ) / 2.0; + } + + // Center the printed page in paper zone + sprintf( (char*) sps.data, "%0.3f %0.3f translate\n", transx, transy ); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + sprintf( (char*) sps.data, "%s: %s\n", "%%BeginDocument", file.fileName().toLocal8Bit().data()); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + if ( !file.open( QIODevice::ReadOnly ) ) + return false; + fileSize = file.size(); + bw = 0; // bytes written + br = file.read( (char*) sps.data, sizeof( sps.data ) ); + while( br > 0 ) + { + sps.numBytes = br; + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + break; + bw += br; + br = file.read( (char*) sps.data, sizeof( sps.data ) ); + } + file.close(); + + sprintf( (char*) sps.data, "%s", "\n%%EndDocument\n"); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + // Set some necessary stuff for embedding ps into ps + QString eEnd = "count op_count sub {pop} repeat\n"; + eEnd += "countdictstack dict_count sub {end} repeat\n"; + eEnd += "b4_Inc_state restore\n"; + sprintf( (char*) sps.data, "%s", eEnd.toLatin1().data() ); + sps.numBytes = strlen( (char*) sps.data ); + if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 ) + return false; + + return ( (fileSize == bw) && ( br >= 0 ) ); +} + +void ScPrintEngine_GDI::setDeviceParams( ScribusDoc* doc, PrintOptions& options, DEVMODEW* devMode ) +{ + HANDLE handle; + QString printer = options.printer; + DWORD devFlags = devMode->dmFields; + + short nCopies = options.copies; + devMode->dmCopies = nCopies; + devFlags = devFlags | DM_COPIES; + + bool greyscale = !options.useColor; + if( greyscale ) + { + devMode->dmDitherType = DMDITHER_GRAYSCALE; + devFlags = devFlags | DM_DITHERTYPE; + } + + devMode->dmFields = devFlags; + + OpenPrinterW( (LPWSTR) printer.utf16(), &handle, NULL ); + DocumentPropertiesW( doc->scMW()->winId(), handle, (LPWSTR) printer.utf16(), devMode, devMode, DM_IN_BUFFER | DM_OUT_BUFFER); + ClosePrinter( handle ); +} + +QString ScPrintEngine_GDI::getDefaultPrinter( void ) +{ + QString defPrinter; + OSVERSIONINFO osvi; + DWORD returned, buffSize; + WCHAR szPrinter[512] = { 0 }; + WCHAR* p; + + buffSize = 512; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5 ) // Win2k and later + { + if ( GetDefaultPrinterW(szPrinter, &buffSize) ) + defPrinter = QString::fromUtf16((const ushort*) szPrinter); + } + else if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion < 5 ) // NT4 or earlier + { + if ( GetProfileStringW(L"windows",L"device",L"", szPrinter, buffSize) < (buffSize - 1) ) + { + p = szPrinter; + while (*p != 0 && *p != ',') + ++p; + *p = 0; + defPrinter = QString::fromUtf16((const ushort*) szPrinter); + } + } + else + { + DWORD numPrinters; + PRINTER_INFO_2W* printerInfos = NULL; + EnumPrintersW ( PRINTER_ENUM_DEFAULT, NULL, 2, NULL, 0, &buffSize, &numPrinters ); + printerInfos = (PRINTER_INFO_2W*) malloc(buffSize); + if ( EnumPrintersW ( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE) printerInfos, buffSize, &buffSize, &returned ) ) + { + if ( returned > 0 ) + { + defPrinter = QString::fromUtf16((const ushort*) printerInfos->pPrinterName); + } + } + if( printerInfos) free(printerInfos); + } + return defPrinter; +} + +bool ScPrintEngine_GDI::isPostscriptPrinter( HDC dc ) +{ + int escapeCode; + char technology[MAX_PATH] = {0}; + + if (!dc) + return false; + + // Test printer support for the POSTSCRIPT_PASSTHROUGH escape (available since win2k) + escapeCode = POSTSCRIPT_PASSTHROUGH; + if ( ExtEscape( dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 ) + return true; + // Test printer support for the POSTSCRIPT_DATA escape (available since win95) + escapeCode = POSTSCRIPT_DATA; + if ( ExtEscape( dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 ) + return true; + // Test the printer technology + escapeCode = GETTECHNOLOGY; + if ( ExtEscape( dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 ) + { + // If GETTECHNOLOGY is supported, then ... get technology + if ( ExtEscape( dc, GETTECHNOLOGY, 0, NULL, MAX_PATH, (LPSTR) technology ) > 0 ) + { + // Check technology string for postscript word + strupr( technology ); + if ( strstr( technology, "POSTSCRIPT" ) ) + return true; + } + } + return false; +} + +int ScPrintEngine_GDI::getPSPassthroughSupport( HDC printerDC ) +{ + int escapeCode; + char technology[MAX_PATH] = {0}; + if (!printerDC) + return 0; + // Test printer support for the POSTSCRIPT_PASSTHROUGH escape (available since win2k) + escapeCode = POSTSCRIPT_PASSTHROUGH; + if ( ExtEscape( printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 ) + return POSTSCRIPT_PASSTHROUGH; + // Test printer support for the POSTSCRIPT_DATA escape (available since win95) + escapeCode = POSTSCRIPT_DATA; + if ( ExtEscape( printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 ) + return POSTSCRIPT_DATA; + // Test printer support for the PASSTHROUGH escape + escapeCode = PASSTHROUGH; + if ( ExtEscape( printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 ) + return PASSTHROUGH; + return 0; +} + +bool ScPrintEngine_GDI::printerUseFilePort( QString& printerName ) +{ + bool done; + bool toFile = false; + HANDLE prnHandle; + DWORD size = 0; + + done = OpenPrinterW( (LPWSTR) printerName.utf16(), &prnHandle, NULL ); + if ( !done ) + return false; + + // Get buffer size for the PRINTER_INFO_2 structure + GetPrinterW( prnHandle, 2, NULL, 0, &size ); + if ( size > 0 ) + { + PRINTER_INFO_2W* pInfos = (PRINTER_INFO_2W*) malloc(size); + if( pInfos ) + { + // Get printer informations + done = GetPrinterW( prnHandle, 2, (LPBYTE) pInfos, size, &size ); + if( done ) + { + // Get printer port + WCHAR* pPortName = pInfos->pPortName; + if( wcsstr(pPortName, L"FILE:") ) + toFile = true; + } + free(pInfos); + } + } + + ClosePrinter( prnHandle ); + return toFile; +} |
