/* $Xorg: psout.c,v 1.9 2001/03/26 15:25:12 coskrey Exp $ */ /* Copyright 1996, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. */ /* * (c) Copyright 1996 Hewlett-Packard Company * (c) Copyright 1996 International Business Machines Corp. * (c) Copyright 1996, 2000 Sun Microsystems, Inc. All Rights Reserved. * (c) Copyright 1996 Novell, Inc. * (c) Copyright 1996 Digital Equipment Corp. * (c) Copyright 1996 Fujitsu Limited * (c) Copyright 1996 Hitachi, Ltd. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject * to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the names of the copyright holders * shall not be used in advertising or otherwise to promote the sale, use * or other dealings in this Software without prior written authorization * from said copyright holders. */ /******************************************************************* ** ** ********************************************************* ** * ** * File: psout.c ** * ** * Contents: Code to output PostScript to file ** * ** * Created By: Roger Helmendach (Liberty Systems) ** * ** * Copyright: Copyright 1996 The Open Group, Inc. ** * ** ********************************************************* ** ********************************************************************/ /* $XFree86: xc/programs/Xserver/Xprint/ps/psout.c,v 1.11 2001/12/19 21:55:59 dawes Exp $ */ /* * For XFree86 3.3.3: * * As a *quick* way of preventing some buffers overflowing onto the stack, * they have been made static. There are potential problems with * PsOutRec.Buf overflowing too which should be investigated as part of a * review of this code, but that is at least always allocated with malloc * and shouldn't pose an immediate stack trashing problem. * */ #include #include "os.h" #include "Ps.h" #include "psout.h" typedef void *voidPtr; typedef struct PsPatRec_ { PsFillEnum type; voidPtr tag; } PsPatRec; typedef PsPatRec *PsPatPtr; typedef struct PsOutRec_ { FILE *Fp; char Buf[256]; int CurColor; int LineWidth; PsCapEnum LineCap; PsJoinEnum LineJoin; int NDashes; int *Dashes; int DashOffset; int LineBClr; PsRuleEnum FillRule; char *FontName; int FontSize; float FontMtx[4]; int ImageFormat; int RevImage; int NPatterns; int MxPatterns; PsPatPtr Patterns; int ClipType; PsClipRec Clip; int InFrame; int XOff; int YOff; PsFillEnum InTile; int ImgSkip; int ImgBClr; int ImgFClr; int ImgX; int ImgY; int ImgW; int ImgH; int SclW; int SclH; int NDownloads; int MxDownloads; char **Downloads; Bool isRaw; int start_image; } PsOutRec; /* * Standard definitions */ static char *S_StandardDefs = "\ /d{def}bind def\ /b{bind}bind d\ /bd{b d}b d\ /x{exch}bd\ /xd{x d}bd\ /dp{dup}bd\ /t{true}bd\ /f{false}bd\ /p{pop}bd\ /r{roll}bd\ /c{copy}bd\ /i{index}bd\ /rp{repeat}bd\ /n{newpath}bd\ /w{setlinewidth}bd\ /lc{setlinecap}bd\ /lj{setlinejoin}bd\ /sml{setmiterlimit}bd\ /ds{setdash}bd\ /ie{ifelse}bd\ /len{length}bd\ /m{moveto}bd\ /l{lineto}bd\ /rl{rlineto}bd\ /a{arc}bd\ /an{arcn}bd\ /st{stroke}bd\ /fl{fill}bd\ /ef{eofill}bd\ /sp{showpage}bd\ /cp{closepath}bd\ /clp{clippath}bd\ /cl{clip}bd\ /pb{pathbbox}bd\ /tr{translate}bd\ /rt{rotate}bd\ /dv{div}bd\ /ml{mul}bd\ /ad{add}bd\ /ng{neg}bd\ /scl{scale}bd\ /sc{setrgbcolor}bd\ /g{setgray}bd\ /gs{gsave}bd\ /gr{grestore}bd\ /sv{save}bd\ /rs{restore}bd\ /mx{matrix}bd\ /cm{currentmatrix}bd\ /sm{setmatrix}bd\ /ccm{concatmatrix}bd\ /cc{concat}bd\ /ff{findfont}bd\ /mf{makefont}bd\ /sf{setfont}bd\ /cft{currentfont}bd\ /fd{FontDirectory}bd\ /sh{show}bd\ /stw{stringwidth}bd\ /ci{colorimage}bd\ /ig{image}bd\ /im{imagemask}bd\ /cf{currentfile}bd\ /rh{readhexstring}bd\ /str{string}bd\ /al{aload}bd\ /wh{where}bd\ /kn{known}bd\ /stp{stopped}bd\ /bg{begin}bd\ /ed{end}bd\ /fa{forall}bd\ /pi{putinterval}bd\ /mk{mark}bd\ /ctm{cleartomark}bd\ /df{definefont}bd\ /cd{currentdict}bd\ /db{20 dict dp bg}bd\ /de{ed}bd\ /languagelevel wh{p languagelevel}{1}ie\ 1 eq{/makepattern{p}bd/setpattern{p}bd/setpagedevice{p}bd}if\ /mp{makepattern}bd\ /spt{setpattern}bd\ /spd{setpagedevice}bd\ "; /* * Composite definitions * * * XYr - Return X/Y dpi for device * * XYr * * Cs - Coordinate setup (for origin upper left) * * Cs * * P - Draw a point * * P * * R - Add rectangle to path * * R * * Ac - Add arc to path * * Ac * * An - Add arc to path (counterclockwise) * * An * * Tf - Set font * * Tf * * Tfm - Set font with matrix * * Tfm * * T - Draw text * * T * * Tb - Draw text with background color * * Tb * * Im1 - Image 1 bit monochrome imagemask * * Im1 * * Im24 - Image 24 bit RGB color * * Im24 * * Im1t - Image 1 bit monochrome imagemask (in tile) * * Im1t * * Im24t - Image 24 bit RGB color (in tile) * * Im24t */ static char *S_CompositeDefs = "\ /XYr{/currentpagedevice wh\ {p currentpagedevice dp /HWResolution kn\ {/HWResolution get al p}{p 300 300}ie}{300 300}ie}bd\ /Cs{dp 0 eq{0 pHt tr XYr -1 x dv 72 ml x 1 x dv 72 ml x scl}if\ dp 1 eq{90 rt XYr -1 x dv 72 ml x 1 x dv 72 ml x scl}if\ dp 2 eq{pWd 0 tr XYr 1 x dv 72 ml x -1 x dv 72 ml x scl}if\ 3 eq{pHt pWd tr 90 rt XYr 1 x dv 72 ml x -1 x dv 72 ml x scl}if}bd\ /P{gs 1 w [] 0 ds 2 c m .1 ad x .1 ad x l st gr}bd\ /R{4 2 r m 1 i 0 rl 0 x rl ng 0 rl cp}bd\ /Ac{mx_ cm p 6 -2 r tr 4 2 r ng scl 0 0 .5 5 3 r a mx_ sm}bd\ /An{mx_ cm p 6 -2 r tr 4 2 r ng scl 0 0 .5 5 3 r an mx_ sm}bd\ /ISO{dp len dict bg{1 i/FID ne{d}{p p}ie}fa\ /Encoding ISOLatin1Encoding d cd ed df}bd\ /iN{dp len str cvs dp len x 1 i 3 ad str 2 c c p x p dp 3 -1 r(ISO)pi}bd\ /Tp{{x dp iN dp fd x kn{x p dp/f_ x d ff}{dp/f_ x d x ff ISO}ie x}\ {x dp/f_ x d ff x}ie}bd\ /Tf{Tp[x 0 0 2 i ng 0 0] dp/fm_ x d mf sf}bd\ /Tfm{Tp 1 -1 tm1_ scl tm2_ ccm dp/fm_ x d mf sf}bd\ /T{m sh}bd\ /Tb{gs sc f_ ff sf cft/FontMatrix get 3 get\ cft/FontBBox get dp 1 get x 3 get 2 i ml 3 1 r ml\ 0 0 m 4 i stw p 4 i 4 i m fm_ cc\ 0 2 i rl dp 0 rl 0 2 i ng rl 0 3 i rl ng 0 rl cp fl p p\ gr T}bd\ /Im1{6 4 r tr scl t [3 i 0 0 5 i 0 0]{cf str1 rh p} im}bd\ /Im1rev{6 4 r tr scl f [3 i 0 0 5 i 0 0]{cf str1 rh p} im}bd\ /Im24{gs 6 4 r tr scl 8 [3 i 0 0 5 i 0 0]{cf str3 rh p} f 3 ci}bd\ /Im1t{6 4 r tr scl t [3 i 0 0 5 i 0 0]{} im}bd\ /Im24t{gs 6 4 r tr scl 8 [3 i 0 0 5 i 0 0]{} f 3 ci}bd\ /ck2{/currentpagedevice wh \ {p dp currentpagedevice dp 3 -1 r kn \ {x get al p 3 -1 r eq 3 1 r eq and } \ {p p p p t}ie} \ {p p p t}ie}bd \ /ck1{/currentpagedevice wh \ {p dp currentpagedevice dp 3 -1 r kn \ {x get eq} {p p p t}ie} \ {p p t}ie}bd \ /mtx{scl t [3 i 0 0 5 i 0 0]}bd \ "; int pagenum = 0; char *pg_orient[] = {"Portrait","Landscape","Reverse Portrait","Reverse Landscape"}; /* * Setup definitions */ static char *S_SetupDefs = "\ /mx_ mx d\ /im_ mx d\ /tm1_ mx d\ /tm2_ mx d\ /str3 3 str d\ /str1 1 str d\ "; /******************************************************************* * PRIVATE FUNCTIONS * *******************************************************************/ static void S_Flush(PsOutPtr self) { if( self->Buf[0] ) { if( self->Buf[strlen(self->Buf)-1]!='\n' ) strcat(self->Buf, "\n"); if (!ferror(self->Fp)) { (void) fputs(self->Buf, self->Fp); } self->Buf[0] = '\0'; } } static void S_Comment(PsOutPtr self, char *comment) { S_Flush(self); strcpy(self->Buf, comment); S_Flush(self); } static void S_OutDefs(PsOutPtr self, char *defs) { int i, k=0; S_Flush(self); memset(self->Buf, 0, 256); for( i=0 ; defs[i]!='\0' ;) { if( k>70 && (i==0 || (i && defs[i-1]!='/')) && (defs[i]==' ' || defs[i]=='/' || defs[i]=='{') ) { S_Flush(self); k = 0; memset(self->Buf, 0, 256); } if( k && self->Buf[k-1]==' ' && defs[i]==' ' ) { i++; continue; } self->Buf[k] = defs[i]; k++; i++; } S_Flush(self); } static void S_OutNum(PsOutPtr self, float num) { int i; static char buf[64]; sprintf(buf, "%.3f", num); for( i=strlen(buf)-1 ; buf[i]=='0' ; i-- ); buf[i+1] = '\0'; if( buf[strlen(buf)-1]=='.' ) buf[strlen(buf)-1] = '\0'; if( self->Buf[0] ) strcat(self->Buf, " "); strcat(self->Buf, buf); if( strlen(self->Buf)>70 ) S_Flush(self); } static void S_OutStr(PsOutPtr self, char *txt, int txtl) { int i, k; static char buf[512]; for( i=0,k=0 ; i=' ' && txt[i]<='~') && txt[i]!='(' && txt[i]!=')' && txt[i]!='\\' ) { buf[k] = txt[i]; k++; continue; } buf[k] = '\\'; k++; sprintf(&buf[k], "%03o", txt[i]&0xFF); k += 3; } strcat(self->Buf, "("); i = strlen(self->Buf); memcpy(&self->Buf[i], buf, k); self->Buf[i+k] = '\0'; strcat(self->Buf, ")"); if( strlen(self->Buf)>70 ) S_Flush(self); } static void S_OutTok(PsOutPtr self, char *tok, int cr) { if( self->Buf[0] ) strcat(self->Buf, " "); strcat(self->Buf, tok); if( cr ) S_Flush(self); } static void S_Color(PsOutPtr self, int clr) { int ir, ig, ib; ir = clr>>16; ig = (clr>>8)&0xFF; ib = clr&0xFF; if( ir==ig && ig==ib ) { S_OutNum(self, (float)ir/255.); S_OutTok(self, "g", 1); } else { S_OutNum(self, (float)ir/255.); S_OutNum(self, (float)ig/255.); S_OutNum(self, (float)ib/255.); S_OutTok(self, "sc", 1); } } static void S_SetPageDevice(PsOutPtr self, int orient, int count, int plex, int res, int wd, int ht, int isPage) { float fwd = ((float)wd/(float)res)*72.; float fht = ((float)ht/(float)res)*72.; S_OutTok(self, "/pWd", 0); S_OutNum(self, fwd); S_OutTok(self, "d /pHt", 0); S_OutNum(self, fht); S_OutTok(self, "d", 1); /* * if these are page attributes, have PostScript check to see if they * have changed. If not, don't do setpagedevice, since it will cause * a page flush and screw up duplex printing. Having PostScript check * means we don't have to keep track ourselves. */ if(isPage) { S_OutNum(self, (float) orient); S_OutTok(self, "/Orientation ck1", 0); S_OutTok(self, "pWd pHt /PageSize ck2 and not {", 1); } S_OutTok(self, "{db", 0); S_OutTok(self, "/Orientation", 0); S_OutNum(self, (float) orient); S_OutTok(self, " d ", 0); S_OutTok(self, "/PageSize [pWd pHt] d", 0); S_OutTok(self, " de spd", 0); /* * save a flag to show if we failed to set orientation... determined * by both/either Orientation and/or PageSize, use this * later to set/not set orientation using Cs command. */ S_OutTok(self,"}stp /orientationFailed x d", 1); /* * if these are page attributes, have PostScript check to see if they * have changed. If not, don't do setpagedevice, since it will cause * a page flush and screw up duplex printing. Having PostScript check * means we don't have to keep track ourselves. */ if(isPage) { S_OutTok(self,"}if",1); S_OutTok(self, (plex==0)?"f":"t", 0); S_OutTok(self, "/Duplex ck1 ", 0); S_OutTok(self, (plex==2)?"t":"f", 0); S_OutTok(self, "/Tumble ck1 and ", 0); S_OutNum(self, (float)res); S_OutNum(self, (float)res); S_OutTok(self, " /HWResolution ck2 and", 0); if( count>1 ) { S_OutNum(self, (float)count); S_OutTok(self, " /NumCopies", 0); S_OutTok(self, " ck1 and ", 0); } S_OutTok(self," not {",1); } S_OutTok(self, "{db", 0); S_OutTok(self, "/Duplex ", 0); S_OutTok(self, (plex==0)?"f":"t", 0); S_OutTok(self, " d ", 0); S_OutTok(self, "/Tumble ", 0); S_OutTok(self, (plex==2)?"t":"f", 0); S_OutTok(self, " d ", 0); S_OutTok(self, " /HWResolution [", 0); S_OutNum(self, (float)res); S_OutNum(self, (float)res); S_OutTok(self, "] d ", 0); if( count>1 ) { S_OutTok(self, " /NumCopies", 0); S_OutNum(self, (float)count); S_OutTok(self, " d ", 0); } S_OutTok(self, " de spd}stp p", 1); if(isPage) { S_OutTok(self, "}if", 1); } } /******************************************************************* * PUBLIC FUNCTIONS * *******************************************************************/ FILE * PsOut_ChangeFile(PsOutPtr self, FILE *fp) { FILE *nfp; nfp = self->Fp; self->Fp = fp; return nfp; } PsOutPtr PsOut_BeginFile(FILE *fp, int orient, int count, int plex, int res, int wd, int ht, Bool raw) { int i; /* * Get ready to output PostScript header */ PsOutPtr psout; psout = (PsOutPtr)xalloc(sizeof(PsOutRec)); memset(psout, 0, sizeof(PsOutRec)); psout->Fp = fp; psout->isRaw = raw; pagenum = 0; if (!raw) { /* * Output PostScript header */ S_Comment(psout, "%!PS-Adobe-3.0 EPSF-3.0"); S_Comment(psout, "%%Creator: The Open Group PostScript Print Server"); /*### BoundingBox ###*/ S_Comment(psout, "%%EndComments"); S_Comment(psout, "%%BeginProlog"); S_Comment(psout, "%%BeginProcSet: XServer_PS_Functions"); S_OutDefs(psout, S_StandardDefs); S_OutDefs(psout, S_CompositeDefs); S_Comment(psout, "%%EndProcSet"); S_Comment(psout, "%%EndProlog"); S_Comment(psout, "%%BeginSetup"); /* set document level page attributes */ S_SetPageDevice(psout, orient, count, plex, res, wd, ht, 0); S_Comment(psout, "%%Pages: atend"); S_OutDefs(psout, S_SetupDefs); S_Comment(psout, "%%EndSetup"); } /* * Initialize the structure */ psout->CurColor = 0xFFFFFFFF; psout->LineWidth = 1; psout->LineCap = PsCButt; psout->LineJoin = PsJMiter; psout->NDashes = 0; psout->Dashes = (int *)0; psout->FontName = (char *)0; psout->FontSize = 0; psout->start_image = 0; for( i=0 ; i<4 ; i++ ) psout->FontMtx[i] = 0.; psout->ImageFormat = 0; return(psout); } void PsOut_EndFile(PsOutPtr self, int closeFile) { char coms[50]; int i; if (!self->isRaw) { S_Comment(self,"%%Trailer"); sprintf(coms,"%%%%Pages: %d",pagenum); S_Comment(self, coms); S_Comment(self, "%%EOF"); } if( self->NDashes && self->Dashes ) xfree(self->Dashes); if( self->FontName ) xfree(self->FontName); if( self->Patterns ) xfree(self->Patterns); if( self->Clip.rects ) xfree(self->Clip.rects); if( closeFile ) fclose(self->Fp); for( i=0 ; iNDownloads ; i++ ) xfree(self->Downloads[i]); if( self->Downloads ) xfree(self->Downloads); pagenum = 0; /* reset page num back to 0 */ xfree(self); } void PsOut_BeginPage(PsOutPtr self, int orient, int count, int plex, int res, int wd, int ht) { char coms[50]; /*** comment for pagenumbers *****/ S_Comment(self,"%%PageHeader"); pagenum++; sprintf(coms,"%%%%Page: %d %d",pagenum,pagenum); S_Comment(self, coms); sprintf(coms,"%%%%PageOrientation: %s",pg_orient[orient]); S_Comment(self, coms); /*** end comment *****************/ /* set page level page attributes */ S_SetPageDevice(self, orient, count, plex, res, wd, ht, 1); S_OutTok(self, "gs ", 0); /* * check to see if we set orientation already; if it wasn't set, * use Cs to set orientation here. */ S_OutNum(self, (float)orient); S_OutTok(self, "orientationFailed { ", 0); S_OutNum(self, (float)orient); S_OutTok(self, " } { 0 }ie Cs 100 sml gs", 1); } void PsOut_EndPage(PsOutPtr self) { S_OutTok(self, "gr gr sp", 1); /* did grestore: mark attributes 'dirty' so they will be re-sent */ PsOut_DirtyAttributes(self); /*** comment for pagenumbers *****/ S_Comment(self,"%%PageTrailer"); /*** end comment *****************/ } void PsOut_DirtyAttributes(PsOutPtr self) { int i; self->CurColor = 0xFFFFFFFF; self->LineWidth = -1; self->LineCap = (PsCapEnum)-1; self->LineJoin = (PsJoinEnum)-1; self->NDashes = -1; self->FontSize = -1; for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.; if( self->Dashes ) { xfree(self->Dashes); self->Dashes = (int *)0; } if( self->FontName ) { xfree(self->FontName); self->FontName = (char *)0; } } void PsOut_Comment(PsOutPtr self, char *comment) { S_Comment(self, comment); } void PsOut_Offset(PsOutPtr self, int x, int y) { self->XOff = x; self->YOff = y; } void PsOut_Clip(PsOutPtr self, int clpTyp, PsClipPtr clpinf) { int i, k; int changed = 0; int xo = self->XOff; int yo = self->YOff; if( self->InTile ) return; if( self->InFrame ) xo = yo = 0; if( clpTyp!=self->ClipType ) changed = 1; else { if( clpinf->nRects!=self->Clip.nRects ) changed = 1; else { if( clpinf->nOutterClips!=self->Clip.nOutterClips ) changed = 1; else { for( i=0 ; inOutterClips ; i++ ) { if( memcmp(&clpinf->outterClips[i], &self->Clip.outterClips[i], sizeof(PsRectRec))!=0 ) break; } if( inOutterClips ) changed = 1; else { for( i=0 ; inRects ; i++ ) { if( memcmp(&clpinf->rects[i], &self->Clip.rects[i], sizeof(PsRectRec))!=0 ) { changed = 1; break; } } } } } if( clpinf->nElms!=self->Clip.nElms ) changed = 1; else { for( i=0 ; inElms ; i++ ) { if( clpinf->elms[i].type!=PSOUT_POINTS ) { if( memcmp(&clpinf->elms[i], &self->Clip.elms[i], sizeof(PsElmRec))!=0 ) { changed = 1; break; } } else { if( clpinf->elms[i].type!=self->Clip.elms[i].type || clpinf->elms[i].nPoints!=self->Clip.elms[i].nPoints ) { changed = 1; break; } else { for( k=0 ; kelms[i].nPoints ; k++ ) { if( memcmp(&clpinf->elms[i].c.points[k], &self->Clip.elms[i].c.points[k], sizeof(PsPointRec)) ) { changed = 1; break; } } if( changed ) break; } } } } } if( self->Clip.rects ) xfree(self->Clip.rects); if( self->Clip.outterClips ) xfree(self->Clip.outterClips); if( self->Clip.elms ) PsDestroyFillElementList(self->Clip.nElms, self->Clip.elms); self->ClipType = clpTyp; self->Clip.nRects = clpinf->nRects; self->Clip.nElms = clpinf->nElms; self->Clip.nOutterClips = clpinf->nOutterClips; if( clpinf->nRects ) { self->Clip.rects = (PsRectPtr)xalloc(clpinf->nRects*sizeof(PsRectRec)); memcpy(self->Clip.rects, clpinf->rects, clpinf->nRects*sizeof(PsRectRec)); } else self->Clip.rects = 0; if( clpinf->nOutterClips ) { self->Clip.outterClips = (PsRectPtr)xalloc(clpinf->nOutterClips* sizeof(PsRectRec)); memcpy(self->Clip.outterClips, clpinf->outterClips, clpinf->nOutterClips*sizeof(PsRectRec)); } else self->Clip.outterClips = 0; if( clpinf->nElms ) self->Clip.elms = PsCloneFillElementList(clpinf->nElms, clpinf->elms); else self->Clip.elms = 0; PsOut_DirtyAttributes(self); S_OutTok(self, "gr gs", 1); if( self->Clip.nOutterClips ) { for( i=0 ; iClip.nOutterClips ; i++ ) { S_OutNum(self, (float)(self->Clip.outterClips[i].x)); S_OutNum(self, (float)(self->Clip.outterClips[i].y)); S_OutNum(self, (float)self->Clip.outterClips[i].w); S_OutNum(self, (float)self->Clip.outterClips[i].h); S_OutTok(self, "R", 1); } S_OutTok(self, "cl n", 1); } if( self->Clip.nRects ) { for( i=0 ; iClip.nRects ; i++ ) { S_OutNum(self, (float)(self->Clip.rects[i].x+xo)); S_OutNum(self, (float)(self->Clip.rects[i].y+yo)); S_OutNum(self, (float)self->Clip.rects[i].w); S_OutNum(self, (float)self->Clip.rects[i].h); S_OutTok(self, "R", 1); } S_OutTok(self, "cl n", 1); } if( self->Clip.nElms ) { PsElmPtr elm = self->Clip.elms; for( i=0 ; iClip.nElms ; i++,elm++ ) { switch(elm->type) { case PSOUT_POINTS: for( k=0 ; knPoints ; k++ ) { S_OutNum(self, (float)elm->c.points[k].x+xo); S_OutNum(self, (float)elm->c.points[k].y+yo); if( k==0 ) S_OutTok(self, "m", 0); else S_OutTok(self, "l", 0); } S_OutTok(self, "cp", 1); break; case PSOUT_RECT: S_OutNum(self, (float)elm->c.rect.x+xo); S_OutNum(self, (float)elm->c.rect.y+yo); S_OutNum(self, (float)elm->c.rect.w); S_OutNum(self, (float)elm->c.rect.h); S_OutTok(self, "R", 1); break; case PSOUT_ARC: if( elm->c.arc.style==PsPieSlice ) { S_OutNum(self, (float)elm->c.arc.x+xo+(float)elm->c.arc.w/2.); S_OutNum(self, (float)elm->c.arc.y+yo+(float)elm->c.arc.h/2.); S_OutTok(self, "m", 0); } S_OutNum(self, (float)elm->c.arc.x+xo+(float)elm->c.arc.w/2.); S_OutNum(self, (float)elm->c.arc.y+yo+(float)elm->c.arc.h/2.); S_OutNum(self, (float)elm->c.arc.w); S_OutNum(self, (float)elm->c.arc.h); S_OutNum(self, (float)elm->c.arc.a1/64.); S_OutNum(self, (float)elm->c.arc.a1/64.+(float)elm->c.arc.a2/64.); if( elm->c.arc.a2<0 ) S_OutTok(self, "An cp", 1); else S_OutTok(self, "Ac cp", 1); break; } } S_OutTok(self, "cl n", 1); } } void PsOut_Color(PsOutPtr self, int clr) { if( clr==self->CurColor || self->InTile>=PsStip ) return; self->CurColor = clr; S_Color(self, clr); } void PsOut_FillRule(PsOutPtr self, PsRuleEnum rule) { self->FillRule = rule; } void PsOut_LineAttrs(PsOutPtr self, int wd, PsCapEnum cap, PsJoinEnum join, int nDsh, int *dsh, int dshOff, int bclr) { int i; int same = 1; if( wd!=self->LineWidth && wd>=0 ) { if( wd==0 ) wd = 1; self->LineWidth = wd; S_OutNum(self, (float)wd); S_OutTok(self, "w", 1); } if( cap!=self->LineCap ) { self->LineCap = cap; S_OutNum(self, (float)cap); S_OutTok(self, "lc", 1); } if( join!=self->LineJoin ) { self->LineJoin = join; S_OutNum(self, (float)join); S_OutTok(self, "lj", 1); } if( nDsh!=self->NDashes ) same = 0; else if( dshOff!=self->DashOffset ) same = 0; else if( nDsh ) { for( i=0 ; iDashes[i] ) break; } if( iNDashes && self->Dashes ) { xfree(self->Dashes); self->Dashes = (int *)0; } self->NDashes = nDsh; self->DashOffset = dshOff; if( nDsh ) self->Dashes = (int *)xalloc(sizeof(int)*nDsh); S_OutTok(self, "[", 0); for( i=0 ; iDashes[i] = dsh[i]; S_OutNum(self, (float)dsh[i]); } S_OutTok(self, "]", 0); S_OutNum(self, (float)dshOff); S_OutTok(self, "ds", 1); } if( nDsh ) self->LineBClr = bclr; else bclr = -1; } void PsOut_TextAttrs(PsOutPtr self, char *fnam, int siz, int iso) { int i; static char buf[256]; if( self->FontName && strcmp(fnam, self->FontName)==0 && siz==self->FontSize ) return; if( self->FontName ) xfree(self->FontName); self->FontName = (char *)xalloc(strlen(fnam)+1); strcpy(self->FontName, fnam); self->FontSize = siz; for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.; strcpy(buf, "/"); strcat(buf, fnam); S_OutTok(self, buf, 0); S_OutNum(self, (float)siz); if( iso ) S_OutTok(self, "t", 0); else S_OutTok(self, "f", 0); S_OutTok(self, "Tf", 1); } void PsOut_TextAttrsMtx(PsOutPtr self, char *fnam, float *mtx, int iso) { int i; static char buf[256]; if( self->FontName && strcmp(fnam, self->FontName)==0 && mtx[0]==self->FontMtx[0] && mtx[1]==self->FontMtx[1] && mtx[2]==self->FontMtx[2] && mtx[3]==self->FontMtx[3] ) return; if( self->FontName ) xfree(self->FontName); self->FontName = (char *)xalloc(strlen(fnam)+1); strcpy(self->FontName, fnam); for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = mtx[i]; self->FontSize = -1; strcpy(buf, "/"); strcat(buf, fnam); strcat(buf, " ["); S_OutTok(self, buf, 0); for( i=0 ; i<4 ; i++ ) S_OutNum(self, mtx[i]); S_OutTok(self, "0 0]", 0); if( iso ) S_OutTok(self, "t", 0); else S_OutTok(self, "f", 0); S_OutTok(self, "Tfm", 1); } void PsOut_Polygon(PsOutPtr self, int nPts, PsPointPtr pts) { int i; int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; if( nPts<=2 ) return; for( i=0 ; iFillRule==PsEvenOdd ) S_OutTok(self, "cp ef", 1); else S_OutTok(self, "cp fl", 1); } void PsOut_FillRect(PsOutPtr self, int x, int y, int w, int h) { int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; S_OutNum(self, (float)x); S_OutNum(self, (float)y); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutTok(self, "R fl", 1); } void PsOut_FillArc(PsOutPtr self, int x, int y, int w, int h, float ang1, float ang2, PsArcEnum style) { int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; if( style==PsPieSlice ) { S_OutNum(self, (float)x+(float)w/2.); S_OutNum(self, (float)y+(float)h/2.); S_OutTok(self, "m", 0); } S_OutNum(self, (float)x+(float)w/2.); S_OutNum(self, (float)y+(float)h/2.); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutNum(self, ang1); S_OutNum(self, ang1+ang2); if( ang2<0 ) S_OutTok(self, "An cp fl", 1); else S_OutTok(self, "Ac cp fl", 1); } void PsOut_Lines(PsOutPtr self, int nPts, PsPointPtr pts) { int i; int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; if( nPts<1 ) return; for( i=0 ; iLineBClr>=0 ) { S_OutTok(self, "gs", 0); S_Color(self, self->LineBClr); S_OutTok(self, "[] 0 ds st gr", 0); } S_OutTok(self, "st", 1); } void PsOut_Points(PsOutPtr self, int nPts, PsPointPtr pts) { int i; int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; if( nPts<1 ) return; for( i=0 ; iXOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; S_OutNum(self, (float)x); S_OutNum(self, (float)y); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutTok(self, "R", 0); if( self->LineBClr>=0 ) { S_OutTok(self, "gs", 0); S_Color(self, self->LineBClr); S_OutTok(self, "[] 0 ds st gr", 0); } S_OutTok(self, "st", 1); } void PsOut_DrawArc(PsOutPtr self, int x, int y, int w, int h, float ang1, float ang2) { int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; S_OutNum(self, (float)x+(float)w/2.); S_OutNum(self, (float)y+(float)h/2.); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutNum(self, ang1); S_OutNum(self, ang1+ang2); if( ang2<0 ) S_OutTok(self, "An", 0); else S_OutTok(self, "Ac", 0); if( self->LineBClr>=0 ) { S_OutTok(self, "gs", 0); S_Color(self, self->LineBClr); S_OutTok(self, "[] 0 ds st gr", 0); } S_OutTok(self, "st", 1); } void PsOut_Text(PsOutPtr self, int x, int y, char *text, int textl, int bclr) { int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; S_OutStr(self, text, textl); S_OutNum(self, (float)x); S_OutNum(self, (float)y); if( bclr<0 ) S_OutTok(self, "T", 1); else { int ir = bclr>>16; int ig = (bclr>>8)&0xFF; int ib = bclr&0xFF; S_OutNum(self, (float)ir/255.); S_OutNum(self, (float)ig/255.); S_OutNum(self, (float)ib/255.); S_OutTok(self, "Tb", 1); } } #ifdef BM_CACHE void /* new */ PsOut_ImageCache(PsOutPtr self, int x, int y, long cache_id, int bclr, int fclr) { char cacheID[10]; int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; sprintf(cacheID, "c%ldi", cache_id); S_OutNum(self, (float)x); S_OutNum(self, (float)y); if( fclr==0xFFFFFF ) { int ir, ig, ib; ir = bclr>>16; ig = (bclr>>8)&0xFF; ib = bclr&0xFF; if( ir==ig && ig==ib ) S_OutNum(self, (float)ir/255.); else S_OutNum(self, (float)0); self->RevImage = 1; } else { int ir, ig, ib; ir = fclr>>16; ig = (fclr>>8)&0xFF; ib = fclr&0xFF; if( ir==ig && ig==ib ) S_OutNum(self, (float)ir/255.); else S_OutNum(self, (float)0); } S_OutTok(self, cacheID, 1); } /* new */ void /* new */ PsOut_BeginImageCache(PsOutPtr self, long cache_id) { char cacheID[10]; sprintf(cacheID, "/c%ldi {", cache_id); S_OutTok(self, cacheID, 0); } /* new */ void /* new */ PsOut_EndImageCache(PsOutPtr self) { S_OutTok(self, "}bd", 1); } /* new */ #endif void PsOut_BeginImage(PsOutPtr self, int bclr, int fclr, int x, int y, int w, int h, int sw, int sh, int format) { int savClr = self->CurColor; int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; if( self->InTile ) { if( self->InTile>=PsStip && format!=1 ) { self->ImgSkip = 1; return; } self->ImgBClr = bclr; self->ImgFClr = fclr; self->ImgX = x; self->ImgY = y; self->ImgW = w; self->ImgH = h; self->SclW = sw; self->SclH = sh; S_OutTok(self, "<", 0); self->ImageFormat = format; self->RevImage = 0; if( self->InTile==PsTile && format==1 && fclr==0xFFFFFF ) self->RevImage = 1; return; } self->RevImage = 0; if( format==1 ) { S_OutTok(self, "gs", 0); if( fclr==0xFFFFFF ) { PsOut_Color(self, fclr); PsOut_FillRect(self, x, y, sw, sh); PsOut_Color(self, bclr); self->RevImage = 1; } else { PsOut_Color(self, bclr); PsOut_FillRect(self, x, y, sw, sh); PsOut_Color(self, fclr); } } S_OutNum(self, (float)x); S_OutNum(self, (float)y); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutNum(self, (float)sw); S_OutNum(self, (float)sh); if( format==1 ) { if(self->RevImage) S_OutTok(self, "Im1rev", 1); else S_OutTok(self, "Im1", 1); } else S_OutTok(self, "Im24", 1); self->ImageFormat = format; self->CurColor = savClr; } void PsOut_BeginImageIM(PsOutPtr self, int bclr, int fclr, int x, int y, int w, int h, int sw, int sh, int format) { int savClr = self->CurColor; int xo = self->XOff; int yo = self->YOff; if( self->InFrame || self->InTile ) xo = yo = 0; x += xo; y += yo; if( self->InTile ) { if( self->InTile>=PsStip && format!=1 ) { self->ImgSkip = 1; return; } self->ImgBClr = bclr; self->ImgFClr = fclr; self->ImgX = x; self->ImgY = y; self->ImgW = w; self->ImgH = h; self->SclW = sw; self->SclH = sh; S_OutTok(self, "<", 0); self->ImageFormat = format; self->RevImage = 0; if( self->InTile==PsTile && format==1 && fclr==0xFFFFFF ) self->RevImage = 1; return; } self->RevImage = 0; if( format==1 ) { S_OutTok(self, "gs", 0); #ifdef BM_CACHE S_OutTok(self, "g", 1); #else if( fclr==0xFFFFFF ) { PsOut_Color(self, bclr); self->RevImage = 1; } else { PsOut_Color(self, fclr); } #endif } #ifdef BM_CACHE S_OutTok(self, "tr", 0); /* new */ #else S_OutNum(self, (float)x); S_OutNum(self, (float)y); #endif S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutNum(self, (float)sw); S_OutNum(self, (float)sh); #ifdef BM_CACHE S_OutTok(self, "mtx", 1); /* new */ S_OutTok(self, "<", 0); /* new */ self->start_image = 1; #else if( format==1 ){ if(self->RevImage) S_OutTok(self, "Im1rev", 1); else S_OutTok(self, "Im1", 1); } else S_OutTok(self, "Im24", 1); #endif self->ImageFormat = format; self->CurColor = savClr; } void PsOut_EndImage(PsOutPtr self) { if( self->ImgSkip ) { self->ImgSkip = 0; return; } if( self->InTile ) { S_OutTok(self, ">", 1); if( self->ImageFormat==1 && self->InTile==PsTile ) { if( self->ImgFClr==0xFFFFFF ) { PsOut_Color(self, self->ImgFClr); PsOut_FillRect(self, self->ImgX, self->ImgY, self->SclW, self->SclH); PsOut_Color(self, self->ImgBClr); } else { PsOut_Color(self, self->ImgBClr); PsOut_FillRect(self, self->ImgX, self->ImgY, self->SclW, self->SclH); PsOut_Color(self, self->ImgFClr); } } S_OutNum(self, (float)self->ImgX); S_OutNum(self, (float)self->ImgY); S_OutNum(self, (float)self->ImgW); S_OutNum(self, (float)self->ImgH); S_OutNum(self, (float)self->SclW); S_OutNum(self, (float)self->SclH); if( self->ImageFormat==1 ) S_OutTok(self, "Im1t", 1); else S_OutTok(self, "Im24t", 1); self->ImageFormat = 0; self->RevImage = 0; return; } #ifdef BM_CACHE if(self->start_image) S_OutTok(self, "> im", 1); /* new */ #endif self->ImageFormat = 0; self->RevImage = 0; S_Flush(self); #ifdef BM_CACHE if(self->start_image) { self->start_image = 0; S_OutTok(self, "gr", 0); } else S_OutTok(self, "gr", 1); #else S_OutTok(self, "gr", 1); #endif } void PsOut_OutImageBytes(PsOutPtr self, int nBytes, char *bytes) { int i; char buf[5]; if( (!self->ImageFormat) || self->ImgSkip ) return; for( i=0 ; iRevImage ) sprintf(buf, "%02x", (int)(bytes[i]^0xFF)&0xFF); else sprintf(buf, "%02x", (int)bytes[i]&0xFF); strcat(self->Buf, buf); if( strlen(self->Buf)>70 ) S_Flush(self); } } void PsOut_BeginFrame(PsOutPtr self, int xoff, int yoff, int x, int y, int w, int h) { int xo = self->XOff; int yo = self->YOff; if( self->InFrame ) xo = yo = 0; S_OutTok(self, "gs", 0); S_OutNum(self, (float)(x+xo)); S_OutNum(self, (float)(y+yo)); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutTok(self, "R cl n", 0); xoff += xo; yoff += yo; if( xoff || yoff ) { S_OutNum(self, (float)xoff); S_OutNum(self, (float)yoff); S_OutTok(self, "tr", 0); } S_OutTok(self, "gs", 1); self->InFrame += 1; } void PsOut_EndFrame(PsOutPtr self) { self->InFrame -= 1; if( self->InFrame<0 ) self->InFrame = 0; S_OutTok(self, "gr gr", 1); PsOut_DirtyAttributes(self); } int PsOut_BeginPattern(PsOutPtr self, void *tag, int w, int h, PsFillEnum type, int bclr, int fclr) { int i; char key[64]; for( i=0 ; iNPatterns ; i++ ) { if( self->Patterns[i].tag==tag && self->Patterns[i].type==type ) break; } if( iNPatterns ) return(1); if( (self->NPatterns+1)>self->MxPatterns ) { if( self->Patterns ) { self->MxPatterns *= 2; self->Patterns = (PsPatPtr)xrealloc(self->Patterns, sizeof(PsPatRec)*self->MxPatterns); } else { self->MxPatterns = 64; self->Patterns = (PsPatPtr)xalloc(sizeof(PsPatRec)*self->MxPatterns); } } self->Patterns[self->NPatterns].tag = tag; self->Patterns[self->NPatterns].type = type; sprintf(key, "/ %ld", (long)tag); switch(type) { case PsTile: key[1] = 't'; break; case PsStip: key[1] = 's'; break; case PsOpStip: key[1] = 'o'; break; default: break; } S_OutTok(self, key, 0); S_OutTok(self, "db/PatternType 1 d/PaintType 1 d", 0); S_OutTok(self, "/TilingType 1 d/BBox[0 0", 0); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutTok(self, "]d/XStep", 0); S_OutNum(self, (float)w); S_OutTok(self, "d/YStep", 0); S_OutNum(self, (float)h); S_OutTok(self, "d/PaintProc{bg sv", 1); if( type==PsOpStip ) { S_Color(self, bclr); S_OutTok(self, "0 0", 0); S_OutNum(self, (float)w); S_OutNum(self, (float)h); S_OutTok(self, "R fl", 1); } if( type!=PsTile ) S_Color(self, fclr); self->NPatterns += 1; self->InTile = type; return(0); } void PsOut_EndPattern(PsOutPtr self) { self->InTile = PsSolid; S_OutTok(self, "rs ed}d de im_ mp d", 1); } void PsOut_SetPattern(PsOutPtr self, void *tag, PsFillEnum type) { int i; char key[64]; for( i=0 ; iNPatterns ; i++ ) { if( tag==self->Patterns[i].tag && type==self->Patterns[i].type ) break; } if( i>=self->NPatterns ) return; sprintf(key, " %ld", (long)tag); switch(type) { case PsTile: key[0] = 't'; break; case PsStip: key[0] = 's'; break; case PsOpStip: key[0] = 'o'; break; default: break; } S_OutTok(self, key, 0); S_OutTok(self, "spt", 1); self->CurColor = 0xFFFFFFFF; } void PsOut_RawData(PsOutPtr self, char *data, int len) { S_Flush(self); if (!ferror(self->Fp)) { (void) fwrite(data, 1, len, self->Fp); } } void PsOut_DownloadType1(PsOutPtr self, char *name, char *fname) { int i; int stt; static char buf[256]; FILE *fp; for( i=0 ; iNDownloads ; i++ ) { if( strcmp(name, self->Downloads[i])==0 ) break; } if( iNDownloads ) return; if( (self->NDownloads+1)>self->MxDownloads ) { if( self->NDownloads ) { self->MxDownloads *= 2; self->Downloads = (char **)xrealloc(self->Downloads, self->MxDownloads*sizeof(char *)); } else { self->MxDownloads = 32; self->Downloads = (char **)xalloc(self->MxDownloads*sizeof(char *)); } } self->Downloads[self->NDownloads] = (char *)xalloc(strlen(name)+1); strcpy(self->Downloads[self->NDownloads], name); self->NDownloads += 1; S_Flush(self); sprintf(buf, "%%%%BeginFont: %s", name); S_Comment(self, buf); fp = fopen(fname, "r"); if( !fp ) return; fread(buf, 1, 1, fp); fseek(fp, (long)0, 0); if( (buf[0]&0xFF)==0x80 ) { int len; for(;;) { stt = fread(buf, 1, 2, fp); if( stt!=2 || (buf[0]&0xFF)!=0x80 ) break; if( (int)buf[1]<1 || (int)buf[1]>2 ) break; stt = fread(buf, 1, 4, fp); if( stt!=4 ) break; len = ((buf[3]&0xFF)<<24)|((buf[2]&0xFF)<<16)| ((buf[1]&0xFF)<<8)|(buf[0]&0xFF); for(; len ;) { i = len<256 ? len : 256; stt = fread(buf, 1, i, fp); if( stt<=0 ) break; if (!ferror(self->Fp)) { (void) fwrite(buf, 1, stt, self->Fp); } if( sttFp)) { (void) fwrite(buf, 1, stt, self->Fp); } if( stt<256 ) break; } } fclose(fp); S_Flush(self); S_Comment(self, "%%EndFont"); }