First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xprint / ps / psout.c
blobc24f88b3d5dc021654037e5ab06a3fac24bfdd47
1 /*
3 Copyright 1996, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
27 * (c) Copyright 1996 Hewlett-Packard Company
28 * (c) Copyright 1996 International Business Machines Corp.
29 * (c) Copyright 1996, 2000 Sun Microsystems, Inc. All Rights Reserved.
30 * (c) Copyright 1996 Novell, Inc.
31 * (c) Copyright 1996 Digital Equipment Corp.
32 * (c) Copyright 1996 Fujitsu Limited
33 * (c) Copyright 1996 Hitachi, Ltd.
35 * Permission is hereby granted, free of charge, to any person obtaining
36 * a copy of this software and associated documentation files (the
37 * "Software"), to deal in the Software without restriction, including
38 * without limitation the rights to use, copy, modify, merge, publish,
39 * distribute, sublicense, and/or sell copies of the Software, and to
40 * permit persons to whom the Software is furnished to do so, subject
41 * to the following conditions:
43 * The above copyright notice and this permission notice shall be included
44 * in all copies or substantial portions of the Software.
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
49 * THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
50 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
51 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52 * SOFTWARE.
54 * Except as contained in this notice, the names of the copyright holders
55 * shall not be used in advertising or otherwise to promote the sale, use
56 * or other dealings in this Software without prior written authorization
57 * from said copyright holders.
60 /*******************************************************************
62 ** *********************************************************
63 ** *
64 ** * File: psout.c
65 ** *
66 ** * Contents: Code to output PostScript to file
67 ** *
68 ** * Created By: Roger Helmendach (Liberty Systems)
69 ** *
70 ** * Copyright: Copyright 1996 The Open Group, Inc.
71 ** *
72 ** *********************************************************
74 ********************************************************************/
76 #ifdef HAVE_DIX_CONFIG_H
77 #include <dix-config.h>
78 #endif
80 #include <stdlib.h>
81 #include <stdio.h>
82 #include "os.h"
83 #define USE_PSOUT_PRIVATE 1
84 #include "Ps.h"
85 #include "psout.h"
86 #ifdef XP_USE_FREETYPE
87 #include <ft2build.h>
88 #include FT_FREETYPE_H
89 #endif /* XP_USE_FREETYPE */
90 /* For VENDOR_STRING and VENDOR_RELEASE */
91 #include "site.h"
94 * Standard definitions
97 static char *S_StandardDefs = "\
98 /d{def}bind def\
99 /b{bind}bind d\
100 /bd{b d}b d\
101 /x{exch}bd\
102 /xd{x d}bd\
103 /dp{dup}bd\
104 /t{true}bd\
105 /f{false}bd\
106 /p{pop}bd\
107 /r{roll}bd\
108 /c{copy}bd\
109 /i{index}bd\
110 /rp{repeat}bd\
111 /n{newpath}bd\
112 /w{setlinewidth}bd\
113 /lc{setlinecap}bd\
114 /lj{setlinejoin}bd\
115 /sml{setmiterlimit}bd\
116 /ds{setdash}bd\
117 /ie{ifelse}bd\
118 /len{length}bd\
119 /m{moveto}bd\
120 /rm{rmoveto}bd\
121 /l{lineto}bd\
122 /rl{rlineto}bd\
123 /a{arc}bd\
124 /an{arcn}bd\
125 /st{stroke}bd\
126 /fl{fill}bd\
127 /ef{eofill}bd\
128 /sp{showpage}bd\
129 /cp{closepath}bd\
130 /clp{clippath}bd\
131 /cl{clip}bd\
132 /pb{pathbbox}bd\
133 /tr{translate}bd\
134 /rt{rotate}bd\
135 /dv{div}bd\
136 /ml{mul}bd\
137 /ad{add}bd\
138 /ng{neg}bd\
139 /scl{scale}bd\
140 /sc{setrgbcolor}bd\
141 /g{setgray}bd\
142 /gs{gsave}bd\
143 /gr{grestore}bd\
144 /sv{save}bd\
145 /rs{restore}bd\
146 /mx{matrix}bd\
147 /cm{currentmatrix}bd\
148 /sm{setmatrix}bd\
149 /ccm{concatmatrix}bd\
150 /cc{concat}bd\
151 /ff{findfont}bd\
152 /mf{makefont}bd\
153 /sf{setfont}bd\
154 /cft{currentfont}bd\
155 /fd{FontDirectory}bd\
156 /sh{show}bd\
157 /stw{stringwidth}bd\
158 /ci{colorimage}bd\
159 /ig{image}bd\
160 /im{imagemask}bd\
161 /cf{currentfile}bd\
162 /rh{readhexstring}bd\
163 /str{string}bd\
164 /al{aload}bd\
165 /wh{where}bd\
166 /kn{known}bd\
167 /stp{stopped}bd\
168 /bg{begin}bd\
169 /ed{end}bd\
170 /fa{forall}bd\
171 /pi{putinterval}bd\
172 /mk{mark}bd\
173 /ctm{cleartomark}bd\
174 /df{definefont}bd\
175 /cd{currentdict}bd\
176 /db{20 dict dp bg}bd\
177 /de{ed}bd\
178 /languagelevel wh{p languagelevel}{1}ie\
179 1 eq{/makepattern{p}bd/setpattern{p}bd/setpagedevice{p}bd}if\
180 /mp{makepattern}bd\
181 /spt{setpattern}bd\
182 /spd{setpagedevice}bd\
184 #ifdef XP_USE_FREETYPE
185 "/trmoveto{currentfont /FontMatrix get transform rm}d"
186 #endif /* XP_USE_FREETYPE */
190 * Composite definitions
193 * XYr - Return X/Y dpi for device
195 * XYr <xdpi> <ydpi>
197 * Cs - Coordinate setup (for origin upper left)
199 * <orient(0,1,2,3)> Cs
201 * P - Draw a point
203 * <x> <y> P
205 * R - Add rectangle to path
207 * <x> <y> <w> <h> R
209 * Ac - Add arc to path
211 * <x> <y> <w> <h> <ang1> <ang2> Ac
213 * An - Add arc to path (counterclockwise)
215 * <x> <y> <w> <h> <ang1> <ang2> An
217 * Tf - Set font
219 * <font_name> <size> <iso> Tf
221 * Tfm - Set font with matrix
223 * <font_name> <matrix> <iso> Tfm
225 * T - Draw text
227 * <text> <x> <y> T
229 * Tb - Draw text with background color
231 * <text> <x> <y> <bg_red> <bg_green> <bg_blue> Tb
233 * Im1 - Image 1 bit monochrome imagemask
235 * <x> <y> <w> <h> <sw> <sh> Im1
237 * Im24 - Image 24 bit RGB color
239 * <x> <y> <w> <h> <sw> <sh> Im24
241 * Im1t - Image 1 bit monochrome imagemask (in tile)
243 * <data> <x> <y> <w> <h> <sw> <sh> Im1t
245 * Im24t - Image 24 bit RGB color (in tile)
247 * <data> <x> <y> <w> <h> <sw> <sh> Im24t
250 static char *S_CompositeDefs = "\
251 /XYr{/currentpagedevice wh\
252 {p currentpagedevice dp /HWResolution kn\
253 {/HWResolution get al p}{p 300 300}ie}{300 300}ie}bd\
254 /Cs{dp 0 eq{0 pHt tr XYr -1 x dv 72 ml x 1 x dv 72 ml x scl}if\
255 dp 1 eq{90 rt XYr -1 x dv 72 ml x 1 x dv 72 ml x scl}if\
256 dp 2 eq{pWd 0 tr XYr 1 x dv 72 ml x -1 x dv 72 ml x scl}if\
257 3 eq{pHt pWd tr 90 rt XYr 1 x dv 72 ml x -1 x dv 72 ml x scl}if}bd\
258 /P{gs 1 w [] 0 ds 2 c m .1 ad x .1 ad x l st gr}bd\
259 /R{4 2 r m 1 i 0 rl 0 x rl ng 0 rl cp}bd\
260 /Ac{mx_ cm p 6 -2 r tr 4 2 r ng scl 0 0 .5 5 3 r a mx_ sm}bd\
261 /An{mx_ cm p 6 -2 r tr 4 2 r ng scl 0 0 .5 5 3 r an mx_ sm}bd\
262 /ISO{dp len dict bg{1 i/FID ne{d}{p p}ie}fa\
263 /Encoding ISOLatin1Encoding d cd ed df}bd\
264 /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\
265 /Tp{{x dp iN dp fd x kn{x p dp/f_ x d ff}{dp/f_ x d x ff ISO}ie x}\
266 {x dp/f_ x d ff x}ie}bd\
267 /Tf{Tp[x 0 0 2 i ng 0 0] dp/fm_ x d mf sf}bd\
268 /Tfm{Tp 1 -1 tm1_ scl tm2_ ccm dp/fm_ x d mf sf}bd\
269 /T{m sh}bd\
270 /Tb{gs sc f_ ff sf cft/FontMatrix get 3 get\
271 cft/FontBBox get dp 1 get x 3 get 2 i ml 3 1 r ml\
272 0 0 m 4 i stw p 4 i 4 i m fm_ cc\
273 0 2 i rl dp 0 rl 0 2 i ng rl 0 3 i rl ng 0 rl cp fl p p\
274 gr T}bd\
275 /Im1{6 4 r tr scl t [3 i 0 0 5 i 0 0]{cf str1 rh p} im}bd\
276 /Im1rev{6 4 r tr scl f [3 i 0 0 5 i 0 0]{cf str1 rh p} im}bd\
277 /Im24{gs 6 4 r tr scl 8 [3 i 0 0 5 i 0 0]{cf str3 rh p} f 3 ci}bd\
278 /Im1t{6 4 r tr scl t [3 i 0 0 5 i 0 0]{} im}bd\
279 /Im24t{gs 6 4 r tr scl 8 [3 i 0 0 5 i 0 0]{} f 3 ci}bd\
280 /ck2{/currentpagedevice wh \
281 {p dp currentpagedevice dp 3 -1 r kn \
282 {x get al p 3 -1 r eq 3 1 r eq and } \
283 {p p p p t}ie} \
284 {p p p t}ie}bd \
285 /ck1{/currentpagedevice wh \
286 {p dp currentpagedevice dp 3 -1 r kn \
287 {x get eq} {p p p t}ie} \
288 {p p t}ie}bd \
289 /mtx{scl t [3 i 0 0 5 i 0 0]}bd \
292 char *pg_orient[] = {"Portrait","Landscape","Reverse Portrait","Reverse Landscape"};
294 * Setup definitions
297 static char *S_SetupDefs = "\
298 /mx_ mx d\
299 /im_ mx d\
300 /tm1_ mx d\
301 /tm2_ mx d\
302 /str3 3 str d\
303 /str1 1 str d\
306 /*******************************************************************
307 * PRIVATE FUNCTIONS *
308 *******************************************************************/
310 void
311 S_Flush(PsOutPtr self)
313 int len;
315 if( self->Buf[0] == '\0' )
316 return;
318 len = strlen(self->Buf);
320 /* Append a newline char ('\n') if there isn't one there already */
321 if( self->Buf[len-1] != '\n' )
323 self->Buf[len++] = '\n';
324 self->Buf[len] = '\0';
327 (void)fwrite(self->Buf, len, 1, self->Fp);
329 self->Buf[0] = '\0';
332 static void
333 S_Comment(PsOutPtr self, char *comment)
335 S_Flush(self);
336 strcpy(self->Buf, comment);
337 S_Flush(self);
340 static void
341 S_OutDefs(PsOutPtr self, char *defs)
343 int i, k=0;
344 S_Flush(self);
345 memset(self->Buf, 0, sizeof(self->Buf));
346 for( i=0 ; defs[i]!='\0' ;)
348 if( k>70 && (i==0 || (i && defs[i-1]!='/')) &&
349 (defs[i]==' ' || defs[i]=='/' || defs[i]=='{') )
351 S_Flush(self);
352 k = 0;
353 memset(self->Buf, 0, sizeof(self->Buf));
355 if( k && self->Buf[k-1]==' ' && defs[i]==' ' ) { i++; continue; }
356 self->Buf[k] = defs[i];
357 k++; i++;
359 S_Flush(self);
362 void
363 S_OutNum(PsOutPtr self, float num)
365 int i;
366 char buf[64];
367 int len;
369 sprintf(buf, "%.3f", num);
371 /* Remove any zeros at the end */
372 for( i=strlen(buf)-1 ; buf[i]=='0' ; i-- ); buf[i+1] = '\0';
373 /* Remove '.' if it is the last character */
374 i = strlen(buf)-1; if( buf[i]=='.' ) buf[i] = '\0';
376 len = strlen(self->Buf);
377 if( len > 0 )
379 self->Buf[len++] = ' ';
380 self->Buf[len] = '\0';
382 strcpy(&self->Buf[len], buf);
383 if( (len+i)>70 ) S_Flush(self);
386 static void
387 S_OutStr(PsOutPtr self, char *txt, int txtl)
389 int i, k;
390 char buf[1024];
391 for( i=0,k=0 ; i<txtl ; i++ )
393 if( (txt[i]>=' ' && txt[i]<='~') &&
394 txt[i]!='(' && txt[i]!=')' && txt[i]!='\\' )
395 { buf[k] = txt[i]; k++; continue; }
396 buf[k] = '\\'; k++;
397 sprintf(&buf[k], "%03o", txt[i]&0xFF);
398 /* Skip to the end of the buffer */
399 while( buf[k] != '\0' )
400 k++;
402 strcat(self->Buf, "(");
403 i = strlen(self->Buf);
404 memcpy(&self->Buf[i], buf, k);
405 self->Buf[i+k] = '\0';
406 strcat(self->Buf, ")");
407 if( strlen(self->Buf)>70 ) S_Flush(self);
410 /* Same as S_OutStr() but takes |short *| instead of |char *| */
411 static void
412 S_OutStr16(PsOutPtr self, unsigned short *txt, int txtl)
414 int i, k;
415 char buf[2048];
416 for( i=0,k=0 ; i<txtl ; i++ )
418 if( (txt[i]>=' ' && txt[i]<='~') &&
419 txt[i]!='(' && txt[i]!=')' && txt[i]!='\\' )
420 { buf[k] = txt[i]; k++; continue; }
421 buf[k] = '\\'; k++;
422 sprintf(&buf[k], "%03o", txt[i]&0xFFFF);
423 /* Skip to the end of the buffer */
424 while( buf[k] != '\0' )
425 k++;
427 strcat(self->Buf, "(");
428 i = strlen(self->Buf);
429 memcpy(&self->Buf[i], buf, k);
430 self->Buf[i+k] = '\0';
431 strcat(self->Buf, ")");
432 if( strlen(self->Buf)>70 ) S_Flush(self);
435 void
436 S_OutTok(PsOutPtr self, char *tok, int cr)
438 int len = strlen(self->Buf);
439 if( len > 0 )
441 self->Buf[len++] = ' ';
442 self->Buf[len] = '\0';
444 strcpy(&self->Buf[len], tok);
445 if( cr ) S_Flush(self);
448 static void
449 S_Color(PsOutPtr self, PsOutColor clr)
451 int ir, ig, ib;
452 ir = PSOUTCOLOR_TO_REDBITS(clr);
453 ig = PSOUTCOLOR_TO_GREENBITS(clr);
454 ib = PSOUTCOLOR_TO_BLUEBITS(clr);
455 if( ir==ig && ig==ib )
456 { S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ir)); S_OutTok(self, "g", 1); }
457 else
459 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ir));
460 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ig));
461 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ib));
462 S_OutTok(self, "sc", 1);
466 static void
467 S_SetPageDevice(PsOutPtr self, int orient, int count, int plex, int res,
468 int wd, int ht, int isPage)
470 float fwd = ((float)wd/(float)res)*72.;
471 float fht = ((float)ht/(float)res)*72.;
473 #define USE_WORKAROUND_COPY_COUNT_BUG 1
475 #ifdef USE_WORKAROUND_COPY_COUNT_BUG
476 /* Workaround (see http://xprint.mozdev.org/bugs/show_bug.cgi?id=1861 -
477 * 'Need workaround for bug 1378 ...') to avoid that we print n^2 copies
478 * instead of n copies.
479 * The problem is that we use both /NumCopies here but pass the
480 * %copy-count% to the spooler, too.
481 * But we only have to use _one_ way...
483 * The final fix for bug 1378 (http://xprint.mozdev.org/bugs/show_bug.cgi?id=1378 -
484 * "PS DDX creates n^2 copies of a job instead of n copies") will back this
485 * workaround out and replace it with a better solution.
486 * (see mozilla.org bug 140030
487 * (http://bugzilla.mozilla.org/show_bug.cgi?id=140030 - "Setting number
488 * of copies causes too many copies to print") for the initial report for
489 * this issue...)
491 count = 1;
492 #endif /* USE_WORKAROUND_COPY_COUNT_BUG */
494 S_OutTok(self, "/pWd", 0);
495 S_OutNum(self, fwd);
496 S_OutTok(self, "d /pHt", 0);
497 S_OutNum(self, fht);
498 S_OutTok(self, "d", 1);
501 * if these are page attributes, have PostScript check to see if they
502 * have changed. If not, don't do setpagedevice, since it will cause
503 * a page flush and screw up duplex printing. Having PostScript check
504 * means we don't have to keep track ourselves.
506 if(isPage) {
507 S_OutNum(self, (float) orient);
508 S_OutTok(self, "/Orientation ck1", 0);
509 S_OutTok(self, "pWd pHt /PageSize ck2 and not {", 1);
511 S_OutTok(self, "{db", 0);
513 S_OutTok(self, "/Orientation", 0);
514 S_OutNum(self, (float) orient);
515 S_OutTok(self, " d ", 0);
516 S_OutTok(self, "/PageSize [pWd pHt] d", 0);
518 S_OutTok(self, " de spd", 0);
520 * save a flag to show if we failed to set orientation... determined
521 * by both/either Orientation and/or PageSize, use this
522 * later to set/not set orientation using Cs command.
524 S_OutTok(self,"}stp /orientationFailed x d", 1);
526 * if these are page attributes, have PostScript check to see if they
527 * have changed. If not, don't do setpagedevice, since it will cause
528 * a page flush and screw up duplex printing. Having PostScript check
529 * means we don't have to keep track ourselves.
531 if(isPage)
533 S_OutTok(self,"}if",1);
535 S_OutTok(self, (plex==0)?"f":"t", 0);
536 S_OutTok(self, "/Duplex ck1 ", 0);
538 S_OutTok(self, (plex==2)?"t":"f", 0);
539 S_OutTok(self, "/Tumble ck1 and ", 0);
542 S_OutNum(self, (float)res);
543 S_OutNum(self, (float)res);
544 S_OutTok(self, " /HWResolution ck2 and", 0);
546 if( count>1 )
548 S_OutNum(self, (float)count);
549 S_OutTok(self, " /NumCopies", 0);
550 S_OutTok(self, " ck1 and ", 0);
552 S_OutTok(self," not {",1);
554 S_OutTok(self, "{db", 0);
556 S_OutTok(self, "/Duplex ", 0);
557 S_OutTok(self, (plex==0)?"f":"t", 0);
558 S_OutTok(self, " d ", 0);
560 S_OutTok(self, "/Tumble ", 0);
561 S_OutTok(self, (plex==2)?"t":"f", 0);
562 S_OutTok(self, " d ", 0);
564 S_OutTok(self, " /HWResolution [", 0);
565 S_OutNum(self, (float)res);
566 S_OutNum(self, (float)res);
567 S_OutTok(self, "] d ", 0);
569 if( count>1 )
571 S_OutTok(self, " /NumCopies", 0);
572 S_OutNum(self, (float)count);
573 S_OutTok(self, " d ", 0);
575 S_OutTok(self, " de spd}stp p", 1);
577 if(isPage)
579 S_OutTok(self, "}if", 1);
583 /*******************************************************************
584 * PUBLIC FUNCTIONS *
585 *******************************************************************/
587 FILE *
588 PsOut_ChangeFile(PsOutPtr self, FILE *fp)
590 FILE *nfp;
592 nfp = self->Fp;
594 self->Fp = fp;
596 return nfp;
599 PsOutPtr
600 PsOut_BeginFile(FILE *fp, char *title, int orient, int count, int plex, int res,
601 int wd, int ht, Bool raw)
603 int i;
604 char buffer[256+32]; /* enougth space for a title with 256 chars... */
606 * Get ready to output PostScript header
608 PsOutPtr psout;
609 psout = (PsOutPtr)xalloc(sizeof(PsOutRec));
610 memset(psout, 0, sizeof(PsOutRec));
611 psout->Fp = fp;
612 psout->isRaw = raw;
613 psout->pagenum = 0;
615 if (!raw) {
617 * Output PostScript header
619 /* GhostScript will rant about the missing BoundingBox if we use
620 * "%!PS-Adobe-3.0 EPSF-3.0" here... */
621 S_Comment(psout, "%!PS-Adobe-3.0");
622 #ifdef XP_USE_FREETYPE
624 FT_Int ftmajor = 0,
625 ftminor = 0,
626 ftpatch = 0;
627 extern FT_Library ftypeLibrary; /* defined in xc/lib/font/FreeType/ftfuncs.c */
629 FT_Library_Version(ftypeLibrary, &ftmajor, &ftminor, &ftpatch);
630 sprintf(buffer,
631 "%%%%Creator: The X Print Server's PostScript DDX "
632 "(%s, release %d, FreeType version %d.%d.%d)",
633 VENDOR_STRING, VENDOR_RELEASE,
634 (int)ftmajor, (int)ftminor, (int)ftpatch);
636 #else
637 sprintf(buffer,
638 "%%%%Creator: The X Print Server's PostScript DDX (%s, release %d)",
639 VENDOR_STRING, VENDOR_RELEASE);
640 #endif /* XP_USE_FREETYPE */
641 S_Comment(psout, buffer);
643 if (title)
645 sprintf(buffer, "%%%%Title: %.256s", title);
646 S_Comment(psout, buffer);
648 S_Comment(psout, "%%EndComments");
649 S_Comment(psout, "%%BeginProlog");
650 S_Comment(psout, "%%BeginProcSet: XServer_PS_Functions");
651 S_OutDefs(psout, S_StandardDefs);
652 S_OutDefs(psout, S_CompositeDefs);
653 S_Comment(psout, "%%EndProcSet");
654 S_Comment(psout, "%%EndProlog");
655 S_Comment(psout, "%%BeginSetup");
656 /* set document level page attributes */
657 S_SetPageDevice(psout, orient, count, plex, res, wd, ht, 0);
658 S_Comment(psout, "%%Pages: atend");
659 S_OutDefs(psout, S_SetupDefs);
660 S_Comment(psout, "%%EndSetup");
663 * Initialize the structure
665 psout->CurColor = PSOUTCOLOR_NOCOLOR;
666 psout->LineWidth = 1;
667 psout->LineCap = PsCButt;
668 psout->LineJoin = PsJMiter;
669 psout->NDashes = 0;
670 psout->Dashes = (int *)0;
671 psout->FontName = (char *)0;
672 psout->FontSize = 0;
673 psout->start_image = 0;
674 for( i=0 ; i<4 ; i++ ) psout->FontMtx[i] = 0.;
675 psout->ImageFormat = 0;
676 return(psout);
679 void
680 PsOut_EndFile(PsOutPtr self, int closeFile)
682 char coms[50];
684 if (!self)
685 return;
687 if (!self->isRaw) {
688 S_Comment(self,"%%Trailer");
689 sprintf(coms,"%%%%Pages: %d", self->pagenum);
690 S_Comment(self, coms);
691 S_Comment(self, "%%EOF");
693 if( self->NDashes && self->Dashes ) xfree(self->Dashes);
694 if( self->FontName ) xfree(self->FontName);
695 if( self->Patterns ) xfree(self->Patterns);
696 if( self->Clip.rects ) xfree(self->Clip.rects);
697 if( closeFile ) fclose(self->Fp);
698 xfree(self);
701 void
702 PsOut_BeginPage(PsOutPtr self, int orient, int count, int plex, int res,
703 int wd, int ht)
705 char coms[50];
707 /*** comment for pagenumbers *****/
709 S_Comment(self,"%%PageHeader");
710 self->pagenum++;
711 sprintf(coms,"%%%%Page: %d %d", self->pagenum, self->pagenum);
712 S_Comment(self, coms);
713 sprintf(coms,"%%%%PageOrientation: %s",pg_orient[orient]);
714 S_Comment(self, coms);
716 /*** end comment *****************/
718 /* set page level page attributes */
719 S_SetPageDevice(self, orient, count, plex, res, wd, ht, 1);
721 S_OutTok(self, "gs ", 0);
723 * check to see if we set orientation already; if it wasn't set,
724 * use Cs to set orientation here.
726 S_OutNum(self, (float)orient);
727 S_OutTok(self, "orientationFailed { ", 0);
728 S_OutNum(self, (float)orient);
729 S_OutTok(self, " } { 0 }ie Cs 100 sml gs", 1);
732 void
733 PsOut_EndPage(PsOutPtr self)
735 S_OutTok(self, "gr gr sp", 1);
737 /* did grestore: mark attributes 'dirty' so they will be re-sent */
738 PsOut_DirtyAttributes(self);
740 /*** comment for pagenumbers *****/
742 S_Comment(self,"%%PageTrailer");
744 /*** end comment *****************/
747 void
748 PsOut_DirtyAttributes(PsOutPtr self)
750 int i;
751 self->CurColor = PSOUTCOLOR_NOCOLOR;
752 self->LineWidth = -1;
753 self->LineCap = (PsCapEnum)-1;
754 self->LineJoin = (PsJoinEnum)-1;
755 self->NDashes = -1;
756 self->FontSize = -1;
757 for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.;
758 if( self->Dashes ) { xfree(self->Dashes); self->Dashes = (int *)0; }
759 if( self->FontName ) { xfree(self->FontName); self->FontName = (char *)0; }
762 void
763 PsOut_Comment(PsOutPtr self, char *comment)
765 S_Comment(self, comment);
768 void
769 PsOut_Offset(PsOutPtr self, int x, int y)
771 self->XOff = x;
772 self->YOff = y;
775 void
776 PsOut_Clip(PsOutPtr self, int clpTyp, PsClipPtr clpinf)
778 int i, k;
779 int changed = 0;
780 int xo = self->XOff;
781 int yo = self->YOff;
783 if( self->InTile ) return;
784 if( self->InFrame ) xo = yo = 0;
785 if( clpTyp!=self->ClipType ) changed = 1;
786 else
788 if( clpinf->nRects!=self->Clip.nRects ) changed = 1;
789 else
791 if( clpinf->nOutterClips!=self->Clip.nOutterClips ) changed = 1;
792 else
794 for( i=0 ; i<clpinf->nOutterClips ; i++ )
796 if( memcmp(&clpinf->outterClips[i], &self->Clip.outterClips[i],
797 sizeof(PsRectRec))!=0 ) break;
799 if( i<clpinf->nOutterClips ) changed = 1;
800 else
802 for( i=0 ; i<clpinf->nRects ; i++ )
804 if( memcmp(&clpinf->rects[i], &self->Clip.rects[i],
805 sizeof(PsRectRec))!=0 ) { changed = 1; break; }
810 if( clpinf->nElms!=self->Clip.nElms ) changed = 1;
811 else
813 for( i=0 ; i<clpinf->nElms ; i++ )
815 if( clpinf->elms[i].type!=PSOUT_POINTS )
817 if( memcmp(&clpinf->elms[i], &self->Clip.elms[i],
818 sizeof(PsElmRec))!=0 ) { changed = 1; break; }
820 else
822 if( clpinf->elms[i].type!=self->Clip.elms[i].type ||
823 clpinf->elms[i].nPoints!=self->Clip.elms[i].nPoints )
824 { changed = 1; break; }
825 else
827 for( k=0 ; k<clpinf->elms[i].nPoints ; k++ )
829 if( memcmp(&clpinf->elms[i].c.points[k],
830 &self->Clip.elms[i].c.points[k], sizeof(PsPointRec)) )
831 { changed = 1; break; }
833 if( changed ) break;
840 if( self->Clip.rects ) xfree(self->Clip.rects);
841 if( self->Clip.outterClips ) xfree(self->Clip.outterClips);
842 if( self->Clip.elms )
843 PsDestroyFillElementList(self->Clip.nElms, self->Clip.elms);
844 self->ClipType = clpTyp;
845 self->Clip.nRects = clpinf->nRects;
846 self->Clip.nElms = clpinf->nElms;
847 self->Clip.nOutterClips = clpinf->nOutterClips;
848 if( clpinf->nRects )
850 self->Clip.rects = (PsRectPtr)xalloc(clpinf->nRects*sizeof(PsRectRec));
851 memcpy(self->Clip.rects, clpinf->rects, clpinf->nRects*sizeof(PsRectRec));
853 else self->Clip.rects = 0;
854 if( clpinf->nOutterClips )
856 self->Clip.outterClips = (PsRectPtr)xalloc(clpinf->nOutterClips*
857 sizeof(PsRectRec));
858 memcpy(self->Clip.outterClips, clpinf->outterClips,
859 clpinf->nOutterClips*sizeof(PsRectRec));
861 else self->Clip.outterClips = 0;
862 if( clpinf->nElms )
863 self->Clip.elms = PsCloneFillElementList(clpinf->nElms, clpinf->elms);
864 else self->Clip.elms = 0;
866 PsOut_DirtyAttributes(self);
867 S_OutTok(self, "gr gs", 1);
868 if( self->Clip.nOutterClips )
870 for( i=0 ; i<self->Clip.nOutterClips ; i++ )
872 S_OutNum(self, (float)(self->Clip.outterClips[i].x));
873 S_OutNum(self, (float)(self->Clip.outterClips[i].y));
874 S_OutNum(self, (float)self->Clip.outterClips[i].w);
875 S_OutNum(self, (float)self->Clip.outterClips[i].h);
876 S_OutTok(self, "R", 1);
878 S_OutTok(self, "cl n", 1);
880 if( self->Clip.nRects )
882 for( i=0 ; i<self->Clip.nRects ; i++ )
884 S_OutNum(self, (float)(self->Clip.rects[i].x+xo));
885 S_OutNum(self, (float)(self->Clip.rects[i].y+yo));
886 S_OutNum(self, (float)self->Clip.rects[i].w);
887 S_OutNum(self, (float)self->Clip.rects[i].h);
888 S_OutTok(self, "R", 1);
890 S_OutTok(self, "cl n", 1);
892 if( self->Clip.nElms )
894 PsElmPtr elm = self->Clip.elms;
895 for( i=0 ; i<self->Clip.nElms ; i++,elm++ )
897 switch(elm->type)
899 case PSOUT_POINTS:
900 for( k=0 ; k<elm->nPoints ; k++ )
902 S_OutNum(self, (float)elm->c.points[k].x+xo);
903 S_OutNum(self, (float)elm->c.points[k].y+yo);
904 if( k==0 ) S_OutTok(self, "m", 0);
905 else S_OutTok(self, "l", 0);
907 S_OutTok(self, "cp", 1);
908 break;
909 case PSOUT_RECT:
910 S_OutNum(self, (float)elm->c.rect.x+xo);
911 S_OutNum(self, (float)elm->c.rect.y+yo);
912 S_OutNum(self, (float)elm->c.rect.w);
913 S_OutNum(self, (float)elm->c.rect.h);
914 S_OutTok(self, "R", 1);
915 break;
916 case PSOUT_ARC:
917 if( elm->c.arc.style==PsPieSlice )
919 S_OutNum(self, (float)elm->c.arc.x+xo+(float)elm->c.arc.w/2.);
920 S_OutNum(self, (float)elm->c.arc.y+yo+(float)elm->c.arc.h/2.);
921 S_OutTok(self, "m", 0);
923 S_OutNum(self, (float)elm->c.arc.x+xo+(float)elm->c.arc.w/2.);
924 S_OutNum(self, (float)elm->c.arc.y+yo+(float)elm->c.arc.h/2.);
925 S_OutNum(self, (float)elm->c.arc.w);
926 S_OutNum(self, (float)elm->c.arc.h);
927 S_OutNum(self, (float)elm->c.arc.a1/64.);
928 S_OutNum(self, (float)elm->c.arc.a1/64.+(float)elm->c.arc.a2/64.);
929 if( elm->c.arc.a2<0 ) S_OutTok(self, "An cp", 1);
930 else S_OutTok(self, "Ac cp", 1);
931 break;
934 S_OutTok(self, "cl n", 1);
938 void
939 PsOut_Color(PsOutPtr self, PsOutColor clr)
941 if( clr==self->CurColor || self->InTile>=PsStip ) return;
942 self->CurColor = clr;
943 S_Color(self, clr);
946 void
947 PsOut_FillRule(PsOutPtr self, PsRuleEnum rule)
949 self->FillRule = rule;
952 void
953 PsOut_LineAttrs(PsOutPtr self, int wd, PsCapEnum cap, PsJoinEnum join,
954 int nDsh, int *dsh, int dshOff, PsOutColor bclr)
956 int i;
957 int same = 1;
959 if( wd!=self->LineWidth && wd>=0 )
961 if( wd==0 ) wd = 1;
962 self->LineWidth = wd;
963 S_OutNum(self, (float)wd); S_OutTok(self, "w", 1);
965 if( cap!=self->LineCap )
967 self->LineCap = cap;
968 S_OutNum(self, (float)cap); S_OutTok(self, "lc", 1);
970 if( join!=self->LineJoin )
972 self->LineJoin = join;
973 S_OutNum(self, (float)join); S_OutTok(self, "lj", 1);
975 if( nDsh!=self->NDashes ) same = 0;
976 else if( dshOff!=self->DashOffset ) same = 0;
977 else if( nDsh )
979 for( i=0 ; i<nDsh ; i++ )
980 { if( dsh[i]!=self->Dashes[i] ) break; }
981 if( i<nDsh ) same = 0;
983 if( !same )
985 if( self->NDashes && self->Dashes )
986 { xfree(self->Dashes); self->Dashes = (int *)0; }
987 self->NDashes = nDsh;
988 self->DashOffset = dshOff;
989 if( nDsh ) self->Dashes = (int *)xalloc(sizeof(int)*nDsh);
990 S_OutTok(self, "[", 0);
991 for( i=0 ; i<nDsh ; i++ )
993 self->Dashes[i] = dsh[i];
994 S_OutNum(self, (float)dsh[i]);
996 S_OutTok(self, "]", 0);
997 S_OutNum(self, (float)dshOff);
998 S_OutTok(self, "ds", 1);
1001 if( nDsh )
1002 self->LineBClr = bclr;
1003 else
1004 bclr = PSOUTCOLOR_NOCOLOR;
1007 void
1008 PsOut_TextAttrs(PsOutPtr self, char *fnam, int siz, int iso)
1010 int i;
1011 char buf[256];
1012 if( self->FontName && strcmp(fnam, self->FontName)==0 &&
1013 siz==self->FontSize ) return;
1014 if( self->FontName ) xfree(self->FontName);
1015 self->FontName = (char *)xalloc(strlen(fnam)+1);
1016 strcpy(self->FontName, fnam);
1017 self->FontSize = siz;
1018 for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = -1.;
1019 strcpy(buf, "/"); strcat(buf, fnam);
1020 S_OutTok(self, buf, 0);
1021 S_OutNum(self, (float)siz);
1022 if( iso ) S_OutTok(self, "t", 0);
1023 else S_OutTok(self, "f", 0);
1024 S_OutTok(self, "Tf", 1);
1027 void
1028 PsOut_TextAttrsMtx(PsOutPtr self, char *fnam, float *mtx, int iso)
1030 int i;
1031 char buf[256];
1032 if( self->FontName && strcmp(fnam, self->FontName)==0 &&
1033 mtx[0]==self->FontMtx[0] && mtx[1]==self->FontMtx[1] &&
1034 mtx[2]==self->FontMtx[2] && mtx[3]==self->FontMtx[3] ) return;
1035 if( self->FontName ) xfree(self->FontName);
1036 self->FontName = (char *)xalloc(strlen(fnam)+1);
1037 strcpy(self->FontName, fnam);
1038 for( i=0 ; i<4 ; i++ ) self->FontMtx[i] = mtx[i];
1039 self->FontSize = -1;
1040 strcpy(buf, "/"); strcat(buf, fnam); strcat(buf, " [");
1041 S_OutTok(self, buf, 0);
1042 for( i=0 ; i<4 ; i++ ) S_OutNum(self, mtx[i]);
1043 S_OutTok(self, "0 0]", 0);
1044 if( iso ) S_OutTok(self, "t", 0);
1045 else S_OutTok(self, "f", 0);
1046 S_OutTok(self, "Tfm", 1);
1049 void
1050 PsOut_Polygon(PsOutPtr self, int nPts, PsPointPtr pts)
1052 int i;
1053 int xo = self->XOff;
1054 int yo = self->YOff;
1056 if( self->InFrame || self->InTile ) xo = yo = 0;
1057 if( nPts<=2 ) return;
1058 for( i=0 ; i<nPts ; i++ )
1060 S_OutNum(self, (float)(pts[i].x+xo));
1061 S_OutNum(self, (float)(pts[i].y+yo));
1062 if( i==0 ) S_OutTok(self, "m", 0);
1063 else S_OutTok(self, "l", 0);
1065 if( self->FillRule==PsEvenOdd ) S_OutTok(self, "cp ef", 1);
1066 else S_OutTok(self, "cp fl", 1);
1069 void
1070 PsOut_FillRect(PsOutPtr self, int x, int y, int w, int h)
1072 int xo = self->XOff;
1073 int yo = self->YOff;
1075 if( self->InFrame || self->InTile ) xo = yo = 0;
1076 x += xo; y += yo;
1077 S_OutNum(self, (float)x);
1078 S_OutNum(self, (float)y);
1079 S_OutNum(self, (float)w);
1080 S_OutNum(self, (float)h);
1081 S_OutTok(self, "R fl", 1);
1084 void
1085 PsOut_FillArc(PsOutPtr self, int x, int y, int w, int h,
1086 float ang1, float ang2, PsArcEnum style)
1088 int xo = self->XOff;
1089 int yo = self->YOff;
1091 if( self->InFrame || self->InTile ) xo = yo = 0;
1092 x += xo; y += yo;
1093 if( style==PsPieSlice )
1095 S_OutNum(self, (float)x+(float)w/2.);
1096 S_OutNum(self, (float)y+(float)h/2.);
1097 S_OutTok(self, "m", 0);
1099 S_OutNum(self, (float)x+(float)w/2.);
1100 S_OutNum(self, (float)y+(float)h/2.);
1101 S_OutNum(self, (float)w);
1102 S_OutNum(self, (float)h);
1103 S_OutNum(self, ang1);
1104 S_OutNum(self, ang1+ang2);
1105 if( ang2<0 ) S_OutTok(self, "An cp fl", 1);
1106 else S_OutTok(self, "Ac cp fl", 1);
1109 void
1110 PsOut_Lines(PsOutPtr self, int nPts, PsPointPtr pts)
1112 int i;
1113 int xo = self->XOff;
1114 int yo = self->YOff;
1116 if( self->InFrame || self->InTile ) xo = yo = 0;
1117 if( nPts<1 ) return;
1118 for( i=0 ; i<nPts ; i++ )
1120 S_OutNum(self, (float)(pts[i].x+xo));
1121 S_OutNum(self, (float)(pts[i].y+yo));
1122 if( i==0 ) S_OutTok(self, "m", 0);
1123 else S_OutTok(self, "l", 0);
1125 if( self->LineBClr != PSOUTCOLOR_NOCOLOR )
1127 S_OutTok(self, "gs", 0);
1128 S_Color(self, self->LineBClr);
1129 S_OutTok(self, "[] 0 ds st gr", 0);
1131 S_OutTok(self, "st", 1);
1134 void
1135 PsOut_Points(PsOutPtr self, int nPts, PsPointPtr pts)
1137 int i;
1138 int xo = self->XOff;
1139 int yo = self->YOff;
1141 if( self->InFrame || self->InTile ) xo = yo = 0;
1142 if( nPts<1 ) return;
1143 for( i=0 ; i<nPts ; i++ )
1145 S_OutNum(self, (float)(pts[i].x+xo));
1146 S_OutNum(self, (float)(pts[i].y+yo));
1147 S_OutTok(self, "P", 1);
1151 void
1152 PsOut_DrawRect(PsOutPtr self, int x, int y, int w, int h)
1154 int xo = self->XOff;
1155 int yo = self->YOff;
1157 if( self->InFrame || self->InTile ) xo = yo = 0;
1158 x += xo; y += yo;
1159 S_OutNum(self, (float)x);
1160 S_OutNum(self, (float)y);
1161 S_OutNum(self, (float)w);
1162 S_OutNum(self, (float)h);
1163 S_OutTok(self, "R", 0);
1164 if( self->LineBClr != PSOUTCOLOR_NOCOLOR )
1166 S_OutTok(self, "gs", 0);
1167 S_Color(self, self->LineBClr);
1168 S_OutTok(self, "[] 0 ds st gr", 0);
1170 S_OutTok(self, "st", 1);
1173 void
1174 PsOut_DrawArc(PsOutPtr self, int x, int y, int w, int h,
1175 float ang1, float ang2)
1177 int xo = self->XOff;
1178 int yo = self->YOff;
1180 if( self->InFrame || self->InTile ) xo = yo = 0;
1181 x += xo; y += yo;
1182 S_OutNum(self, (float)x+(float)w/2.);
1183 S_OutNum(self, (float)y+(float)h/2.);
1184 S_OutNum(self, (float)w);
1185 S_OutNum(self, (float)h);
1186 S_OutNum(self, ang1);
1187 S_OutNum(self, ang1+ang2);
1188 if( ang2<0 ) S_OutTok(self, "An", 0);
1189 else S_OutTok(self, "Ac", 0);
1190 if( self->LineBClr != PSOUTCOLOR_NOCOLOR )
1192 S_OutTok(self, "gs", 0);
1193 S_Color(self, self->LineBClr);
1194 S_OutTok(self, "[] 0 ds st gr", 0);
1196 S_OutTok(self, "st", 1);
1199 void
1200 PsOut_Text(PsOutPtr self, int x, int y, char *text, int textl, PsOutColor bclr)
1202 int xo = self->XOff;
1203 int yo = self->YOff;
1205 if( self->InFrame || self->InTile ) xo = yo = 0;
1206 x += xo; y += yo;
1207 S_OutStr(self, text, textl);
1208 S_OutNum(self, (float)x);
1209 S_OutNum(self, (float)y);
1210 if( bclr == PSOUTCOLOR_NOCOLOR )
1211 S_OutTok(self, "T", 1);
1212 else
1214 int ir = PSOUTCOLOR_TO_REDBITS(bclr);
1215 int ig = PSOUTCOLOR_TO_GREENBITS(bclr);
1216 int ib = PSOUTCOLOR_TO_BLUEBITS(bclr);
1218 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ir));
1219 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ig));
1220 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ib));
1221 S_OutTok(self, "Tb", 1);
1225 void
1226 PsOut_Text16(PsOutPtr self, int x, int y, unsigned short *text, int textl, PsOutColor bclr)
1228 int xo = self->XOff;
1229 int yo = self->YOff;
1231 if( self->InFrame || self->InTile ) xo = yo = 0;
1232 x += xo; y += yo;
1233 S_OutStr16(self, text, textl);
1234 S_OutNum(self, (float)x);
1235 S_OutNum(self, (float)y);
1236 if( bclr == PSOUTCOLOR_NOCOLOR )
1237 S_OutTok(self, "T", 1);
1238 else
1240 int ir = PSOUTCOLOR_TO_REDBITS(bclr);
1241 int ig = PSOUTCOLOR_TO_GREENBITS(bclr);
1242 int ib = PSOUTCOLOR_TO_BLUEBITS(bclr);
1243 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ir));
1244 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ig));
1245 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ib));
1246 S_OutTok(self, "Tb", 1);
1250 #ifdef BM_CACHE
1251 void /* new */
1252 PsOut_ImageCache(PsOutPtr self, int x, int y, long cache_id, PsOutColor bclr, PsOutColor fclr)
1254 char cacheID[10];
1255 int xo = self->XOff;
1256 int yo = self->YOff;
1258 if( self->InFrame || self->InTile ) xo = yo = 0;
1259 x += xo; y += yo;
1260 sprintf(cacheID, "c%di", cache_id);
1262 S_OutNum(self, (float)x);
1263 S_OutNum(self, (float)y);
1265 if( fclr==PSOUTCOLOR_WHITE )
1267 int ir = PSOUTCOLOR_TO_REDBITS(bclr);
1268 int ig = PSOUTCOLOR_TO_GREENBITS(bclr);
1269 int ib = PSOUTCOLOR_TO_BLUEBITS(bclr);
1271 if( ir==ig && ig==ib )
1272 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ir));
1273 else
1274 S_OutNum(self, (float)0);
1275 self->RevImage = 1;
1277 else
1279 int ir = PSOUTCOLOR_TO_REDBITS(fclr);
1280 int ig = PSOUTCOLOR_TO_GREENBITS(fclr);
1281 int ib = PSOUTCOLOR_TO_BLUEBITS(fclr);
1283 if( ir==ig && ig==ib )
1284 S_OutNum(self, PSOUTCOLOR_BITS_TO_PSFLOAT(ir));
1285 else
1286 S_OutNum(self, (float)0);
1289 S_OutTok(self, cacheID, 1);
1290 } /* new */
1292 void /* new */
1293 PsOut_BeginImageCache(PsOutPtr self, long cache_id)
1295 char cacheID[10];
1297 sprintf(cacheID, "/c%di {", cache_id);
1299 S_OutTok(self, cacheID, 0);
1300 } /* new */
1302 void /* new */
1303 PsOut_EndImageCache(PsOutPtr self)
1305 S_OutTok(self, "}bd", 1);
1306 } /* new */
1307 #endif
1309 void
1310 PsOut_BeginImage(PsOutPtr self, PsOutColor bclr, PsOutColor fclr, int x, int y,
1311 int w, int h, int sw, int sh, int format)
1313 PsOutColor savClr = self->CurColor;
1314 int xo = self->XOff;
1315 int yo = self->YOff;
1317 if( self->InFrame || self->InTile ) xo = yo = 0;
1318 x += xo; y += yo;
1319 if( self->InTile )
1321 if( self->InTile>=PsStip && format!=1 ) { self->ImgSkip = 1; return; }
1322 self->ImgBClr = bclr; self->ImgFClr = fclr;
1323 self->ImgX = x; self->ImgY = y;
1324 self->ImgW = w; self->ImgH = h;
1325 self->SclW = sw; self->SclH = sh;
1326 S_OutTok(self, "<", 0);
1327 self->ImageFormat = format;
1328 self->RevImage = 0;
1329 if( self->InTile==PsTile && format==1 && fclr==PSOUTCOLOR_WHITE )
1330 self->RevImage = 1;
1331 return;
1334 self->RevImage = 0;
1335 if( format==1 )
1337 S_OutTok(self, "gs", 0);
1338 if( fclr==PSOUTCOLOR_WHITE )
1340 PsOut_Color(self, fclr);
1341 PsOut_FillRect(self, x, y, sw, sh);
1342 PsOut_Color(self, bclr);
1343 self->RevImage = 1;
1345 else
1347 PsOut_Color(self, bclr);
1348 PsOut_FillRect(self, x, y, sw, sh);
1349 PsOut_Color(self, fclr);
1352 S_OutNum(self, (float)x);
1353 S_OutNum(self, (float)y);
1354 S_OutNum(self, (float)w);
1355 S_OutNum(self, (float)h);
1356 S_OutNum(self, (float)sw);
1357 S_OutNum(self, (float)sh);
1358 if( format==1 ) {
1359 if(self->RevImage)
1360 S_OutTok(self, "Im1rev", 1);
1361 else
1362 S_OutTok(self, "Im1", 1);
1364 else S_OutTok(self, "Im24", 1);
1365 self->ImageFormat = format;
1366 self->CurColor = savClr;
1369 void
1370 PsOut_BeginImageIM(PsOutPtr self, PsOutColor bclr, PsOutColor fclr, int x, int y,
1371 int w, int h, int sw, int sh, int format)
1373 PsOutColor savClr = self->CurColor;
1374 int xo = self->XOff;
1375 int yo = self->YOff;
1377 if( self->InFrame || self->InTile ) xo = yo = 0;
1378 x += xo; y += yo;
1379 if( self->InTile )
1381 if( self->InTile>=PsStip && format!=1 ) { self->ImgSkip = 1; return; }
1382 self->ImgBClr = bclr; self->ImgFClr = fclr;
1383 self->ImgX = x; self->ImgY = y;
1384 self->ImgW = w; self->ImgH = h;
1385 self->SclW = sw; self->SclH = sh;
1386 S_OutTok(self, "<", 0);
1387 self->ImageFormat = format;
1388 self->RevImage = 0;
1389 if( self->InTile==PsTile && format==1 && fclr==PSOUTCOLOR_WHITE )
1390 self->RevImage = 1;
1391 return;
1394 self->RevImage = 0;
1395 if( format==1 )
1397 S_OutTok(self, "gs", 0);
1398 #ifdef BM_CACHE
1399 S_OutTok(self, "g", 1);
1400 #else
1401 if( fclr==PSOUTCOLOR_WHITE )
1403 PsOut_Color(self, bclr);
1404 self->RevImage = 1;
1406 else
1408 PsOut_Color(self, fclr);
1410 #endif
1413 #ifdef BM_CACHE
1414 S_OutTok(self, "tr", 0); /* new */
1415 #else
1416 S_OutNum(self, (float)x);
1417 S_OutNum(self, (float)y);
1418 #endif
1419 S_OutNum(self, (float)w);
1420 S_OutNum(self, (float)h);
1421 S_OutNum(self, (float)sw);
1422 S_OutNum(self, (float)sh);
1423 #ifdef BM_CACHE
1424 S_OutTok(self, "mtx", 1); /* new */
1425 S_OutTok(self, "<", 0); /* new */
1426 self->start_image = 1;
1427 #else
1428 if( format==1 ){
1429 if(self->RevImage)
1430 S_OutTok(self, "Im1rev", 1);
1431 else
1432 S_OutTok(self, "Im1", 1);
1434 else S_OutTok(self, "Im24", 1);
1435 #endif
1436 self->ImageFormat = format;
1437 self->CurColor = savClr;
1440 void
1441 PsOut_EndImage(PsOutPtr self)
1443 if( self->ImgSkip ) { self->ImgSkip = 0; return; }
1444 if( self->InTile )
1446 S_OutTok(self, ">", 1);
1447 if( self->ImageFormat==1 && self->InTile==PsTile )
1449 if( self->ImgFClr==PSOUTCOLOR_WHITE )
1451 PsOut_Color(self, self->ImgFClr);
1452 PsOut_FillRect(self, self->ImgX, self->ImgY, self->SclW, self->SclH);
1453 PsOut_Color(self, self->ImgBClr);
1455 else
1457 PsOut_Color(self, self->ImgBClr);
1458 PsOut_FillRect(self, self->ImgX, self->ImgY, self->SclW, self->SclH);
1459 PsOut_Color(self, self->ImgFClr);
1462 S_OutNum(self, (float)self->ImgX);
1463 S_OutNum(self, (float)self->ImgY);
1464 S_OutNum(self, (float)self->ImgW);
1465 S_OutNum(self, (float)self->ImgH);
1466 S_OutNum(self, (float)self->SclW);
1467 S_OutNum(self, (float)self->SclH);
1468 if( self->ImageFormat==1 ) S_OutTok(self, "Im1t", 1);
1469 else S_OutTok(self, "Im24t", 1);
1470 self->ImageFormat = 0;
1471 self->RevImage = 0;
1472 return;
1475 * Bug 4639307: Move flush before "> im" to get all of bitmap into ps file.
1477 S_Flush(self);
1478 #ifdef BM_CACHE
1479 if(self->start_image)
1480 S_OutTok(self, "> im", 1); /* new */
1481 #endif
1482 self->ImageFormat = 0;
1483 self->RevImage = 0;
1484 #ifdef BM_CACHE
1485 if(self->start_image)
1487 self->start_image = 0;
1488 S_OutTok(self, "gr", 0);
1490 else
1491 S_OutTok(self, "gr", 1);
1492 #else
1493 S_OutTok(self, "gr", 1);
1494 #endif
1497 void
1498 PsOut_OutImageBytes(PsOutPtr self, int nBytes, char *bytes)
1500 int i;
1501 int b;
1502 int len;
1503 const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
1504 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
1506 if( (!self->ImageFormat) || self->ImgSkip ) return;
1508 len = strlen(self->Buf);
1510 for( i=0 ; i<nBytes ; i++ )
1512 if( self->RevImage ) b = (int)((bytes[i]^0xFF)&0xFF);
1513 else b = (int)(bytes[i]&0xFF);
1515 self->Buf[len++] = hex[(b&0xF0) >> 4];
1516 self->Buf[len++] = hex[(b&0x0F)];
1517 self->Buf[len] = '\0';
1519 if( len>70 )
1521 S_Flush(self);
1522 len = 0;
1527 void
1528 PsOut_BeginFrame(PsOutPtr self, int xoff, int yoff, int x, int y,
1529 int w, int h)
1531 int xo = self->XOff;
1532 int yo = self->YOff;
1534 if( self->InFrame ) xo = yo = 0;
1535 S_OutTok(self, "gs", 0);
1536 S_OutNum(self, (float)(x+xo));
1537 S_OutNum(self, (float)(y+yo));
1538 S_OutNum(self, (float)w);
1539 S_OutNum(self, (float)h);
1540 S_OutTok(self, "R cl n", 0);
1541 xoff += xo; yoff += yo;
1542 if( xoff || yoff )
1544 S_OutNum(self, (float)xoff);
1545 S_OutNum(self, (float)yoff);
1546 S_OutTok(self, "tr", 0);
1548 S_OutTok(self, "gs", 1);
1549 self->InFrame += 1;
1552 void
1553 PsOut_EndFrame(PsOutPtr self)
1555 self->InFrame -= 1;
1556 if( self->InFrame<0 ) self->InFrame = 0;
1557 S_OutTok(self, "gr gr", 1);
1558 PsOut_DirtyAttributes(self);
1562 PsOut_BeginPattern(PsOutPtr self, void *tag, int w, int h, PsFillEnum type,
1563 PsOutColor bclr, PsOutColor fclr)
1565 int i;
1566 char key[64];
1568 for( i=0 ; i<self->NPatterns ; i++ )
1569 { if( self->Patterns[i].tag==tag && self->Patterns[i].type==type ) break; }
1570 if( i<self->NPatterns ) return(1);
1571 if( (self->NPatterns+1)>self->MxPatterns )
1573 if( self->Patterns )
1575 self->MxPatterns *= 2;
1576 self->Patterns =
1577 (PsPatPtr)xrealloc(self->Patterns, sizeof(PsPatRec)*self->MxPatterns);
1579 else
1581 self->MxPatterns = 64;
1582 self->Patterns = (PsPatPtr)xalloc(sizeof(PsPatRec)*self->MxPatterns);
1585 self->Patterns[self->NPatterns].tag = tag;
1586 self->Patterns[self->NPatterns].type = type;
1587 sprintf(key, "/ %d", (int)tag);
1588 switch(type) {
1589 case PsTile: key[1] = 't'; break;
1590 case PsStip: key[1] = 's'; break;
1591 case PsOpStip: key[1] = 'o'; break;
1592 default: break; }
1593 S_OutTok(self, key, 0);
1594 S_OutTok(self, "db/PatternType 1 d/PaintType 1 d", 0);
1595 S_OutTok(self, "/TilingType 1 d/BBox[0 0", 0);
1596 S_OutNum(self, (float)w);
1597 S_OutNum(self, (float)h);
1598 S_OutTok(self, "]d/XStep", 0);
1599 S_OutNum(self, (float)w);
1600 S_OutTok(self, "d/YStep", 0);
1601 S_OutNum(self, (float)h);
1602 S_OutTok(self, "d/PaintProc{bg sv", 1);
1603 if( type==PsOpStip )
1605 S_Color(self, bclr);
1606 S_OutTok(self, "0 0", 0);
1607 S_OutNum(self, (float)w);
1608 S_OutNum(self, (float)h);
1609 S_OutTok(self, "R fl", 1);
1611 if( type!=PsTile ) S_Color(self, fclr);
1612 self->NPatterns += 1;
1613 self->InTile = type;
1614 return(0);
1617 void
1618 PsOut_EndPattern(PsOutPtr self)
1620 self->InTile = PsSolid;
1621 S_OutTok(self, "rs ed}d de im_ mp d", 1);
1624 void
1625 PsOut_SetPattern(PsOutPtr self, void *tag, PsFillEnum type)
1627 int i;
1628 char key[64];
1630 for( i=0 ; i<self->NPatterns ; i++ )
1631 { if( tag==self->Patterns[i].tag && type==self->Patterns[i].type ) break; }
1632 if( i>=self->NPatterns ) return;
1633 sprintf(key, " %d", (int)tag);
1634 switch(type) {
1635 case PsTile: key[0] = 't'; break;
1636 case PsStip: key[0] = 's'; break;
1637 case PsOpStip: key[0] = 'o'; break;
1638 default: break; }
1639 S_OutTok(self, key, 0);
1640 S_OutTok(self, "spt", 1);
1641 self->CurColor = PSOUTCOLOR_NOCOLOR;
1644 void
1645 PsOut_RawData(PsOutPtr self, char *data, int len)
1647 S_Flush(self);
1648 if (!ferror(self->Fp)) {
1649 (void) fwrite(data, 1, len, self->Fp);
1653 typedef enum PsDownfontFontType_
1655 PsDFT_Type1PFA=0,
1656 PsDFT_Type1PFB,
1657 PsDFT_TrueType /* not implemented yet */
1658 } PsDownfontFontType;
1660 /* Download a PS Type1 font */
1662 PsOut_DownloadType1(PsOutPtr self, const char *auditmsg, const char *name, const char *fname)
1664 int stt;
1665 char buf[256];
1666 FILE *fp;
1667 PsDownfontFontType type;
1669 fp = fopen(fname, "r");
1670 if( !fp )
1671 return 0;
1673 #ifdef DEBUG_gisburn
1674 /* This should be log-able! */
1675 fprintf(stderr, "PsOut_DownloadType1: %s: Downloading '%s' from '%s'\n", auditmsg, name, fname);
1676 #endif /* DEBUG_gisburn */
1678 fread(buf, 32, 1, fp);
1679 fseek(fp, (long)0, 0);
1681 /* Is this a Adobe PostScript Type 1 binary font (PFB) ? */
1682 if( (buf[0]&0xFF)==0x80 && (buf[1]&0xFF)==0x01 )
1684 type = PsDFT_Type1PFB;
1686 /* Is this a Adobe PostScript ASCII font (PFA) ? */
1687 else if (!strncmp(buf, "%!PS-AdobeFont", 14))
1689 type = PsDFT_Type1PFA;
1691 else
1693 /* This should be log-able! */
1694 fprintf(stderr, "PsOut_DownloadType1: Unknown font type for '%s'\n", fname);
1695 return 0;
1698 S_Flush(self);
1699 sprintf(buf, "%%%%BeginFont: %s", name);
1700 S_Comment(self, buf);
1702 if( type == PsDFT_Type1PFB )
1704 char *buf,
1705 *pt;
1706 int len,
1708 stype;
1710 ch = fgetc(fp);
1711 /* Strip out the binary headers and de-binary it */
1712 while( (ch&0xFF) == 0x80 )
1714 stype = fgetc(fp);
1715 if( stype==3 ) /* eof mark */
1716 break;
1717 len = fgetc(fp);
1718 len |= fgetc(fp)<<8;
1719 len |= fgetc(fp)<<16;
1720 len |= fgetc(fp)<<24;
1721 buf = (char *)xalloc(len+1);
1722 if( stype==1 )
1724 /* Process ASCII section */
1725 len = fread(buf, 1, len, fp);
1726 /* convert any lone CRs (ie Mac eol) to LFs */
1727 for( pt = buf ; (pt = memchr(pt, '\r', len-(pt-buf))) != NULL ; pt++ )
1729 if ( pt[1]!='\n' )
1730 *pt = '\n';
1732 fwrite(buf, 1, len, self->Fp);
1734 else if( stype==2 )
1736 int i;
1738 /* Process binary section */
1739 len = fread(buf, 1, len, fp);
1740 for( i=0 ; i<len ; i++ )
1742 ch = buf[i];
1743 if( ((ch>>4)&0xf) <= 9 )
1744 fputc('0'+((ch>>4)&0xf), self->Fp);
1745 else
1746 fputc('A'-10+((ch>>4)&0xf), self->Fp);
1748 if( (ch&0xf) <= 9 )
1749 fputc('0'+(ch&0xf), self->Fp);
1750 else
1751 fputc('A'-10+(ch&0xf), self->Fp);
1753 if( (i&0x1f)==0x1f )
1754 fputc('\n', self->Fp);
1757 xfree(buf);
1759 /* Next block... */
1760 ch = fgetc(fp);
1763 /* Is this a Adobe PostScript ASCII font (PFA) ? */
1764 else if (type == PsDFT_Type1PFA)
1766 for(;;)
1768 stt = fread(buf, 1, 256, fp);
1769 if( stt<=0 ) break;
1770 if (!ferror(self->Fp)) {
1771 (void) fwrite(buf, 1, stt, self->Fp);
1773 if( stt<256 )
1774 break;
1777 fclose(fp);
1778 S_Flush(self);
1779 S_Comment(self, "%%EndFont");
1781 /* Success... */
1782 return 1;