Ignore:
Timestamp:
Aug 2, 2006, 3:02:52 PM (15 years ago)
Author:
Eugene Romanenko
Message:

bitmap printing, preliminary postscript printing, export to PS for djvu plugin, other improvements

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Lucide/SOURCE/gui/print.cpp

    r90 r91  
    3535#define INCL_WIN
    3636#define INCL_GPI
     37#define INCL_DOS
    3738#define INCL_DEV
    3839#define INCL_ERRORS
     
    4445
    4546#include <string.h>
    46 
     47#include <process.h>
     48#include <stdio.h>
     49#include <io.h>
     50
     51#include "globals.h"
     52#include "progressDlg.h"
    4753#include "print.h"
     54#include "luutils.h"
     55#include "messages.h"
    4856
    4957// OpenWatcom headers doesn't have GpiDrawBits() declaration
     
    5462
    5563#define UNITS_MULTIPLIER    100
    56 
     64#define STD_IMAGE_ZOOM      2.0
     65#define HIGH_IMAGE_ZOOM     3.0
     66#define PS_PRINT_BUF_SIZE   32768
    5767#define TEST_MARGIN         10
    5868
    59 void printPage( LuDocument *doc, long page, HPS hpsPrinter, PHCINFO pcurForm );
    60 void queryCurrentForm( HDC hdcPrinter, PHCINFO pcurForm );
    61 
    62 void printDocument( LuDocument *doc, void *q )
    63 {
    64     PPRQINFO3    pQueueInfo = (PPRQINFO3)q;
     69
     70class LucidePrinting
     71{
     72    public:
     73        LucidePrinting( HWND hWndFrame, LuDocument *_doc,
     74                        const char *_title, PrintSetup *_psetup );
     75        ~LucidePrinting();
     76        void doPrint();
     77
     78    private:
     79        bool queryCurrentForm( HAB lhab, PHCINFO pcurForm );
     80        void printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm );
     81        bool doPmPrint( HAB lhab );
     82        bool doPsPrint( HAB lhab );
     83
     84        HWND hFrame;
     85        LuDocument *doc;
     86        char *title;
     87        PrintSetup *psetup;
     88        bool abortPrinting;
     89        ProgressDlg *progressDlg;
     90
     91        static void printabort( void *data );
     92        static void printthread( void *data );
     93};
     94
     95
     96void printDocument( HWND hWndFrame, LuDocument *doc, const char *title, PrintSetup *psetup )
     97{
     98    LucidePrinting *p = new LucidePrinting( hWndFrame, doc, title, psetup );
     99    p->doPrint();
     100}
     101
     102
     103LucidePrinting::LucidePrinting( HWND hWndFrame, LuDocument *_doc,
     104                                const char *_title, PrintSetup *_psetup )
     105{
     106    hFrame = hWndFrame;
     107    doc    = _doc;
     108    title  = newstrdup( _title );
     109    psetup = new PrintSetup;
     110    memcpy( psetup, _psetup, sizeof( PrintSetup ) );
     111    abortPrinting = false;
     112    progressDlg = new ProgressDlg( hWndFrame );
     113}
     114
     115LucidePrinting::~LucidePrinting()
     116{
     117    delete title;
     118    delete psetup;
     119    delete progressDlg;
     120}
     121
     122void LucidePrinting::doPrint()
     123{
     124    progressDlg->setBreakFunc( printabort, this );
     125    progressDlg->setText( "" );
     126    progressDlg->show( printthread, this );
     127}
     128
     129bool LucidePrinting::doPmPrint( HAB lhab )
     130{
    65131    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
     132    DEVOPENSTRUC dos   = { 0 };
    66133    SIZEL        sizel = { 0 };
    67     DEVOPENSTRUC dos   = { 0 };
     134
     135    HCINFO curForm = { 0 };
     136    if ( !queryCurrentForm( lhab, &curForm ) ) {
     137        return false;
     138    }
    68139
    69140    // build a devopenstruct for the call to DevOpenDC
    70     dos.pszLogAddress = pQueueInfo->pszName;
    71     strcpy( achDriverName, pQueueInfo->pszDriverName );
     141    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
     142    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
    72143    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
    73     dos.pszDriverName = achDriverName;
    74     dos.pdriv = pQueueInfo->pDriverData;
    75 
    76     HDC hdcPrinter = DevOpenDC( hab, OD_QUEUED, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
     144    dos.pszDriverName = achDriverName;                          // 2
     145    dos.pdriv         = psetup->QueueInfo.pDriverData;          // 3
     146    dos.pszDataType   = "PM_Q_STD";                             // 4
     147
     148    HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 4L, (PDEVOPENDATA)&dos, NULLHANDLE );
    77149    if ( hdcPrinter == DEV_ERROR ) {
    78         somPrintf( "DevOpenDC error\n" );
    79         return;
     150        return false;
    80151    }
    81152
    82153    // PS in HiMetric, 0.01 mm
    83     HPS hpsPrinter = GpiCreatePS( hab, hdcPrinter, &sizel, PU_HIMETRIC | GPIA_ASSOC );
     154    HPS hpsPrinter = GpiCreatePS( lhab, hdcPrinter, &sizel, PU_HIMETRIC | GPIA_ASSOC );
    84155    if ( hpsPrinter == DEV_ERROR ) {
    85156        DevCloseDC( hdcPrinter );
    86         somPrintf( "GpiCreatePS error\n" );
    87         return;
    88     }
    89 
    90     HCINFO curForm = { 0 };
    91     queryCurrentForm( hdcPrinter, &curForm );
    92     char *psz = "test";
     157        return false;
     158    }
     159
    93160    // Issue STARTDOC to begin printing
    94     DevEscape( hdcPrinter, DEVESC_STARTDOC, (LONG)strlen(psz), (PBYTE)psz, NULL, NULL );
    95 
    96     somPrintf( "begin!\n" );
    97 
    98     printPage( doc, 0, hpsPrinter, &curForm );
    99 
    100     somPrintf( "end!\n" );
    101 
    102     DevEscape( hdcPrinter, DEVESC_ENDDOC, 0L, NULL, NULL, NULL );
     161    DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
     162
     163    long totalpages = psetup->pgto - psetup->pgfrom + 1;
     164    for ( long pg = psetup->pgfrom; pg <= psetup->pgto; pg++ )
     165    {
     166        char *fmt = newstrdupL( PRINT_PRINTING_PAGE_OF );
     167        char *buf = new char[ 255 ];
     168        snprintf( buf, 255, fmt, pg, totalpages );
     169        progressDlg->setText( buf );
     170        delete fmt;
     171        delete buf;
     172
     173        printPagePm( pg - 1, hpsPrinter, &curForm );
     174
     175        if ( pg != psetup->pgto ) {
     176            DevEscape( hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL );
     177        }
     178
     179        if ( abortPrinting ) {
     180            break;
     181        }
     182    }
     183
     184    // Issue DEVESC_ENDDOC, or DEVESC_ABORTDOC if printing was aborted
     185    DevEscape( hdcPrinter, abortPrinting ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
     186               0L, NULL, NULL, NULL );
    103187
    104188    // Release PS and DC
     
    106190    GpiDestroyPS( hpsPrinter );
    107191    DevCloseDC( hdcPrinter );
    108 }
    109 
    110 
    111 static void printPage( LuDocument *doc, long page, HPS hpsPrinter, PHCINFO pcurForm )
     192    return true;
     193}
     194
     195
     196void LucidePrinting::printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm )
    112197{
    113198    long bpp = doc->getBpp( ev );
     
    125210    LONG pheight = ( pcurForm->cy - mTop - mBottom ) * UNITS_MULTIPLIER;
    126211
    127     double zoom = __min( (double)pwidth / w, (double)pheight / h );
    128     if ( zoom > 2.0 ) {
    129         zoom = 2.0;
    130     }
    131 
    132     somPrintf( "Doc pgsz: %g/%g  zoom: %g\n", w, h, zoom );
    133     somPrintf( "Paper %s, pgsz: %d/%d\n", pcurForm->szFormname, pcurForm->cx, pcurForm->cy );
    134     somPrintf( "pw/ph %d/%d\n", pwidth, pheight );
     212    double zoom = 1.0;
     213    if ( doc->isScalable( ev ) )
     214    {
     215        double maxcoeff = psetup->higherQuality ? HIGH_IMAGE_ZOOM : STD_IMAGE_ZOOM;
     216        zoom = __min( (double)pwidth / w, (double)pheight / h );
     217        if ( zoom > maxcoeff ) {
     218            zoom = maxcoeff;
     219        }
     220    }
     221
     222    //somPrintf( "Doc pgsz: %g/%g  zoom: %g\n", w, h, zoom );
     223    //somPrintf( "Paper %s, pgsz: %d/%d\n", pcurForm->szFormname, pcurForm->cx, pcurForm->cy );
     224    //somPrintf( "pw/ph %d/%d\n", pwidth, pheight );
     225
    135226    w *= zoom;
    136227    h *= zoom;
     
    149240    LONG rclx = w;
    150241    LONG rcly = h;
    151     LuPixbuf *pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
    152     POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
    153                            rclDraw.xRight-1, rclDraw.yTop-1,
    154                            0, 0, rclx, rcly };
    155 
    156     doc->renderPageToPixbuf( ev, page, 0, 0, rclx, rcly, zoom, 0, pixbuf );
    157 
    158     LONG lRop = ROP_SRCCOPY;
    159     BITMAPINFO2 pbmi;
    160     pbmi.cbFix = 16L;
    161     pbmi.cx = rclx;
    162     pbmi.cy = rcly;
    163     pbmi.cPlanes = 1;
    164     pbmi.cBitCount = bpp * 8;
    165     GpiDrawBits( hpsPrinter, pixbuf->getDataPtr( ev ), &pbmi, 4L,
    166                  aptlPoints, lRop, BBO_IGNORE );
    167     delete pixbuf;
    168 }
    169 
    170 
    171 static void queryCurrentForm( HDC hdcPrinter, PHCINFO pcurForm )
    172 {
    173     LONG lForms = DevQueryHardcopyCaps( hdcPrinter, 0, 0, NULL );
     242    if ( doc->isRenderIntoPS( ev ) )
     243    {
     244        doc->renderPageToPS( ev, page, 0, 0, rclx, rcly, zoom, 0, hpsPrinter, &rclDraw );
     245    }
     246    else
     247    {
     248        LuPixbuf *pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
     249        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
     250                               rclDraw.xRight-1, rclDraw.yTop-1,
     251                               0, 0, rclx, rcly };
     252
     253        doc->renderPageToPixbuf( ev, page, 0, 0, rclx, rcly, zoom, 0, pixbuf );
     254
     255        LONG lRop = ROP_SRCCOPY;
     256        BITMAPINFO2 pbmi;
     257        pbmi.cbFix = 16L;
     258        pbmi.cx = rclx;
     259        pbmi.cy = rcly;
     260        pbmi.cPlanes = 1;
     261        pbmi.cBitCount = bpp * 8;
     262        GpiDrawBits( hpsPrinter, pixbuf->getDataPtr( ev ), &pbmi, 4L,
     263                     aptlPoints, lRop, BBO_IGNORE );
     264        delete pixbuf;
     265    }
     266}
     267
     268
     269
     270bool LucidePrinting::doPsPrint( HAB lhab )
     271{
     272    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
     273    DEVOPENSTRUC dos   = { 0 };
     274    SIZEL        sizel = { 0 };
     275
     276    HCINFO curForm = { 0 };
     277    if ( !queryCurrentForm( lhab, &curForm ) ) {
     278        return false;
     279    }
     280
     281    char *generating_ps = newstrdupL( PRINT_GENERATING_POSTSCRIPT );
     282    progressDlg->setText( generating_ps );
     283    delete generating_ps;
     284
     285    // Magrins
     286    LONG mLeft   = __max( TEST_MARGIN, curForm.xLeftClip );
     287    LONG mBottom = __max( TEST_MARGIN, curForm.yBottomClip );
     288    LONG mRight  = __max( TEST_MARGIN, curForm.cx - curForm.xRightClip );
     289    LONG mTop    = __max( TEST_MARGIN, curForm.cy - curForm.yTopClip );
     290
     291    // Count paper page size in 1/72 inches
     292    double pwidth = ( (double)( curForm.cx - mLeft - mRight ) / 25.4 ) * 72.0;
     293    double pheight = ( (double)( curForm.cy - mTop - mBottom ) / 25.4 ) * 72.0;
     294
     295    char *tmpps = "TMPLUCID.PS";
     296    BOOL rc = doc->exportToPostScript( ev, tmpps, psetup->pgfrom-1, psetup->pgto-1,
     297                                       pwidth, pheight, false );
     298    if ( !rc ) {
     299        unlink( tmpps );
     300        return false;
     301    }
     302    if ( abortPrinting ) {
     303        unlink( tmpps );
     304        return true;
     305    }
     306
     307    char *spooling_ps = newstrdupL( PRINT_SPOOLING_POSTSCRIPT );
     308    progressDlg->setText( spooling_ps );
     309    delete spooling_ps;
     310
     311    // build a devopenstruct for the call to SplQmOpen
     312    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
     313    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
     314    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
     315    dos.pszDriverName = achDriverName;                          // 2
     316    dos.pdriv         = psetup->QueueInfo.pDriverData;          // 3
     317    dos.pszDataType   = "PM_Q_RAW";                             // 4
     318
     319    HSPL hspl = SplQmOpen( "*", 4L, (PQMOPENDATA)&dos );
     320    if ( hspl == SPL_ERROR ) {
     321        unlink( tmpps );
     322        return false;
     323    }
     324
     325    rc = SplQmStartDoc( hspl, title );
     326    if ( !rc ) {
     327        SplQmAbort( hspl );
     328        unlink( tmpps );
     329        return false;
     330    }
     331
     332    FILE *f = fopen( tmpps, "rb" );
     333    if ( f == NULL ) {
     334        SplQmAbort( hspl );
     335        unlink( tmpps );
     336        return false;
     337    }
     338
     339    bool splerr = false;
     340    void *buf = malloc( PS_PRINT_BUF_SIZE );
     341    int rd = 0;
     342    while ( rc && ( rd = fread( buf, 1, PS_PRINT_BUF_SIZE, f ) ) != 0 ) {
     343        rc = SplQmWrite( hspl, rd, buf );
     344        if ( !rc || abortPrinting ) {
     345            splerr = true;
     346            break;
     347        }
     348    }
     349    free( buf );
     350    fclose( f );
     351    unlink( tmpps );
     352
     353    if ( splerr ) {
     354        SplQmAbort( hspl );
     355        if ( !abortPrinting ) {
     356            return false;
     357        }
     358    }
     359    else {
     360        SplQmEndDoc( hspl );
     361        SplQmClose( hspl );
     362    }
     363
     364    return true;
     365}
     366
     367bool LucidePrinting::queryCurrentForm( HAB lhab, PHCINFO pcurForm )
     368{
     369    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
     370    DEVOPENSTRUC dos   = { 0 };
     371    // build a devopenstruct for the call to DevOpenDC
     372    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
     373    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
     374    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
     375    dos.pszDriverName = achDriverName;                          // 2
     376    dos.pdriv = psetup->QueueInfo.pDriverData;                  // 3
     377
     378    HDC hdcPrinterInfo = DevOpenDC( lhab, OD_INFO, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
     379    if ( hdcPrinterInfo == DEV_ERROR ) {
     380        return false;
     381    }
     382
     383    //long lTech = 0;
     384    //DevQueryCaps( hdcPrinterInfo, CAPS_TECHNOLOGY, sizeof(long), &lTech );
     385    //somPrintf( "lTech: 0x%x\n", lTech );
     386
     387    LONG lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, 0, NULL );
    174388    if ( lForms == DQHC_ERROR ) {
    175         return;
     389        DevCloseDC( hdcPrinterInfo );
     390        return false;
    176391    }
    177392
    178393    HCINFO *forms = new HCINFO[ lForms ];
    179394    memset( forms, 0, sizeof( HCINFO ) * lForms );
    180     lForms = DevQueryHardcopyCaps( hdcPrinter, 0, lForms, forms );
     395    lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, lForms, forms );
    181396    if ( lForms == DQHC_ERROR ) {
    182397        delete forms;
    183         return;
     398        DevCloseDC( hdcPrinterInfo );
     399        return false;
    184400    }
    185401
     
    190406        }
    191407    }
     408
    192409    delete forms;
    193 }
    194 
     410    DevCloseDC( hdcPrinterInfo );
     411    return true;
     412}
     413
     414// static method
     415void LucidePrinting::printabort( void *data )
     416{
     417    ((LucidePrinting *)data)->abortPrinting = true;
     418}
     419
     420// static method, thread for asynchronous printing
     421void LucidePrinting::printthread( void *p )
     422{
     423    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0 );
     424    LucidePrinting *_this = (LucidePrinting *)p;
     425
     426    HAB thab = WinInitialize( 0 );
     427    HMQ thmq = WinCreateMsgQueue( thab, 0 );
     428
     429    bool printOk = false;
     430    if ( _this->psetup->ptype == TypePostScript ) {
     431        printOk = _this->doPsPrint( thab );
     432    }
     433    else {
     434        printOk = _this->doPmPrint( thab );
     435    }
     436    _this->progressDlg->hide();
     437
     438    if ( !printOk )
     439    {
     440        char *printfailed = newstrdupL( PRINT_FAILED );
     441        WinMessageBox( HWND_DESKTOP, _this->hFrame, printfailed, NULL,
     442                       1, MB_OK | MB_ERROR | MB_MOVEABLE );
     443        delete printfailed;
     444    }
     445
     446    WinDestroyMsgQueue( thmq );
     447    WinTerminate( thab );
     448    _endthread();
     449
     450    delete _this;
     451}
     452
Note: See TracChangeset for help on using the changeset viewer.