LCOV - code coverage report
Current view: top level - gdraw - gpsdraw.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 875 0.0 %
Date: 2017-08-04 Functions: 0 119 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2000-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include <stdio.h>
      28             : #include <math.h>
      29             : #include <time.h>
      30             : #include <sys/types.h>
      31             : #if !defined(__MINGW32__)
      32             : #include <sys/wait.h>
      33             : #endif
      34             : #include "fontforge-config.h"
      35             : #include <unistd.h>
      36             : 
      37             : #include "gpsdrawP.h"
      38             : #include "gresource.h"
      39             : #include "colorP.h"
      40             : #include "fontP.h"
      41             : #include "ustring.h"
      42             : #include "fileutil.h"
      43             : 
      44             : /* ************************************************************************** */
      45             : /* ********************** Noops & Meaningless functions ********************* */
      46             : /* ************************************************************************** */
      47             : 
      48           0 : static void PSDrawInit(GDisplay *UNUSED(gdisp)) {
      49             :     /* delay any real initialization until they actually want to print */
      50             :     /*  no point in reading up on a bunch of fonts which never get used */
      51           0 : }
      52             : 
      53           0 : static void PSDrawTerm(GDisplay *UNUSED(gdisp)) {
      54           0 : }
      55             : 
      56           0 : static void *PSDrawNativeDisplay(GDisplay *UNUSED(gdisp)) {
      57           0 : return( NULL );
      58             : }
      59             : 
      60           0 : static void PSDrawSetDefaultIcon(GWindow UNUSED(icon)) {
      61           0 : }
      62             : 
      63           0 : static GWindow PSDrawCreateSubWindow(GWindow UNUSED(w), GRect *UNUSED(pos),
      64             :         int (*eh)(GWindow,GEvent *), void *UNUSED(user_data),
      65             :         GWindowAttrs *UNUSED(wattrs)) {
      66             :     (void)eh;
      67           0 :     fprintf( stderr, "CreateSubWindow not implemented for postscript\n" );
      68           0 : return NULL;
      69             : }
      70             : 
      71           0 : static GWindow PSDrawCreatePixmap(GDisplay *UNUSED(gdisp), uint16 UNUSED(width),
      72             :         uint16 UNUSED(height)) {
      73           0 :     fprintf( stderr, "CreatePixmap not implemented for postscript\n" );
      74           0 : return NULL;
      75             : }
      76             : 
      77           0 : static GWindow PSDrawCreateBitmap(GDisplay *UNUSED(gdisp), uint16 UNUSED(width),
      78             :         uint16 UNUSED(height), uint8 *UNUSED(data)) {
      79           0 :     fprintf( stderr, "CreateBitmap not implemented for postscript\n" );
      80           0 : return NULL;
      81             : }
      82             : 
      83           0 : static GCursor PSDrawCreateCursor(GWindow UNUSED(src), GWindow UNUSED(mask),
      84             :         Color UNUSED(fg), Color UNUSED(bg), int16 UNUSED(x), int16 UNUSED(y) ) {
      85           0 :     fprintf( stderr, "CreateCursor not implemented for postscript\n" );
      86           0 : return 0;
      87             : }
      88             : 
      89           0 : static void PSSetZoom(GWindow UNUSED(w), GRect *UNUSED(r),
      90             :         enum gzoom_flags UNUSED(flags) ) {
      91           0 :     fprintf( stderr, "SetZoom not implemented for postscript\n" );
      92           0 : }
      93             : 
      94           0 : static void PSDestroyCursor(GDisplay *UNUSED(gdisp), GCursor UNUSED(ct) ) {
      95           0 :     fprintf( stderr, "DestroyCursor not implemented for postscript\n" );
      96           0 : }
      97             : 
      98           0 : static int PSNativeWindowExists(GDisplay *UNUSED(gdisp), void *UNUSED(native) ) {
      99           0 : return( false );
     100             : }
     101             : 
     102           0 : static void PSSetWindowBorder(GWindow UNUSED(w), int UNUSED(width),
     103             :         Color UNUSED(col) ) {
     104           0 :     fprintf( stderr, "SetWindowBorder not implemented for postscript\n" );
     105           0 : }
     106             : 
     107           0 : static void PSSetWindowBackground(GWindow UNUSED(w), Color UNUSED(col) ) {
     108           0 :     fprintf( stderr, "SetWindowBackground not implemented for postscript\n" );
     109           0 : }
     110             : 
     111           0 : static int PSSetDither(GDisplay *UNUSED(gdisp), int UNUSED(dither) ) {
     112           0 :     fprintf( stderr, "SetDither not implemented for postscript\n" );
     113           0 : return( true );
     114             : }
     115             : 
     116           0 : static void PSDrawReparentWindow(GWindow UNUSED(child),
     117             :         GWindow UNUSED(newparent), int UNUSED(x), int UNUSED(y)) {
     118             :     /* It's a noop */
     119           0 : }
     120             : 
     121           0 : static void PSDrawSetVisible(GWindow UNUSED(w), int UNUSED(vis) ) {
     122             :     /* It's a noop */
     123           0 : }
     124             : 
     125           0 : static void PSDrawMove(GWindow UNUSED(w), int32 UNUSED(x), int32 UNUSED(y)) {
     126             :     /* Not meaningful */
     127           0 : }
     128             : 
     129           0 : static void PSDrawResize(GWindow UNUSED(w),
     130             :         int32 UNUSED(width), int32 UNUSED(height)) {
     131             :     /* Not meaningful */
     132           0 : }
     133             : 
     134           0 : static void PSDrawMoveResize(GWindow UNUSED(w), int32 UNUSED(x), int32 UNUSED(y),
     135             :         int32 UNUSED(width), int32 UNUSED(height)) {
     136             :     /* Not meaningful */
     137           0 : }
     138             : 
     139           0 : static void PSDrawRaise(GWindow UNUSED(w)) {
     140             :     /* Not meaningful */
     141           0 : }
     142             : 
     143           0 : static void PSDrawRaiseAbove(GWindow UNUSED(w), GWindow UNUSED(below)) {
     144             :     /* Not meaningful */
     145           0 : }
     146             : 
     147           0 : static int PSDrawIsAbove(GWindow UNUSED(w), GWindow UNUSED(below)) {
     148           0 : return( -1 );           /* Not meaningful */
     149             : }
     150             : 
     151           0 : static void PSDrawLower(GWindow UNUSED(w)) {
     152             :     /* Not meaningful */
     153           0 : }
     154             : 
     155           0 : static void PSDrawSetWindowTitles(GWindow UNUSED(w),
     156             :         const unichar_t *UNUSED(title), const unichar_t *UNUSED(icontit)) {
     157             :     /* Not meaningful */
     158           0 : }
     159             : 
     160           0 : static void PSDrawSetWindowTitles8(GWindow UNUSED(w),
     161             :         const char *UNUSED(title), const char *UNUSED(icontit)) {
     162             :     /* Not meaningful */
     163           0 : }
     164             : 
     165           0 : static void PSDrawSetTransientFor(GWindow UNUSED(transient), GWindow UNUSED(owner)) {
     166             :     /* Not meaningful */
     167           0 : }
     168             : 
     169           0 : static void PSDrawGetPointerPosition(GWindow UNUSED(w), GEvent *ret) {
     170             :     /* Not meaningful */
     171             : 
     172           0 :     ret->u.mouse.state = 0;
     173           0 :     ret->u.mouse.x = 0;
     174           0 :     ret->u.mouse.y = 0;
     175           0 : }
     176             : 
     177           0 : static GWindow PSDrawGetPointerWindow(GWindow UNUSED(w)) {
     178             :     /* Not meaningful */
     179           0 : return( NULL );
     180             : }
     181             : 
     182           0 : static void PSDrawSetCursor(GWindow UNUSED(w), GCursor UNUSED(ct)) {
     183             :     /* Not meaningful */
     184           0 : }
     185             : 
     186           0 : static GCursor PSDrawGetCursor(GWindow UNUSED(w)) {
     187             :     /* Not meaningful */
     188           0 : return( ct_default );
     189             : }
     190             : 
     191           0 : static GWindow PSDrawGetRedirectWindow(GDisplay *UNUSED(gd)) {
     192             :     /* Not meaningful */
     193           0 : return( NULL );
     194             : }
     195             : 
     196           0 : static unichar_t *PSDrawGetWindowTitle(GWindow UNUSED(w)) {
     197           0 : return(NULL);
     198             : }
     199             : 
     200           0 : static char *PSDrawGetWindowTitle8(GWindow UNUSED(w)) {
     201           0 : return(NULL);
     202             : }
     203             : 
     204           0 : static void PSDrawTranslateCoordinates(GWindow UNUSED(_from),
     205             :         GWindow UNUSED(_to), GPoint *UNUSED(pt)) {
     206             :     /* Only one window active at a time, translation is a noop */
     207           0 : }
     208             : 
     209           0 : static void PSDrawScroll(GWindow UNUSED(w), GRect *UNUSED(rect),
     210             :         int32 UNUSED(hor), int32 UNUSED(vert)) {
     211             :     /* Not meaningful */
     212           0 : }
     213             : 
     214           0 : static void PSDrawBeep(GDisplay *UNUSED(gdisp)) {
     215             :     /* Not meaningful */
     216           0 : }
     217             : 
     218           0 : static void PSDrawFlush(GDisplay *gdisp) {
     219             :     /* Not meaningful */
     220           0 :     if ( gdisp->groot!=NULL )
     221           0 :         fflush(((GPSWindow) (gdisp->groot))->output_file);
     222           0 : }
     223             : 
     224           0 : static GIC *PSDrawCreateInputContext(GWindow UNUSED(w),
     225             :         enum gic_style UNUSED(def_style)) {
     226             :     /* Not meaningful */
     227           0 : return( NULL );
     228             : }
     229             : 
     230           0 : static void PSDrawSetGIC(GWindow UNUSED(w), GIC *UNUSED(gic),
     231             :         int UNUSED(x), int UNUSED(y)) {
     232             :     /* Not meaningful */
     233           0 : }
     234             : 
     235           0 : static void PSDrawPointerUngrab(GDisplay *UNUSED(gdisp)) {
     236             :     /* Not meaningful */
     237           0 : }
     238             : 
     239           0 : static void PSDrawPointerGrab(GWindow UNUSED(w)) {
     240             :     /* Not meaningful */
     241           0 : }
     242             : 
     243           0 : static void PSDrawGrabSelection(GWindow UNUSED(w), enum selnames UNUSED(sel)) {
     244             :     /* Not meaningful */
     245           0 : }
     246             : 
     247           0 : static void PSDrawAddSelectionType(GWindow UNUSED(w), enum selnames UNUSED(sel),
     248             :         char *UNUSED(type), void *UNUSED(data), int32 UNUSED(len),
     249             :         int32 UNUSED(unitsize), void *(*gendata)(void *,int32 *len),
     250             :         void (*freedata)(void *)) {
     251             :     /* Not meaningful */
     252             :     (void)gendata;
     253             :     (void)freedata;
     254           0 : }
     255             : 
     256           0 : static void *PSDrawRequestSelection(GWindow UNUSED(w), enum selnames UNUSED(sn),
     257             :         char *UNUSED(typename), int32 *UNUSED(len)) {
     258             :     /* Not meaningful */
     259           0 : return( NULL );
     260             : }
     261             : 
     262           0 : static int PSDrawSelectionHasType(GWindow UNUSED(w), enum selnames UNUSED(sn),
     263             :         char *UNUSED(typename)) {
     264             :     /* Not meaningful */
     265           0 : return( false );
     266             : }
     267             : 
     268           0 : static void PSDrawBindSelection(GDisplay *UNUSED(disp), enum selnames UNUSED(sn),
     269             :         char *UNUSED(atomname)) {
     270             :     /* Not meaningful */
     271           0 : }
     272             : 
     273           0 : static int PSDrawSelectionHasOwner(GDisplay *UNUSED(disp), enum selnames UNUSED(sn)) {
     274             :     /* Not meaningful */
     275           0 : return( false );
     276             : }
     277             : 
     278           0 : static void PSDrawRequestExpose(GWindow UNUSED(gw), GRect *UNUSED(rect),
     279             :     int UNUSED(doclear)) {
     280             :     /* Not meaningful */
     281           0 : }
     282             : 
     283           0 : static GTimer *PSDrawRequestTimer(GWindow UNUSED(w), int32 UNUSED(time_from_now),
     284             :         int32 UNUSED(frequency), void *UNUSED(userdata)) {
     285           0 : return( NULL );
     286             : }
     287             : 
     288           0 : static void PSDrawCancelTimer(GTimer *UNUSED(timer)) {
     289           0 : }
     290             : 
     291           0 : static void PSDrawSyncThread(GDisplay *UNUSED(gdisp), void (*func)(void *), void *data) {
     292           0 :     (func)(data);
     293           0 : }
     294             : 
     295           0 : static void PSDrawForceUpdate(GWindow UNUSED(gw)) {
     296           0 : }
     297             : 
     298           0 : static void PSDrawSync(GDisplay *UNUSED(gdisp)) {
     299           0 : }
     300             : 
     301           0 : static void PSDrawSkipMouseMoveEvents(GWindow UNUSED(gw), GEvent *UNUSED(last)) {
     302           0 : }
     303             : 
     304           0 : static void PSDrawProcessPendingEvents(GDisplay *UNUSED(gdisp)) {
     305           0 : }
     306             : 
     307           0 : static void PSDrawProcessWindowEvents(GWindow UNUSED(gw)) {
     308           0 : }
     309             : 
     310           0 : static void PSDrawEventLoop(GDisplay *UNUSED(gd)) {
     311           0 : }
     312             : 
     313           0 : static void PSDrawPostEvent(GEvent *UNUSED(e)) {
     314           0 : }
     315             : 
     316           0 : static void PSDrawPostDragEvent(GWindow UNUSED(w), GEvent *UNUSED(mouse),
     317             :         enum event_type UNUSED(et)) {
     318           0 : }
     319             : 
     320           0 : static int  PSDrawRequestDeviceEvents(GWindow UNUSED(w), int UNUSED(devcnt),
     321             :         struct gdeveventmask *UNUSED(de)) {
     322           0 : return( 0 );
     323             : }
     324             : 
     325           0 : static GImage *_PSDraw_CopyScreenToImage(GWindow UNUSED(w), GRect *UNUSED(rect)) {
     326           0 : return( NULL );
     327             : }
     328             : 
     329           0 : static void _PSDraw_Pixmap( GWindow UNUSED(_w), GWindow UNUSED(_pixmap),
     330             :         GRect *UNUSED(src), int32 UNUSED(x), int32 UNUSED(y)) {
     331           0 : }
     332             : 
     333           0 : static void _PSDraw_TilePixmap( GWindow UNUSED(_w), GWindow UNUSED(_pixmap),
     334             :         GRect *UNUSED(src), int32 UNUSED(x), int32 UNUSED(y)) {
     335           0 : }
     336             : 
     337             : /* ************************************************************************** */
     338             : /* ******************************* Draw Stuff ******************************* */
     339             : /* ************************************************************************** */
     340             : 
     341           0 : double _GSPDraw_Distance(GPSWindow ps,int x) {
     342           0 : return( 72.0*(double) x/(double)ps->display->res );
     343             : }
     344             : 
     345           0 : double _GSPDraw_XPos(GPSWindow ps,int x) {
     346           0 : return( 72.0*(double) x/(double)ps->display->res );
     347             : }
     348             : 
     349           0 : double _GSPDraw_YPos(GPSWindow ps,int y) {
     350           0 : return( -72.0*(double) y/(double)ps->display->res );
     351             : }
     352             : 
     353           0 : static void PSUnbufferLine(GPSWindow ps) {
     354           0 :     if ( ps->buffered_line ) {
     355           0 :         fprintf( ps->output_file,"  %g %g lineto\n", _GSPDraw_XPos(ps,ps->line_x), _GSPDraw_YPos(ps,ps->line_y) );
     356           0 :         ++ps->pnt_cnt;
     357           0 :         ps->buffered_line = false;
     358             :     }
     359           0 : }
     360             : 
     361           0 : void _GPSDraw_FlushPath(GPSWindow ps) {
     362           0 :     if ( ps->buffered_line )
     363           0 :         PSUnbufferLine(ps);
     364           0 :     if ( ps->pnt_cnt>0 ) {
     365           0 :         fprintf( ps->output_file,"stroke\n" );
     366           0 :         ps->pnt_cnt = 0;
     367           0 :         ps->cur_x = ps->cur_y = -1;
     368             :     }
     369           0 : }
     370             : 
     371           0 : static void PSDrawNewpath(GPSWindow ps) {
     372           0 :     if ( ps->pnt_cnt!=0 ) {
     373           0 :         _GPSDraw_FlushPath(ps);
     374           0 :         fprintf( ps->output_file,"newpath\n" );
     375           0 :         ps->pnt_cnt = 0;
     376           0 :         ps->cur_x = ps->cur_y = -1;
     377             :     }
     378           0 : }
     379             : 
     380           0 : static void PSMoveTo(GPSWindow ps, int x, int y) {
     381           0 :     if ( ps->pnt_cnt>=STROKE_CACHE )
     382           0 :         _GPSDraw_FlushPath(ps);
     383           0 :     if ( ps->pnt_cnt==-1 )
     384           0 :         PSDrawNewpath(ps);
     385           0 :     if ( ps->cur_x!=x || ps->cur_y!=y ) {
     386           0 :         if ( ps->buffered_line )
     387           0 :             PSUnbufferLine(ps);
     388           0 :         fprintf( ps->output_file,"  %g %g moveto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
     389           0 :         ++ps->pnt_cnt;
     390           0 :         ps->cur_x = x; ps->cur_y = y;
     391             :     }
     392           0 : }
     393             : 
     394           0 : static void PSLineTo(GPSWindow ps, int x, int y) {
     395           0 :     if ( ps->pnt_cnt>=STROKE_CACHE )
     396           0 :         _GPSDraw_FlushPath(ps);
     397           0 :     if ( ps->pnt_cnt==-1 )
     398           0 :         PSDrawNewpath(ps);
     399           0 :     if ( ps->cur_x!=x || ps->cur_y!=y ) {
     400           0 :         if ( !ps->buffered_line && ps->cur_y==y ) {
     401           0 :             ps->line_x = x; ps->line_y = y;
     402           0 :             ps->buffered_line = true;
     403           0 :         } else if ( ps->buffered_line && ps->cur_y==y ) {
     404           0 :             ps->line_x = x;
     405             :         } else {
     406           0 :             if ( ps->buffered_line )
     407           0 :                 PSUnbufferLine(ps);
     408           0 :             fprintf( ps->output_file,"  %g %g lineto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
     409           0 :             ++ps->pnt_cnt;
     410             :         }
     411           0 :         ps->cur_x = x; ps->cur_y = y;
     412             :     }
     413           0 : }
     414             : 
     415             : /* This is my version of the postscript "arc" function. I've written it because*/
     416             : /*  I can't use arc for stroking elipses. The obvious thing to do is to scale */
     417             : /*  x and y differently so that the circle becomes an elipse. Sadly that also */
     418             : /*  scales the line width so I get a different width at different points on   */
     419             : /*  the elipse. Can't have that. */
     420             : /* So here we approximate an elipse by four bezier curves. There is one curve */
     421             : /*  for each quadrant of the elipse (0->90), (90->180), (180->270), (270-360) */
     422             : /*  of course if we're just doing bits of the arc (rather than the whole      */
     423             : /*  elipse) we'll not have all of those, nor will they be filled in. The      */
     424             : /*  magic numbers here do indeed produce a good fit to an elipse */
     425           0 : static void PSDoArc(GPSWindow ps, double cx, double cy, double radx, double rady,
     426             :         double sa, double ea ) {
     427             :     double ss, sc, es, ec;
     428             :     double lenx, leny;
     429             :     double sx, sy, ex, ey;
     430             :     double c1x, c1y, c2x, c2y;
     431             : 
     432           0 :     lenx = ((ea-sa)/90.0) * radx * .552;
     433           0 :     leny = ((ea-sa)/90.0) * rady * .552;
     434           0 :     sa *= 3.1415926535897932/180; ea *= 3.1415926535897932/180;
     435           0 :     ss = -sin(sa); sc = cos(sa); es = -sin(ea); ec = cos(ea);
     436           0 :     sx = cx+sc*radx; sy = cy+ss*rady;
     437           0 :     PSMoveTo(ps,sx,sy);
     438           0 :     ex = cx+ec*radx; ey = cy+es*rady;
     439           0 :     c1x = sx + lenx*ss; c1y = sy - leny*sc;
     440           0 :     c2x = ex - lenx*es; c2y = ey + leny*ec;
     441           0 :     fprintf( ps->output_file, " %g %g %g %g %g %g curveto",
     442             :             _GSPDraw_XPos(ps,c1x), _GSPDraw_YPos(ps,c1y),
     443             :             _GSPDraw_XPos(ps,c2x), _GSPDraw_YPos(ps,c2y),
     444             :             _GSPDraw_XPos(ps,ex), _GSPDraw_YPos(ps,ey) );
     445           0 :     ps->cur_x = ex; ps->cur_y = ey;
     446           0 : }
     447             : 
     448           0 : static void PSMyArc(GPSWindow ps, double cx, double cy, double radx, double rady,
     449             :         double sa, double ta ) {
     450             :     double ea, temp;
     451             : 
     452           0 :     if ( ta<0 ) {
     453           0 :         sa += ta;
     454           0 :         ta = -ta;
     455             :     }
     456           0 :     if ( ta>360 ) ta = 360;
     457           0 :     if ( ta==360 ) sa = 0;
     458           0 :     while ( sa<0 ) sa+= 360;
     459           0 :     while ( sa>=360 ) sa -= 360;
     460           0 :     ea = sa+ta;
     461             : 
     462           0 :     while ( sa<ea ) {
     463           0 :         temp = ((int) ((sa+90)/90))*90;
     464           0 :         PSDoArc(ps,cx,cy,radx,rady,sa,ea<temp?ea:temp);
     465           0 :         sa = temp;
     466             :     }
     467           0 : }
     468             : 
     469           0 : static void PSDrawElipse(GPSWindow ps, GRect *rct,char *command) {
     470             :     float cx, cy, radx, rady;
     471             :     /* This does not make a very good stroked elipse if it isn't a circle */
     472             :     /*  the line width is scaled along with the elipse and so it varies!!! */
     473             : 
     474           0 :     _GPSDraw_FlushPath(ps);
     475           0 :     radx = rct->width/2.0;
     476           0 :     rady = rct->height/2.0;
     477           0 :     cx = rct->x + radx;
     478           0 :     cy = rct->y + rady;
     479           0 :     PSDrawNewpath(ps);
     480             : 
     481             :     /* I can't use arc to draw an elipse. Doing so would mean scaling the */
     482             :     /*  x and y axes differently, which will also scale the stroke width */
     483             :     /*  differently. So I've written my own version that will work for */
     484             :     /*  elipses without scaling. I use arc for circles because it produces */
     485             :     /*  less text in the printing file */
     486           0 :     if ( radx!=rady )
     487           0 :         PSMyArc(ps,cx,cy,radx,rady,0,360);
     488             :     else
     489           0 :         fprintf( ps->output_file, "  %g %g %g 0 360 arc", _GSPDraw_XPos(ps,cx), _GSPDraw_YPos(ps,cy), _GSPDraw_Distance(ps,radx));
     490           0 :     fprintf( ps->output_file, " closepath %s\n", command );
     491           0 :     ps->pnt_cnt = 0;
     492           0 :     ps->cur_x = ps->cur_y = -1;
     493           0 : }
     494             : 
     495           0 : static void PSDrawDoPoly(GPSWindow ps, GPoint *pt, int cnt, char *command) {
     496             :     int i;
     497             : 
     498           0 :     if ( pt[cnt-1].x==pt[0].x && pt[cnt-1].y==pt[0].y )
     499           0 :         --cnt;          /* We close paths differently in postscript */
     500           0 :     _GPSDraw_FlushPath(ps);
     501           0 :     if ( cnt==4 ) {
     502           0 :         fprintf( ps->output_file, "  %g %g  %g %g  %g %g  %g %g g_quad ",
     503           0 :                 _GSPDraw_XPos(ps,pt[3].x), _GSPDraw_YPos(ps,pt[3].y),
     504           0 :                 _GSPDraw_XPos(ps,pt[2].x), _GSPDraw_YPos(ps,pt[2].y),
     505           0 :                 _GSPDraw_XPos(ps,pt[1].x), _GSPDraw_YPos(ps,pt[1].y),
     506           0 :                 _GSPDraw_XPos(ps,pt[0].x), _GSPDraw_YPos(ps,pt[0].y));
     507             :     } else {
     508           0 :         PSMoveTo(ps,pt[0].x,pt[0].y);
     509           0 :         for ( i=1; i<cnt; ++i )
     510           0 :             PSLineTo(ps,pt[i].x,pt[i].y);
     511             :     }
     512           0 :     fprintf( ps->output_file, "closepath %s %%Polygon\n", command );
     513           0 :     ps->pnt_cnt = 0;
     514           0 :     ps->cur_x = ps->cur_y = -1;
     515           0 : }
     516             : 
     517           0 : void _GPSDraw_SetClip(GPSWindow ps) {
     518             : 
     519           0 :     if ( ps->ggc->clip.x!=ps->cur_clip.x ||
     520           0 :             ps->ggc->clip.width!=ps->cur_clip.width ||
     521           0 :             ps->ggc->clip.y!=ps->cur_clip.y ||
     522           0 :             ps->ggc->clip.height!=ps->cur_clip.height ) {
     523           0 :         _GPSDraw_FlushPath(ps);
     524           0 :         if ( ps->ggc->clip.x<ps->cur_clip.x ||
     525           0 :                 ps->ggc->clip.x+ps->ggc->clip.width>ps->cur_clip.x+ps->cur_clip.width ||
     526           0 :                 ps->ggc->clip.y<ps->cur_clip.y ||
     527           0 :                 ps->ggc->clip.y+ps->ggc->clip.height>ps->cur_clip.y+ps->cur_clip.height )
     528           0 :             fprintf( ps->output_file, "initclip " );       /* we hope never to fall into this case, postscript doesn't like it */
     529           0 :         fprintf( ps->output_file, "  %g %g  %g %g  %g %g  %g %g g_quad clip newpath\n",
     530           0 :                 _GSPDraw_XPos(ps,ps->ggc->clip.x), _GSPDraw_YPos(ps,ps->ggc->clip.y+ps->ggc->clip.height),
     531           0 :                 _GSPDraw_XPos(ps,ps->ggc->clip.x+ps->ggc->clip.width), _GSPDraw_YPos(ps,ps->ggc->clip.y+ps->ggc->clip.height),
     532           0 :                 _GSPDraw_XPos(ps,ps->ggc->clip.x+ps->ggc->clip.width), _GSPDraw_YPos(ps,ps->ggc->clip.y),
     533           0 :                 _GSPDraw_XPos(ps,ps->ggc->clip.x), _GSPDraw_YPos(ps,ps->ggc->clip.y));
     534           0 :         ps->cur_clip = ps->ggc->clip;
     535             :     }
     536           0 : }
     537             : 
     538           0 : void _GPSDraw_SetColor(GPSWindow ps,Color fg) {
     539           0 :     if ( ps->display->do_color ) {
     540           0 :         fprintf( ps->output_file, "%g %g %g setrgbcolor\n", COLOR_RED(fg)/255.0,
     541           0 :                 COLOR_GREEN(fg)/255.0, COLOR_BLUE(fg)/255.0 );
     542             :     } else {
     543           0 :         fprintf( ps->output_file, "%g setgray\n", COLOR2GREYR(fg));
     544             :     }
     545           0 :     ps->cur_fg = fg;
     546           0 : }
     547             : 
     548           0 : static int PSDrawSetcol(GPSWindow ps) {
     549             : 
     550           0 :     _GPSDraw_SetClip(ps);
     551           0 :     if ( ps->ggc->fg!=ps->cur_fg || ps->ggc->ts!=ps->cur_ts ) {
     552           0 :         _GPSDraw_FlushPath(ps);
     553           0 :         if ( ps->ggc->ts!=ps->cur_ts ) {
     554           0 :             if ( ps->ggc->ts ) {
     555           0 :                 fprintf( ps->output_file, "currentcolor DotPattern setpattern\n" );
     556           0 :                 ps->cur_ts = ps->ggc->ts;
     557             :             } else {
     558           0 :                 fprintf( ps->output_file, "%s setcolorspace\n",
     559           0 :                         ps->display->do_color?"/DeviceRGB":"/DeviceGray" );
     560           0 :                 ps->cur_ts = 0;
     561             :             }
     562             :         }
     563           0 :         _GPSDraw_SetColor(ps,ps->ggc->fg);
     564             :     }
     565           0 : return( true );
     566             : }
     567             : 
     568           0 : static int PSDrawSetline(GPSWindow ps) {
     569             : 
     570           0 :     PSDrawSetcol(ps);
     571           0 :     if ( ps->ggc->line_width!=ps->cur_line_width ) {
     572           0 :         _GPSDraw_FlushPath(ps);
     573           0 :         fprintf( ps->output_file, "%g setlinewidth\n", _GSPDraw_XPos(ps,ps->ggc->line_width) );
     574           0 :         ps->cur_line_width = ps->ggc->line_width;
     575             :     }
     576           0 :     if ( ps->ggc->dash_len != ps->cur_dash_len || ps->ggc->skip_len != ps->cur_skip_len ||
     577           0 :             ps->ggc->dash_offset != ps->cur_dash_offset ) {
     578           0 :         _GPSDraw_FlushPath(ps);
     579           0 :         if ( ps->ggc->dash_len==0 ) {
     580           0 :             fprintf( ps->output_file, "[] 0 setdash\n" );
     581             :         } else {
     582           0 :             fprintf( ps->output_file, "[%d %d] %d setdash\n",
     583           0 :                     ps->ggc->dash_len, ps->ggc->skip_len,
     584           0 :                     PixelToPoint(ps->ggc->dash_offset,ps->res)%(ps->ggc->dash_len+ps->ggc->skip_len) );
     585             :         }
     586           0 :         ps->cur_dash_offset = ps->ggc->dash_offset;
     587           0 :         ps->cur_dash_len = ps->ggc->dash_len;
     588           0 :         ps->cur_skip_len = ps->ggc->skip_len;
     589             :     }
     590           0 : return( true );
     591             : }
     592             : 
     593           0 : static void PSDrawPushClip(GWindow w,GRect *rct, GRect *old) {
     594           0 :     GPSWindow ps = (GPSWindow ) w;
     595             : 
     596           0 :     _GPSDraw_FlushPath(ps);
     597           0 :     fprintf( ps->output_file,"gsave\n" );
     598           0 :     ps->last_dash_len = ps->cur_dash_len;
     599           0 :     ps->last_skip_len = ps->cur_skip_len;
     600           0 :     ps->last_dash_offset = ps->cur_dash_offset;
     601           0 :     ps->last_line_width = ps->cur_line_width;
     602           0 :     ps->last_ts = ps->cur_ts;
     603           0 :     ps->last_fg = ps->cur_fg;
     604           0 :     ps->last_font = ps->cur_font;
     605           0 :     *old = ps->ggc->clip;
     606           0 :     ps->ggc->clip = *rct;
     607           0 : }
     608             : 
     609           0 : static void PSDrawPopClip(GWindow w,GRect *old) {
     610           0 :     GPSWindow ps = (GPSWindow ) w;
     611             : 
     612           0 :     _GPSDraw_FlushPath(ps);
     613           0 :     ps->cur_clip = *old;
     614           0 :     fprintf( ps->output_file,"grestore\n" );
     615           0 :     ps->cur_dash_len = ps->last_dash_len;
     616           0 :     ps->cur_skip_len = ps->last_skip_len;
     617           0 :     ps->cur_line_width = ps->last_line_width;
     618           0 :     ps->cur_dash_offset = ps->last_dash_offset;
     619           0 :     ps->cur_ts = ps->last_ts;
     620           0 :     ps->cur_fg = ps->last_fg;
     621           0 :     ps->cur_font = ps->last_font;
     622           0 :     ps->last_dash_len = -1;
     623           0 :     ps->last_skip_len = -1;
     624           0 :     ps->last_line_width = -1;
     625           0 :     ps->last_dash_offset = -1;
     626           0 :     ps->last_ts = -1;
     627           0 :     ps->last_fg = -1;
     628           0 :     ps->last_font = NULL;
     629           0 :     ps->ggc->clip = *old;
     630           0 : }
     631             : 
     632           0 : static void PSDrawDrawLine(GWindow w, int32 x,int32 y,int32 xend,int32 yend,Color col) {
     633           0 :     GPSWindow ps = (GPSWindow ) w;
     634             : 
     635           0 :     ps->ggc->fg = col;
     636           0 :     PSDrawSetline(ps);
     637           0 :     PSMoveTo(ps,x,y);
     638           0 :     PSLineTo(ps,xend,yend);
     639           0 : }
     640             : 
     641           0 : static void PSDrawArrow(GPSWindow ps, int32 x, int32 y, int32 xother, int32 yother ) {
     642             :     GPoint points[3];
     643             :     double a;
     644             :     int off1, off2;
     645             :     double len;
     646           0 :     int line_width = ps->ggc->line_width;
     647             : 
     648           0 :     if ( x==xother && y==yother )
     649           0 : return;
     650           0 :     a = atan2(y-yother,x-xother);
     651           0 :     len = 72.0*sqrt((double) (x-xother)*(x-xother)+(y-yother)*(y-yother))/ps->res;
     652           0 :     if ( len>30 ) len = 10+3*line_width/2; else len = (len+line_width)/3;
     653           0 :     if ( len<2 )
     654           0 : return;
     655           0 :     len *= ps->res/72.0;
     656             : 
     657           0 :     points[0].x = x; points[0].y = y;
     658           0 :     if ( line_width!=0 ) {
     659           0 :         points[0].x += line_width*1.3*cos(a); points[0].y += line_width*1.3*sin(a);
     660             :     }
     661           0 :     off1 = len*sin(a+3.1415926535897932/8)+.5; off2 = len*cos(a+3.1415926535897932/8)+.5;
     662           0 :     points[1].x = x-off2; points[1].y = y-off1;
     663           0 :     off1 = len*sin(a-3.1415926535897932/8)+.5; off2 = len*cos(a-3.1415926535897932/8)+.5;
     664           0 :     points[2].x = x-off2; points[2].y = y-off1;
     665           0 :     PSDrawDoPoly(ps,points,3,"fill");
     666             : }
     667             : 
     668           0 : static void PSDrawDrawArrowLine(GWindow w, int32 x,int32 y,int32 xend,int32 yend,int16 arrows,Color col) {
     669           0 :     GPSWindow ps = (GPSWindow ) w;
     670             : 
     671           0 :     ps->ggc->fg = col;
     672           0 :     PSDrawSetline(ps);
     673           0 :     PSMoveTo(ps,x,y);
     674           0 :     PSLineTo(ps,xend,yend);
     675           0 :     if ( arrows&1 )
     676           0 :         PSDrawArrow(ps,x,y,xend,yend);
     677           0 :     if ( arrows&2 )
     678           0 :         PSDrawArrow(ps,xend,yend,x,y);
     679           0 : }
     680             : 
     681           0 : static void PSDrawDrawRect(GWindow w, GRect *rct,Color col) {
     682           0 :     GPSWindow ps = (GPSWindow ) w;
     683             : 
     684           0 :     ps->ggc->fg = col;
     685           0 :     PSDrawSetline(ps);
     686           0 :     fprintf( ps->output_file, "  %g %g  %g %g  %g %g  %g %g g_quad stroke\n",
     687           0 :             _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y+rct->height),
     688           0 :             _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y+rct->height),
     689           0 :             _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y),
     690             :             _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y));
     691           0 :     ps->pnt_cnt = 0;
     692           0 : }
     693             : 
     694           0 : static void PSDrawFillRect(GWindow w, GRect *rct,Color col) {
     695           0 :     GPSWindow ps = (GPSWindow ) w;
     696             : 
     697           0 :     ps->ggc->fg = col;
     698           0 :     PSDrawSetcol(ps);
     699           0 :     _GPSDraw_FlushPath(ps);
     700           0 :     fprintf( ps->output_file, "  %g %g  %g %g  %g %g  %g %g g_quad fill\n",
     701           0 :             _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y+rct->height),
     702           0 :             _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y+rct->height),
     703           0 :             _GSPDraw_XPos(ps,rct->x+rct->width), _GSPDraw_YPos(ps,rct->y),
     704             :             _GSPDraw_XPos(ps,rct->x), _GSPDraw_YPos(ps,rct->y));
     705           0 :     ps->pnt_cnt = 0;
     706           0 : }
     707             : 
     708           0 : static void PSDrawFillRoundRect(GWindow UNUSED(w), GRect *UNUSED(rct),
     709             :         int UNUSED(radius), Color UNUSED(col)) {
     710           0 :     fprintf( stderr, "DrawFillRoundRect not implemented for postscript\n" );
     711           0 : return;
     712             : }
     713             : 
     714           0 : static void PSDrawClear(GWindow w,GRect *rect) {
     715           0 :     GPSWindow ps = (GPSWindow ) w;
     716           0 :     if ( rect==NULL )
     717           0 :         rect = &ps->ggc->clip;
     718           0 :     PSDrawFillRect(w,rect,COLOR_CREATE(255,255,255));
     719           0 : }
     720             : 
     721           0 : static void PSDrawDrawCircle(GWindow w, GRect *rct,Color col) {
     722           0 :     GPSWindow ps = (GPSWindow ) w;
     723             : 
     724           0 :     ps->ggc->fg = col;
     725           0 :     PSDrawSetline(ps);
     726           0 :     PSDrawElipse(ps,rct,"stroke");
     727           0 : }
     728             : 
     729           0 : static void PSDrawFillCircle(GWindow w, GRect *rct,Color col) {
     730           0 :     GPSWindow ps = (GPSWindow ) w;
     731             : 
     732           0 :     ps->ggc->fg = col;
     733           0 :     PSDrawSetcol(ps);
     734           0 :     _GPSDraw_FlushPath(ps);
     735           0 :     PSDrawElipse(ps,rct,"fill");
     736           0 : }
     737             : 
     738           0 : static void PSDrawDrawArc(GWindow w, GRect *rct,int32 sa, int32 ta, Color col) {
     739           0 :     GPSWindow ps = (GPSWindow ) w;
     740             :     float cx, cy, radx, rady;
     741             : 
     742           0 :     ps->ggc->fg = col;
     743           0 :     PSDrawSetline(ps);
     744           0 :     _GPSDraw_FlushPath(ps);
     745             : 
     746           0 :     radx = rct->width/2.0;
     747           0 :     rady = rct->height/2.0;
     748           0 :     cx = rct->x + radx;
     749           0 :     cy = rct->y + rady;
     750           0 :     if ( radx==0 || rady==0 )
     751           0 : return;
     752           0 :     PSDrawNewpath(ps);
     753           0 :     if ( radx!=rady )
     754           0 :         PSMyArc(ps,cx,cy,radx,rady,sa/64.0,ta/64.0);
     755             :     else
     756           0 :         fprintf( ps->output_file, "  %g %g %g %g %g arc", _GSPDraw_XPos(ps,cx), _GSPDraw_YPos(ps,cy), _GSPDraw_Distance(ps,radx),
     757           0 :                     sa/64.0, (sa+ta)/64.0 );
     758           0 :     fprintf( ps->output_file, " stroke\n" );
     759           0 :     ps->pnt_cnt = 0;
     760           0 :     ps->cur_x = ps->cur_y = -1;
     761             : }
     762             : 
     763           0 : static void PSDrawDrawPoly(GWindow w, GPoint *pt, int16 cnt,Color col) {
     764           0 :     GPSWindow ps = (GPSWindow ) w;
     765             : 
     766           0 :     ps->ggc->fg = col;
     767           0 :     PSDrawSetline(ps);
     768           0 :     PSDrawDoPoly(ps,pt,cnt,"stroke");
     769           0 : }
     770             : 
     771           0 : static void PSDrawFillPoly(GWindow w, GPoint *pt, int16 cnt,Color col) {
     772           0 :     GPSWindow ps = (GPSWindow ) w;
     773             : 
     774           0 :     ps->ggc->fg = col;
     775           0 :     PSDrawSetcol(ps);
     776           0 :     _GPSDraw_FlushPath(ps);
     777           0 :     PSDrawDoPoly(ps,pt,cnt,"fill");
     778           0 : }
     779             : 
     780           0 : static void PSDrawFontMetrics(GWindow w, FontInstance *fi, int *as, int *ds, int *ld) {
     781           0 :     GDrawWindowFontMetrics(w, fi, as, ds, ld);
     782           0 : }
     783             : 
     784           0 : static enum gcairo_flags PSDrawHasCairo(GWindow UNUSED(w)) {
     785           0 : return( gc_buildpath );
     786             : }
     787             : 
     788           0 : static void PSDrawPathStartNew(GWindow w) {
     789           0 :     GPSWindow ps = (GPSWindow ) w;
     790           0 :     fprintf( ps->output_file,"  newpath\n" );
     791           0 : }
     792             : 
     793           0 : static void PSDrawPathClose(GWindow w) {
     794           0 :     GPSWindow ps = (GPSWindow ) w;
     795           0 :     fprintf( ps->output_file,"  closepath\n" );
     796           0 : }
     797             : 
     798           0 : static void PSDrawPathMoveTo(GWindow w,double x, double y) {
     799           0 :     GPSWindow ps = (GPSWindow ) w;
     800           0 :     fprintf( ps->output_file,"  %g %g moveto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
     801           0 : }
     802             : 
     803           0 : static void PSDrawPathLineTo(GWindow w,double x, double y) {
     804           0 :     GPSWindow ps = (GPSWindow ) w;
     805           0 :     fprintf( ps->output_file,"  %g %g lineto\n", _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
     806           0 : }
     807             : 
     808           0 : static void PSDrawPathCurveTo(GWindow w,
     809             :                     double cx1, double cy1,
     810             :                     double cx2, double cy2,
     811             :                     double x, double y) {
     812           0 :     GPSWindow ps = (GPSWindow ) w;
     813           0 :     fprintf( ps->output_file,"  %g %g %g %g %g %g curveto\n",
     814             :             _GSPDraw_XPos(ps,cx1), _GSPDraw_YPos(ps,cy1),
     815             :             _GSPDraw_XPos(ps,cx2), _GSPDraw_YPos(ps,cy2),
     816             :             _GSPDraw_XPos(ps,x), _GSPDraw_YPos(ps,y) );
     817           0 : }
     818             : 
     819           0 : static void PSDrawPathStroke(GWindow w,Color col) {
     820           0 :     GPSWindow ps = (GPSWindow ) w;
     821           0 :     ps->ggc->fg = col;
     822           0 :     PSDrawSetcol(ps);
     823           0 :     fprintf( ps->output_file,"   stroke\n" );
     824           0 : }
     825             : 
     826           0 : static void PSDrawPathFill(GWindow w,Color col) {
     827           0 :     GPSWindow ps = (GPSWindow ) w;
     828           0 :     ps->ggc->fg = col;
     829           0 :     PSDrawSetcol(ps);
     830           0 :     fprintf( ps->output_file,"   fill\n" );
     831           0 : }
     832             : 
     833           0 : static void PSDrawPathFillAndStroke(GWindow w,Color fillcol, Color strokecol) {
     834           0 :     GPSWindow ps = (GPSWindow ) w;
     835           0 :     ps->ggc->fg = fillcol;
     836           0 :     PSDrawSetcol(ps);
     837           0 :     fprintf( ps->output_file,"   save fill restore " );
     838           0 :     ps->ggc->fg = strokecol;
     839           0 :     PSDrawSetcol(ps);
     840           0 :     fprintf( ps->output_file,"   stroke\n" );
     841           0 : }
     842             : 
     843           0 : static void PSPageSetup(GPSWindow ps,FILE *out, float thumbscale) {
     844           0 :     GPSDisplay *gdisp = ps->display;
     845             :     /* I want to put this somewhere in the document header, but DSC conventions*/
     846             :     /*  don't let me. Frustrating. Or I don't understand how, also frustrating*/
     847             : 
     848           0 :     fprintf( out, "  %g %g translate\t\t%%Left & Top Margins\n",
     849           0 :             gdisp->lmargin*72.0, (gdisp->yheight-gdisp->tmargin)*72.0 );
     850           0 :     fprintf( out, "  %g %g  %g %g  %g %g  %g %g g_quad clip newpath\t%%Clip to margins\n",
     851             :             _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,0),
     852           0 :             _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,(gdisp->yheight-gdisp->tmargin-gdisp->bmargin)*gdisp->res),
     853           0 :             _GSPDraw_XPos(ps,(gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)*gdisp->res), _GSPDraw_YPos(ps,(gdisp->yheight-gdisp->tmargin-gdisp->bmargin)*gdisp->res),
     854           0 :             _GSPDraw_XPos(ps,(gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)*gdisp->res), _GSPDraw_YPos(ps,0));
     855           0 :     if ( gdisp->scale*thumbscale!=1 )
     856           0 :         fprintf( out, "  %g %g scale\n", gdisp->scale*thumbscale, gdisp->scale*thumbscale );
     857           0 : }
     858             : 
     859           0 : static void PSPageInit(GPSWindow ps) {
     860           0 :     GPSDisplay *gdisp = (GPSDisplay *) (ps->display);
     861           0 :     int thumb_per_page = gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt;
     862           0 :     int real_page = ( ps->page_cnt%thumb_per_page == 0 );
     863             : 
     864           0 :     ++ps->page_cnt;
     865           0 :     if ( gdisp->eps ) {
     866           0 :         fprintf( ps->output_file, "\n%%%%Page: 1 1\n" );
     867           0 :         fprintf( ps->output_file, "%%%%BeginPageSetup\n" );
     868           0 :         PSPageSetup(ps,ps->output_file,1.0);
     869           0 :         fprintf( ps->output_file, "%%%%EndPageSetup\n" );
     870           0 :     } else if ( real_page ) {
     871           0 :         int page = (ps->page_cnt+thumb_per_page-1)/thumb_per_page;
     872           0 :         fprintf( ps->output_file, "\n%%%%Page: %d %d\n", page, page );
     873           0 :         fprintf( ps->output_file, "%%%%BeginPageSetup\n" );
     874           0 :         fprintf( ps->output_file, "g_startpage\n" );
     875           0 :         fprintf( ps->output_file, "%%%%EndPageSetup\n" );
     876             :     } else
     877           0 :         fprintf( ps->output_file, "\n%% Psuedo Page: \ng_startpage\n" );
     878           0 :     ps->ggc->clip.y = ps->ggc->clip.x = 0;
     879           0 :     ps->ggc->clip.height = ps->pos.height; ps->ggc->clip.width = ps->pos.width;
     880           0 :     ps->cur_clip = ps->ggc->clip;
     881           0 :     ps->cur_skip_len = ps->cur_dash_len = ps->cur_line_width = ps->cur_dash_offset = ps->cur_ts = 0;
     882           0 :     ps->cur_font = NULL; ps->cur_fg = 0;
     883           0 : }
     884             : 
     885           0 : static void PSPageTerm(GPSWindow ps, int last) {
     886           0 :     GPSDisplay *gdisp = (GPSDisplay *) (ps->display);
     887           0 :     int thumb_per_page = gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt;
     888             : 
     889           0 :     _GPSDraw_FlushPath(ps);
     890           0 :     if ( gdisp->eps )
     891           0 : return;
     892           0 :     if ( last || ps->page_cnt%thumb_per_page==0 ) {
     893           0 :         fprintf( ps->output_file, "%%%%PageTrailer\n" );
     894           0 :         if ( last )
     895           0 :             fprintf( ps->output_file, "g_finalpage\t\t%%End of Page\n" );
     896             :         else
     897           0 :             fprintf( ps->output_file, "g_endpage\t\t%%End of Page\n" );
     898           0 :         fprintf( ps->output_file, "%%%%EndPageTrailer\n" );
     899             :     } else
     900           0 :         fprintf( ps->output_file, "g_endpage\t\t%%End of Psuedo Page\n" );
     901             : }
     902             : 
     903           0 : static void PSTrailer(GPSWindow ps) {
     904           0 :     GPSDisplay *gdisp = (GPSDisplay *) (ps->display);
     905           0 :     int thumb_per_page = gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt;
     906             : 
     907           0 :     fprintf( ps->output_file, "%%%%Trailer\n" );
     908           0 :     if ( !gdisp->eps )
     909           0 :         fprintf( ps->output_file, "%%%%Pages: %d\n",
     910           0 :                 (int) (ps->page_cnt+thumb_per_page-1)/thumb_per_page);
     911           0 :     _GPSDraw_ListNeededFonts(ps);
     912           0 :     fprintf( ps->output_file, "%%%%EndTrailer\n" );
     913           0 :     fprintf( ps->output_file, "%%%%EOF\n" );
     914           0 : }
     915             : 
     916           0 : static void PSInitJob(GPSWindow ps, unichar_t *title) {
     917           0 :     GPSDisplay *gdisp = ps->display;
     918             :     char buf[200];
     919             :     time_t now;
     920             : 
     921             :     /* output magic line to tell lpr this is a postscript file */
     922           0 :     if ( gdisp->eps ) {
     923           0 :         fprintf( ps->init_file, "%%!PS-Adobe-3.0 EPSF-3.0\n" );
     924           0 :         fprintf( ps->init_file, "%%%%Pages: 1\n" );
     925             :     } else {
     926           0 :         fprintf( ps->init_file, "%%!PS-Adobe-3.0%s\n", gdisp->eps?" EPSF-3.0":"" );
     927           0 :         fprintf( ps->init_file, "%%%%Pages: (atend)\n" );
     928             :     }
     929           0 :     fprintf( ps->init_file, "%%%%BoundingBox: %g %g %g %g\n",
     930           0 :             72.0*gdisp->lmargin, 72.0*gdisp->bmargin,
     931           0 :             72.0*(gdisp->xwidth-gdisp->rmargin), 72.0*(gdisp->yheight-gdisp->tmargin));
     932           0 :     fprintf( ps->init_file, "%%%%Creator: %s\n", GResourceProgramName );
     933           0 :     time(&now);
     934           0 :     fprintf( ps->init_file, "%%%%CreationDate: %s", ctime(&now) );
     935           0 :     if ( title!=NULL )
     936           0 :         fprintf( ps->init_file, "%%%%Title: %s\n", u2def_strncpy(buf,title,sizeof(buf)) );
     937           0 :     fprintf( ps->init_file, "%%%%DocumentData: Clean7Bit\n" );
     938           0 :     fprintf( ps->init_file, "%%%%LanguageLevel: 2\n" );
     939           0 :     fprintf( ps->init_file, "%%%%Orientation: %s\n", gdisp->landscape?
     940             :             "Landscape":"Portrait" );
     941           0 :     fprintf( ps->init_file, "%%%%PageOrder: Ascend\n" );
     942           0 :     fprintf( ps->init_file, "%%%%DocumentNeededResources: (atend)\n" );
     943           0 :     fprintf( ps->init_file, "%%%%DocumentSuppliedResources: (atend)\n" );
     944           0 :     fprintf( ps->init_file, "%%%%EndComments\n\n" );
     945             : 
     946             :     /* Need to output a setdevice thing to specify the page size (num copies?) ??? */
     947           0 :     fprintf( ps->init_file, "%%%%BeginPrologue\n" );
     948             : 
     949             :     /* Any predefined functions? */
     950             :         /* Need one to remap an adobe encoding to some other encoding */
     951           0 :     fprintf( ps->init_file, "%% <font> <encoding> font_remap <font>\t; from the cookbook\n" );
     952           0 :     fprintf( ps->init_file, "/reencodedict 5 dict def\n" );
     953           0 :     fprintf( ps->init_file, "/g_font_remap { reencodedict begin\n" );
     954           0 :     fprintf( ps->init_file, "  /newencoding exch def\n" );
     955           0 :     fprintf( ps->init_file, "  /basefont exch def\n" );
     956           0 :     fprintf( ps->init_file, "  /newfont basefont  maxlength dict def\n" );
     957           0 :     fprintf( ps->init_file, "  basefont {\n" );
     958           0 :     fprintf( ps->init_file, "    exch dup dup /FID ne exch /Encoding ne and\n" );
     959           0 :     fprintf( ps->init_file, "\t{ exch newfont 3 1 roll put }\n" );
     960           0 :     fprintf( ps->init_file, "\t{ pop pop }\n" );
     961           0 :     fprintf( ps->init_file, "    ifelse\n" );
     962           0 :     fprintf( ps->init_file, "  } forall\n" );
     963           0 :     fprintf( ps->init_file, "  newfont /Encoding newencoding put\n" );
     964           0 :     fprintf( ps->init_file, "  newfont\t%%Leave on stack\n" );
     965           0 :     fprintf( ps->init_file, "  end } def\n" );
     966             :         /* Simple routine to move somewhere and draw a string */
     967           0 :     fprintf( ps->init_file, "/g_show { moveto show } bind def\n" );
     968           0 :     fprintf( ps->init_file, "/g_ashow { moveto ashow } bind def\n" );
     969           0 :     fprintf( ps->init_file, "/g_quad { moveto lineto lineto lineto closepath } bind def\n" );
     970             :         /* Routines to start and end pages. simple unless we do thumbnails */
     971           0 :     if ( gdisp->eps ) {
     972             :         /* No page procedures at all */
     973           0 :     } else if ( gdisp->linear_thumb_cnt <= 1 ) {
     974           0 :         fprintf( ps->init_file, "/g_startpage { save \n" );
     975           0 :         PSPageSetup(ps,ps->init_file,1.0);
     976           0 :         fprintf( ps->init_file, "} bind def\n" );
     977           0 :         fprintf( ps->init_file, "/g_endpage { restore showpage } bind def\n" );
     978           0 :         fprintf( ps->init_file, "/g_finalpage { g_endpage } bind def\n" );
     979             :     } else {
     980             :         float stemp, thumbscale;
     981           0 :         thumbscale = (gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)/
     982           0 :                 (gdisp->linear_thumb_cnt*gdisp->xwidth-gdisp->lmargin-gdisp->rmargin);
     983           0 :         stemp = (gdisp->yheight-gdisp->tmargin-gdisp->bmargin)/
     984           0 :                 (gdisp->linear_thumb_cnt*gdisp->yheight-gdisp->tmargin-gdisp->bmargin);
     985           0 :         if ( stemp<thumbscale ) thumbscale = stemp;
     986           0 :         thumbscale *= .97;      /* rounding errors make the real thing slightly too big */
     987           0 :         fprintf( ps->init_file, "/g_thumbnum 0 def\n" );
     988           0 :         fprintf( ps->init_file, "/g_startpage { \n" );
     989           0 :         fprintf( ps->init_file, "  g_thumbnum %d mod 0 eq { save \n",
     990           0 :                 gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt );
     991           0 :         PSPageSetup(ps,ps->init_file,thumbscale);
     992           0 :         fprintf( ps->init_file, "  } if\n" );
     993           0 :         fprintf( ps->init_file, "  save\n" );
     994           0 :         fprintf( ps->init_file, "  g_thumbnum %d mod %d mul g_thumbnum %d idiv %d mul translate\n",
     995           0 :                 gdisp->linear_thumb_cnt, (int) ps->pos.width,
     996           0 :                 gdisp->linear_thumb_cnt, (int) -ps->pos.height );
     997           0 :         fprintf( ps->init_file, "  %g %g  %g %g  %g %g  %g %g g_quad clip newpath\n",
     998             :                 _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,0),
     999             :                 _GSPDraw_XPos(ps,0), _GSPDraw_YPos(ps,ps->pos.height),
    1000             :                 _GSPDraw_XPos(ps,ps->pos.width), _GSPDraw_YPos(ps,ps->pos.height),
    1001             :                 _GSPDraw_XPos(ps,ps->pos.width), _GSPDraw_YPos(ps,0));
    1002           0 :         fprintf(ps->init_file, "} bind def\n" );
    1003           0 :         fprintf( ps->init_file, "/g_endpage { restore /g_thumbnum g_thumbnum 1 add def\n   g_thumbnum %d eq { restore /g_thumbnum 0 def showpage } if\n } bind def\n",
    1004           0 :                 gdisp->linear_thumb_cnt*gdisp->linear_thumb_cnt );
    1005           0 :         fprintf( ps->init_file, "/g_finalpage { restore restore showpage } bind def\n" );
    1006             :     }
    1007           0 :     _GPSDraw_InitPatterns(ps);
    1008           0 :     _GPSDraw_InitFonts(gdisp->fontstate);
    1009             : 
    1010           0 :     fprintf( ps->init_file, "%% Font Initialization (download needed fonts, remap locals)\n" );
    1011           0 :     fprintf( ps->init_file, "/MyFontDict 100 dict def\n" );
    1012             : 
    1013           0 :     fprintf( ps->output_file, "\n%%%%EndProlog\n\n" );
    1014           0 :     fprintf( ps->output_file, "\n%%%%BeginSetup\n" );
    1015           0 :     if ( !gdisp->eps )
    1016           0 :         fprintf( ps->output_file, "<< /PageSize [%g %g] >> setpagedevice\n\n",
    1017           0 :                 72.0*gdisp->xwidth, 72.0*gdisp->yheight );
    1018             :     /* Could set NumCopies in the InputAttributes sub-dictionary but I think */
    1019             :     /*  that is best done on the lpr command line */
    1020           0 :     fprintf( ps->output_file, "%%%%EndSetup\n\n" );
    1021           0 :     ps->cur_clip.x = ps->cur_clip.y = 0;
    1022           0 :     ps->cur_clip.width = ps->pos.width;
    1023           0 :     ps->cur_clip.height = ps->pos.height;
    1024           0 :     ps->ggc->clip = ps->cur_clip;
    1025           0 :     PSPageInit(ps);
    1026           0 : }
    1027             : 
    1028           0 : static int PSQueueFile(GPSWindow ps) {
    1029             : #if !defined(__MINGW32__)
    1030           0 :     GPSDisplay *gdisp = ps->display;
    1031           0 :     int pid = fork();
    1032             : 
    1033           0 :     rewind( ps->init_file );
    1034           0 :     if ( pid==0 ) {
    1035             :         /* In child */
    1036           0 :         int in = fileno(stdin);
    1037             :         char *prog;
    1038             :         char *argv[30];
    1039           0 :         int argc=0;
    1040             :         char pbuf[200], cbuf[40];
    1041             :         char buffer[1025];
    1042             :         char *parg, *carg, *spt, *pt;
    1043             : 
    1044           0 :         close(in);
    1045           0 :         dup2(fileno(ps->init_file),in);
    1046           0 :         close(fileno(ps->init_file));
    1047             : 
    1048           0 :         if ( gdisp->use_lpr ) {
    1049           0 :             prog = "lpr";
    1050           0 :             parg = "P";
    1051           0 :             carg = "#";
    1052             :         } else {
    1053           0 :             prog = "lp";
    1054           0 :             parg = "d";
    1055           0 :             carg = "n";
    1056             :         }
    1057           0 :         argv[argc++] = prog;
    1058           0 :         if ( !gdisp->use_lpr )
    1059           0 :             argv[argc++] = "-s";
    1060           0 :         if ( gdisp->printer_name!=NULL ) {
    1061           0 :             sprintf(pbuf, "-%s%s ", parg, gdisp->printer_name );
    1062           0 :             argv[argc++] = pbuf;
    1063             :         }
    1064           0 :         if ( gdisp->num_copies!=0 ) {
    1065           0 :             sprintf(cbuf, "-%s%d ", carg, gdisp->num_copies );
    1066           0 :             argv[argc++] = pbuf;
    1067             :         }
    1068           0 :         if ( gdisp->lpr_args!=NULL ) {
    1069           0 :             strncpy(buffer, gdisp->lpr_args,sizeof(buffer)-1 );
    1070           0 :             for ( spt = buffer; *spt==' '; ++spt );
    1071           0 :             while ( (pt = strchr(spt,' '))!=NULL ) {
    1072           0 :                 argv[argc++] = spt;
    1073           0 :                 *pt = '\0';
    1074           0 :                 for ( spt=pt+1; *spt==' '; ++spt );
    1075             :             }
    1076           0 :             if ( *spt!='\0' )
    1077           0 :                 argv[argc++] = spt;
    1078             :         }
    1079           0 :         argv[argc] = NULL;
    1080           0 :         if ( execvp(prog,argv)==-1 )
    1081           0 :             _exit(1);
    1082           0 :     } else if ( pid==-1 )
    1083           0 : return( false );
    1084             :     else {
    1085             :         /* in parent */
    1086             :         int status;
    1087           0 :         if ( waitpid(pid,&status,0)==-1 )
    1088           0 : return( false );
    1089           0 :         if ( WIFEXITED(status))
    1090           0 : return( true );
    1091             :     }
    1092             : #endif
    1093           0 : return( false );
    1094             : }
    1095             : 
    1096           0 : static int PSFinishJob(GPSWindow ps,int cancel) {
    1097           0 :     GPSDisplay *gdisp = ps->display;
    1098           0 :     int error = ferror(ps->output_file);
    1099             : 
    1100           0 :     if ( ps->output_file!=ps->init_file ) {
    1101           0 :         rewind(ps->output_file);
    1102           0 :         _GPSDraw_CopyFile(ps->init_file,ps->output_file);
    1103           0 :         fclose(ps->output_file);
    1104             :     }
    1105           0 :     error |= ferror(ps->init_file);
    1106           0 :     if ( error || cancel ) {
    1107           0 :         if ( !cancel )
    1108           0 :             GDrawError("An error occurred while saving the print job to disk.\nNot printed." );
    1109           0 :         if ( gdisp->filename!=NULL )
    1110           0 :             GFileUnlink(gdisp->filename);
    1111           0 :         fclose(ps->init_file);
    1112           0 : return(false);
    1113             :     }
    1114           0 :     if ( !gdisp->print_to_file ) {
    1115           0 :         if ( !PSQueueFile(ps)) {
    1116           0 :             GDrawError("Could not queue print job" );
    1117           0 :             fclose(ps->init_file);
    1118           0 : return( false );
    1119             :         }
    1120             :     }
    1121           0 :     fclose(ps->init_file);
    1122           0 : return( true );
    1123             : }
    1124             : 
    1125           0 : static void PSDestroyContext(GPSDisplay *gd) {
    1126           0 :     free(gd->groot->ggc);
    1127           0 :     free(gd->groot);
    1128           0 :     gd->groot = NULL;
    1129           0 : }
    1130             : 
    1131           0 : static GGC *_GPSDraw_NewGGC(GPSDisplay *ps) {
    1132           0 :     GGC *ggc = calloc(1,sizeof(GGC));
    1133           0 :     ggc->clip.width = ggc->clip.height = 0x7fff;
    1134           0 :     ggc->fg = 0;
    1135           0 :     ggc->bg = 0xffffff;
    1136           0 :     ggc->line_width = ps->scale_screen_by;
    1137           0 : return( ggc );
    1138             : }
    1139             : 
    1140           0 : static GWindow GPSPrinterStartJob(GDisplay *gd,void *user_data,GPrinterAttrs *attrs) {
    1141           0 :     GPSDisplay *gdisp = (GPSDisplay *) gd;
    1142           0 :     double factor = 1;
    1143             :     char *oldpn, *oldea, *oldfn;
    1144             :     FILE *output, *init;
    1145             :     GPSWindow groot;
    1146             : 
    1147           0 :     if ( gd->groot!=NULL ) {
    1148           0 :         GDrawError("Please wait for current print job to complete before starting a new one" );
    1149           0 : return( NULL );
    1150             :     }
    1151             : 
    1152           0 :     if ( attrs!=NULL ) {
    1153           0 :         if ( attrs->units==pu_mm )
    1154           0 :             factor = 25.4;
    1155           0 :         else if ( attrs->units == pu_points )
    1156           0 :             factor = 72;
    1157             : 
    1158           0 :         if ( attrs->mask&pam_pagesize ) {
    1159           0 :             gdisp->xwidth = attrs->width/factor;
    1160           0 :             gdisp->yheight = attrs->height/factor;
    1161             :         }
    1162           0 :         if ( attrs->mask&pam_margins ) {
    1163           0 :             gdisp->lmargin = attrs->lmargin/factor;
    1164           0 :             gdisp->rmargin = attrs->rmargin/factor;
    1165           0 :             gdisp->tmargin = attrs->tmargin/factor;
    1166           0 :             gdisp->bmargin = attrs->bmargin/factor;
    1167             :         }
    1168           0 :         if ( attrs->mask&pam_scale )
    1169           0 :             gdisp->scale = attrs->scale;
    1170           0 :         if ( gdisp->scale<=0 ) gdisp->scale = 1.0;
    1171           0 :         gdisp->last_units = attrs->units;
    1172           0 :         if ( attrs->mask&pam_res )
    1173           0 :             gdisp->res = attrs->res;
    1174           0 :         gdisp->scale_screen_by = gdisp->res/screen_display->res;
    1175           0 :         if ( gdisp->scale_screen_by==0 ) gdisp->scale_screen_by =1;
    1176           0 :         if ( attrs->mask&pam_copies )
    1177           0 :             gdisp->num_copies = attrs->num_copies;
    1178             :         else
    1179           0 :             gdisp->num_copies = 1;
    1180           0 :         if ( attrs->mask&pam_thumbnails )
    1181           0 :             gdisp->linear_thumb_cnt = attrs->thumbnails;
    1182             :         else
    1183           0 :             gdisp->linear_thumb_cnt = 1;
    1184           0 :         if ( gdisp->linear_thumb_cnt<=0 )
    1185           0 :             gdisp->linear_thumb_cnt = 1;
    1186           0 :         if ( attrs->mask&pam_transparent )
    1187           0 :             gdisp->do_transparent = attrs->do_transparent;
    1188           0 :         if ( attrs->mask&pam_color )
    1189           0 :             gdisp->do_color = attrs->do_color;
    1190           0 :         if ( attrs->mask&pam_lpr )
    1191           0 :             gdisp->use_lpr = attrs->use_lpr;
    1192           0 :         if ( attrs->mask&pam_queue )
    1193           0 :             gdisp->print_to_file = attrs->donot_queue;
    1194           0 :         if ( attrs->mask&pam_eps )
    1195           0 :             gdisp->eps = attrs->eps;
    1196             :         else
    1197           0 :             gdisp->eps = false;
    1198           0 :         if ( gdisp->eps ) {
    1199           0 :             gdisp->print_to_file = true;
    1200           0 :             gdisp->linear_thumb_cnt = 1;
    1201           0 :             gdisp->scale_screen_by =1;
    1202             :         }
    1203           0 :         if ( attrs->mask&pam_landscape )
    1204           0 :             gdisp->landscape = attrs->landscape;
    1205             : 
    1206           0 :         oldpn = gdisp->printer_name; oldea = gdisp->lpr_args; oldfn = gdisp->filename;
    1207           0 :         if ( gdisp->print_to_file && (attrs->mask&pam_filename) )
    1208           0 :             gdisp->filename = copy(attrs->file_name);
    1209             :         else
    1210           0 :             gdisp->filename = NULL;
    1211           0 :         if ( attrs->mask&pam_printername )
    1212           0 :             gdisp->printer_name = copy(attrs->printer_name);
    1213             :         else
    1214           0 :             oldpn = NULL;
    1215           0 :         if ( attrs->mask&pam_args )
    1216           0 :             gdisp->lpr_args = copy(attrs->extra_lpr_args);
    1217             :         else
    1218           0 :             oldea = NULL;
    1219           0 :         free(oldfn); free(oldpn); free(oldea);
    1220             :     }
    1221           0 :     if ( gdisp->filename==NULL ) {
    1222           0 :         init = tmpfile();
    1223           0 :         if ( init==NULL ) {
    1224           0 :             GDrawError("Can't open printer temporary file" );
    1225           0 : return( NULL );
    1226             :         }
    1227           0 :     } else if (( init = fopen(gdisp->filename,"wb"))==NULL ) {
    1228           0 :         GDrawError("Can't open %s: %s", gdisp->print_to_file?"user file":"printer spooling file",
    1229             :                 gdisp->filename);
    1230           0 : return( NULL );
    1231             :     }
    1232           0 :     output = tmpfile();
    1233           0 :     if ( output==NULL )
    1234           0 :         output = init;
    1235             : 
    1236           0 :     gdisp->fontstate->res = gdisp->res;
    1237             : 
    1238           0 :     gdisp->groot = calloc(1,sizeof(struct gpswindow));
    1239           0 :     groot = (GPSWindow)(gdisp->groot);
    1240           0 :     groot->ggc = _GPSDraw_NewGGC(gdisp);
    1241           0 :     groot->display = gdisp;
    1242           0 :     groot->pos.width = (gdisp->xwidth-gdisp->lmargin-gdisp->rmargin)*gdisp->res/gdisp->scale;
    1243           0 :     groot->pos.height = (gdisp->yheight-gdisp->tmargin-gdisp->bmargin)*gdisp->res/gdisp->scale;
    1244           0 :     groot->user_data = user_data;
    1245           0 :     groot->output_file = output;
    1246           0 :     groot->init_file = init;
    1247           0 :     groot->cur_x = groot->cur_y = -1;
    1248           0 :     groot->cur_fg = COLOR_UNKNOWN;
    1249           0 :     groot->pnt_cnt = -1;
    1250           0 :     groot->res = gdisp->res;
    1251           0 :     groot->cur_dash_len = groot->cur_skip_len = -1;
    1252           0 :     groot->cur_line_width = -1;
    1253           0 :     groot->cur_dash_offset = -1;
    1254           0 :     groot->cur_ts = -1;
    1255           0 :     groot->last_dash_len = groot->last_skip_len = -1;
    1256           0 :     groot->last_line_width = -1;
    1257           0 :     groot->last_dash_offset = -1;
    1258           0 :     groot->last_ts = -1;
    1259           0 :     groot->last_fg = COLOR_UNKNOWN;
    1260           0 :     groot->is_toplevel = true;
    1261           0 :     groot->is_visible = true;
    1262             : 
    1263           0 :     PSInitJob(groot,(attrs->mask&pam_title)?attrs->title:NULL);
    1264           0 : return( (GWindow) groot);
    1265             : }
    1266             : 
    1267           0 : static void GPSPrinterNextPage(GWindow w) {
    1268           0 :     GPSWindow ps = (GPSWindow) w;
    1269           0 :     if (ps->display->eps )
    1270           0 :         GDrawIError("Attempt to start a new page within an encapsulated postscript document");
    1271             :     else {
    1272           0 :         PSPageTerm(ps,false);
    1273           0 :         PSPageInit(ps);
    1274             :     }
    1275           0 : }
    1276             : 
    1277           0 : static int GPSPrinterEndJob(GWindow w,int cancel) {
    1278           0 :     GPSWindow ps = (GPSWindow) w;
    1279           0 :     GPSDisplay *gdisp = ps->display;
    1280             :     int ret;
    1281             : 
    1282           0 :     PSPageTerm(ps,true);
    1283           0 :     PSTrailer(ps);
    1284           0 :     ret = PSFinishJob(ps,cancel);
    1285           0 :     _GPSDraw_ResetFonts(gdisp->fontstate);
    1286           0 :     PSDestroyContext(gdisp);
    1287           0 :     free(gdisp->filename); gdisp->filename=NULL;
    1288           0 : return( ret );
    1289             : }
    1290             : 
    1291           0 : static GWindow PSDrawCreateTopWindow(GDisplay *gdisp, GRect *UNUSED(pos),
    1292             :         int (*eh)(GWindow,GEvent *), void *user_data, GWindowAttrs *wattrs) {
    1293             :     (void)eh;
    1294           0 : return( GPSPrinterStartJob(gdisp, wattrs==NULL ? NULL : user_data, NULL));
    1295             : }
    1296             : 
    1297           0 : static void PSDrawDestroyWindow(GWindow w) {
    1298           0 :     GPSPrinterEndJob(w,true);
    1299           0 : }
    1300             : 
    1301             : static struct displayfuncs psfuncs = {
    1302             :     PSDrawInit,
    1303             :     PSDrawTerm,
    1304             :     PSDrawNativeDisplay,
    1305             : 
    1306             :     PSDrawSetDefaultIcon,
    1307             : 
    1308             :     PSDrawCreateTopWindow,
    1309             :     PSDrawCreateSubWindow,
    1310             :     PSDrawCreatePixmap,
    1311             :     PSDrawCreateBitmap,
    1312             :     PSDrawCreateCursor,
    1313             :     PSDrawDestroyWindow,
    1314             :     PSDestroyCursor,
    1315             :     PSNativeWindowExists,
    1316             :     PSSetZoom,
    1317             :     PSSetWindowBorder,
    1318             :     PSSetWindowBackground,
    1319             :     PSSetDither,
    1320             : 
    1321             :     PSDrawReparentWindow,
    1322             :     PSDrawSetVisible,
    1323             :     PSDrawMove,
    1324             :     PSDrawMove,
    1325             :     PSDrawResize,
    1326             :     PSDrawMoveResize,
    1327             :     PSDrawRaise,
    1328             :     PSDrawRaiseAbove,
    1329             :     PSDrawIsAbove,
    1330             :     PSDrawLower,
    1331             :     PSDrawSetWindowTitles,
    1332             :     PSDrawSetWindowTitles8,
    1333             :     PSDrawGetWindowTitle,
    1334             :     PSDrawGetWindowTitle8,
    1335             :     PSDrawSetTransientFor,
    1336             :     PSDrawGetPointerPosition,
    1337             :     PSDrawGetPointerWindow,
    1338             :     PSDrawSetCursor,
    1339             :     PSDrawGetCursor,
    1340             :     PSDrawGetRedirectWindow,
    1341             :     PSDrawTranslateCoordinates,
    1342             : 
    1343             :     PSDrawBeep,
    1344             :     PSDrawFlush,
    1345             : 
    1346             :     PSDrawPushClip,
    1347             :     PSDrawPopClip,
    1348             : 
    1349             :     PSDrawClear,
    1350             :     PSDrawDrawLine,
    1351             :     PSDrawDrawArrowLine,
    1352             :     PSDrawDrawRect,
    1353             :     PSDrawFillRect,
    1354             :     PSDrawFillRoundRect,
    1355             :     PSDrawDrawCircle,
    1356             :     PSDrawFillCircle,
    1357             :     PSDrawDrawArc,
    1358             :     PSDrawDrawPoly,
    1359             :     PSDrawFillPoly,
    1360             :     PSDrawScroll,
    1361             : 
    1362             :     _GPSDraw_Image,
    1363             :     _GPSDraw_TileImage,
    1364             :     _GPSDraw_Image,
    1365             :     _GPSDraw_ImageMagnified,
    1366             :     _PSDraw_CopyScreenToImage,
    1367             :     _PSDraw_Pixmap,
    1368             :     _PSDraw_TilePixmap,
    1369             : 
    1370             :     PSDrawCreateInputContext,
    1371             :     PSDrawSetGIC,
    1372             : 
    1373             :     PSDrawGrabSelection,
    1374             :     PSDrawAddSelectionType,
    1375             :     PSDrawRequestSelection,
    1376             :     PSDrawSelectionHasType,
    1377             :     PSDrawBindSelection,
    1378             :     PSDrawSelectionHasOwner,
    1379             : 
    1380             :     PSDrawPointerUngrab,
    1381             :     PSDrawPointerGrab,
    1382             :     PSDrawRequestExpose,
    1383             :     PSDrawForceUpdate,
    1384             :     PSDrawSync,
    1385             :     PSDrawSkipMouseMoveEvents,
    1386             :     PSDrawProcessPendingEvents,
    1387             :     PSDrawProcessWindowEvents,
    1388             :     PSDrawProcessPendingEvents,         /* Same as for OneEvent */
    1389             :     PSDrawEventLoop,
    1390             :     PSDrawPostEvent,
    1391             :     PSDrawPostDragEvent,
    1392             :     PSDrawRequestDeviceEvents,
    1393             : 
    1394             :     PSDrawRequestTimer,
    1395             :     PSDrawCancelTimer,
    1396             : 
    1397             :     PSDrawSyncThread,
    1398             : 
    1399             :     GPSPrinterStartJob,
    1400             :     GPSPrinterNextPage,
    1401             :     GPSPrinterEndJob,
    1402             : 
    1403             :     PSDrawFontMetrics,
    1404             : 
    1405             :     PSDrawHasCairo,
    1406             : 
    1407             :     PSDrawPathStartNew,
    1408             :     PSDrawPathClose,
    1409             :     PSDrawPathMoveTo,
    1410             :     PSDrawPathLineTo,
    1411             :     PSDrawPathCurveTo,
    1412             :     PSDrawPathStroke,
    1413             :     PSDrawPathFill,
    1414             :     PSDrawPathFillAndStroke,
    1415             : 
    1416             :     NULL,               /* Pango layout */
    1417             :     NULL,
    1418             :     NULL,
    1419             :     NULL,
    1420             :     NULL,
    1421             :     NULL,
    1422             :     NULL,
    1423             :     NULL,
    1424             :     NULL,
    1425             :     NULL
    1426             : };
    1427             : 
    1428           0 : void _GPSDraw_DestroyDisplay(GDisplay *gdisp) {
    1429           0 :   if (gdisp->fontstate != NULL) { free(gdisp->fontstate); gdisp->fontstate = NULL; }
    1430           0 :   free(gdisp);
    1431           0 :   return;
    1432             : }
    1433             : 
    1434           0 : GDisplay *_GPSDraw_CreateDisplay() {
    1435             :     GPSDisplay *gdisp;
    1436             : 
    1437           0 :     gdisp = calloc(1,sizeof(GPSDisplay));
    1438           0 :     if ( gdisp==NULL ) {
    1439           0 : return( NULL );
    1440             :     }
    1441             : 
    1442           0 :     gdisp->funcs = &psfuncs;
    1443           0 :     gdisp->res = 600;
    1444           0 :     if ( screen_display!=NULL )
    1445           0 :         gdisp->scale_screen_by = gdisp->res/screen_display->res;
    1446           0 :     if ( gdisp->scale_screen_by==0 ) gdisp->scale_screen_by =1;
    1447             : 
    1448           0 :     gdisp->scale = 1.;
    1449           0 :     gdisp->xwidth = 8.5;
    1450           0 :     gdisp->yheight = 11;
    1451           0 :     gdisp->lmargin = gdisp->rmargin = gdisp->tmargin = gdisp->bmargin = 1;
    1452           0 :     gdisp->use_lpr = true;
    1453           0 :     gdisp->do_transparent = true;
    1454           0 :     gdisp->num_copies = 1;
    1455           0 :     gdisp->linear_thumb_cnt = 1;
    1456           0 :     gdisp->fontstate = calloc(1,sizeof(FState));
    1457           0 :     gdisp->fontstate->res = gdisp->res;
    1458             : 
    1459           0 :     gdisp->def_background = COLOR_CREATE(0xff,0xff,0xff);
    1460           0 :     gdisp->def_background = COLOR_CREATE(0x00,0x00,0x00);
    1461             : 
    1462           0 :     (gdisp->funcs->init)((GDisplay *) gdisp);
    1463           0 : return( (GDisplay *) gdisp);
    1464             : }

Generated by: LCOV version 1.10