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