1 /*  Printer.c
2  *      Simple screen printing functions for FRACTINT
3  *      By Matt Saucier CIS: [72371,3101]      7/2/89
4  *      "True-to-the-spirit" of FRACTINT, this code makes few checks that you
5  *      have specified a valid resolution for the printer (just in case yours
6  *      has more dots/line than the Standard HP and IBM/EPSON,
7  *      (eg, Wide Carriage, etc.))
8  *
9  *      PostScript support by Scott Taylor [72401,410] / (DGWM18A)   10/8/90
10  *      For PostScript, use 'printer=PostScript/resolution' where resolution
11  *      is ANY NUMBER between 10 and 600. Common values: 300,150,100,75.
12  *      Default resolution for PostScript is 150 pixels/inch.
13  *      At 200 DPI, a fractal that is 640x480 prints as a 3.2"x2.4" picture.
14  *      PostScript printer names:
15  *
16  *      PostScript/PS                   = Portrait printing
17  *      PostScriptH/PostScriptL/PSH/PSL = Landscape printing
18  *
19  *      This code supports printers attached to a LPTx (1-3) parallel port.
20  *      It also now supports serial printers AFTER THEY ARE CONFIGURED AND
21  *      WORKING WITH THE DOS MODE COMMAND, eg. MODE COM1:9600,n,8,1 (for HP)
22  *      (NOW you can also configure the serial port with the comport= command)
23  *      Printing calls are made directly to the BIOS for DOS can't handle fast
24  *      transfer of data to the HP.  (Or maybe visa-versa, HP can't handle the
25  *      slow transfer of data from DOS)
26  *
27  *      I just added direct port access for COM1 and COM2 **ONLY**. This method
28  *      does a little more testing than BIOS, and may work (especially on
29  *      serial printer sharing devices) where the old method doesn't. I noticed
30  *      maybe a 5% speed increase at 9600 baud. These are selected in the
31  *      printer=.../.../31 for COM1 or 32 for COM2.
32  *
33  *      I also added direct parallel port access for LPT1 and LPT2 **ONLY**.
34  *      This toggles the "INIT" line of the parallel port to reset the printer
35  *      for each print session. It will also WAIT for a error / out of paper /
36  *      not selected condition instead of quitting with an error.
37  *
38  *      Supported Printers:     Tested Ok:
39  *       HP LaserJet
40  *          LJ+,LJII             MDS
41  *       Toshiba PageLaser       MDS (Set FRACTINT to use HP)
42  *       IBM Graphics            MDS
43  *       EPSON
44  *          Models?              Untested.
45  *       IBM LaserPrinter
46  *          with PostScript      SWT
47  *       HP Plotter              SWT
48  *
49  *      Future support to include OKI 20 (color) printer, and just about
50  *      any printer you request.
51  *
52  *      Future modifications to include a more flexible, standard interface
53  *      with the surrounding program, for easier portability to other
54  *      programs.
55  *
56  * PostScript Styles:
57  *  0  Dot
58  *  1  Dot*            [Smoother]
59  *  2  Inverted Dot
60  *  3  Ring
61  *  4  Inverted Ring
62  *  5  Triangle        [45-45-90]
63  *  6  Triangle*       [30-75-75]
64  *  7  Grid
65  *  8  Diamond
66  *  9  Line
67  * 10  Microwaves
68  * 11  Ellipse
69  * 12  RoundBox
70  * 13  Custom
71  * 14  Star
72  * 15  Random
73  * 16  Line*           [Not much different]
74  *
75  *  *  Alternate style
76  *
77 
78  */
79 
80 
81 #ifndef XFRACT
82 #include <bios.h>
83 #include <io.h>
84 #endif
85 
86 #include <fcntl.h>
87 #include <sys/types.h>
88 #include <errno.h>
89 
90 #ifndef XFRACT
91 #include <conio.h>
92 #endif
93 
94 #ifndef USE_VARARGS
95 #include <stdarg.h>
96 #else
97 #include <varargs.h>
98 #endif
99 
100 #ifdef XFRACT
101 extern char *PSviewer;
102 #endif
103 
104 #include <string.h>
105 
106   /* see Fractint.c for a description of the "include"  hierarchy */
107 #include "port.h"
108 #include "prototyp.h"
109 #include "fractype.h"
110 
111 /* macros for near-space-saving purposes */
112 /* CAE 9211 changed these for BC++ */
113 
114 #define PRINTER_PRINTF1(X) {\
115    static FCODE tmp[] = X;\
116    Printer_printf(tmp);\
117 }
118 
119 #define PRINTER_PRINTF2(X,Y) {\
120    static FCODE tmp[] = X;\
121    Printer_printf(tmp,(Y));\
122 }
123 #define PRINTER_PRINTF3(X,Y,Z) {\
124    static FCODE tmp[] = X;\
125    Printer_printf(tmp,(Y),(Z));\
126 }
127 #define PRINTER_PRINTF4(X,Y,Z,W) {\
128    static FCODE tmp[] = X;\
129    Printer_printf(tmp,(Y),(Z),(W));\
130 }
131 #define PRINTER_PRINTF5(X,Y,Z,W,V) {\
132    static FCODE tmp[] = X;\
133    Printer_printf(tmp,(Y),(Z),(W),(V));\
134 }
135 #define PRINTER_PRINTF6(X,Y,Z,W,V,U) {\
136    static FCODE tmp[] = X;\
137    Printer_printf(tmp,(Y),(Z),(W),(V),(U));\
138 }
139 #define PRINTER_PRINTF7(X,Y,Z,W,V,U,T) {\
140    static FCODE tmp[] = X;\
141    Printer_printf(tmp,(Y),(Z),(W),(V),(U),(T));\
142 }
143 
144 /********      PROTOTYPES     ********/
145 
146 #ifndef USE_VARARGS
147 static void Printer_printf(char far *fmt,...);
148 #else
149 static void Printer_printf();
150 #endif
151 static int  _fastcall printer(int c);
152 static void _fastcall print_title(int,int,char *);
153 static void printer_reset(void);
154 static void rleprolog(int x,int y);
155 static void _fastcall graphics_init(int,int,char *);
156 
157 /********       GLOBALS       ********/
158 
159 int Printer_Resolution,        /* 75,100,150,300 for HP;                   */
160                                /* 60,120,240 for IBM;                      */
161                                /* 90 or 180 for the PaintJet;              */
162                                /* 10-600 for PS                            */
163                                /* 1-20 for Plotter                         */
164     LPTNumber,                 /* ==1,2,3 LPTx; or 11,12,13,14 for COM1-4  */
165                                /* 21,22 for direct port access for LPT1-2  */
166                                /* 31,32 for direct port access for COM1-2  */
167     Printer_Type,                      /* ==1 HP,
168                                           ==2 IBM/EPSON,
169                                           ==3 Epson color,
170                                           ==4 HP PaintJet,
171                                           ==5,6 PostScript,
172                                           ==7 HP Plotter                   */
173     Printer_Titleblock,       /* Print info about the fractal?             */
174     Printer_Compress,         /* PostScript only - rle encode output       */
175     Printer_ColorXlat,        /* PostScript only - invert colors           */
176     Printer_SetScreen,        /* PostScript only - reprogram halftone ?    */
177     Printer_SFrequency,       /* PostScript only - Halftone Frequency K    */
178     Printer_SAngle,           /* PostScript only - Halftone angle     K    */
179     Printer_SStyle,           /* PostScript only - Halftone style     K    */
180     Printer_RFrequency,       /* PostScript only - Halftone Frequency R    */
181     Printer_RAngle,           /* PostScript only - Halftone angle     R    */
182     Printer_RStyle,           /* PostScript only - Halftone style     R    */
183     Printer_GFrequency,       /* PostScript only - Halftone Frequency G    */
184     Printer_GAngle,           /* PostScript only - Halftone angle     G    */
185     Printer_GStyle,           /* PostScript only - Halftone style     G    */
186     Printer_BFrequency,       /* PostScript only - Halftone Frequency B    */
187     Printer_BAngle,           /* PostScript only - Halftone angle     B    */
188     Printer_BStyle,           /* PostScript only - Halftone style     B    */
189     Print_To_File,            /* Print to file toggle                      */
190     EPSFileType,              /* EPSFileType -
191                                                1 = well-behaved,
192                                                2 = much less behaved,
193                                                3 = not well behaved        */
194     Printer_CRLF,             /* (0) CRLF (1) CR (2) LF                    */
195     ColorPS;                  /* (0) B&W  (1) Color                        */
196 int pj_width;
197 double ci,ck;
198 
199 static int repeat, item, count, repeatitem, itembuf[128], rlebitsperitem,
200     rlebitshift, bitspersample, rleitem, repeatcount, itemsperline, items,
201     /* bitsperitem, */ bitshift2;
202 /*
203  *  The tables were copied from Lee Crocker's PGIF program, with
204  *  the 8 undithered colors moved to the first 8 table slots.
205  *
206  *  This file contains various lookup tables used by PJGIF.  Patterns contains
207  *  unsigned values representing each of the 330 HP PaintJet colors.  Each color
208  *  at 90 DPI is composed of four dots in 8 colors.  Each hex digit of these
209  *  unsigned values represents one of the four dots.  Although the PaintJet will
210  *  produce these patterns automatically in 90 DPI mode, it is much faster to do
211  *  it in software with the PaintJet in 8-color 180 DPI mode.
212  *
213  *  920501 Hans Wolfgang Schulze converted from printera.asm for xfractint.
214  *         (hans@garfield.metal2.polymtl.ca)
215  */
216 
217 static UIFCODE pj_patterns [] = {
218       0x7777,0x0000,0x1111,0x2222,0x3333,0x4444,0x5555,0x6666,
219              0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
220       0x0110,0x0120,0x0130,0x0140,0x0150,0x0160,0x0170,0x0220,
221       0x0230,0x0240,0x0250,0x0260,0x0270,0x0330,0x0340,0x0350,
222       0x0360,0x0370,0x0440,0x0450,0x0460,0x0470,0x0550,0x0560,
223       0x0570,0x0660,0x0670,0x0770,0x0111,0x0112,0x0113,0x0114,
224       0x0115,0x0116,0x0117,0x2012,0x0123,0x0124,0x0125,0x0126,
225       0x0127,0x3013,0x0134,0x0135,0x0136,0x0137,0x4014,0x0145,
226       0x0146,0x0147,0x5015,0x0156,0x0157,0x6016,0x0167,0x7017,
227       0x0222,0x0223,0x0224,0x0225,0x0226,0x0227,0x3023,0x0234,
228       0x0235,0x0236,0x0237,0x4024,0x0245,0x0246,0x0247,0x5025,
229       0x0256,0x0257,0x6026,0x0267,0x7027,0x0333,0x0334,0x0335,
230       0x0336,0x0337,0x4034,0x0345,0x0346,0x0347,0x5035,0x0356,
231       0x0357,0x6036,0x0367,0x7037,0x0444,0x0445,0x0446,0x0447,
232       0x5045,0x0456,0x0457,0x6046,0x0467,0x7047,0x0555,0x0556,
233       0x0557,0x6056,0x0567,0x7057,0x0666,0x0667,0x7067,0x0777,
234              0x1112,0x1113,0x1114,0x1115,0x1116,0x1117,0x2112,
235       0x1123,0x2114,0x2115,0x2116,0x2117,0x3113,0x3114,0x3115,
236       0x3116,0x3117,0x4114,0x4115,0x4116,0x4117,0x5115,0x5116,
237       0x5117,0x6116,0x6117,0x7117,0x1222,0x1223,0x1224,0x1225,
238       0x1226,0x1227,0x3123,0x1234,0x1235,0x1236,0x1237,0x4124,
239       0x1245,0x1246,0x1247,0x5125,0x1256,0x1257,0x6126,0x1267,
240       0x7127,0x1333,0x1334,0x1335,0x1336,0x1337,0x4134,0x1345,
241       0x1346,0x1347,0x5135,0x1356,0x1357,0x6136,0x1367,0x7137,
242       0x1444,0x1445,0x1446,0x1447,0x5145,0x1456,0x1457,0x6146,
243       0x1467,0x7147,0x1555,0x1556,0x1557,0x6156,0x1567,0x7157,
244       0x1666,0x1667,0x7167,0x1777,       0x2223,0x2224,0x2225,
245       0x2226,0x2227,0x3223,0x3224,0x3225,0x3226,0x3227,0x4224,
246       0x4225,0x4226,0x4227,0x5225,0x5226,0x5227,0x6226,0x6227,
247       0x7227,0x2333,0x2334,0x2335,0x2336,0x2337,0x4234,0x2345,
248       0x2346,0x2347,0x5235,0x2356,0x2357,0x6236,0x2367,0x7237,
249       0x2444,0x2445,0x2446,0x2447,0x5245,0x2456,0x2457,0x6246,
250       0x2467,0x7247,0x2555,0x2556,0x2557,0x6256,0x2567,0x7257,
251       0x2666,0x2667,0x7267,0x2777,       0x3334,0x3335,0x3336,
252       0x3337,0x4334,0x4335,0x4336,0x4337,0x5335,0x5336,0x5337,
253       0x6336,0x6337,0x7337,0x3444,0x3445,0x3446,0x3447,0x5345,
254       0x3456,0x3457,0x6346,0x3467,0x7347,0x3555,0x3556,0x3557,
255       0x6356,0x3567,0x7357,0x3666,0x3667,0x7367,0x3777,
256       0x4445,0x4446,0x4447,0x5445,0x5446,0x5447,0x6446,0x6447,
257       0x7447,0x4555,0x4556,0x4557,0x6456,0x4567,0x7457,0x4666,
258       0x4667,0x7467,0x4777,       0x5556,0x5557,0x6556,0x6557,
259       0x7557,0x5666,0x5667,0x7567,0x5777,       0x6667,0x7667,
260       0x6777};
261 
262 /*
263  * The 3 tables below contain the red, green, and blue values (on a scale of
264  *  0..255) of each of the 330 PaintJet colors.  These values are based on data
265  *  generously provided by HP customer service.
266  *       11 <- changed black's value from this, seemed wrong
267  *         135 <- changed red's value from this
268  *           11 <- changed blue's value from this
269  */
270 #ifndef XFRACT
271 static BFCODE  pj_reds[] = {
272         229,  2,145,  7,227,  9,136, 5,
273              17, 10, 17, 10, 16, 10, 16, 29, 16, 32, 15, 30, 15, 31,  9,
274          15, 10, 15,  9, 13, 37, 15, 32, 16, 36, 10, 15,  9, 13, 30, 15,
275          31,  8, 13, 38, 62, 26, 68, 26, 63, 26, 68, 16, 35, 16, 33, 16,
276          33, 77, 26, 69, 29, 77, 16, 31, 16, 31, 64, 27, 71, 16, 36, 81,
277           9, 15, 10, 15,  8, 13, 37, 15, 31, 15, 33, 10, 15,  9, 13, 29,
278          15, 28,  8, 12, 28, 98, 28, 79, 32, 94, 16, 34, 17, 35, 73, 30,
279          82, 17, 43,101, 11, 15, 10, 13, 29, 15, 27,  9, 13, 25, 65, 27,
280          71, 16, 35, 88,  7, 12, 39,110,     54,146, 53,136, 58,144, 29,
281          57, 28, 53, 29, 56,159, 54,144, 61,160, 27, 51, 28, 52,135, 55,
282         144, 30, 60,159, 14, 23, 15, 22, 14, 21, 64, 30, 58, 32, 64, 15,
283          22, 15, 21, 54, 31, 56, 14, 22, 64,185, 59,160, 69,185, 29, 57,
284          31, 60,145, 63,162, 33, 71,186, 15, 22, 16, 21, 50, 30, 52, 15,
285          21, 54,134, 58,145, 30, 60,161, 15, 22, 69,187,     13,  9, 14,
286           6, 11, 31, 14, 27, 12, 27, 10, 14,  9, 12, 24,  9, 23,  6,  9,
287          22, 76, 23, 61, 25, 74, 15, 29, 14, 28, 55, 23, 62, 12, 30, 73,
288          11, 15, 10, 12, 25, 14, 23,  8, 11, 20, 50, 22, 53, 13, 26, 61,
289           5,  8, 21, 71,     71,189, 87,227, 30, 63, 32, 69,164, 76,190,
290          37, 89,227, 15, 22, 14, 20, 54, 31, 57, 14, 21, 63,147, 67,163,
291          33, 72,191, 13, 24, 94,228,     15, 10, 13, 26, 14, 23, 10, 13,
292          20, 50, 23, 50, 15, 26, 52,  8, 11, 23, 65,     60,147, 32, 67,
293         166, 14, 24, 77,194,      8, 32, 97};
294 
295 /*
296  *                   11 <- changed black's value from this, seemed wrong
297  *                           65 <- changed green from this
298  */
299 
300 static BFCODE pj_greens[] = {
301         224,  2, 20, 72,211, 10, 11, 55,
302              12, 15, 19, 11, 11, 14, 17, 14, 18, 22, 12, 13, 16, 19, 24,
303          29, 16, 17, 23, 27, 41, 17, 22, 29, 39, 11, 10, 14, 14, 11, 14,
304          17, 21, 25, 40, 16, 21, 28, 14, 16, 19, 25, 28, 37, 18, 20, 26,
305          33, 48, 20, 26, 33, 46, 13, 12, 16, 18, 14, 18, 22, 24, 30, 42,
306          40, 49, 25, 27, 39, 50, 69, 27, 33, 48, 66, 17, 17, 24, 27, 19,
307          28, 35, 38, 48, 68,100, 32, 46, 65, 98, 18, 22, 29, 36, 27, 39,
308          54, 49, 71,105, 11, 10, 14, 12, 10, 14, 13, 20, 20, 25, 11, 15,
309          18, 22, 29, 49, 36, 46, 69,111,     23, 31, 16, 19, 22, 28, 30,
310          37, 20, 22, 28, 34, 54, 22, 29, 36, 53, 14, 15, 17, 19, 17, 19,
311          26, 25, 32, 46, 43, 50, 27, 28, 41, 49, 68, 29, 37, 51, 68, 19,
312          19, 25, 28, 22, 30, 36, 40, 47, 66,104, 35, 51, 68,105, 20, 24,
313          31, 37, 30, 38, 56, 50, 69,103, 13, 12, 15, 14, 13, 15, 16, 21,
314          21, 26, 14, 16, 22, 23, 28, 44, 35, 42, 62,102,     78, 40, 44,
315          65, 78, 98, 43, 53, 76, 99, 26, 27, 36, 40, 29, 43, 50, 63, 75,
316          99,136, 49, 69, 98,142, 28, 32, 42, 51, 39, 52, 73, 77,103,145,
317          17, 17, 21, 21, 18, 22, 24, 34, 37, 43, 19, 23, 30, 40, 48, 69,
318          62, 76,101,147,     72,113,145,218, 33, 42, 52, 71, 61, 77,116,
319         105,148,221, 18, 17, 21, 23, 21, 26, 30, 37, 43, 64, 30, 35, 48,
320          50, 69,115, 77, 99,149,224,     10, 13, 11, 10, 12, 11, 17, 16,
321          15,  9, 11, 12, 17, 17, 22, 26, 27, 36, 61,     14, 18, 21, 26,
322          48, 34, 41, 68,115,     69, 99,149};
323 
324 /*                    15 <- changed black's value from this, seemed wrong
325  *                           56 <- changed green from this
326  *                                          163 <- changed cyan from this
327  */
328 static BFCODE pj_blues[] = {
329         216,  2, 34, 48, 33, 73, 64,168,
330              18, 19, 18, 20, 19, 22, 21, 22, 24, 22, 26, 24, 27, 24, 27,
331          24, 29, 27, 31, 29, 22, 27, 25, 30, 28, 31, 29, 33, 33, 28, 32,
332          32, 41, 40, 46, 28, 32, 28, 34, 30, 36, 31, 35, 32, 38, 34, 41,
333          35, 27, 35, 31, 39, 34, 40, 37, 44, 40, 34, 42, 37, 49, 47, 45,
334          40, 36, 43, 40, 47, 43, 33, 40, 36, 45, 41, 44, 41, 49, 46, 40,
335          49, 45, 58, 56, 58, 30, 38, 34, 44, 40, 42, 39, 49, 46, 38, 49,
336          46, 59, 62, 67, 49, 46, 55, 52, 44, 55, 52, 64, 64, 66, 43, 55,
337          53, 66, 70, 78, 87, 91,101,115,     39, 34, 42, 37, 43, 36, 45,
338          38, 47, 42, 49, 43, 34, 41, 36, 44, 38, 49, 45, 52, 46, 40, 47,
339          42, 56, 51, 45, 49, 45, 52, 48, 56, 50, 40, 47, 44, 52, 47, 54,
340          51, 59, 55, 47, 58, 50, 66, 60, 56, 34, 44, 38, 48, 42, 52, 47,
341          56, 50, 42, 51, 46, 64, 59, 57, 60, 56, 64, 61, 52, 61, 57, 72,
342          67, 64, 48, 58, 53, 69, 65, 65, 87, 83, 87, 94,     53, 59, 55,
343          64, 60, 46, 53, 49, 59, 54, 60, 56, 65, 62, 53, 62, 58, 76, 71,
344          68, 41, 50, 45, 56, 51, 58, 53, 63, 59, 49, 60, 56, 74, 71, 71,
345          66, 63, 73, 70, 60, 69, 67, 84, 81, 79, 55, 67, 64, 84, 81, 83,
346         104,104,106,116,     32, 40, 53, 48, 54, 50, 61, 57, 46, 59, 56,
347          76, 75, 80, 64, 59, 70, 67, 57, 69, 65, 83, 81, 85, 54, 68, 66,
348          86, 88, 96,110,114,125,137,     71, 81, 78, 68, 77, 76, 93, 92,
349          90, 65, 77, 75, 92, 93, 96,117,119,126,138,     78, 79, 98,102,
350         110,124,131,143,157,    173,185,200};
351 #endif
352 
353 static void putitem(void);
354 static void rleputxelval(int);
355 static void rleflush(void);
356 static void rleputrest(void);
357 
358 static int LPTn;                   /* printer number we're gonna use */
359 
360 static FILE *PRFILE;
361 
362 #define TONES 17                   /* Number of PostScript halftone styles */
363 
364 #if 1
365 static FCODE ht00[] = {"D mul exch D mul add 1 exch sub"};
366 static FCODE ht01[] = {"abs exch abs 2 copy add 1 gt {1 sub D mul exch 1 sub D mul add 1 sub} {D mul exch D mul add 1 exch sub} ifelse"};
367 static FCODE ht02[] = {"D mul exch D mul add 1 sub"};
368 static FCODE ht03[] = {"D mul exch D mul add 0.6 exch sub abs -0.5 mul"};
369 static FCODE ht04[] = {"D mul exch D mul add 0.6 exch sub abs 0.5 mul"};
370 static FCODE ht05[] = {"add 2 div"};
371 static FCODE ht06[] = {"2 exch sub exch abs 2 mul sub 3 div"};
372 static FCODE ht07[] = {"2 copy abs exch abs gt {exch} if pop 2 mul 1 exch sub 3.5 div"};
373 static FCODE ht08[] = {"abs exch abs add 1 exch sub"};
374 static FCODE ht09[] = {"pop"};
375 static FCODE ht10[] = {"/wy exch def 180 mul cos 2 div wy D D D mul mul sub mul wy add 180 mul cos"};
376 static FCODE ht11[] = {"D 5 mul 8 div mul exch D mul exch add sqrt 1 exch sub"};
377 static FCODE ht12[] = {"D mul D mul exch D mul D mul add 1 exch sub"};
378 static FCODE ht13[] = {"D mul exch D mul add sqrt 1 exch sub"};
379 static FCODE ht14[] = {"abs exch abs 2 copy gt {exch} if 1 sub D 0 eq {0.01 add} if atan 360 div"};
380 static FCODE ht15[] = {"pop pop rand 1 add 10240 mod 5120 div 1 exch sub"};
381 static FCODE ht16[] = {"pop abs 2 mul 1 exch sub"};
382 #endif
383 
384 static FCODE *HalfTone[TONES]=  {ht00,ht01,ht02,ht03,ht04,ht05,ht06,ht07,
385     ht08,ht09,ht10,ht11,ht12,ht13,ht14,ht15,ht16};
386 
387 #if 0
388                          "D mul exch D mul add 1 exch sub",
389                          "abs exch abs 2 copy add 1 gt {1 sub D mul exch 1 sub D mul add 1 sub} {D mul exch D mul add 1 exch sub} ifelse",
390                          "D mul exch D mul add 1 sub",
391                          "D mul exch D mul add 0.6 exch sub abs -0.5 mul",
392                          "D mul exch D mul add 0.6 exch sub abs 0.5 mul",
393                          "add 2 div",
394                          "2 exch sub exch abs 2 mul sub 3 div",
395                          "2 copy abs exch abs gt {exch} if pop 2 mul 1 exch sub 3.5 div",
396                          "abs exch abs add 1 exch sub",
397                          "pop",
398                          "/wy exch def 180 mul cos 2 div wy D D D mul mul sub mul wy add 180 mul cos",
399                          "D 5 mul 8 div mul exch D mul exch add sqrt 1 exch sub",
400                          "D mul D mul exch D mul D mul add 1 exch sub",
401                          "D mul exch D mul add sqrt 1 exch sub",
402                          "abs exch abs 2 copy gt {exch} if 1 sub D 0 eq {0.01 add} if atan 360 div",
403                          "pop pop rand 1 add 10240 mod 5120 div 1 exch sub",
404                          "pop abs 2 mul 1 exch sub"
405                         };
406 #endif
407 
408 #ifdef __BORLANDC__
409 #if(__BORLANDC__ > 2)
410    #pragma warn -eff
411 #endif
412 #endif
413 
414 static char EndOfLine[3];
415 
416 /* workaround for the old illicit decflaration of dstack */
417 
418 typedef int (*TRIPLE)[2][3][400];
419 #define triple   (*((TRIPLE)dstack))
420 
421 void
Print_Screen(void)422 Print_Screen (void)
423 {
424     int y,j;
425     char buff[192];             /* buffer for 192 sets of pixels  */
426                                 /* This is very large so that we can*/
427                                 /* get reasonable times printing  */
428                                 /* from modes like MAXPIXELSxMAXPIXELS disk-*/
429                                 /* video.  When this was 24, a MAXPIXELS*/
430                                 /* by MAXPIXELS pic took over 2 hours to*/
431                                 /* print.  It takes about 15 min now*/
432     int BuffSiz;                /* how much of buff[] we'll use   */
433     char far *es;               /* pointer to extraseg for buffer */
434     int i,x,k,                  /* more indices                   */
435         imax,                   /* maximum i value (ydots/8)      */
436         res,                    /* resolution we're gonna' use    */
437         high,                   /* if LPTn>10 COM == com port to use*/
438         low,                    /* misc                           */
439                                 /************************************/
440         ptrid;                  /* Printer Id code.               */
441                                 /* Currently, the following are   */
442                                 /* assigned:                      */
443                                 /*            1. HPLJ (all)       */
444                                 /*               Toshiba PageLaser*/
445                                 /*            2. IBM Graphics     */
446                                 /*            3. Color Printer    */
447                                 /*            4. HP PaintJet      */
448                                 /*            5. PostScript       */
449                                 /************************************/
450     int pj_color_ptr[256];      /* Paintjet color translation */
451 
452                                 /********   SETUP VARIABLES  ********/
453     memset(buff,0,192);
454     i = 0;
455 
456     EndOfLine[0]=(char)(((Printer_CRLF==1) || (Printer_CRLF==0)) ? 0x0D : 0x0A);
457     EndOfLine[1]=(char)((Printer_CRLF==0) ? 0x0A : 0x00);
458     EndOfLine[2]=0x00;
459 
460     if (Print_To_File>0)
461       {
462       while ((PRFILE = fopen(PrintName,"r")) != NULL) {
463          j = fgetc(PRFILE);
464          fclose(PRFILE);
465          if (j == EOF) break;
466          updatesavename((char *)PrintName);
467          }
468       if ((PRFILE = fopen(PrintName,"wb")) == NULL) Print_To_File = 0;
469       }
470 
471 #ifdef XFRACT
472 /*
473       putstring(3,0,0,"Printing to:");
474       putstring(4,0,0,PrintName);
475       putstring(5,0,0,"               ");
476 */
477 #endif
478 
479     es=MK_FP(extraseg,0);
480 
481     LPTn=LPTNumber-1;
482     if (((LPTn>2)&&(LPTn<10))||
483         ((LPTn>13)&&(LPTn<20))||
484         ((LPTn>21)&&(LPTn<30))||
485         (LPTn<0)||(LPTn>31)) LPTn=0;   /* default of LPT1 (==0)          */
486     ptrid=Printer_Type;
487     if ((ptrid<1)||(ptrid>7)) ptrid=2; /* default of IBM/EPSON           */
488     res=Printer_Resolution;
489 #ifndef XFRACT
490     if ((LPTn==20)||(LPTn==21))
491         {
492         k = (inp((LPTn==20) ? 0x37A : 0x27A)) & 0xF7;
493         outp((LPTn==20) ? 0x37A : 0x27A,k);
494         k = k & 0xFB;
495         outp((LPTn==20) ? 0x37A : 0x27A,k);
496         k = k | 0x0C;
497         outp((LPTn==20) ? 0x37A : 0x27A,k);
498         }
499     if ((LPTn==30)||(LPTn==31))
500         {
501         outp((LPTn==30) ? 0x3F9 : 0x2F9,0x00);
502         outp((LPTn==30) ? 0x3FC : 0x2FC,0x00);
503         outp((LPTn==30) ? 0x3FC : 0x2FC,0x03);
504         }
505 #endif
506 
507     switch (ptrid) {
508 
509         case 1:
510             if (res<75) res=75;
511             if ( (res<= 75)&&(ydots> 600)) res=100;
512             if ( (res<=100)&&(ydots> 800)) res=150;
513             if (((res<=150)&&(ydots>1200))||(res>300)) res=300;
514             break;
515 
516         case 2:
517         case 3:
518             if (res<60) res=60;
519             if ((res<=60)&&(ydots>480)) res=120;
520             if (((res<=120)&&(ydots>960))||(res>240)) res=240;
521             break;
522 
523         case 4: /****** PaintJet  *****/
524             {
525 #ifndef XFRACT
526             /* Pieter Branderhorst:
527                My apologies if the numbers and approach here seem to be
528                picked out of a hat.  They were.  They happen to result in
529                a tolerable mapping of screen colors to printer colors on
530                my machine.  There are two sources of error in getting colors
531                to come out right.
532                1) Must match some dacbox values to the 330 PaintJet dithered
533                   colors so that they look the same.  For this we use HP's
534                   color values in printera.asm and modify by gamma separately
535                   for each of red/green/blue.  This mapping is ok if the
536                   preview shown on screen is a fairly close match to what
537                   gets printed. The defaults are what work for me.
538                2) Must find nearest color in HP palette to each color in
539                   current image. For this we use Lee Crocker's least sum of
540                   differences squared approach, modified to spread the
541                   values using gamma 1.7.  This mods was arrived at by
542                   trial and error, just because it improves the mapping.
543                */
544             long ldist;
545             int r,g,b;
546             double gamma_val,gammadiv;
547             BYTE convert[256];
548             BYTE scale[64];
549 
550             BYTE far *table_ptr = NULL;
551             res = (res < 150) ? 90 : 180;   /* 90 or 180 dpi */
552             if (Printer_SetScreen == 0) {
553                 Printer_SFrequency = 21;  /* default red gamma */
554                 Printer_SAngle     = 19;  /*       green gamma */
555                 Printer_SStyle     = 16;  /*        blue gamma */
556             }
557             /* Convert the values in printera.asm.  We might do this just   */
558             /* once per run, but we'd need separate memory for that - can't */
559             /* just convert table in-place cause it could be in an overlay, */
560             /* might be paged out and then back in in original form.  Also, */
561             /* user might change gammas with a .par file entry mid-run.     */
562             for (j = 0; j < 3; ++j) {
563                 switch (j) {
564                     case 0: table_ptr = pj_reds;
565                             i = Printer_SFrequency;
566                             break;
567                     case 1: table_ptr = pj_greens;
568                             i = Printer_SAngle;
569                             break;
570                     case 2: table_ptr = pj_blues;
571                             i = Printer_SStyle;
572                     }
573                 gamma_val = 10.0 / i;
574                 gammadiv = pow(255,gamma_val) / 255;
575                 for (i = 0; i < 256; ++i) { /* build gamma conversion table */
576                     static FCODE msg[]={"Calculating color translation"};
577                     if ((i & 15) == 15)
578                         thinking(1,msg);
579                     convert[i] = (BYTE)((pow((double)i,gamma_val) / gammadiv) + 0.5);
580                     }
581                 for (i = 0; i < 330; ++i) {
582                     k = convert[table_ptr[i]];
583                     if (k > 252) k = 252;
584                     triple[0][j][i] = (k + 2) >> 2;
585                 }
586             }
587             /* build comparison lookup table */
588             gamma_val = 1.7;
589             gammadiv = pow(63,gamma_val) / 63;
590             for (i = 0; i < 64; ++i) {
591                if ((j = (int)((pow((double)i,gamma_val) / gammadiv) * 4 + 0.5)) < i)
592                   j = i;
593                scale[i] = (char)j;
594             }
595             for (i = 0; i < 3; ++i) /* convert values via lookup */
596                 for (j = 0; j < 330; ++j)
597                     triple[1][i][j] = scale[triple[0][i][j]];
598             /* Following code and the later code which writes to Paintjet    */
599             /* using pj_patterns was adapted from Lee Crocker's PGIF program */
600             for (i = 0; i < colors; ++i) { /* find nearest match colors */
601                 r = scale[dacbox[i][0]];
602                 g = scale[dacbox[i][1]];
603                 b = scale[dacbox[i][2]];
604                 ldist = 9999999L;
605                 /* check variance vs each PaintJet color */
606                 /* if high-res 8 color mode, consider only 1st 8 colors */
607                 j = (res == 90) ? 330 : 8;
608                 while (--j >= 0) {
609                     long dist;
610                     dist  = (unsigned)(r-triple[1][0][j]) * (r-triple[1][0][j]);
611                     dist += (unsigned)(g-triple[1][1][j]) * (g-triple[1][1][j]);
612                     dist += (unsigned)(b-triple[1][2][j]) * (b-triple[1][2][j]);
613                     if (dist < ldist) {
614                         ldist = dist;
615                         k = j;
616                     }
617                 }
618                 pj_color_ptr[i] = k; /* remember best fit */
619             }
620             thinking(0,NULL);
621         /*  if (debugflag == 900 || debugflag == 902) {
622                 color_test();
623                 return;
624             }  */
625             if (dotmode != 11) { /* preview */
626                 static char far msg[] = {"Preview. Enter=go, Esc=cancel, k=keep"};
627                 memcpy(triple[1],dacbox,768);
628                 for (i = 0; i < colors; ++i)
629                     for (j = 0; j < 3; ++j)
630                         dacbox[i][j] = (BYTE)triple[0][j][pj_color_ptr[i]];
631                 spindac(0,1);
632                 texttempmsg(msg);
633                 i = getakeynohelp();
634                 if (i == 'K' || i == 'k') {
635                     return;
636                 }
637                 memcpy(dacbox,triple[1],768);
638                 spindac(0,1);
639                 if (i == 0x1B) {
640                     return;
641                 }
642             }
643             break;
644 #endif
645             }
646 
647         case 5:
648         case 6: /***** PostScript *****/
649             if ( res < 10 && res != 0 ) res = 10; /* PostScript scales... */
650             if ( res > 600 ) res = 600; /* it can handle any range! */
651             if ((Printer_SStyle < 0) || (Printer_SStyle >= TONES))
652                 Printer_SStyle = 0;
653             break;
654     }
655 
656     /*****  Set up buffer size for immediate user gratification *****/
657     /*****    AKA, if we don't have to, don't buffer the data   *****/
658     BuffSiz=8;
659     if (xdots>1024) BuffSiz=192;
660 
661     /*****   Initialize printer  *****/
662     if (Print_To_File < 1) {
663         printer_reset();
664         /* wait a bit, some printers need time after reset */
665         delay((ptrid == 4) ? 2000 : 500);
666     }
667 
668     /******  INITIALIZE GRAPHICS MODES  ******/
669 
670     graphics_init(ptrid,res,EndOfLine);
671 
672     if (keypressed()) {         /* one last chance before we start...*/
673         return;
674         }
675 
676     memset(buff,0,192);
677 
678                                 /*****  Get And Print Screen **** */
679     switch (ptrid) {
680 
681         case 1:                        /* HP LaserJet (et al)            */
682             imax=(ydots/8)-1;
683             for (x=0;((x<xdots)&&(!keypressed()));x+=BuffSiz) {
684                 for (i=imax;((i>=0)&&(!keypressed()));i--) {
685                     for (y=7;((y>=0)&&(!keypressed()));y--) {
686                         for (j=0;j<BuffSiz;j++) {
687                             if ((x+j)<xdots) {
688                                 buff[j]<<=1;
689                                 buff[j]=(char)(buff[j]+(char)(getcolor(x+j,i*8+y)&1));
690                                 }
691                             }
692                         }
693                     for (j=0;j<BuffSiz;j++) {
694                         *(es+j+BuffSiz*i)=buff[j];
695                         buff[j]=0;
696                         }
697                     }
698                 for (j=0;((j<BuffSiz)&&(!keypressed()));j++) {
699                     if ((x+j)<xdots) {
700                         PRINTER_PRINTF2("\033*b%iW",imax+1);
701                         for (i=imax;((i>=0)&&(!keypressed()));i--) {
702                             printer(*(es+j+BuffSiz*i));
703                             }
704                         }
705                     }
706                 }
707             if (!keypressed()) PRINTER_PRINTF1("\033*rB\014");
708             break;
709 
710         case 2:                        /* IBM Graphics/Epson             */
711             for (x=0;((x<xdots)&&(!keypressed()));x+=8) {
712                 switch (res) {
713                     case 60:  Printer_printf("\033K"); break;
714                     case 120: Printer_printf("\033L"); break;
715                     case 240: Printer_printf("\033Z"); break;
716                     }
717                 high=ydots/256;
718                 low=ydots-(high*256);
719                 printer(low);
720                 printer(high);
721                 for (y=ydots-1;(y>=0);y--) {
722                     buff[0]=0;
723                     for (i=0;i<8;i++) {
724                         buff[0]<<=1;
725                         buff[0]=(char)(buff[0]+(char)(getcolor(x+i,y)&1));
726                         }
727                     printer(buff[0]);
728                     }
729                 if (keypressed()) break;
730                 Printer_printf(EndOfLine);
731                 }
732             if (!keypressed()) printer(12);
733             break;
734 
735         case 3:                        /* IBM Graphics/Epson Color      */
736             high=ydots/256;
737             low=ydots%256;
738             for (x=0;((x<xdots)&&(!keypressed()));x+=8)
739                 {
740                 for (k=0; k<8; k++)  /* colors */
741                     {
742                     Printer_printf("\033r%d",k); /* set printer color */
743                     switch (res)
744                         {
745                         case 60:  Printer_printf("\033K"); break;
746                         case 120: Printer_printf("\033L"); break;
747                         case 240: Printer_printf("\033Z"); break;
748                         }
749                     printer(low);
750                     printer(high);
751                     for (y=ydots-1;y>=0;y--)
752                         {
753                         buff[0]=0;
754                         for (i=0;i<8;i++)
755                             {
756                             buff[0]<<=1;
757                             if ((getcolor(x+i,y)%8)==k)
758                                 buff[0]++;
759                             }
760                         printer(buff[0]);
761                         }
762                     if (Printer_CRLF<2) printer(13);
763                     }
764                 if ((Printer_CRLF==0) || (Printer_CRLF==2)) printer(10);
765                 }
766             printer(12);
767             printer(12);
768             printer_reset();
769             break;
770 
771         case 4:                       /* HP PaintJet       */
772             {
773             unsigned int fetchrows,fetched;
774             BYTE far *pixels = NULL, far *nextpixel = NULL;
775             /* for reasonable speed when using disk video, try to fetch
776                and store the info for 8 columns at a time instead of
777                doing getcolor calls down each column in separate passes */
778             fetchrows = 16;
779             for(;;) {
780                 if ((pixels = (BYTE far *)farmemalloc((long)(fetchrows)*ydots)) != NULL)
781                    break;
782                 if ((fetchrows >>= 1) == 0) {
783                     static char far msg[]={"insufficient memory"};
784                     stopmsg(0,msg);
785                     break;
786                 }
787             }
788             if (!pixels) break;
789             fetched = 0;
790             for (x = 0; (x < xdots && !keypressed()); ++x) {
791                 if (fetched == 0) {
792                     if ((fetched = xdots-x) > fetchrows)
793                         fetched = fetchrows;
794                     for (y = ydots-1; y >= 0; --y) {
795                         if (debugflag == 602) /* flip image */
796                             nextpixel = pixels + y;
797                         else                  /* reverse order for unflipped */
798                             nextpixel = pixels + ydots-1 - y;
799                         for (i = 0; i < (int)fetched; ++i) {
800                             *nextpixel = (BYTE)getcolor(x+i,y);
801                             nextpixel += ydots;
802                         }
803                     }
804                     nextpixel = pixels;
805                 }
806                 --fetched;
807                 if (res == 180) { /* high-res 8 color mode */
808                     int offset;
809                     BYTE bitmask;
810                     offset = -1;
811                     bitmask = 0;
812                     for (y = ydots - 1; y >= 0; --y) {
813                         BYTE color;
814                         if ((bitmask >>= 1) == 0) {
815                             ++offset;
816                             triple[0][0][offset] = triple[0][1][offset]
817                                                  = triple[0][2][offset] = 0;
818                             bitmask = 0x80;
819                         }
820                         /* translate 01234567 to 70123456 */
821                         color = (BYTE)(pj_color_ptr[*(nextpixel++)] - 1);
822                         if ((color & 1)) triple[0][0][offset] += bitmask;
823                         if ((color & 2)) triple[0][1][offset] += bitmask;
824                         if ((color & 4)) triple[0][2][offset] += bitmask;
825                     }
826                 }
827                 else { /* 90 dpi, build 2 lines, 2 dots per pixel */
828                     int bitct,offset;
829                     bitct = offset = 0;
830                     for (y = ydots - 1; y >= 0; --y) {
831                         unsigned int color;
832                         color = pj_patterns[pj_color_ptr[*(nextpixel++)]];
833                         for (i = 0; i < 3; ++i) {
834                             BYTE *bufptr;
835                             bufptr = (BYTE *)&triple[0][i][offset];
836                             *bufptr <<= 2;
837                             if ((color & 0x1000)) *bufptr += 2;
838                             if ((color & 0x0100)) ++*bufptr;
839                             bufptr = (BYTE *)&triple[1][i][offset];
840                             *bufptr <<= 2;
841                             if ((color & 0x0010)) *bufptr += 2;
842                             if ((color & 0x0001)) ++*bufptr;
843                             color >>= 1;
844                         }
845                         if (++bitct == 4) {
846                             bitct = 0;
847                             ++offset;
848                         }
849                     }
850                 }
851                 for (i = 0; i < ((res == 90) ? 2 : 1); ++i) {
852                     for (j = 0; j < 3; ++j) {
853                         BYTE *bufptr,*bufend;
854                         Printer_printf((j < 2) ? "\033*b%dV" : "\033*b%dW",
855                                        pj_width);
856                         bufend = pj_width + (bufptr = (BYTE *)(triple[i][j]));
857                         do {
858                             while (printer(*bufptr)) { }
859                         } while (++bufptr < bufend);
860                     }
861                 }
862             }
863             PRINTER_PRINTF1("\033*r0B"); /* end raster graphics */
864             if (!keypressed()) {
865                if (debugflag != 600)
866                   printer(12); /* form feed */
867                else
868                   Printer_printf("\n\n");
869             }
870             farmemfree(pixels);
871             break;
872             }
873 
874         case 5:
875         case 6:         /***** PostScript Portrait & Landscape *****/
876             {
877             char convert[513];
878             if (!ColorPS) {
879               for (i=0; i<256; ++i)
880                 if (Printer_Compress) {
881                     convert[i] = (char)((.3*255./63. * (double)dacbox[i][0])+
882                                         (.59*255./63. * (double)dacbox[i][1])+
883                                         (.11*255./63. * (double)dacbox[i][2]));
884                 } else
885                 {
886                     sprintf(&convert[2*i], "%02X",
887                               (int)((.3*255./63. * (double)dacbox[i][0])+
888                                     (.59*255./63. * (double)dacbox[i][1])+
889                                     (.11*255./63. * (double)dacbox[i][2])));
890                 }
891             }
892             i=0;
893             j=0;
894             for (y=0;((y<ydots)&&(!keypressed()));y++)
895             {   unsigned char bit8 = 0;
896                 if (Printer_Compress) {
897                     if (ColorPS) {
898                         for (x=0;x<xdots;x++) {
899                             k=getcolor(x,y);
900                             rleputxelval((int)dacbox[k][0]<<2);
901                         }
902                         rleflush();
903                         for (x=0;x<xdots;x++) {
904                             k=getcolor(x,y);
905                             rleputxelval((int)dacbox[k][1]<<2);
906                         }
907                         rleflush();
908                         for (x=0;x<xdots;x++) {
909                             k=getcolor(x,y);
910                             rleputxelval((int)dacbox[k][2]<<2);
911                         }
912                         rleflush();
913                      } else {
914                         if (Printer_ColorXlat==-2 || Printer_ColorXlat==2) {
915                            for (x=0;x<xdots;x++) {
916                               k=getcolor(x,y);
917                               k=getcolor(x,y) & 1;
918                               if (x % 8 == 0) {
919                                  if (x) rleputxelval((int)bit8);
920                                  if (k) bit8 = 1; else bit8 = 0;
921                               }
922                               else
923                                  bit8 = (unsigned char)((bit8 << 1) + ((k) ? 1 : 0));
924                            }
925                            if (xdots % 8) bit8 <<= (8 - (xdots % 8));
926                            rleputxelval((int)bit8);
927                            rleflush();
928                         } else {
929                            for (x=0;x<xdots;x++) {
930                               k=getcolor(x,y);
931                               rleputxelval((int)(unsigned char)convert[k]);
932                            }
933                            rleflush();
934                         }
935                      }
936                 } else
937                 {
938                     for (x=0;x<xdots;x++)
939                     {
940                         k=getcolor(x,y);
941                         if (ColorPS)
942                           {
943                           sprintf(&buff[i], "%02X%02X%02X", dacbox[k][0]<<2,
944                                                             dacbox[k][1]<<2,
945                                                             dacbox[k][2]<<2);
946                           i+=6;
947                           }
948                         else
949                           {
950                           k*=2;
951                           buff[i++]=convert[k];
952                           buff[i++]=convert[k+1];
953                           }
954                         if (i>=64)
955                         {
956                             strcpy(&buff[i],"  ");
957                             Printer_printf("%s%s",buff,EndOfLine);
958                             i=0;
959                             j++;
960                             if (j>9)
961                             {
962                                 j=0;
963                                 Printer_printf(EndOfLine);
964                             }
965                         }
966                     }
967                 }
968             }
969             if (Printer_Compress) {
970                 rleputrest();
971             } else {
972                 strcpy(&buff[i],"  ");
973                 Printer_printf("%s%s",buff,EndOfLine);
974                 i=0;
975                 j++;
976                 if (j>9)
977                 {
978                     j=0;
979                     Printer_printf(EndOfLine);
980                 }
981             }
982             if ( (EPSFileType > 0) && (EPSFileType <3) )
983             {
984                 PRINTER_PRINTF4("%s%%%%Trailer%sEPSFsave restore%s",EndOfLine,
985                         EndOfLine,EndOfLine);
986             }
987             else
988             {
989 #ifndef XFRACT
990                 PRINTER_PRINTF4("%sshowpage%s%c",EndOfLine,EndOfLine,4);
991 #else
992                 PRINTER_PRINTF3("%sshowpage%s",EndOfLine,EndOfLine);
993 #endif
994             }
995             break;
996             }
997 
998         case 7: /* HP Plotter */
999             {
1000             double parm1=0,parm2=0;
1001             for (i=0;i<3;i++)
1002             {
1003               PRINTER_PRINTF4("%sSP %d;%s\0",EndOfLine,(i+1),EndOfLine);
1004               for (y=0;(y<ydots)&&(!keypressed());y++)
1005               {
1006                 for (x=0;x<xdots;x++)
1007                 {
1008                   j=dacbox[getcolor(x,y)][i];
1009                   if (j>0)
1010                   {
1011                     switch(Printer_SStyle)
1012                     {
1013                       case 0:
1014                         ci=0.004582144*(double)j;
1015                         ck= -.007936057*(double)j;
1016                         parm1 = (double)x+.5+ci+(((double)i-1.0)/3);
1017                         parm2 = (double)y+.5+ck;
1018                         break;
1019                       case 1:
1020                         ci= -.004582144*(double)j+(((double)i+1.0)/8.0);
1021                         ck= -.007936057*(double)j;
1022                         parm1 = (double)x+.5+ci;
1023                         parm2 = (double)y+.5+ck;
1024                         break;
1025                       case 2:
1026                         ci= -.0078125*(double)j+(((double)i+1.0)*.003906250);
1027                         ck= -.0078125*(double)j;
1028                         parm1 = (double)x+.5+ci;
1029                         parm2 = (double)y+.5+ck;
1030                         break;
1031                     }
1032                     PRINTER_PRINTF5("PA %f,%f;PD;PR %f,%f;PU;\0",
1033                         parm1,parm2, ci*((double)-2), ck*((double)-2));
1034                   }
1035                 }
1036               }
1037             }
1038             PRINTER_PRINTF3("%s;SC;PA 0,0;SP0;%s\0",EndOfLine,EndOfLine);
1039             PRINTER_PRINTF2(";;SP 0;%s\0",EndOfLine);
1040             break;
1041             }
1042     }
1043 
1044     if (Print_To_File > 0) fclose(PRFILE);
1045 #ifdef XFRACT
1046 /*
1047     putstring(5,0,0,"Printing done\n");
1048 */
1049     {
1050     char cmd[256];
1051     int dummy; /* to clear up compiler warning */
1052     sprintf(cmd, "%s %s &", PSviewer, PrintName);
1053     dummy = system(cmd);
1054     }
1055 #else
1056     if ((LPTn==30)||(LPTn==31))
1057         {
1058         for (x=0;x<2000;x++);
1059         outp((LPTn==30) ? 0x3FC : 0x2FC,0x00);
1060         outp((LPTn==30) ? 0x3F9 : 0x2F9,0x00);
1061         }
1062 #endif
1063 }
1064 
1065 
graphics_init(int ptrid,int res,char * EndOfLine)1066 static void _fastcall graphics_init(int ptrid,int res,char *EndOfLine)
1067 {
1068     int i,j;
1069 
1070     switch (ptrid) {
1071 
1072         case 1:
1073             print_title(ptrid,res,EndOfLine);
1074             PRINTER_PRINTF2("\033*t%iR\033*r0A",res);/* HP           */
1075             break;
1076 
1077         case 2:
1078         case 3:
1079             print_title(ptrid,res,EndOfLine);
1080             PRINTER_PRINTF1("\033\063\030");/* IBM                   */
1081             break;
1082 
1083         case 4: /****** PaintJet *****/
1084             print_title(ptrid,res,EndOfLine);
1085             pj_width = ydots;
1086             if (res == 90) pj_width <<= 1;
1087             PRINTER_PRINTF2("\033*r0B\033*t180R\033*r3U\033*r%dS\033*b0M\033*r0A",
1088                 pj_width);
1089             pj_width >>= 3;
1090             break;
1091 
1092         case 5:   /***** PostScript *****/
1093         case 6:   /***** PostScript Landscape *****/
1094             if (!((EPSFileType > 0) && (ptrid==5)))
1095                 PRINTER_PRINTF2("%%!PS-Adobe%s",EndOfLine);
1096             if ((EPSFileType > 0) &&     /* Only needed if saving to .EPS */
1097                 (ptrid == 5))
1098                 {
1099                 PRINTER_PRINTF2("%%!PS-Adobe-1.0 EPSF-2.0%s",EndOfLine);
1100 
1101                 if (EPSFileType==1)
1102                     i=xdots+78;
1103                 else
1104                     i=(int)((double)xdots * (72.0 / (double)res))+78;
1105 
1106                 if (Printer_Titleblock==0)
1107                     {
1108                     if (EPSFileType==1) { j = ydots + 78; }
1109                     else { j = (int)(((double)ydots * (72.0 / (double)res) / (double)finalaspectratio)+78); }
1110                     }
1111                 else
1112                     {
1113                     if (EPSFileType==1) { j = ydots + 123; }
1114                     else { j = (int)(((double)ydots * (72.0 / (double)res))+123); }
1115                     }
1116                 PRINTER_PRINTF4("%%%%TemplateBox: 12 12 %d %d%s",i,j,EndOfLine);
1117                 PRINTER_PRINTF4("%%%%BoundingBox: 12 12 %d %d%s",i,j,EndOfLine);
1118                 PRINTER_PRINTF4("%%%%PrinterRect: 12 12 %d %d%s",i,j,EndOfLine);
1119                 PRINTER_PRINTF2("%%%%Creator: Fractint PostScript%s",EndOfLine);
1120                 PRINTER_PRINTF5("%%%%Title: A %s fractal - %s - Fractint EPSF Type %d%s",
1121                                        curfractalspecific->name[0]=='*' ?
1122                                        &curfractalspecific->name[1] :
1123                                        curfractalspecific->name,
1124                                        PrintName,
1125                                        EPSFileType,
1126                                        EndOfLine);
1127                 if (Printer_Titleblock==1)
1128                     PRINTER_PRINTF2("%%%%DocumentFonts: Helvetica%s",EndOfLine);
1129                 PRINTER_PRINTF2("%%%%EndComments%s",EndOfLine);
1130                 PRINTER_PRINTF2("/EPSFsave save def%s",EndOfLine);
1131                 PRINTER_PRINTF2("0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin%s",EndOfLine);
1132                 PRINTER_PRINTF2("10 setmiterlimit [] 0 setdash newpath%s",EndOfLine);
1133                 }
1134 
1135             /* Common code for all PostScript */
1136             PRINTER_PRINTF2("/Tr {translate} def%s",EndOfLine);
1137             PRINTER_PRINTF2("/Mv {moveto} def%s",EndOfLine);
1138             PRINTER_PRINTF2("/D {dup} def%s",EndOfLine);
1139             PRINTER_PRINTF2("/Rh {readhexstring} def%s",EndOfLine);
1140             PRINTER_PRINTF2("/Cf {currentfile} def%s",EndOfLine);
1141             PRINTER_PRINTF2("/Rs {readstring} def%s",EndOfLine);
1142 
1143             if (Printer_Compress) {
1144                 rleprolog(xdots,ydots);
1145             } else
1146             {
1147                 PRINTER_PRINTF3("/picstr %d string def%s",
1148                         ColorPS?xdots*3:xdots,EndOfLine);
1149                 PRINTER_PRINTF7("/dopic { gsave %d %d 8 [%d 0 0 %d 0 %d]%s",
1150                                          xdots, ydots, xdots, -ydots, ydots,
1151                                          EndOfLine);
1152                 PRINTER_PRINTF2("{ Cf picstr Rh pop }%s", EndOfLine);
1153                 if (ColorPS)
1154                 {
1155                     PRINTER_PRINTF2(" false 3 colorimage grestore } def%s",
1156                      EndOfLine);
1157                 }
1158                 else
1159                 {
1160                     PRINTER_PRINTF2(" image grestore } def%s", EndOfLine);
1161                 }
1162             }
1163             if (Printer_Titleblock==1)
1164                 {
1165                 PRINTER_PRINTF2("/Helvetica findfont 8 scalefont setfont%s",EndOfLine);
1166                 if (ptrid==5) {PRINTER_PRINTF1("30 60 Mv ");}
1167                 else          {PRINTER_PRINTF1("552 30 Mv 90 rotate ");}
1168                 print_title(ptrid,res,EndOfLine);
1169                 if (ptrid==6) {PRINTER_PRINTF1("-90 rotate ");}
1170                 }
1171 
1172             if (EPSFileType != 1) /* Do not use on a WELL BEHAVED .EPS */
1173               {
1174               if (ptrid == 5 && EPSFileType==2
1175                              && (Printer_ColorXlat || Printer_SetScreen))
1176                         PRINTER_PRINTF2("%%%%BeginFeature%s",EndOfLine);
1177               if (ColorPS)
1178                 {
1179                 if (Printer_ColorXlat==1)
1180                     PRINTER_PRINTF2("{1 exch sub} D D D setcolortransfer%s",EndOfLine);
1181                 if (Printer_ColorXlat>1)
1182                     PRINTER_PRINTF4("{%d mul round %d div} D D D setcolortransfer%s",
1183                                        Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
1184                 if (Printer_ColorXlat<-1)
1185                     PRINTER_PRINTF4("{%d mul round %d div 1 exch sub} D D D setcolortransfer",
1186                                        Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
1187 
1188                 if (Printer_SetScreen==1)
1189                     {
1190 #ifndef XFRACT
1191                     static char far fmt_str[] = "%d %d {%Fs}%s";
1192 #else
1193                     static char fmt_str[] = "%d %d {%s}%s";
1194 #endif
1195                     Printer_printf(fmt_str,
1196                                        Printer_RFrequency,
1197                                        Printer_RAngle,
1198                                        (char far *)HalfTone[Printer_RStyle],
1199                                        EndOfLine);
1200                     Printer_printf(fmt_str,
1201                                        Printer_GFrequency,
1202                                        Printer_GAngle,
1203                                        (char far *)HalfTone[Printer_GStyle],
1204                                        EndOfLine);
1205                     Printer_printf(fmt_str,
1206                                        Printer_BFrequency,
1207                                        Printer_BAngle,
1208                                        (char far *)HalfTone[Printer_BStyle],
1209                                        EndOfLine);
1210                     Printer_printf(fmt_str,
1211                                        Printer_SFrequency,
1212                                        Printer_SAngle,
1213                                        (char far *)HalfTone[Printer_SStyle],
1214                                        EndOfLine);
1215                     PRINTER_PRINTF2("setcolorscreen%s", EndOfLine);
1216                     }
1217                 }
1218               else
1219               {
1220                  if (Printer_ColorXlat!=-2 && Printer_ColorXlat!=2) {
1221                     /* b&w case requires no mask building */
1222                    if (Printer_ColorXlat==1)
1223                       PRINTER_PRINTF2("{1 exch sub} settransfer%s",EndOfLine);
1224                    if (Printer_ColorXlat>1)
1225                       PRINTER_PRINTF4("{%d mul round %d div} settransfer%s",
1226                                       Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
1227                    if (Printer_ColorXlat<-1)
1228                       PRINTER_PRINTF4("{%d mul round %d div 1 exch sub} settransfer",
1229                                       Printer_ColorXlat,Printer_ColorXlat,EndOfLine);
1230 
1231                    if (Printer_SetScreen==1)
1232                    {
1233 #ifndef XFRACT
1234                       PRINTER_PRINTF5("%d %d {%Fs} setscreen%s",
1235                                      Printer_SFrequency,
1236                                      Printer_SAngle,
1237                                      (char far *)HalfTone[Printer_SStyle],
1238                                      EndOfLine);
1239 #else
1240                       Printer_printf("%d %d {%s} setscreen%s",
1241                                      Printer_SFrequency,
1242                                      Printer_SAngle,
1243                                      (char far *)HalfTone[Printer_SStyle],
1244                                      EndOfLine);
1245 #endif
1246                    }
1247                 }
1248               }
1249 
1250               if (ptrid == 5)
1251                  {
1252                     if ((EPSFileType==2) && (Printer_ColorXlat || Printer_SetScreen))
1253                         PRINTER_PRINTF2("%%%%EndFeature%s",EndOfLine);
1254                     if (res == 0)
1255                     {
1256                         PRINTER_PRINTF2("30 191.5 Tr 552 %4.1f",
1257                                         (552.0*(double)finalaspectratio));
1258                     }
1259                     else
1260                     {
1261                         PRINTER_PRINTF4("30 %d Tr %f %f",
1262                                      75 - ((Printer_Titleblock==1) ? 0 : 45),
1263                                      ((double)xdots*(72.0/(double)res)),
1264                                      ((double)xdots*(72.0/(double)res)*(double)finalaspectratio));
1265                     }
1266                   }
1267                 else                         /* For Horizontal PostScript */
1268                 {
1269                     if (res == 0)
1270                     {
1271                         PRINTER_PRINTF2("582 30 Tr 90 rotate 732 %4.1f",
1272                                         (732.0*(double)finalaspectratio));
1273                     }
1274                     else
1275                     {
1276                         PRINTER_PRINTF4("%d 30 Tr 90 rotate %f %f",
1277                                      537 + ((Printer_Titleblock==1) ? 0 : 45),
1278                                      ((double)xdots*(72.0/(double)res)),
1279                                      ((double)xdots*(72.0/(double)res)*(double)finalaspectratio));
1280                     }
1281                 }
1282                 PRINTER_PRINTF2(" scale%s",EndOfLine);
1283               }
1284 
1285             else if (ptrid == 5)       /* To be used on WELL-BEHAVED .EPS */
1286                 PRINTER_PRINTF5("30 %d Tr %d %d scale%s",
1287                                     75 - ((Printer_Titleblock==1) ? 0 : 45),
1288                                     xdots,ydots,EndOfLine);
1289 
1290             PRINTER_PRINTF2("dopic%s",EndOfLine);
1291             break;
1292 
1293         case 7: /* HP Plotter */
1294             if (res<1) res=1;
1295             if (res>10) res=10;
1296             ci = (((double)xdots*((double)res-1.0))/2.0);
1297             ck = (((double)ydots*((double)res-1.0))/2.0);
1298             PRINTER_PRINTF6(";IN;SP0;SC%d,%d,%d,%d;%s\0",
1299                 (int)(-ci),(int)((double)xdots+ci),
1300                 (int)((double)ydots+ck),(int)(-ck),EndOfLine);
1301             break;
1302         }
1303 }
1304 
1305 
print_title(int ptrid,int res,char * EndOfLine)1306 static void _fastcall print_title(int ptrid,int res,char *EndOfLine)
1307 {
1308     char buff[80];
1309     int postscript;
1310     if (Printer_Titleblock == 0)
1311         return;
1312     postscript = (ptrid == 5 || ptrid ==6);
1313     if (!postscript)
1314         Printer_printf(EndOfLine);
1315     else
1316         Printer_printf("(");
1317     Printer_printf((curfractalspecific->name[0]=='*')
1318                      ? &curfractalspecific->name[1]
1319                      : curfractalspecific->name);
1320     if (fractype == FORMULA || fractype == FFORMULA)
1321         Printer_printf(" %s",FormName);
1322     if (fractype == LSYSTEM)
1323         Printer_printf(" %s",LName);
1324     if (fractype == IFS || fractype == IFS3D)
1325         Printer_printf(" %s",IFSName);
1326     PRINTER_PRINTF4(" - %dx%d - %d DPI", xdots, ydots, res);
1327     if (!postscript)
1328         Printer_printf(EndOfLine);
1329     else {
1330         PRINTER_PRINTF2(") show%s",EndOfLine);
1331         if (ptrid==5) {PRINTER_PRINTF1("30 50 moveto (");}
1332         else          PRINTER_PRINTF1("-90 rotate 562 30 moveto 90 rotate (");
1333         }
1334     PRINTER_PRINTF5("Corners: Top-Left=%.16g/%.16g Bottom-Right=%.16g/%.16g",
1335                    xxmin,yymax,xxmax,yymin);
1336     if (xx3rd != xxmin || yy3rd != yymin) {
1337         if (!postscript)
1338             Printer_printf("%s        ",EndOfLine);
1339         PRINTER_PRINTF3(" Bottom-Left=%4.4f/%4.4f",xx3rd,yy3rd);
1340         }
1341     if (!postscript)
1342         Printer_printf(EndOfLine);
1343     else {
1344         PRINTER_PRINTF2(") show%s",EndOfLine);
1345         if (ptrid==5) {PRINTER_PRINTF1("30 40 moveto (");}
1346         else          PRINTER_PRINTF1("-90 rotate 572 30 moveto 90 rotate (");
1347         }
1348     showtrig(buff);
1349     PRINTER_PRINTF6("Parameters: %4.4f/%4.4f/%4.4f/%4.4f %s",
1350                    param[0],param[1],param[2],param[3],buff);
1351     if (!postscript)
1352         Printer_printf(EndOfLine);
1353     else
1354         PRINTER_PRINTF2(") show%s",EndOfLine);
1355 }
1356 
1357 /* This function prints a string to the the printer with BIOS calls. */
1358 
1359 #ifndef USE_VARARGS
Printer_printf(char far * fmt,...)1360 static void Printer_printf(char far *fmt,...)
1361 #else
1362 static void Printer_printf(va_alist)
1363 va_dcl
1364 #endif
1365 {
1366 int i;
1367 char s[500];
1368 int x=0;
1369 va_list arg;
1370 
1371 #ifndef USE_VARARGS
1372 va_start(arg,fmt);
1373 #else
1374 char far *fmt;
1375 va_start(arg);
1376 fmt = va_arg(arg,char far *);
1377 #endif
1378 
1379 {
1380    /* copy far to near string */
1381    char fmt1[100];
1382    i=0;
1383    while(fmt[i]) {
1384      fmt1[i] = fmt[i];
1385      i++;
1386    }
1387    fmt1[i] = '\0';
1388    vsprintf(s,fmt1,arg);
1389 }
1390 
1391 if (Print_To_File>0)    /* This is for printing to file */
1392     fprintf(PRFILE,"%s",s);
1393 else                    /* And this is for printing to printer */
1394     while (s[x])
1395         if (printer(s[x++]) != 0)
1396             while (!keypressed()) { if (printer(s[x-1])==0) break; }
1397 }
1398 
1399 /* This function standardizes both _bios_printer and _bios_serialcom
1400  * in one function.  It takes its arguments and rearranges them and calls
1401  * the appropriate bios call.  If it then returns result !=0, there is a
1402  * problem with the printer.
1403  */
printer(int c)1404 static int _fastcall printer(int c)
1405 {
1406     if (Print_To_File>0) return ((fprintf(PRFILE,"%c",c))<1);
1407 #ifndef XFRACT
1408     if (LPTn<9)  return (((_bios_printer(0,LPTn,c))+0x0010)&0x0010);
1409     if (LPTn<19) return ((_bios_serialcom(1,(LPTn-10),c))&0x9E00);
1410     if ((LPTn==20)||(LPTn==21))
1411         {
1412         int PS=0;
1413         while ((PS & 0xF8) != 0xD8)
1414             { PS = inp((LPTn==20) ? 0x379 : 0x279);
1415               if (keypressed()) return(1); }
1416         outp((LPTn==20) ? 0x37C : 0x27C,c);
1417         PS = inp((LPTn==20) ? 0x37A : 0x27A);
1418         outp((LPTn==20) ? 0x37A : 0x27A,(PS | 0x01));
1419         outp((LPTn==20) ? 0x37A : 0x27A,PS);
1420         return(0);
1421         }
1422     if ((LPTn==30)||(LPTn==31))
1423         {
1424         while (((inp((LPTn==30) ? 0x3FE : 0x2FE)&0x30)!=0x30) ||
1425                ((inp((LPTn==30) ? 0x3FD : 0x2FD)&0x60)!=0x60))
1426             { if (keypressed()) return (1); }
1427         outp((LPTn==30) ? 0x3F8 : 0x2F8,c);
1428         return(0);
1429         }
1430 #endif
1431 
1432     /* MCP 7-7-91, If we made it down to here, we may as well error out. */
1433     return(-1);
1434 }
1435 
1436 #ifdef __BORLANDC__
1437 #if(__BORLANDC__ > 2)
1438    #pragma warn +eff
1439 #endif
1440 #endif
1441 
printer_reset(void)1442 static void printer_reset(void)
1443 {
1444 #ifndef XFRACT
1445     if (Print_To_File < 1)
1446         if (LPTn<9)       _bios_printer(1,LPTn,0);
1447         else if (LPTn<19) _bios_serialcom(3,(LPTn-10),0);
1448 #endif
1449 }
1450 
1451 
1452 /** debug code for pj_ color table checkout
1453 color_test()
1454 {
1455    int x,y,color,i,j,xx,yy;
1456    int bw,cw,bh,ch;
1457    setvideomode(videoentry.videomodeax,
1458                 videoentry.videomodebx,
1459                 videoentry.videomodecx,
1460                 videoentry.videomodedx);
1461    bw = xdots/25; cw = bw * 2 / 3;
1462    bh = ydots/10; ch = bh * 2 / 3;
1463    dacbox[0][0] = dacbox[0][1] = dacbox[0][2] = 60;
1464    if (debugflag == 902)
1465       dacbox[0][0] = dacbox[0][1] = dacbox[0][2] = 0;
1466    for (x = 0; x < 25; ++x)
1467       for (y = 0; y < 10; ++y) {
1468          if (x < 11) i = (32 - x) * 10 + y;
1469              else    i = (24 - x) * 10 + y;
1470          color = x * 10 + y + 1;
1471          dacbox[color][0] = triple[0][0][i];
1472          dacbox[color][1] = triple[0][1][i];
1473          dacbox[color][2] = triple[0][2][i];
1474          for (i = 0; i < cw; ++i) {
1475             xx = x * bw + bw / 6 + i;
1476             yy = y * bh + bh / 6;
1477             for (j = 0; j < ch; ++j)
1478                putcolor(xx,yy++,color);
1479             }
1480          }
1481    spindac(0,1);
1482    getakey();
1483 }
1484 **/
1485 
1486 
1487 /*
1488  * The following code for compressed PostScript is based on pnmtops.c.  It is
1489  * copyright (C) 1989 by Jef Poskanzer, and carries the following notice:
1490  * "Permission to use, copy, modify, and distribute this software and its
1491  *  documentation for any purpose and without fee is hereby granted, provided
1492  *  that the above copyright notice appear in all copies and that both that
1493  *  copyright notice and this permission notice appear in supporting
1494  *  documentation.  This software is provided "as is" without express or
1495  *  implied warranty."
1496  */
1497 
1498 
rleprolog(int x,int y)1499 static void rleprolog(int x,int y)
1500 {
1501     itemsperline = 0;
1502     items = 0;
1503     bitspersample = 8;
1504     repeat = 1;
1505     rlebitsperitem = 0;
1506     rlebitshift = 0;
1507     count = 0;
1508 
1509     PRINTER_PRINTF2( "/rlestr1 1 string def%s", EndOfLine );
1510     PRINTER_PRINTF2( "/rdrlestr {%s", EndOfLine );      /* s -- nr */
1511     PRINTER_PRINTF2( "  /rlestr exch def%s", EndOfLine );    /* - */
1512     PRINTER_PRINTF2( "  Cf rlestr1 Rh pop%s", EndOfLine );  /* s1 */
1513     PRINTER_PRINTF2( "  0 get%s", EndOfLine );                     /* c */
1514     PRINTER_PRINTF2( "  D 127 le {%s", EndOfLine );              /* c */
1515     PRINTER_PRINTF2( "    Cf rlestr 0%s", EndOfLine );    /* c f s 0 */
1516     PRINTER_PRINTF2( "    4 3 roll%s", EndOfLine );                /* f s 0 c */
1517     PRINTER_PRINTF2( "    1 add  getinterval%s", EndOfLine );      /* f s */
1518     PRINTER_PRINTF2( "    Rh pop%s", EndOfLine );       /* s */
1519     PRINTER_PRINTF2( "    length%s", EndOfLine );                  /* nr */
1520     PRINTER_PRINTF2( "  } {%s", EndOfLine );                       /* c */
1521     PRINTER_PRINTF2( "    256 exch sub D%s", EndOfLine );        /* n n */
1522     PRINTER_PRINTF2( "    Cf rlestr1 Rh pop%s", EndOfLine );/* n n s1 */
1523     PRINTER_PRINTF2( "    0 get%s", EndOfLine );                   /* n n c */
1524     PRINTER_PRINTF2( "    exch 0 exch 1 exch 1 sub {%s", EndOfLine );           /* n c 0 1 n-1*/
1525     PRINTER_PRINTF2( "      rlestr exch 2 index put%s", EndOfLine );
1526     PRINTER_PRINTF2( "    } for%s", EndOfLine );                   /* n c */
1527     PRINTER_PRINTF2( "    pop%s", EndOfLine );                     /* nr */
1528     PRINTER_PRINTF2( "  } ifelse%s", EndOfLine );                  /* nr */
1529     PRINTER_PRINTF2( "} bind def%s", EndOfLine );
1530     PRINTER_PRINTF2( "/Rs {%s", EndOfLine );               /* s -- s */
1531     PRINTER_PRINTF2( "  D length 0 {%s", EndOfLine );            /* s l 0 */
1532     PRINTER_PRINTF2( "    3 copy exch%s", EndOfLine );          /* s l n s n l*/
1533     PRINTER_PRINTF2( "    1 index sub%s", EndOfLine );          /* s l n s n r*/
1534     PRINTER_PRINTF2( "    getinterval%s", EndOfLine );          /* s l n ss */
1535     PRINTER_PRINTF2( "    rdrlestr%s", EndOfLine );        /* s l n nr */
1536     PRINTER_PRINTF2( "    add%s", EndOfLine );                     /* s l n */
1537     PRINTER_PRINTF2( "    2 copy le { exit } if%s", EndOfLine );   /* s l n */
1538     PRINTER_PRINTF2( "  } loop%s", EndOfLine );                    /* s l l */
1539     PRINTER_PRINTF2( "  pop pop%s", EndOfLine );                   /* s */
1540     PRINTER_PRINTF2( "} bind def%s", EndOfLine );
1541     if (ColorPS) {
1542         PRINTER_PRINTF3( "/rpicstr %d string def%s", x,EndOfLine );
1543         PRINTER_PRINTF3( "/gpicstr %d string def%s", x,EndOfLine );
1544         PRINTER_PRINTF3( "/bpicstr %d string def%s", x,EndOfLine );
1545     } else {
1546         PRINTER_PRINTF3( "/picstr %d string def%s", x,EndOfLine );
1547     }
1548     PRINTER_PRINTF2( "/dopic {%s", EndOfLine);
1549     PRINTER_PRINTF2( "/gsave%s", EndOfLine);
1550     if (ColorPS) {
1551        PRINTER_PRINTF4( "%d %d 8%s", x, y, EndOfLine);
1552     } else { /* b&w */
1553        if (Printer_ColorXlat==-2) {
1554           PRINTER_PRINTF4( "%d %d true%s", x, y, EndOfLine);
1555        } else if (Printer_ColorXlat==2) {
1556           PRINTER_PRINTF4( "%d %d false%s", x, y, EndOfLine);
1557        } else {
1558           PRINTER_PRINTF4( "%d %d 8%s", x, y, EndOfLine);
1559        }
1560     }
1561     PRINTER_PRINTF5( "[%d 0 0 %d 0 %d]%s", x, -y, y, EndOfLine);
1562     if (ColorPS) {
1563         PRINTER_PRINTF2( "{rpicstr Rs}%s", EndOfLine);
1564         PRINTER_PRINTF2( "{gpicstr Rs}%s", EndOfLine);
1565         PRINTER_PRINTF2( "{bpicstr Rs}%s", EndOfLine);
1566         PRINTER_PRINTF2( "true 3 colorimage%s", EndOfLine);
1567     } else {
1568        if (Printer_ColorXlat==-2 || Printer_ColorXlat==2) {
1569           /* save file space and printing time (if scaling is right) */
1570           PRINTER_PRINTF2( "{picstr Rs} imagemask%s", EndOfLine);
1571        } else {
1572           PRINTER_PRINTF2( "{picstr Rs} image%s", EndOfLine);
1573        }
1574     }
1575     PRINTER_PRINTF2( "} def%s", EndOfLine);
1576 }
1577 
1578 static void
rleputbuffer(void)1579 rleputbuffer(void)
1580     {
1581     int i;
1582 
1583     if ( repeat )
1584         {
1585         item = 256 - count;
1586         putitem();
1587         item = repeatitem;
1588         putitem();
1589         }
1590     else
1591         {
1592         item = count - 1;
1593         putitem();
1594         for ( i = 0; i < count; ++i )
1595             {
1596             item = itembuf[i];
1597             putitem();
1598             }
1599         }
1600     repeat = 1;
1601     count = 0;
1602     }
1603 
1604 static void
rleputitem(void)1605 rleputitem(void)
1606     {
1607     int i;
1608 
1609     if ( count == 128 )
1610         rleputbuffer();
1611 
1612     if ( repeat && count == 0 )
1613         { /* Still initializing a repeat buf. */
1614         itembuf[count] = repeatitem = rleitem;
1615         ++count;
1616         }
1617     else if ( repeat )
1618         { /* Repeating - watch for end of run. */
1619         if ( rleitem == repeatitem )
1620             { /* Run continues. */
1621             itembuf[count] = rleitem;
1622             ++count;
1623             }
1624         else
1625             { /* Run ended - is it long enough to dump? */
1626             if ( count > 2 )
1627                 { /* Yes, dump a repeat-mode buffer and start a new one. */
1628                 rleputbuffer();
1629                 itembuf[count] = repeatitem = rleitem;
1630                 ++count;
1631                 }
1632             else
1633                 { /* Not long enough - convert to non-repeat mode. */
1634                 repeat = 0;
1635                 itembuf[count] = repeatitem = rleitem;
1636                 ++count;
1637                 repeatcount = 1;
1638                 }
1639             }
1640         }
1641     else
1642         { /* Not repeating - watch for a run worth repeating. */
1643         if ( rleitem == repeatitem )
1644             { /* Possible run continues. */
1645             ++repeatcount;
1646             if ( repeatcount > 3 )
1647                 { /* Long enough - dump non-repeat part and start repeat. */
1648                 count = count - ( repeatcount - 1 );
1649                 rleputbuffer();
1650                 count = repeatcount;
1651                 for ( i = 0; i < count; ++i )
1652                     itembuf[i] = rleitem;
1653                 }
1654             else
1655                 { /* Not long enough yet - continue as non-repeat buf. */
1656                 itembuf[count] = rleitem;
1657                 ++count;
1658                 }
1659             }
1660         else
1661             { /* Broken run. */
1662             itembuf[count] = repeatitem = rleitem;
1663             ++count;
1664             repeatcount = 1;
1665             }
1666         }
1667 
1668     rleitem = 0;
1669     rlebitsperitem = 0;
1670     }
1671 
1672 static void
putitem(void)1673 putitem (void)
1674     {
1675     char* hexits = "0123456789abcdef";
1676 
1677     if ( itemsperline == 30 )
1678         {
1679         Printer_printf("%s",EndOfLine);
1680         itemsperline = 0;
1681         }
1682     Printer_printf("%c%c", hexits[item >> 4], hexits[item & 15] );
1683     ++itemsperline;
1684     ++items;
1685     item = 0;
1686     /* bitsperitem = 0; */
1687     bitshift2 = 8 - bitspersample;
1688     }
1689 
1690 static void
rleputxelval(int xv)1691 rleputxelval( int xv )
1692     {
1693     if ( rlebitsperitem == 8 )
1694         rleputitem();
1695     rleitem += xv<<bitshift2;
1696     rlebitsperitem += bitspersample;
1697     rlebitshift -= bitspersample;
1698     }
1699 
1700 static void
rleflush(void)1701 rleflush(void)
1702     {
1703     if ( rlebitsperitem > 0 )
1704         rleputitem();
1705     if ( count > 0 )
1706         rleputbuffer();
1707     }
1708 
1709 static void
rleputrest(void)1710 rleputrest(void)
1711     {
1712     rleflush();
1713     Printer_printf( "%s",EndOfLine );
1714     Printer_printf( "grestore%s",EndOfLine );
1715     }
1716