Back to index

scribus-ng  1.3.4.dfsg+svn20071115
scwinprint.cpp
Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 #ifdef WIN32_LEAN_AND_MEAN
00008 #undef WIN32_LEAN_AND_MEAN
00009 #endif
00010 
00011 #ifndef _WIN32
00012 #error "This file compiles on win32 platform only!"
00013 #endif
00014 
00015 #include <memory>
00016 #include <valarray>
00017 #include <windows.h>
00018 using namespace ::std;
00019 
00020 #include "scconfig.h"
00021 
00022 #ifdef HAVE_ICM
00023 #include <icm.h>
00024 #endif
00025 
00026 #ifdef SC_USE_GDIPLUS
00027 #include <gdiplus.h>
00028 using namespace Gdiplus;
00029 #endif
00030 
00031 #include "util.h"
00032 #include "gsutil.h"
00033 #include "scwinprint.h"
00034 #include "scwinprint.moc"
00035 #include "scpainterex_gdi.h"
00036 #include "scpageoutput.h"
00037 #include "scribusview.h"
00038 #include "scribusapp.h"
00039 #include "scribuscore.h"
00040 #include "scribus.h"
00041 #include "page.h"
00042 
00043 #include "prefsfile.h"
00044 #include "prefscontext.h"
00045 #include "prefsmanager.h"
00046 #include "customfdialog.h"
00047 #include "commonstrings.h"
00048 #include "multiprogressdialog.h"
00049 #include "scpaths.h"
00050 #include "pslib.h"
00051 
00052 #ifdef SC_USE_GDIPLUS
00053 ULONG_PTR gdiplusToken;
00054 GdiplusStartupInput gdiplusStartupInput;
00055 void gdiplusBegin(void) { GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); }
00056 void gdiplusEnd(void) { GdiplusShutdown(gdiplusToken); }
00057 #endif
00058 
00059 // Calculates fixed point from floating point.
00060 #define __FXPTMANTISSA(d, f)  ( (DWORD)d << f )
00061 #define __FXPTFRACTION(d, f)  ( (DWORD)ldexp((d - (DWORD)d), f) )
00062 #define __FXPT32(d, f)      ( __FXPTMANTISSA(d, f) | __FXPTFRACTION(d, f) )
00063 #define __FXPT2DOT30(d)   __FXPT32(d, 30)
00064 #define __FXPT16DOT16(d)  __FXPT32(d, 16)
00065 
00066 // Convenient structure for performing postscript passthrough
00067 typedef struct 
00068 {
00069        WORD numBytes;
00070        BYTE  data[32768];
00071 } sPSPassthrough;
00072 
00073 // Generic type for page printing function
00074 //typedef bool (ScWinPrint::*PrintPageFunc) ( ScribusDoc* doc, Page* page, PrintOptions& options, HDC printerDC, DEVMODE* devMode );
00075 
00076 ScWinPrint::ScWinPrint(void)
00077 {
00078        resetData();
00079 }
00080 
00081 void ScWinPrint::resetData(void)
00082 {
00083        m_abort = false;
00084 }
00085 
00086 void ScWinPrint::cancelRequested()
00087 {
00088        m_abort = true;
00089 }
00090 
00091 bool ScWinPrint::print( ScribusDoc* doc, PrintOptions& options, QByteArray& devMode, bool forceGDI )
00092 {
00093        bool toFile;
00094        bool success;
00095        HDC printerDC;
00096        QString diaSelection, docDir, prefsDocDir;
00097        QCString printerName = options.printer;
00098        QCString fileName;
00099 
00100        if( !doc || options.toFile )       
00101               return false;
00102        resetData();
00103 
00104        toFile = printerUseFilePort( options.printer );
00105        if ( toFile )
00106        {
00107               diaSelection = doc->DocName.right( doc->DocName.length() - doc->DocName.findRev("/") - 1 );
00108               diaSelection = diaSelection.left( diaSelection.find(".") );
00109               diaSelection += ".prn";
00110               PrefsContext* dirs = PrefsManager::instance()->prefsFile->getContext("dirs");
00111               QString prefsDocDir = PrefsManager::instance()->documentDir();
00112               if (!prefsDocDir.isEmpty())
00113                      docDir = dirs->get("winprn", prefsDocDir);
00114               else
00115                      docDir = ".";
00116               CustomFDialog dia( doc->scMW()->view, docDir, QObject::tr("Save as"), "Spool Files (*.prn *.ps);;All Files (*)", fdNone);
00117               dia.setSelection( diaSelection );
00118               if (dia.exec() == QDialog::Accepted)
00119               {
00120                      QString selectedFile = dia.selectedFile();
00121                      if ( overwrite(doc->scMW()->view, selectedFile) )
00122                      {
00123                             dirs->set("winprn", selectedFile.left(selectedFile.findRev("/")));
00124                             selectedFile = QDir::convertSeparators( selectedFile );
00125                             fileName = selectedFile.local8Bit();
00126                      }
00127               }
00128               else
00129                      return true;
00130        }
00131 
00132 #ifdef SC_USE_GDIPLUS
00133        gdiplusBegin();
00134 #endif
00135 
00136        // Set user options in the DEVmode structure
00137        setDeviceParams( doc, options, (DEVMODE*) devMode.data() );
00138               
00139        // Create the device context
00140        printerDC = CreateDC( NULL, printerName.data(), NULL, (DEVMODE*) devMode.data() );
00141        if( printerDC )
00142        {
00143               success = printPages( doc, options, printerDC, (DEVMODE*) devMode.data(), fileName, forceGDI );
00144               DeleteDC( printerDC );
00145        }
00146        else
00147        {
00148               qWarning("doPrintPages : the device context could not be created");
00149               success = false;
00150        }
00151 
00152 #ifdef SC_USE_GDIPLUS
00153        gdiplusEnd();
00154 #endif
00155 
00156        return success;
00157 }
00158 
00159 bool ScWinPrint::gdiPrintPreview( ScribusDoc* doc, Page* page, QImage* image, PrintOptions& options, double scale )
00160 {
00161        HDC dc = NULL;
00162        bool success = true;
00163        ScPainterEx_GDI *painter;
00164        ScPageOutput *pageOutput;
00165        HCOLORSPACE hColorSpace = NULL;
00166        int imagew, imageh;
00167        double scalex = 1, scaley = 1;
00168        bool rotate = false;
00169 
00170        if ( !doc || !page || !image)
00171               return false;
00172        resetData();
00173 
00174 #ifdef SC_USE_GDIPLUS
00175        gdiplusBegin();
00176 #endif
00177 
00178        // Get page position
00179        int clipx = static_cast<int>(page->xOffset());
00180        int clipy = static_cast<int>(page->yOffset());
00181        int clipw = qRound(page->width());
00182        int cliph = qRound(page->height());
00183 
00184        // Setup image
00185        imagew = clipw * scale;
00186        imageh = cliph * scale;
00187        success = image->create( imagew, imageh, 32 );
00188        if (!success)
00189               return false;
00190 
00191        // Create a memory device context
00192        dc = CreateCompatibleDC( NULL );
00193        if (!dc )
00194               return false;
00195 
00196        // Create a DIB Section
00197        long* bmpData = NULL;
00198        BITMAPINFO bmpInfo;
00199        BITMAPINFOHEADER *bmpHeader;
00200        bmpHeader = &(bmpInfo.bmiHeader);
00201        bmpHeader->biSize = sizeof(BITMAPINFOHEADER);
00202        bmpHeader->biWidth = imagew;
00203        bmpHeader->biHeight = -imageh;
00204        bmpHeader->biPlanes = 1;
00205        bmpHeader->biBitCount = 32;
00206        bmpHeader->biCompression = BI_RGB;
00207        bmpHeader->biSizeImage = 0; // Valid only if biCompression = BI_RGB
00208        bmpHeader->biXPelsPerMeter = 0;
00209        bmpHeader->biYPelsPerMeter = 0;
00210        bmpHeader->biClrUsed = 0;
00211        bmpHeader->biClrImportant = 0;
00212        HBITMAP hBmp = CreateDIBSection(dc, &bmpInfo, DIB_RGB_COLORS, (void** ) &bmpData, NULL, NULL);
00213        if ( !hBmp )
00214        {
00215               DeleteDC(dc);
00216               return false;
00217        }
00218 
00219        // And select it into the created dc
00220        HGDIOBJ obj = SelectObject( dc, hBmp );
00221 
00222        // Get horizontal and vertical resolution of device context
00223        double logPixelsX = GetDeviceCaps( dc, LOGPIXELSX );
00224        double logPixelsY = GetDeviceCaps( dc, LOGPIXELSY );
00225 
00226        // Calculate scaling factors and offsets
00227        scalex = options.mirrorH ? -1.0 : 1.0;
00228        scaley = options.mirrorV ? -1.0 : 1.0; 
00229        double dx = - clipx * scalex;
00230        double dy = - clipy * scaley;
00231        if ( options.mirrorH ) dx += clipw;
00232        if ( options.mirrorV ) dy += cliph;
00233 
00234 #ifdef SC_USE_GDIPLUS
00235        // When using gdiplus ScPainterEx_GDI use point units
00236        scalex *= ( 72.0 / logPixelsX );
00237        scaley *= ( 72.0 / logPixelsY );
00238        dx *= ( 72.0 / logPixelsX );
00239        dy *= ( 72.0 / logPixelsY );
00240 #endif
00241 
00242        scalex *= scale;
00243        scaley *= scale;
00244        dx *= scale;
00245        dy *= scale;
00246         
00247        // Create the GDI painters
00248        pageOutput = new ScPageOutput(doc, false);
00249        QRect drawRect( 0, 0, imagew, imageh );
00250        painter = new ScPainterEx_GDI( dc, drawRect, doc, !options.useColor );
00251        
00252        // Set the world transformation matrix
00253        QWMatrix matrix( scalex, 0.0, 0.0, scaley, dx, dy );
00254        painter->setWorldMatrix( matrix );
00255 
00256        painter->clear();
00257        pageOutput->DrawPage(page, painter); 
00258 
00259        delete painter;
00260        delete pageOutput;
00261 
00262        // Copy DibSection data in QImage
00263        int* pDib = (int*) bmpData;
00264        int* pImage = (int*) image->bits();
00265        int words = imagew * imageh;
00266        for( int i = 0; i < words; i++ )
00267        {
00268               *pImage++ = *pDib;
00269               pDib++;
00270        }
00271 
00272        // Delete GDI objects
00273        SelectObject( dc, obj );
00274        DeleteDC( dc );
00275        DeleteObject( hBmp );
00276 
00277 #ifdef SC_USE_GDIPLUS
00278        gdiplusEnd();
00279 #endif
00280 
00281        return success;
00282 }
00283 
00284 bool ScWinPrint::printPages( ScribusDoc* doc, PrintOptions& options, HDC printerDC, DEVMODE* devMode, QCString& fileName, bool forceGDI )
00285 {
00286  int  jobId;
00287  bool psPrint;
00288  auto_ptr<MultiProgressDialog> progress;
00289  PrintPageFunc doPrintPage = NULL;
00290  bool success = true;
00291  char docName[512];
00292  DOCINFO docInfo;
00293  Page* docPage;
00294 
00295        // Test printer for PostScript support and
00296        // choose appropriate page printing function
00297        psPrint = isPostscriptPrinter( printerDC );
00298        if ( psPrint && !forceGDI )
00299               doPrintPage = &ScWinPrint::printPage_PS;
00300        else
00301               doPrintPage = &ScWinPrint::printPage_GDI;
00302 
00303        // Setup document infos structure
00304        strncpy( docName, doc->DocName.local8Bit(), sizeof(docName) - 1);
00305        ZeroMemory( &docInfo, sizeof(docInfo) );
00306        docInfo.cbSize = sizeof(docInfo);
00307        docInfo.lpszDocName = docName;
00308        docInfo.lpszOutput = ( fileName.size() > 0 ? fileName.data() : NULL );
00309        docInfo.lpszDatatype = NULL;
00310        docInfo.fwType = 0;
00311 
00312        jobId = StartDoc( printerDC, &docInfo );
00313        if ( jobId <= 0 )
00314        {
00315               AbortDoc( printerDC ) ;
00316               return false;
00317        }
00318 
00319        bool usingGui = ScCore->usingGUI();
00320        if ( usingGui )
00321        {
00322               progress.reset( new MultiProgressDialog( tr("Printing..."), CommonStrings::tr_Cancel, doc->scMW(), "printprogress") );
00323               progress->setOverallTotalSteps( options.pageNumbers.size() );
00324               progress->setOverallProgress(0);
00325               connect(progress->buttonCancel, SIGNAL(clicked()), this, SLOT(cancelRequested()));
00326               progress->show();
00327        }
00328 
00329        for ( uint index = 0; index < options.pageNumbers.size(); index++ )
00330        {
00331               if( usingGui )
00332                      progress->setOverallProgress(index);
00333               docPage = doc->Pages->at( options.pageNumbers[index] - 1 );
00334               success = (this->*doPrintPage)( doc, docPage, options, printerDC, devMode );
00335               ScQApp->processEvents();
00336               if (!success || m_abort )
00337                      break;
00338               if ( usingGui )
00339                      progress->setOverallProgress(index + 1);
00340        }
00341 
00342        if ( usingGui )
00343               progress->close();
00344 
00345        if( m_abort )
00346               AbortDoc( printerDC ) ;
00347        EndDoc( printerDC );
00348 
00349        return success;
00350 }
00351 
00352 bool ScWinPrint::printPage_GDI( ScribusDoc* doc, Page* page, PrintOptions& options, HDC printerDC, DEVMODE* devMode )
00353 {
00354        int logPixelsX;
00355        int logPixelsY;
00356        int physicalWidth;
00357        int physicalHeight;
00358        int physicalWidthP;
00359        int physicalHeightP;
00360        int physicalOffsetX;
00361        int physicalOffsetY;
00362        bool success = true;
00363        ScPainterEx_GDI *painter;
00364        ScPageOutput *pageOutput;
00365        QCString inputProfile;
00366        QCString printerProfile;
00367        HCOLORSPACE hColorSpace = NULL;
00368        double scalex = 1, scaley = 1;
00369        bool rotate = false;
00370 
00371        StartPage( printerDC );
00372 
00373 #ifdef HAVE_ICM
00374        if ( options.useICC && isPostscriptPrinter(printerDC) )
00375        {
00376               success = false;
00377               QString mProf = doc->CMSSettings.DefaultSolidColorRGBProfile;
00378               QString pProf = doc->CMSSettings.DefaultPrinterProfile;
00379               if ( ScCore->MonitorProfiles.contains(mProf) && ScCore->PrinterProfiles.contains(pProf) )
00380               {
00381                      inputProfile  = QDir::convertSeparators(ScCore->InputProfiles[mProf]).local8Bit();
00382                      printerProfile = QDir::convertSeparators(ScCore->PrinterProfiles[pProf]).local8Bit();
00383                      // Avoid color transform if input and output profile are the same
00384                      if ( inputProfile != printerProfile )
00385                      {
00386                             // Setup input color space
00387                             LOGCOLORSPACE logColorSpace;
00388                             logColorSpace.lcsSize = sizeof(logColorSpace);
00389                             logColorSpace.lcsVersion = 0x400;
00390                             logColorSpace.lcsSignature = LCS_SIGNATURE;
00391                             logColorSpace.lcsCSType = LCS_CALIBRATED_RGB;
00392                             logColorSpace.lcsIntent = LCS_GM_GRAPHICS;
00393                             strncpy(logColorSpace.lcsFilename, inputProfile.data(), MAX_PATH);
00394                             // MSDN recommend to setup reasonable values even if profile is specified
00395                             // so let's use sRGB colorspace values
00396                             logColorSpace.lcsEndpoints.ciexyzRed.ciexyzX = __FXPT2DOT30(0.64);
00397                             logColorSpace.lcsEndpoints.ciexyzRed.ciexyzY = __FXPT2DOT30(0.33);
00398                             logColorSpace.lcsEndpoints.ciexyzRed.ciexyzZ = __FXPT2DOT30(0.03);
00399                             logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzX = __FXPT2DOT30(0.3);
00400                             logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzY = __FXPT2DOT30(0.6);
00401                             logColorSpace.lcsEndpoints.ciexyzGreen.ciexyzZ = __FXPT2DOT30(0.1);
00402                             logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzX = __FXPT2DOT30(0.15);
00403                             logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzY = __FXPT2DOT30(0.06);
00404                             logColorSpace.lcsEndpoints.ciexyzBlue.ciexyzZ = __FXPT2DOT30(0.79);
00405                             logColorSpace.lcsGammaRed = __FXPT16DOT16(0.45);
00406                             logColorSpace.lcsGammaGreen = __FXPT16DOT16(0.45);
00407                             logColorSpace.lcsGammaBlue = __FXPT16DOT16(0.45);
00408                             // Create the color space handle
00409                             hColorSpace = CreateColorSpace( &logColorSpace );
00410                             if ( hColorSpace )
00411                             {
00412                                    // Setup the input and output profiles for the device context
00413                                    if ( SetColorSpace(printerDC, hColorSpace) && SetICMProfile(printerDC, printerProfile.data()) )
00414                                    {
00415                                           int result = SetICMMode( printerDC, ICM_ON );
00416                                           success = ( result != 0 );
00417                                    }
00418                             }
00419                      }
00420                      else
00421                             success = true;
00422               }
00423               // Return if color managament could not be setup
00424               if ( !success )
00425               {
00426                      EndPage( printerDC );
00427                      if ( hColorSpace )
00428                             DeleteColorSpace( hColorSpace );
00429                      return false;
00430               }
00431        }
00432 #endif
00433 
00434        // Get page position
00435        int clipx = static_cast<int>(page->xOffset());
00436        int clipy = static_cast<int>(page->yOffset());
00437        int clipw = qRound(page->width());
00438        int cliph = qRound(page->height());
00439 
00440        // Get horizontal and vertical resolution of printer
00441        logPixelsX = GetDeviceCaps( printerDC, LOGPIXELSX );
00442        logPixelsY = GetDeviceCaps( printerDC, LOGPIXELSY );
00443 
00444        // Get paper dimensions ( in pixels and points)
00445        physicalWidth = GetDeviceCaps( printerDC, PHYSICALWIDTH );
00446        physicalHeight = GetDeviceCaps( printerDC, PHYSICALHEIGHT );
00447        physicalWidthP = physicalWidth / (double) logPixelsX * 72.0;
00448        physicalHeightP = physicalHeight / (double) logPixelsY * 72.0;
00449 
00450        // Get margins dimensions
00451        physicalOffsetX = GetDeviceCaps( printerDC, PHYSICALOFFSETX );
00452        physicalOffsetY = GetDeviceCaps( printerDC, PHYSICALOFFSETY );
00453 
00454        // Calculate scaling factors and offsets
00455        scalex = options.mirrorH ? -1.0 : 1.0;
00456        scaley = options.mirrorV ? -1.0 : 1.0; 
00457        double dx = ( physicalWidthP - clipw ) / 2.0 - clipx * scalex;
00458        double dy = ( physicalHeightP - cliph ) / 2.0 - clipy * scaley;
00459        if ( options.mirrorH ) dx += clipw;
00460        if ( options.mirrorV ) dy += cliph;
00461        dx -= ( physicalOffsetX / (double) logPixelsX * 72.0 );
00462        dy -= ( physicalOffsetY / (double) logPixelsY * 72.0 );
00463 
00464 #ifndef SC_USE_GDIPLUS
00465        // When using GDI, it's better to draw directly using device coordinates
00466        // otherwise we may have crappy rendering of bezier curves
00467        scalex *= ( logPixelsX / 72.0 );
00468        scaley *= ( logPixelsY / 72.0 );
00469        dx *= ( logPixelsX / 72.0 );
00470        dy *= ( logPixelsY / 72.0 );
00471 #endif
00472         
00473        // Create the GDI painter
00474        MarksOptions marksOptions(options);
00475        pageOutput = new ScPageOutput(doc, true, 300, options.useICC);
00476        pageOutput->setMarksOptions(marksOptions);
00477        
00478        QRect drawRect( 0, 0, physicalWidth, physicalHeight);
00479        painter = new ScPainterEx_GDI( printerDC, drawRect, doc, !options.useColor );
00480        painter->clear();
00481        
00482        QWMatrix matrix( scalex, 0.0, 0.0, scaley, dx, dy );
00483        painter->setWorldMatrix( matrix );
00484 
00485        pageOutput->DrawPage(page, painter); 
00486 
00487        delete painter;
00488        delete pageOutput;
00489 
00490        EndPage( printerDC );
00491 
00492        if (hColorSpace)
00493               DeleteColorSpace( hColorSpace );
00494 
00495        return success;
00496 }
00497 
00498 bool ScWinPrint::printPage_PS ( ScribusDoc* doc, Page* page, PrintOptions& options, HDC printerDC, DEVMODE* devMode )
00499 {
00500        bool succeed = false;
00501        ColorList usedColors;
00502        PrintOptions options2 = options;
00503        QMap<QString, QMap<uint, FPointArray> > usedFonts;
00504        QString tempFilePath;
00505        int ret = 0;
00506 
00507        doc->getUsedFonts(usedFonts);
00508        doc->getUsedColors(usedColors);
00509        options2.pageNumbers.clear();
00510        options2.pageNumbers.push_back(page->pageNr() + 1 );
00511 
00512        tempFilePath = PrefsManager::instance()->preferencesLocation() + "/tmp.ps";
00513        PSLib *dd = new PSLib(options2, false, PrefsManager::instance()->appPrefs.AvailFonts, usedFonts, usedColors, false, options2.useSpotColors );
00514        dd->PS_set_file( tempFilePath );
00515        dd->CreatePS( doc, options2);
00516        delete dd;
00517 
00518        if ( options.PSLevel == 1 || options.PSLevel == 2 )
00519        {
00520               QString tmp;
00521               QStringList opts;
00522               QString tempFilePath2 = PrefsManager::instance()->preferencesLocation() + "/tmp2.ps";
00523               opts.append( QString("-dDEVICEWIDTHPOINTS=%1").arg(tmp.setNum(doc->pageWidth)) );
00524               opts.append( QString("-dDEVICEHEIGHTPOINTS=%1").arg(tmp.setNum(doc->pageHeight)) );
00525               if ( QFile::exists( tempFilePath2 ) )
00526                      QFile::remove( tempFilePath2 );
00527               ret = convertPS2PS(tempFilePath, tempFilePath2, opts, options.PSLevel);
00528               if ( ret == 0 )
00529               {
00530                      unlink( tempFilePath );
00531                      tempFilePath = tempFilePath2;
00532               }
00533               else
00534               {
00535                      QFile::remove( tempFilePath2 );
00536               }
00537        }
00538        
00539        if( ret == 0 )
00540        {
00541               StartPage( printerDC );
00542               succeed = sendPSFile( tempFilePath, printerDC, page->width(), page->height() );
00543               EndPage( printerDC );
00544        }
00545        
00546        QFile::remove( tempFilePath );
00547        return succeed;
00548 }
00549 
00550 bool ScWinPrint::sendPSFile( QString filePath, HDC printerDC, int pageWidth, int pageHeight  )
00551 {
00552        int  escape;
00553        int  logPixelsX;
00554        int  logPixelsY;
00555        int  physicalWidth;
00556        int  physicalHeight;
00557        bool done = true;
00558        sPSPassthrough sps;
00559        double transx, transy;
00560        double scalex, scaley;
00561        QFile file( filePath );
00562        int fileSize = 0;
00563        int br, bw;
00564 
00565        if (!printerDC)
00566               return false;
00567        escape = getPSPassthroughSupport( printerDC );
00568        if (!escape)
00569               return false;
00570 
00571        // Get printer resolution
00572        logPixelsX = GetDeviceCaps(printerDC, LOGPIXELSX);
00573        logPixelsY = GetDeviceCaps(printerDC, LOGPIXELSY);
00574 
00575        // Get paper dimensions ( in point units )
00576        physicalWidth = GetDeviceCaps( printerDC, PHYSICALWIDTH ) / (double) logPixelsX * 72.0;
00577        physicalHeight = GetDeviceCaps( printerDC, PHYSICALHEIGHT ) / (double) logPixelsY * 72.0;
00578 
00579        // Calculate and set scaling factor
00580        scalex = logPixelsX / 72.0;
00581        scaley = -logPixelsY / 72.0;
00582        sprintf( (char*) sps.data, "%0.3f %0.3f scale\n", scalex, scaley );
00583        sps.numBytes = strlen( (char*) sps.data );
00584        if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 )
00585               return false;
00586 
00587        // Set some necessary stuff for embedding ps into ps
00588        QString eBegin = "/b4_Inc_state save def\n";
00589        eBegin += "/dict_count countdictstack def\n";
00590        eBegin += "/op_count count 1 sub def\n";
00591        eBegin += "userdict begin\n";
00592        eBegin += "/showpage { } def\n";
00593        eBegin += "0 setgray 0 setlinecap\n";
00594        eBegin += "1 setlinewidth 0 setlinejoin\n";
00595        eBegin += "10 setmiterlimit [ ] 0 setdash newpath\n";
00596        eBegin += "/languagelevel where\n";
00597        eBegin += "{pop languagelevel\n";
00598        eBegin += "1 ne\n";
00599        eBegin += "{false setstrokeadjust false setoverprint\n";
00600        eBegin += "} if } if\n";
00601        sprintf( (char*) sps.data, "%s", eBegin.latin1() );
00602        sps.numBytes = strlen( (char*) sps.data );
00603        if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 )
00604               return false;
00605 
00606        // Center the printed page in paper zone
00607        transx = ( physicalWidth - pageWidth ) / 2.0;
00608        transy = ( pageHeight - physicalHeight ) / 2.0 - pageHeight;
00609        sprintf( (char*) sps.data, "%0.3f %0.3f translate\n", transx, transy );
00610        sps.numBytes = strlen( (char*) sps.data );
00611        if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 )
00612               return false;
00613 
00614        if ( !file.open( IO_ReadOnly ) )
00615               return false;
00616        fileSize = file.size();
00617        bw = 0; // bytes written
00618        br = file.readBlock( (char*) sps.data, sizeof( sps.data ) );
00619        while( br > 0 )
00620        {
00621               sps.numBytes = br;
00622               if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) > 0 )
00623                      bw += br;
00624               else
00625                      break;
00626               br = file.readBlock( (char*) sps.data, sizeof( sps.data ) );
00627        }
00628        file.close();
00629 
00630        // Set some necessary stuff for embedding ps into ps
00631        QString eEnd = "count op_count sub {pop} repeat\n";
00632        eEnd += "countdictstack dict_count sub {end} repeat\n";
00633        eEnd += "b4_Inc_state restore\n";
00634        sprintf( (char*) sps.data, "%s", eEnd.latin1() );
00635        sps.numBytes = strlen( (char*) sps.data );
00636        if( ExtEscape( printerDC, escape, sizeof(sps), (LPCSTR) &sps, 0, NULL) <= 0 )
00637               return false;
00638 
00639        return ( (fileSize == bw) && ( br >= 0 ) );
00640 }
00641 
00642 void ScWinPrint::setDeviceParams( ScribusDoc* doc, PrintOptions& options, DEVMODE* devMode )
00643 {
00644        HANDLE handle;
00645        QCString printer = options.printer.local8Bit();
00646        DWORD devFlags = devMode->dmFields;
00647 
00648        short nCopies = options.copies;
00649        devMode->dmCopies = nCopies;
00650        devFlags  = devFlags | DM_COPIES;
00651 
00652        bool greyscale = !options.useColor;
00653        if( greyscale )
00654        {
00655               devMode->dmDitherType = DMDITHER_GRAYSCALE;
00656               devFlags = devFlags | DM_DITHERTYPE;
00657        }
00658 
00659        devMode->dmFields = devFlags;
00660 
00661        OpenPrinter( printer.data(), &handle, NULL );
00662        DocumentProperties( doc->scMW()->winId(), handle, printer.data(), devMode, devMode, DM_IN_BUFFER | DM_OUT_BUFFER);
00663        ClosePrinter( handle );
00664 }
00665 
00666 QString ScWinPrint::getDefaultPrinter( void )
00667 {
00668        QString defPrinter;
00669        OSVERSIONINFO osvi;
00670        DWORD returned, buffSize;
00671        char szPrinter[512] = { 0 };
00672        char* p;
00673        
00674        buffSize = sizeof( szPrinter );
00675        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00676        GetVersionEx(&osvi);
00677 
00678        if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 5 ) // Win2k and later
00679        {
00680               if ( GetDefaultPrinter(szPrinter, &buffSize) )
00681                      defPrinter = szPrinter;
00682        }
00683        else if( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion < 5 ) // NT4 or earlier
00684        {
00685               if ( GetProfileString("windows","device","", szPrinter, buffSize) < (buffSize - 1) )
00686               {
00687                      p = szPrinter;
00688                      while (*p != 0 && *p != ',')
00689                             ++p;
00690                      *p = 0;
00691                      defPrinter = szPrinter;
00692               }
00693        }
00694        else
00695        {
00696               DWORD numPrinters;
00697               PRINTER_INFO_2* printerInfos = NULL;
00698               EnumPrinters ( PRINTER_ENUM_DEFAULT, NULL, 2, NULL, 0, &buffSize, &numPrinters );
00699               printerInfos = (PRINTER_INFO_2*) malloc(buffSize);
00700               if ( EnumPrinters ( PRINTER_ENUM_LOCAL, NULL, 2, (LPBYTE) printerInfos, buffSize, &buffSize, &returned ) )
00701               {
00702                      if ( returned > 0 )
00703                      {
00704                             defPrinter = printerInfos->pPrinterName;
00705                      }
00706               }
00707               if( printerInfos) free(printerInfos);
00708        }
00709        return defPrinter;
00710 }
00711 
00712 bool ScWinPrint::isPostscriptPrinter( HDC dc )
00713 {
00714        int    escapeCode;
00715        char technology[MAX_PATH] = {0};
00716 
00717        if (!dc)
00718               return false;
00719        
00720        // Test printer support for the POSTSCRIPT_PASSTHROUGH escape (available since win2k)
00721        escapeCode = POSTSCRIPT_PASSTHROUGH;
00722        if ( ExtEscape( dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 )
00723               return true;
00724        // Test printer support  for the POSTSCRIPT_DATA escape (available since win95)
00725        escapeCode = POSTSCRIPT_DATA;
00726        if ( ExtEscape( dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 )
00727               return true;
00728        // Test the printer technology
00729        escapeCode = GETTECHNOLOGY;
00730        if ( ExtEscape( dc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 )
00731        {
00732               // If GETTECHNOLOGY is supported, then ... get technology
00733               if ( ExtEscape( dc, GETTECHNOLOGY, 0, NULL, MAX_PATH, (LPSTR) technology ) > 0 )
00734               {
00735                      // Check technology string for postscript word
00736                      strupr( technology );
00737                      if ( strstr( technology, "POSTSCRIPT" ) )
00738                             return true;
00739               }
00740        }
00741        return false;
00742 }
00743 
00744 int     ScWinPrint::getPSPassthroughSupport( HDC printerDC )
00745 {
00746        int    escapeCode;
00747        char technology[MAX_PATH] = {0};
00748        if (!printerDC)
00749               return 0;
00750        // Test printer support for the POSTSCRIPT_PASSTHROUGH escape (available since win2k)
00751        escapeCode = POSTSCRIPT_PASSTHROUGH;
00752        if ( ExtEscape( printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 )
00753               return POSTSCRIPT_PASSTHROUGH;
00754        // Test printer support for the POSTSCRIPT_DATA escape (available since win95)
00755        escapeCode = POSTSCRIPT_DATA;
00756        if ( ExtEscape( printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 )
00757               return POSTSCRIPT_DATA;
00758        // Test printer support for the PASSTHROUGH escape
00759        escapeCode = PASSTHROUGH;
00760        if ( ExtEscape( printerDC, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL ) > 0 )
00761               return PASSTHROUGH;
00762        return 0;
00763 }
00764 
00765 bool ScWinPrint::printerUseFilePort( QString& printerName )
00766 {
00767  bool done;
00768  bool toFile = false;
00769  QCString printer = printerName.local8Bit();
00770  HANDLE prnHandle;
00771  DWORD size = 0;
00772 
00773        done = OpenPrinter( printer.data(), &prnHandle, NULL );
00774        if ( !done )
00775               return false;
00776        
00777        // Get buffer size for the PRINTER_INFO_2 structure
00778        GetPrinter( prnHandle, 2, NULL, 0, &size );
00779        if ( size > 0 )
00780        {
00781               PRINTER_INFO_2* pInfos = (PRINTER_INFO_2*) malloc(size);
00782               if( pInfos )
00783               {
00784                      // Get printer informations
00785                      done = GetPrinter( prnHandle, 2, (LPBYTE) pInfos, size, &size );
00786                      if( done )
00787                      {
00788                             // Get printer port
00789                             char* pPortName = pInfos->pPortName;
00790                             if( strstr(pPortName, "FILE:") )
00791                                    toFile = true;
00792                      }
00793                      free(pInfos);
00794               }
00795        }
00796 
00797        ClosePrinter( prnHandle );
00798        return toFile;
00799 }