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

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

basic printing, postscript and bitmap

File size: 14.6 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// OpenWatcom headers doesn't have GpiDrawBits() declaration
58extern "C" {
59    LONG APIENTRY GpiDrawBits(HPS hps, PVOID pBits, PBITMAPINFO2 pbmiInfoTable,
60                              LONG lCount, PPOINTL aptlPoints, LONG lRop, ULONG flOptions);
61}
62
63#ifndef DEVESC_ERROR
64#define DEVESC_ERROR        (-1L)
65#endif
66
67#define UNITS_MULTIPLIER    100
68#define STD_IMAGE_ZOOM      2.0
69#define HIGH_IMAGE_ZOOM     3.0
70#define PS_PRINT_BUF_SIZE   32768
71#define TEST_MARGIN         10
72
73
74class LucidePrinting
75{
76    public:
77        LucidePrinting( HWND hWndFrame, LuDocument *_doc,
78                        const char *_title, PrintSetup *_psetup );
79        ~LucidePrinting();
80        void doPrint();
81
82    private:
83        bool queryCurrentForm( HAB lhab, PHCINFO pcurForm );
84        void printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm );
85        bool doPmPrint( HAB lhab );
86        bool doPsPrint( HAB lhab );
87
88        HWND hFrame;
89        LuDocument *doc;
90        char *title;
91        PrintSetup *psetup;
92        boolean abortPrinting;
93        ProgressDlg *progressDlg;
94
95        static void printabort( void *data );
96        static void printthread( void *data );
97};
98
99
100void printDocument( HWND hWndFrame, LuDocument *doc, const char *title, PrintSetup *psetup )
101{
102    LucidePrinting *p = new LucidePrinting( hWndFrame, doc, title, psetup );
103    p->doPrint();
104}
105
106
107LucidePrinting::LucidePrinting( HWND hWndFrame, LuDocument *_doc,
108                                const char *_title, PrintSetup *_psetup )
109{
110    hFrame = hWndFrame;
111    doc    = _doc;
112    title  = newstrdup( _title );
113    psetup = new PrintSetup;
114    memcpy( psetup, _psetup, sizeof( PrintSetup ) );
115    abortPrinting = false;
116    progressDlg = new ProgressDlg( hWndFrame );
117}
118
119LucidePrinting::~LucidePrinting()
120{
121    delete title;
122    delete psetup;
123    delete progressDlg;
124}
125
126void LucidePrinting::doPrint()
127{
128    progressDlg->setBreakFunc( printabort, this );
129    progressDlg->setText( "" );
130    progressDlg->show( printthread, this );
131}
132
133bool LucidePrinting::doPmPrint( HAB lhab )
134{
135    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
136    DEVOPENSTRUC dos   = { 0 };
137    SIZEL        sizel = { 0 };
138
139    HCINFO curForm = { 0 };
140    if ( !queryCurrentForm( lhab, &curForm ) ) {
141        return false;
142    }
143
144    // build a devopenstruct for the call to DevOpenDC
145    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
146    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
147    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
148    dos.pszDriverName = achDriverName;                          // 2
149    dos.pdriv         = psetup->QueueInfo.pDriverData;          // 3
150    dos.pszDataType   = "PM_Q_STD";                             // 4
151
152    HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 4L, (PDEVOPENDATA)&dos, NULLHANDLE );
153    if ( hdcPrinter == DEV_ERROR ) {
154        return false;
155    }
156
157    // PS in HiMetric, 0.01 mm
158    HPS hpsPrinter = GpiCreatePS( lhab, hdcPrinter, &sizel, PU_HIMETRIC | GPIA_ASSOC );
159    if ( hpsPrinter == DEV_ERROR ) {
160        DevCloseDC( hdcPrinter );
161        return false;
162    }
163
164    // Issue STARTDOC to begin printing
165    DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
166
167    long totalpages = psetup->pgto - psetup->pgfrom + 1;
168    for ( long pg = psetup->pgfrom; pg <= psetup->pgto; pg++ )
169    {
170        char *fmt = newstrdupL( PRINT_PRINTING_PAGE_OF );
171        char *buf = new char[ 255 ];
172        snprintf( buf, 255, fmt, pg, totalpages );
173        progressDlg->setText( buf );
174        delete fmt;
175        delete buf;
176
177        printPagePm( pg - 1, hpsPrinter, &curForm );
178
179        if ( pg != psetup->pgto ) {
180            DevEscape( hdcPrinter, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL );
181        }
182
183        if ( abortPrinting ) {
184            break;
185        }
186    }
187
188    // Issue DEVESC_ENDDOC, or DEVESC_ABORTDOC if printing was aborted
189    DevEscape( hdcPrinter, abortPrinting ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
190               0L, NULL, NULL, NULL );
191
192    // Release PS and DC
193    GpiAssociate( hpsPrinter, NULLHANDLE );
194    GpiDestroyPS( hpsPrinter );
195    DevCloseDC( hdcPrinter );
196    return true;
197}
198
199
200void LucidePrinting::printPagePm( long page, HPS hpsPrinter, PHCINFO pcurForm )
201{
202    long bpp = doc->getBpp( ev );
203    double w = 0, h = 0;
204    doc->getPageSize( ev, page, &w, &h );
205
206    // Magrins
207    LONG mLeft   = __max( TEST_MARGIN, pcurForm->xLeftClip );
208    LONG mBottom = __max( TEST_MARGIN, pcurForm->yBottomClip );
209    LONG mRight  = __max( TEST_MARGIN, pcurForm->cx - pcurForm->xRightClip );
210    LONG mTop    = __max( TEST_MARGIN, pcurForm->cy - pcurForm->yTopClip );
211
212    // Count paper page size in hi-metric
213    LONG pwidth = ( pcurForm->cx - mLeft - mRight ) * UNITS_MULTIPLIER;
214    LONG pheight = ( pcurForm->cy - mTop - mBottom ) * UNITS_MULTIPLIER;
215
216    double zoom = 1.0;
217    if ( doc->isScalable( ev ) )
218    {
219        double maxcoeff = psetup->higherQuality ? HIGH_IMAGE_ZOOM : STD_IMAGE_ZOOM;
220        zoom = __min( (double)pwidth / w, (double)pheight / h );
221        if ( zoom > maxcoeff ) {
222            zoom = maxcoeff;
223        }
224    }
225
226    //somPrintf( "Doc pgsz: %g/%g  zoom: %g\n", w, h, zoom );
227    //somPrintf( "Paper %s, pgsz: %d/%d\n", pcurForm->szFormname, pcurForm->cx, pcurForm->cy );
228    //somPrintf( "pw/ph %d/%d\n", pwidth, pheight );
229
230    w *= zoom;
231    h *= zoom;
232    double pgzoom = __min( (double)pwidth / w, (double)pheight / h );
233
234    // Printed size
235    LONG prwidth = w * pgzoom;
236    LONG prheight = h * pgzoom;
237    LONG yPos = 0;
238    if ( prheight < pheight ) {
239        yPos = pheight - prheight;
240    }
241    RECTL rclDraw = { mLeft*UNITS_MULTIPLIER, (mBottom*UNITS_MULTIPLIER)+yPos,
242                      prwidth, prheight+yPos };
243
244    LONG rclx = w;
245    LONG rcly = h;
246    if ( doc->isRenderIntoPS( ev ) )
247    {
248        doc->renderPageToPS( ev, page, 0, 0, rclx, rcly, zoom, 0, hpsPrinter, &rclDraw );
249    }
250    else
251    {
252        LuPixbuf *pixbuf = new LuPixbuf( ev, rclx, rcly, bpp );
253        POINTL aptlPoints[4]={ rclDraw.xLeft, rclDraw.yBottom,
254                               rclDraw.xRight-1, rclDraw.yTop-1,
255                               0, 0, rclx, rcly };
256
257        doc->renderPageToPixbuf( ev, page, 0, 0, rclx, rcly, zoom, 0, pixbuf );
258
259        LONG lRop = ROP_SRCCOPY;
260        BITMAPINFO2 pbmi;
261        pbmi.cbFix = 16L;
262        pbmi.cx = rclx;
263        pbmi.cy = rcly;
264        pbmi.cPlanes = 1;
265        pbmi.cBitCount = bpp * 8;
266        GpiDrawBits( hpsPrinter, pixbuf->getDataPtr( ev ), &pbmi, 4L,
267                     aptlPoints, lRop, BBO_IGNORE );
268        delete pixbuf;
269    }
270}
271
272
273bool LucidePrinting::doPsPrint( HAB lhab )
274{
275    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
276    DEVOPENSTRUC dos   = { 0 };
277    SIZEL        sizel = { 0 };
278
279    HCINFO curForm = { 0 };
280    if ( !queryCurrentForm( lhab, &curForm ) ) {
281        return false;
282    }
283
284    char *generating_ps = newstrdupL( PRINT_GENERATING_POSTSCRIPT );
285    progressDlg->setText( generating_ps );
286    delete generating_ps;
287
288    // Magrins
289    LONG mLeft   = __max( TEST_MARGIN, curForm.xLeftClip );
290    LONG mBottom = __max( TEST_MARGIN, curForm.yBottomClip );
291    LONG mRight  = __max( TEST_MARGIN, curForm.cx - curForm.xRightClip );
292    LONG mTop    = __max( TEST_MARGIN, curForm.cy - curForm.yTopClip );
293
294    // Count paper page size in 1/72 inches
295    double pwidth = ( (double)( curForm.cx - mLeft - mRight ) / 25.4 ) * 72.0;
296    double pheight = ( (double)( curForm.cy - mTop - mBottom ) / 25.4 ) * 72.0;
297
298    char tmpps[ CCHMAXPATHCOMP ] = "";
299    char *tmpenv = getenv( "TMP" );
300    strcpy( tmpps, ( tmpenv == NULL ) ? ".\\" : tmpenv );
301    if ( tmpps[ strlen( tmpps ) - 1 ] != '\\' ) {
302        strcat( tmpps, "\\" );
303    }
304    strcat( tmpps, "TMPLUCID.PS" );
305
306    boolean rcexp = doc->exportToPostScript( ev, tmpps, psetup->pgfrom-1, psetup->pgto-1,
307                                             pwidth, pheight, false, &abortPrinting );
308
309    if ( abortPrinting ) {
310        unlink( tmpps );
311        return true;
312    }
313    if ( !rcexp ) {
314        unlink( tmpps );
315        return false;
316    }
317
318    char *spooling_ps = newstrdupL( PRINT_SPOOLING_POSTSCRIPT );
319    progressDlg->setText( spooling_ps );
320    delete spooling_ps;
321
322    // build a devopenstruct for the call to DevOpenDC
323    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
324    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
325    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
326    dos.pszDriverName = achDriverName;                          // 2
327    dos.pdriv         = psetup->QueueInfo.pDriverData;          // 3
328    dos.pszDataType   = "PM_Q_RAW";                             // 4
329
330    HDC hdcPrinter = DevOpenDC( lhab, OD_QUEUED, "*", 4L, (PDEVOPENDATA)&dos, NULLHANDLE );
331    if ( hdcPrinter == DEV_ERROR ) {
332        unlink( tmpps );
333        return false;
334    }
335
336    // Issue STARTDOC to begin printing
337    LONG rc = DevEscape( hdcPrinter, DEVESC_STARTDOC, strlen(title), (PBYTE)title, NULL, NULL );
338    if ( rc == DEVESC_ERROR ) {
339        DevCloseDC( hdcPrinter );
340        unlink( tmpps );
341        return false;
342    }
343
344    FILE *f = fopen( tmpps, "rb" );
345    if ( f == NULL ) {
346        DevEscape( hdcPrinter, DEVESC_ABORTDOC, 0L, NULL, NULL, NULL );
347        DevCloseDC( hdcPrinter );
348        unlink( tmpps );
349        return false;
350    }
351
352    bool splerr = false;
353    void *buf = malloc( PS_PRINT_BUF_SIZE );
354    int rd = 0;
355    while ( ( rc != DEVESC_ERROR ) && ( rd = fread( buf, 1, PS_PRINT_BUF_SIZE, f ) ) != 0 )
356    {
357        rc = DevEscape( hdcPrinter, DEVESC_RAWDATA, rd, (char *)buf, NULL, NULL );
358        if ( ( rc == DEVESC_ERROR ) || abortPrinting ) {
359            splerr = true;
360            break;
361        }
362    }
363    free( buf );
364    fclose( f );
365    unlink( tmpps );
366
367    DevEscape( hdcPrinter, splerr ? DEVESC_ABORTDOC : DEVESC_ENDDOC,
368               0L, NULL, NULL, NULL );
369    DevCloseDC( hdcPrinter );
370
371    if ( splerr && !abortPrinting ) {
372        return false;
373    }
374
375    return true;
376}
377
378
379bool LucidePrinting::queryCurrentForm( HAB lhab, PHCINFO pcurForm )
380{
381    CHAR         achDriverName[ DRIVERNAME_LENGTH ] = "";
382    DEVOPENSTRUC dos   = { 0 };
383    // build a devopenstruct for the call to DevOpenDC
384    dos.pszLogAddress = psetup->QueueInfo.pszName;              // 1
385    strcpy( achDriverName, psetup->QueueInfo.pszDriverName );
386    achDriverName[ strcspn( achDriverName, "." ) ] = '\0';
387    dos.pszDriverName = achDriverName;                          // 2
388    dos.pdriv = psetup->QueueInfo.pDriverData;                  // 3
389
390    HDC hdcPrinterInfo = DevOpenDC( lhab, OD_INFO, "*", 3L, (PDEVOPENDATA)&dos, NULLHANDLE );
391    if ( hdcPrinterInfo == DEV_ERROR ) {
392        return false;
393    }
394
395    //long lTech = 0;
396    //DevQueryCaps( hdcPrinterInfo, CAPS_TECHNOLOGY, sizeof(long), &lTech );
397    //somPrintf( "lTech: 0x%x\n", lTech );
398
399    LONG lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, 0, NULL );
400    if ( lForms == DQHC_ERROR ) {
401        DevCloseDC( hdcPrinterInfo );
402        return false;
403    }
404
405    HCINFO *forms = new HCINFO[ lForms ];
406    memset( forms, 0, sizeof( HCINFO ) * lForms );
407    lForms = DevQueryHardcopyCaps( hdcPrinterInfo, 0, lForms, forms );
408    if ( lForms == DQHC_ERROR ) {
409        delete forms;
410        DevCloseDC( hdcPrinterInfo );
411        return false;
412    }
413
414    for ( LONG i = 0; i < lForms; i++ ) {
415        if ( forms[i].flAttributes & HCAPS_CURRENT ) {
416            memcpy( pcurForm, &( forms[i] ), sizeof( HCINFO ) );
417            break;
418        }
419    }
420
421    delete forms;
422    DevCloseDC( hdcPrinterInfo );
423    return true;
424}
425
426// static method
427void LucidePrinting::printabort( void *data )
428{
429    ((LucidePrinting *)data)->abortPrinting = true;
430}
431
432// static method, thread for asynchronous printing
433void LucidePrinting::printthread( void *p )
434{
435    DosSetPriority( PRTYS_THREAD, PRTYC_IDLETIME, PRTYD_MAXIMUM, 0 );
436    LucidePrinting *_this = (LucidePrinting *)p;
437
438    HAB thab = WinInitialize( 0 );
439    HMQ thmq = WinCreateMsgQueue( thab, 0 );
440
441    bool printOk = false;
442    if ( _this->psetup->ptype == TypePostScript ) {
443        printOk = _this->doPsPrint( thab );
444    }
445    else {
446        printOk = _this->doPmPrint( thab );
447    }
448    _this->progressDlg->hide();
449
450    if ( !printOk )
451    {
452        char *printfailed = newstrdupL( PRINT_FAILED );
453        WinMessageBox( HWND_DESKTOP, _this->hFrame, printfailed, NULL,
454                       1, MB_OK | MB_ERROR | MB_MOVEABLE );
455        delete printfailed;
456    }
457
458    WinDestroyMsgQueue( thmq );
459    WinTerminate( thab );
460    _endthread();
461
462    delete _this;
463}
464
Note: See TracBrowser for help on using the repository browser.