source: trunk/Lucide/SOURCE/gui/print.cpp @ 179

Last change on this file since 179 was 179, checked in by Eugene Romanenko, 15 years ago

Use raw data format for print queue, this avoid metafile creation during 'as image' printing and speedups printing. Removed NeuQuant? as not used anymore.

File size: 15.4 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2 * Version: CDDL 1.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the COMMON DEVELOPMENT AND
5 * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6 * this file except in compliance with the License. You may obtain a copy of
7 * the License at http://www.sun.com/cddl/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Initial Developer of the Original Code is
15 * Eugene Romanenko, netlabs.org.
16 * Portions created by the Initial Developer are Copyright (C) 2006
17 * the Initial Developer. All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the terms of
22 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
23 * in which case the provisions of the LGPL are applicable instead of those
24 * above. If you wish to allow use of your version of this file only under the
25 * terms of the LGPL, and not to allow others to use your version of this file
26 * under the terms of the CDDL, indicate your decision by deleting the
27 * provisions above and replace them with the notice and other provisions
28 * required by the LGPL. If you do not delete the provisions above, a recipient
29 * may use your version of this file under the terms of any one of the CDDL
30 * or the LGPL.
31 *
32 * ***** END LICENSE BLOCK ***** */
33
34
35#define INCL_WIN
36#define INCL_GPI
37#define INCL_DOS
38#define INCL_DEV
39#define INCL_ERRORS
40#define INCL_SPL
41#define INCL_SPLDOSPRINT
42#include <os2.h>
43
44#include <ludoc.xh>
45
46#include <string.h>
47#include <process.h>
48#include <stdio.h>
49#include <io.h>
50
51#include "globals.h"
52#include "progressDlg.h"
53#include "print.h"
54#include "luutils.h"
55#include "messages.h"
56
57
58#ifndef DEVESC_ERROR
59#define DEVESC_ERROR        (-1L)
60#endif
61
62#define UNITS_MULTIPLIER    100
63#define STD_IMAGE_ZOOM      2.0
64#define HIGH_IMAGE_ZOOM     3.0
65#define PS_PRINT_BUF_SIZE   32768
66
67
68class LucidePrinting
69{
70    public:
71        LucidePrinting( HWND hWndFrame, LuDocument *_doc,
72                        const char *_title, PrintSetup *_psetup );
73        ~LucidePrinting();
74        void doPrint();
75
76    private:
77        bool queryCurrentForm( HAB lhab, PHCINFO pcurForm );
78        void printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm );
79        bool doPmPrint( HAB lhab );
80        bool doPsPrint( HAB lhab );
81
82        HWND hFrame;
83        LuDocument *doc;
84        char *title;
85        PrintSetup *psetup;
86        boolean abortPrinting;
87        ProgressDlg *progressDlg;
88
89        static void printabort( void *data );
90        static void printthread( void *data );
91};
92
93
94void printDocument( HWND hWndFrame, LuDocument *doc, const char *title, PrintSetup *psetup )
95{
96    LucidePrinting *p = new LucidePrinting( hWndFrame, doc, title, psetup );
97    p->doPrint();
98}
99
100
101LucidePrinting::LucidePrinting( HWND hWndFrame, LuDocument *_doc,
102                                const char *_title, PrintSetup *_psetup )
103{
104    hFrame = hWndFrame;
105    doc    = _doc;
106    title  = newstrdup( _title );
107    psetup = new PrintSetup;
108    memcpy( psetup, _psetup, sizeof( PrintSetup ) );
109    abortPrinting = false;
110    progressDlg = new ProgressDlg( hWndFrame );
111}
112
113LucidePrinting::~LucidePrinting()
114{
115    delete title;
116    delete psetup;
117    delete progressDlg;
118}
119
120void LucidePrinting::doPrint()
121{
122    progressDlg->setBreakFunc( printabort, this );
123    progressDlg->setText( "" );
124    progressDlg->show( printthread, this );
125}
126
127bool LucidePrinting::doPmPrint( HAB lhab )
128{
129    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
130    CHAR         achQueueProcParams[ 8 ] = "";
131    DEVOPENSTRUC dos   = { 0 };
132    SIZEL        sizel = { 0 };
133
134    HCINFO curForm = { 0 };
135    if ( !queryCurrentForm( lhab, &curForm ) ) {
136        return false;
137    }
138
139    // build a devopenstruct for the call to DevOpenDC
140    dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
141    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
142    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
143    dos.pszDriverName      = achDriverName;                          // 2
144    dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
145    dos.pszDataType        = "PM_Q_RAW";                             // 4
146    dos.pszComment         = (PSZ)appName;                           // 5
147    dos.pszQueueProcName   = NULL;                                   // 6
148    snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
149    dos.pszQueueProcParams = achQueueProcParams;                     // 7
150
151    HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
152    if ( hdcPrinter == DEV_ERROR ) {
153        return false;
154    }
155
156    // PS in HiMetric, 0.01 mm
157    HPS hpsPrinter = GpiCreatePS( lhab, hdcPrinter, &sizel, PU_HIMETRIC | GPIA_ASSOC );
158    if ( hpsPrinter == DEV_ERROR ) {
159        DevCloseDC( hdcPrinter );
160        return false;
161    }
162
163    // Issue STARTDOC to begin printing
164    DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
165
166
167    long totalpages = abs( psetup->pgto - psetup->pgfrom ) + 1;
168    long pg = psetup->pgfrom;
169    for ( long i = 0; i < totalpages; i++ )
170    {
171        char *fmt = newstrdupL( PRINT_PRINTING_PAGE_OF );
172        char *buf = new char[ 255 ];
173        snprintf( buf, 255, fmt, pg, i + 1, totalpages );
174        progressDlg->setText( buf );
175        delete fmt;
176        delete buf;
177
178        printPagePm( pg - 1, hpsPrinter, &curForm );
179
180        if ( pg != psetup->pgto ) {
181            DevEscape( hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL );
182        }
183
184        if ( abortPrinting ) {
185            break;
186        }
187
188        pg += ( psetup->pgfrom <= psetup->pgto ) ? 1 : -1;
189    }
190
191    // Issue DEVESC_ENDDOC, or DEVESC_ABORTDOC if printing was aborted
192    DevEscape( hdcPrinter, abortPrinting ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
193               0L, NULL, NULL, NULL );
194
195    // Release PS and DC
196    GpiAssociate( hpsPrinter, NULLHANDLE );
197    GpiDestroyPS( hpsPrinter );
198    DevCloseDC( hdcPrinter );
199    return true;
200}
201
202
203void LucidePrinting::printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm )
204{
205    long bpp = doc->getBpp( ev );
206    double w = 0, h = 0;
207    doc->getPageSize( ev, page, &w, &h );
208
209    // Magrins
210    LONG mLeft   = __max( psetup->margin_left, pcurForm->xLeftClip );
211    LONG mBottom = __max( psetup->margin_bottom, pcurForm->yBottomClip );
212    LONG mRight  = __max( psetup->margin_right, pcurForm->cx - pcurForm->xRightClip );
213    LONG mTop    = __max( psetup->margin_top, pcurForm->cy - pcurForm->yTopClip );
214
215    // Count paper page size in hi-metric
216    LONG pwidth = ( pcurForm->cx - mLeft - mRight ) * UNITS_MULTIPLIER;
217    LONG pheight = ( pcurForm->cy - mTop - mBottom ) * UNITS_MULTIPLIER;
218
219    double zoom = 1.0;
220    if ( doc->isScalable( ev ) && !doc->isFixedImage( ev ) )
221    {
222        double maxcoeff = psetup->higherQuality ? HIGH_IMAGE_ZOOM : STD_IMAGE_ZOOM;
223        zoom = __min( (double)pwidth / w, (double)pheight / h );
224        if ( zoom > maxcoeff ) {
225            zoom = maxcoeff;
226        }
227    }
228
229    //somPrintf( "Doc pgsz: %g/%g  zoom: %g\n", w, h, zoom );
230    //somPrintf( "Paper %s, pgsz: %d/%d\n", pcurForm->szFormname, pcurForm->cx, pcurForm->cy );
231    //somPrintf( "pw/ph %d/%d\n", pwidth, pheight );
232
233    w *= zoom;
234    h *= zoom;
235    double pgzoom = __min( (double)pwidth / w, (double)pheight / h );
236
237    // Printed size
238    LONG prwidth = w * pgzoom;
239    LONG prheight = h * pgzoom;
240    LONG yPos = 0;
241    if ( prheight < pheight ) {
242        yPos = pheight - prheight;
243    }
244    RECTL rclDraw = { mLeft*UNITS_MULTIPLIER, (mBottom*UNITS_MULTIPLIER)+yPos,
245                      prwidth, prheight+yPos };
246
247    LONG rclx = w;
248    LONG rcly = h;
249
250    if ( doc->isRenderIntoPS( ev ) )
251    {
252        doc->renderPageToPS( ev, page, 0, 0, rclx, rcly, zoom, 0, hpsPrinter, &rclDraw,
253                             NULL, NULL );
254    }
255    else
256    {
257        LuPixbuf *pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
258        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
259                               rclDraw.xRight-1, rclDraw.yTop-1,
260                               0, 0, rclx, rcly };
261
262        doc->renderPageToPixbuf( ev, page, 0, 0, rclx, rcly, zoom, 0, pixbuf,
263                                 NULL, NULL );
264
265        LONG lRop = ROP_SRCCOPY;
266        BITMAPINFO2 pbmi;
267        pbmi.cbFix = 16L;
268        pbmi.cx = rclx;
269        pbmi.cy = rcly;
270        pbmi.cPlanes = 1;
271        pbmi.cBitCount = bpp * 8;
272        GpiDrawBits( hpsPrinter, pixbuf->getDataPtr( ev ), &pbmi, 4L,
273                     aptlPoints, lRop, BBO_IGNORE );
274        delete pixbuf;
275    }
276}
277
278
279bool LucidePrinting::doPsPrint( HAB lhab )
280{
281    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
282    CHAR         achQueueProcParams[ 8 ] = "";
283    DEVOPENSTRUC dos   = { 0 };
284    SIZEL        sizel = { 0 };
285
286    HCINFO curForm = { 0 };
287    if ( !queryCurrentForm( lhab, &curForm ) ) {
288        return false;
289    }
290
291    char *generating_ps = newstrdupL( PRINT_GENERATING_POSTSCRIPT );
292    progressDlg->setText( generating_ps );
293    delete generating_ps;
294
295    // Magrins
296    LONG mLeft   = __max( psetup->margin_left, curForm.xLeftClip );
297    LONG mBottom = __max( psetup->margin_bottom, curForm.yBottomClip );
298    LONG mRight  = __max( psetup->margin_right, curForm.cx - curForm.xRightClip );
299    LONG mTop    = __max( psetup->margin_top, curForm.cy - curForm.yTopClip );
300
301    // Count paper page size in 1/72 inches
302    double pwidth = ( (double)( curForm.cx - mLeft - mRight ) / 25.4 ) * 72.0;
303    double pheight = ( (double)( curForm.cy - mTop - mBottom ) / 25.4 ) * 72.0;
304
305    char tmpps[ CCHMAXPATH ] = "";
306    if ( psetup->psToFile ) {
307        strcpy( tmpps, psetup->psFile );
308    }
309    else {
310        getTmpDir( tmpps );
311        strcat( tmpps, "TMPLUCID.PS" );
312    }
313
314    boolean rcexp = doc->exportToPostScript( ev, tmpps, psetup->pgfrom-1, psetup->pgto-1,
315                                             pwidth, pheight, &abortPrinting );
316
317    if ( abortPrinting ) {
318        unlink( tmpps );
319        return true;
320    }
321    if ( !rcexp ) {
322        unlink( tmpps );
323        return false;
324    }
325
326    if ( !psetup->psToFile )
327    {
328        char *spooling_ps = newstrdupL( PRINT_SPOOLING_POSTSCRIPT );
329        progressDlg->setText( spooling_ps );
330        delete spooling_ps;
331
332        // build a devopenstruct for the call to DevOpenDC
333        dos.pszLogAddress      = psetup->QueueInfo.pszName;              // 1
334        strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
335        achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
336        dos.pszDriverName      = achDriverName;                          // 2
337        dos.pdriv              = psetup->QueueInfo.pDriverData;          // 3
338        dos.pszDataType        = "PM_Q_RAW";                             // 4
339        dos.pszComment         = (PSZ)appName;                           // 5
340        dos.pszQueueProcName   = NULL;                                   // 6
341        snprintf( achQueueProcParams, sizeof( achQueueProcParams ), "COP=%d", psetup->copies );
342        dos.pszQueueProcParams = achQueueProcParams;                     // 7
343
344        HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 7L, (PDEVOPENDATA)&dos, NULLHANDLE );
345        if ( hdcPrinter == DEV_ERROR ) {
346            unlink( tmpps );
347            return false;
348        }
349
350        // Issue STARTDOC to begin printing
351        LONG rc = DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
352        if ( rc == DEVESC_ERROR ) {
353            DevCloseDC( hdcPrinter );
354            unlink( tmpps );
355            return false;
356        }
357
358        FILE *f = fopen( tmpps, "rb" );
359        if ( f == NULL ) {
360            DevEscape( hdcPrinter, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL );
361            DevCloseDC( hdcPrinter );
362            unlink( tmpps );
363            return false;
364        }
365
366        bool splerr = false;
367        void *buf = malloc( PS_PRINT_BUF_SIZE );
368        int rd = 0;
369        while ( ( rc != DEVESC_ERROR ) && ( rd = fread( buf, 1, PS_PRINT_BUF_SIZE, f ) ) != 0 )
370        {
371            rc = DevEscape( hdcPrinter, DEVESC_RAWDATA, rd, (char *)buf, NULL, NULL );
372            if ( ( rc == DEVESC_ERROR ) || abortPrinting ) {
373                splerr = true;
374                break;
375            }
376        }
377        free( buf );
378        fclose( f );
379        unlink( tmpps );
380
381        DevEscape( hdcPrinter, splerr ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
382                   0L, NULL, NULL, NULL );
383        DevCloseDC( hdcPrinter );
384
385        if ( splerr && !abortPrinting ) {
386            return false;
387        }
388    }
389
390    return true;
391}
392
393
394bool LucidePrinting::queryCurrentForm( HAB lhab, PHCINFO pcurForm )
395{
396    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
397    DEVOPENSTRUC dos   = { 0 };
398    // build a devopenstruct for the call to DevOpenDC
399    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
400    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
401    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
402    dos.pszDriverName = achDriverName;                          // 2
403    dos.pdriv = psetup->QueueInfo.pDriverData;                  // 3
404
405    HDC hdcPrinterInfo = DevOpenDC( lhab, OD_INFO, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
406    if ( hdcPrinterInfo == DEV_ERROR ) {
407        return false;
408    }
409
410    LONG lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, 0, NULL );
411    if ( lForms == DQHC_ERROR ) {
412        DevCloseDC( hdcPrinterInfo );
413        return false;
414    }
415
416    HCINFO *forms = new HCINFO[ lForms ];
417    memset( forms, 0, sizeof( HCINFO ) * lForms );
418    lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, lForms, forms );
419    if ( lForms == DQHC_ERROR ) {
420        delete forms;
421        DevCloseDC( hdcPrinterInfo );
422        return false;
423    }
424
425    for ( LONG i = 0; i < lForms; i++ ) {
426        if ( forms[i].flAttributes & HCAPS_CURRENT ) {
427            memcpy( pcurForm, &( forms[i] ), sizeof( HCINFO ) );
428            break;
429        }
430    }
431
432    delete forms;
433    DevCloseDC( hdcPrinterInfo );
434    return true;
435}
436
437// static method
438void LucidePrinting::printabort( void *data )
439{
440    ((LucidePrinting *)data)->abortPrinting = true;
441}
442
443// static method, thread for asynchronous printing
444void LucidePrinting::printthread( void *p )
445{
446    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0 );
447    LucidePrinting *_this = (LucidePrinting *)p;
448
449    HAB thab = WinInitialize( 0 );
450    HMQ thmq = WinCreateMsgQueue( thab, 0 );
451
452    bool printOk = false;
453    if ( _this->psetup->ptype == TypePostScript ) {
454        printOk = _this->doPsPrint( thab );
455    }
456    else {
457        printOk = _this->doPmPrint( thab );
458    }
459    _this->progressDlg->hide();
460
461    if ( !printOk )
462    {
463        char *printfailed = newstrdupL( PRINT_FAILED );
464        WinMessageBox( HWND_DESKTOP, _this->hFrame, printfailed, NULL,
465                       1, MB_OK | MB_ERROR | MB_MOVEABLE );
466        delete printfailed;
467    }
468
469    WinDestroyMsgQueue( thmq );
470    WinTerminate( thab );
471    _endthread();
472
473    delete _this;
474}
475
Note: See TracBrowser for help on using the repository browser.