1 /* Copyright (c) 1991 - 1994 Heinz W. Werntges. All rights reserved.
2 Parts Copyright (c) 1999 - 2001 Martin Kroeker All rights reserved.
3
4 Distributed by Free Software Foundation, Inc.
5
6 This file is part of HP2xx.
7
8 HP2xx is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
10 to anyone for the consequences of using it or for whether it serves any
11 particular purpose or works at all, unless he says so in writing. Refer
12 to the GNU General Public License, Version 2 or later, for full details.
13
14 Everyone is granted permission to copy, modify and redistribute
15 HP2xx, but only under the conditions described in the GNU General Public
16 License. A copy of this license is supposed to have been
17 given to you along with HP2xx so you can know your rights and
18 responsibilities. It should be in a file named COPYING. Among other
19 things, the copyright notice and this notice must be preserved on all
20 copies.
21
22 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23 */
24
25 /** HPGL.c: HPGL parser & i/o part of HP2xx (based on D. Donath's "HPtoGF.c")
26 **
27 ** 91/01/13 V 1.00 HWW Originating
28 ** 91/01/19 V 1.01 HWW reorganized
29 ** 91/01/24 V 1.02 HWW ESC.-Sequences acknowledged (preliminary!!)
30 ** 91/01/29 V 1.03 HWW Incl. SUN portation
31 ** 91/01/31 V 1.04 HWW Parser: ESC sequences should be skipped now
32 ** 91/02/10 V 1.05 HWW Parser renewed
33 ** 91/02/15 V 1.06 HWW stdlib.h supported
34 ** 91/02/19 V 1.07a HWW parser refined, bugs fixed
35 ** 91/06/09 V 1.08 HWW New options added; some restructuring
36 ** 91/06/16 V 1.09 HWW VGA mode added; some renaming; silent_mode!
37 ** 91/06/20 V 1.10 HWW Rotation added
38 ** 91/10/15 V 1.11 HWW ANSI_C; header files reorganized
39 ** 91/10/20 V 1.11a HWW VAX_C support
40 ** 91/10/25 V 1.11b HWW Support of LT; and LT0; (line type, partial)
41 ** 91/11/20 V 1.12 HWW SPn; support: many changes!
42 ** 91/11/21 V 1.12b HWW First comma in "PA,xxxx,yyyy..." accepted
43 ** 91/12/22 V 1.13 HWW Multiple MOVE compression; "plot_rel", "old_pen"
44 ** 92/01/13 V 1.13c HWW VAX problem with ungetc()/fscanf() fixed; bug fixed
45 ** 92/01/15 V 1.13d HWW "vga" --> "pre"
46 ** 92/01/30 V 1.14c HWW Parser: no need of ';', better portable
47 ** 92/02/06 V 1.15a HWW Parser: AR, AA, CI, read_float() added;
48 ** toupper() removed (MACH problems)
49 ** 92/02/19 V 1.16c HWW LB etc. supported
50 ** 92/02/23 V 1.17b HWW LB etc. improved, PG supported
51 ** 92/02/25 V 1.17c HWW Parser improved: SP, LT, multi-mv suppression
52 ** 92/03/01 V 1.17d HWW Char sizes: debugged
53 ** 92/03/03 V 1.17e HWW LB_Mode introduced
54 ** 92/04/15 V 1.17f HWW Width x Height limit assumed
55 ** 92/05/21 V 1.18a HWW Multiple-file usage
56 ** 92/05/28 V 1.19a HWW XT, YT, TL, SM added
57 ** 92/10/20 V 1.20c HWW More line types added (debugged)
58 ** 92/11/08 V 1.20d HWW Interval of active pages
59 ** 92/12/13 V 1.20e HWW truesize option added
60 ** 93/02/10 V 1.21a HWW Arcs & circles now properly closed;
61 ** Bug fixed: SC does not interfere with last move
62 ** 93/03/10 V 1.21b HWW Bug fixed in LT scanner part
63 ** 93/03/22, V 1.21c HWW HYPOT() workaround for a weird BCC behavior;
64 ** 93/04/02 Line_Generator(): Case *pb==*pa caught
65 ** 93/04/13 V 1.22a HWW UC supported (code by Alois Treindl)
66 ** 93/04/25 V 1.22b HWW LB/PR bug fix by E. Norum included
67 ** 93/05/20 V 1.22c HWW LT1 pattern adjustment (report by E. Frambach)
68 ** 93/09/02 V 1.22d HWW EA (rect) added (by Th. Hiller)
69 ** 94/01/01 V 1.22e HWW Misc. additions suggested by L. Lowe:
70 ** 1) PlotCmd_from_tmpfile(): int --> PlotCmd
71 ** 2) ES: 2nd parameter now optional
72 ** 3) evaluate_HPGL(): center_mode introduced
73 ** 94/02/14 V 1.30a HWW Re-organized; many changes; min/max bug fixed
74 ** 99/02/28 MK IW,CA,CS,SA,SS commands added
75 ** 99/04/24 MK PC,PW commands added
76 ** 99/05/10 MK RO command added (code by rs@daveg.com)
77 ** 99/05/18 MK partial PE support (by Eugene Doudine)
78 ** 99/06/05 MK PC improvements and fixes
79 ** 99/11/30 MK support for fractional PE; PS/RO fixes
80 ** 00/02/06 MK allow commandline overrides for PC/PW
81 ** 00/02/13 MK DV support (backport from delayed 3.4.prealpha)
82 ** 00/02/26 MK ER,EP,FP,FT,PM,PT,RA,RR,WG commands added
83 ** 00/02/27 MK WU command added
84 ** 00/03/02 MK SC types 1 and 2, more robust handling of PE,
85 ** removed PE_line(), split lines() into file reader
86 ** and common linedrawing backend for PD/PA and PE
87 ** added PJL parser and RTL escape sequences
88 ** (all these patches provided by Eugene Doudine)
89 ** 00/03/03 MK convert IW parameters if scaling is in effect
90 ** 00/03/05 MK AT/RT (arc through three points) added
91 ** 01/01/01 MK UL added and PW rewritten (Andrew J.Bird)
92 ** empty PUPD sequence now draws a small dot
93 ** linedrawing fixed (added two moves when IW was
94 ** in effect, ever since IW support was added)
95 ** 01/04/01 MK BR/BZ added
96 ** 01/04/22 MK reset PW and RO flags/values on reinitialization
97 ** (Yuri Strelenko)
98 ** 01/12/04 MK moved reinitialization of n_unknown and n_unexpected
99 ** from reset_HPGL to init_HPGL so that they are not overwritten
100 ** when a single drawing contains several IN statements
101 ** 02/06/02 AJB Moved HYPOT macro to hpgl.h - so we can use it in murphy.c
102 **/
103
104 #include <stdio.h>
105 #include <stdlib.h>
106
107 #ifndef _NO_VCL
108 #include <unistd.h>
109 #endif
110
111 #include <string.h>
112 #include <ctype.h>
113 #include <math.h>
114 #include "bresnham.h"
115 #include "hp2xx.h"
116 #include "chardraw.h"
117 #include "clip.h"
118 #include "pendef.h"
119 #include "lindef.h"
120 #include "hpgl.h"
121
122 #define ETX '\003'
123
124 /*
125 #define P1X_default 603.0
126 #define P1Y_default 521.0
127 #define P2X_default 10603.0
128 #define P2Y_default 7721.0
129 */
130 #define P1X_default 0.0 /* drop margins */
131 #define P1Y_default 0.0
132 /*
133 #define P2X_default 11880.
134 #define P2Y_default 16800.
135 */
136 #define P2X_default 33600. /* A0 media */
137 #define P2Y_default 47520.
138
139
140 #ifdef NORINT
141 #define rint(a) (long)(a+0.5)
142 #endif
143
144 /**
145 ** Globals needed in other source files:
146 **/
147 LineType CurrentLineType = LT_solid;
148 short scale_flag = FALSE;
149 short record_off = FALSE;
150 long vec_cntr_w = 0L;
151 long n_commands = 0L;
152 short silent_mode = FALSE;
153 FILE *td;
154
155 HPGL_Pt HP_pos = { 0, 0 }; /* Actual plotter pen position */
156 HPGL_Pt P1 = { P1X_default, P1Y_default }; /* Scaling points */
157 HPGL_Pt P2 = { P2X_default, P2Y_default };
158 int iwflag = 0; /*MK */
159 int mode_vert = 0;
160 HPGL_Pt C1 = { P1X_default, P1Y_default }; /* Clipping points */
161 HPGL_Pt C2 = { P2X_default, P2Y_default };
162 HPGL_Pt S1 = { P1X_default, P1Y_default }; /* Scaled */
163 HPGL_Pt S2 = { P2X_default, P2Y_default }; /* points */
164 HPGL_Pt Q = { 1., 1. }; /* Delta-P/Delta-S: Initialized with first SC */
165 HPGL_Pt M; /* maximum coordinates set by PS instruction */
166 /**
167 ** Global from chardraw.c:
168 **/
169 extern TextPar tp;
170
171 /**
172 ** "Local" globals (I know this is messy...) :
173 **/
174 static float xmin, xmax, ymin, ymax, neg_ticklen, pos_ticklen;
175 static double Diag_P1_P2, pat_pos;
176 static HPGL_Pt p_last = { M_PI, M_PI }; /* Init. to "impossible" values */
177
178 static HPGL_Pt polygons[MAXPOLY];
179 static int vertices = -1;
180 static short polygon_mode = FALSE;
181 static int filltype = 1;
182 static float hatchspace = 0.;
183 static float hatchangle = 0.;
184 static float saved_hatchspace[2] = { 0., 0. };
185 static float saved_hatchangle[2] = { 0., 0. };
186 static float thickness = 0.;
187 static short polygon_penup = FALSE;
188 static HPGL_Pt anchor = { 100000.0, 100000.0 };
189 static HPGL_Pt polystart = { 0.0, 0.0 };
190 static float rot_cos, rot_sin;
191
192 static short rotate_flag = FALSE; /* Flags tec external to HP-GL */
193 static short ps_flag = FALSE;
194 static short ac_flag = FALSE;
195 static double rot_ang = 0.;
196 static double rot_tmp = 0.; /* saved RO value for resetting after drawing */
197 static short mv_flag = FALSE;
198 static short pg_flag = FALSE;
199 static short ct_dist = FALSE;
200 static short fixedcolor = FALSE;
201 static short fixedwidth = FALSE;
202 static int first_page = 0;
203 static int last_page = 0;
204 static int n_unexpected = 0;
205 static int n_unknown = 0;
206 static int page_number = 1;
207 static long vec_cntr_r = 0L;
208 static short pen = -1;
209 static short pens_in_use[NUMPENS];
210 static short pen_down = FALSE; /* Internal HP-GL book-keeping: */
211 static short plot_rel = FALSE;
212 static short saved_penstate = FALSE; /* to track penstate over polygon mode */
213 static short wu_relative = FALSE;
214 static int again = FALSE;
215 static char StrTerm = ETX; /* String terminator char */
216 static short StrTermSilent = 1; /* only terminates, or prints too */
217 static char *strbuf = NULL;
218 static unsigned int strbufsize = MAX_LB_LEN + 1;
219 static char symbol_char = '\0'; /* Char in Symbol Mode (0=off) */
220 static unsigned char r_base = 0;
221 static unsigned char g_base = 0;
222 static unsigned char b_base = 0;
223 static unsigned char r_max = 255;
224 static unsigned char g_max = 255;
225 static unsigned char b_max = 255;
226
227 /* Known HPGL commands, ASCII-coded as High-byte/low-byte int's */
228
229 #define AA 0x4141
230 #define AC 0x4143
231 #define AD 0x4144
232 #define AF 0x4146
233 #define AH 0x4148
234 #define AR 0x4152
235 #define AT 0x4154
236 #define BL 0x424C
237 #define BP 0x4250
238 #define BR 0x4252
239 #define BZ 0x425A
240 #define CA 0x4341 /*MK */
241 #define CI 0x4349
242 #define CO 0x434F /*AJB*/
243 #define CP 0x4350
244 #define CR 0x4352
245 #define CS 0x4353 /*MK */
246 #define CT 0x4354
247 #define DF 0x4446
248 #define DI 0x4449
249 #define DR 0x4452
250 #define DT 0x4454
251 #define DV 0x4456
252 #define EA 0x4541
253 #define EC 0x4543 /*AJB*/
254 #define EP 0x4550
255 #define ER 0x4552
256 #define ES 0x4553
257 #define EW 0x4557 /*MK */
258 #define FP 0x4650
259 #define FT 0x4654
260 #define IN 0x494E
261 #define IP 0x4950
262 #define IR 0x4952
263 #define IW 0x4957 /*MK */
264 #define LA 0x4C41 /*AJB*/
265 #define LB 0x4C42
266 #define LO 0x4C4F
267 #define LT 0x4C54
268 #define MG 0x4D47
269 #define NP 0x4E50
270 #define NR 0x4E52
271 #define OP 0x4F50
272 #define OW 0x4F57
273 #define PA 0x5041
274 #define PB 0x5042
275 #define PC 0x5043 /*MK */
276 #define PD 0x5044
277 #define PE 0x5045
278 #define PG 0x5047
279 #define PM 0x504D
280 #define PR 0x5052
281 #define PS 0x5053
282 #define PT 0x5054
283 #define PU 0x5055
284 #define PW 0x5057 /*MK */
285 #define RA 0x5241
286 #define RO 0x524F /*RS */
287 #define RR 0x5252
288 #define RT 0x5254
289 #define SA 0x5341 /*MK */
290 #define SC 0x5343
291 #define SD 0x5344
292 #define SI 0x5349
293 #define SL 0x534C
294 #define SM 0x534D
295 #define SP 0x5350
296 #define SR 0x5352
297 #define SS 0x5353 /*MK */
298 #define TL 0x544C
299 #define UC 0x5543
300 #define UL 0x554C /*AJB*/
301 #define VS 0x5653
302 #define WD 0x5744
303 #define WG 0x5747
304 #define WU 0x5755
305 #define XT 0x5854
306 #define YT 0x5954
par_err_exit(int code,int cmd,FILE * hd)307 static void par_err_exit(int code, int cmd, FILE * hd)
308 {
309
310 const char *msg;
311 char tmpstr[21];
312
313 switch (code) {
314 case 0:
315 msg = "Illegal parameters";
316 break;
317 case 1:
318 msg = "Error in first parameter";
319 break;
320 case 2:
321 msg = "No second parameter";
322 break;
323 case 3:
324 msg = "No third parameter";
325 break;
326 case 4:
327 msg = "No fourth parameter";
328 break;
329 case 98:
330 msg = "sscanf error: corrupted file?";
331 break;
332 case 99:
333 default:
334 msg = "Internal error";
335 break;
336 }
337 Eprintf("\nError in command %c%c: %s\n", cmd >> 8, cmd & 0xFF,
338 msg);
339 Eprintf(" @ Cmd %ld\n", vec_cntr_w);
340 fseek(hd, -10L, SEEK_CUR);
341 read_string(tmpstr, hd);
342 tmpstr[20] = '\0';
343 Eprintf(" lately read: %s\n", tmpstr);
344 exit(ERROR);
345 }
346
347
348
349
reset_HPGL(void)350 static void reset_HPGL(void)
351 {
352 int i;
353
354 p_last.x = p_last.y = M_PI;
355 pen_down = FALSE;
356 plot_rel = FALSE;
357 pen = -1;
358 /* n_unexpected = 0;
359 n_unknown = 0;*/
360 mv_flag = FALSE;
361 wu_relative = FALSE;
362 pg_flag = FALSE;
363 iwflag = FALSE;
364 ps_flag = FALSE;
365 ac_flag = FALSE;
366 filltype = 1;
367 saved_hatchangle[0] = saved_hatchangle[1] = 0.;
368 saved_hatchspace[0] = saved_hatchspace[1] = 0.;
369 ct_dist = FALSE;
370 CurrentLineType = LT_solid;
371
372 set_line_style_defaults();
373 /* set_line_attr_defaults();*/
374 CurrentLineAttr.Join = LAJ_plain_miter;
375 CurrentLineAttr.End = LAE_butt;
376 CurrentLineAttr.Limit = 5;
377 tp->sstrokewidth = tp->astrokewidth = tp->strokewidth = 0.11;
378 StrTerm = ETX;
379 StrTermSilent = 1;
380 if (strbuf == NULL) {
381 strbuf = malloc(strbufsize);
382 if (strbuf == NULL) {
383 fprintf(stderr, "\nNo memory !\n");
384 exit(ERROR);
385 }
386 }
387 strbuf[0] = '\0';
388
389 P1.x = P1X_default;
390 P1.y = P1Y_default;
391
392 Diag_P1_P2 = /*@-unrecog@ */ HYPOT(P2.x - P1.x, P2.y - P1.y);
393 CurrentLinePatLen = 0.04 * Diag_P1_P2;
394 pat_pos = 0.0;
395 scale_flag = FALSE;
396 S1 = P1;
397 S2 = P2;
398 Q.x = Q.y = 1.0;
399 HP_pos.x = HP_pos.y = 0.0;
400 neg_ticklen = 0.005; /* 0.5 % */
401 pos_ticklen = 0.005;
402 symbol_char = '\0';
403 rot_ang -= rot_tmp;
404 rot_tmp = 0.;
405 if (rot_ang == 0.)
406 rotate_flag = FALSE;
407 if (rotate_flag) {
408 rot_cos = cos(M_PI * rot_ang / 180.0);
409 rot_sin = sin(M_PI * rot_ang / 180.0);
410 }
411 init_text_par();
412 if (fixedcolor == FALSE) {
413 set_color_rgb(xxBackground, 255, 255, 255);
414 set_color_rgb(xxForeground, 0, 0, 0);
415 set_color_rgb(xxRed, 255, 0, 0);
416 set_color_rgb(xxGreen, 0, 255, 0);
417 set_color_rgb(xxBlue, 0, 0, 255);
418 set_color_rgb(xxCyan, 0, 255, 255);
419 set_color_rgb(xxMagenta, 255, 0, 255);
420 set_color_rgb(xxYellow, 255, 255, 0);
421 pt.color[0] = xxBackground;
422 pt.color[1] = xxForeground;
423 pt.color[2] = xxRed;
424 pt.color[3] = xxGreen;
425 pt.color[4] = xxBlue;
426 pt.color[5] = xxCyan;
427 pt.color[6] = xxMagenta;
428 pt.color[7] = xxYellow;
429 }
430 if (fixedwidth == FALSE)
431 for (i = 0; i < 8; i++)
432 pt.width[i] = 0.1;
433 record_off = (first_page > page_number)
434 || ((last_page < page_number) && (last_page > 0));
435 }
436
init_HPGL(GEN_PAR * pg,const IN_PAR * pi)437 static void init_HPGL(GEN_PAR * pg, const IN_PAR * pi)
438 {
439 /**
440 ** Re-init. global var's for multiple-file applications
441 **/
442 /*fprintf(stderr,"init_HPGL\n");*/
443 td = pg->td;
444 silent_mode = (short) pg->quiet;
445 xmin = pi->x0;
446 ymin = pi->y0;
447 xmax = pi->x1;
448 ymax = pi->y1;
449 fixedcolor = (short) pi->hwcolor;
450 fixedwidth = (short) pi->hwsize;
451 r_base = g_base = b_base = 0;
452 r_max = g_max = b_max = 255;
453
454 /* pens_in_use = 0; */
455 pg->maxpens = 8;
456 pg->maxcolor = 1;
457 memset(pens_in_use, 0, NUMPENS * sizeof(short));
458 /**
459 ** Record ON if no page selected (pg->page == 0)!
460 **/
461 first_page = pi->first_page; /* May be 0 */
462 last_page = pi->last_page; /* May be 0 */
463 record_off = (first_page > page_number)
464 || ((last_page < page_number) && (last_page > 0));
465
466 rot_ang = pi->rotation;
467 rotate_flag = (rot_ang != 0.0) ? TRUE : FALSE;
468 if (rotate_flag) {
469 rot_cos = cos(M_PI * rot_ang / 180.0);
470 rot_sin = sin(M_PI * rot_ang / 180.0);
471 }
472 vec_cntr_r = 0L;
473 vec_cntr_w = 0L;
474 n_unexpected = 0;
475 n_commands = 0;
476 n_unknown = 0;
477
478 if (pi->hwlimit.x > 0.)
479 P2.x = S2.x = pi->hwlimit.x;
480 if (pi->hwlimit.y > 0.)
481 P2.y = S2.y = pi->hwlimit.y;
482
483 reset_HPGL();
484 }
485
486
487
User_to_Plotter_coord(const HPGL_Pt * p_usr,HPGL_Pt * p_plot)488 static void User_to_Plotter_coord(const HPGL_Pt * p_usr, HPGL_Pt * p_plot)
489 /**
490 ** Utility: Transformation from (scaled) user coordinates
491 ** to plotter coordinates
492 **/
493 {
494 p_plot->x = P1.x + (p_usr->x - S1.x) * Q.x;
495 p_plot->y = P1.y + (p_usr->y - S1.y) * Q.y;
496 }
497
498
499
Plotter_to_User_coord(const HPGL_Pt * p_plot,HPGL_Pt * p_usr)500 static void Plotter_to_User_coord(const HPGL_Pt * p_plot, HPGL_Pt * p_usr)
501 /**
502 ** Utility: Transformation from plotter coordinates
503 ** to (scaled) user coordinates
504 **/
505 {
506 p_usr->x = S1.x + (p_plot->x - P1.x) / Q.x;
507 p_usr->y = S1.y + (p_plot->y - P1.y) / Q.y;
508 }
509
510
511
PlotCmd_to_tmpfile(PlotCmd cmd)512 void PlotCmd_to_tmpfile(PlotCmd cmd)
513 {
514 if (record_off) /* Wrong page! */
515 return;
516
517 if (!silent_mode)
518 switch (vec_cntr_w++) {
519 case 0:
520 Eprintf("Writing Cmd: ");
521 break;
522 case 1:
523 Eprintf("1 ");
524 break;
525 case 2:
526 Eprintf("2 ");
527 break;
528 case 5:
529 Eprintf("5 ");
530 break;
531 case 10:
532 Eprintf("10 ");
533 break;
534 case 20:
535 Eprintf("20 ");
536 break;
537 case 50:
538 Eprintf("50 ");
539 break;
540 case 100:
541 Eprintf("100 ");
542 break;
543 case 200:
544 Eprintf("200 ");
545 break;
546 case 500:
547 Eprintf("500 ");
548 break;
549 case 1000:
550 Eprintf("1k ");
551 break;
552 case 2000:
553 Eprintf("2k ");
554 break;
555 case 5000:
556 Eprintf("5k ");
557 break;
558 case 10000:
559 Eprintf("10k ");
560 break;
561 case 20000:
562 Eprintf("20k ");
563 break;
564 case 50000L:
565 Eprintf("50k ");
566 break;
567 case 100000L:
568 Eprintf("100k ");
569 break;
570 case 200000L:
571 Eprintf("200k ");
572 break;
573 case 500000L:
574 Eprintf("500k ");
575 break;
576 case 1000000L:
577 Eprintf("1000k ");
578 break;
579 case 2000000L:
580 Eprintf("2000k ");
581 break;
582 case 3000000L:
583 Eprintf("3000k ");
584 break;
585 case 4000000L:
586 Eprintf("4000k ");
587 break;
588 case 5000000L:
589 Eprintf("5000k... ");
590 break;
591 case 10000000L:
592 Eprintf("10000k ");
593 break;
594 }
595
596 if (fputc((int) cmd, td) == EOF) {
597 PError("PlotCmd_to_tmpfile");
598 Eprintf("Error @ Cmd %ld\n", vec_cntr_w);
599 exit(ERROR);
600 }
601 }
602
603
604
605
HPGL_Pt_to_tmpfile(const HPGL_Pt * pf)606 void HPGL_Pt_to_tmpfile(const HPGL_Pt * pf)
607 {
608 if (record_off) /* Wrong page! */
609 return;
610
611 if (fwrite((VOID *) pf, sizeof(*pf), 1, td) != 1) {
612 PError("HPGL_Pt_to_tmpfile");
613 Eprintf("Error @ Cmd %ld\n", vec_cntr_w);
614 exit(ERROR);
615 }
616 xmin = MIN(pf->x, xmin);
617 ymin = MIN(pf->y, ymin);
618 xmax = MAX(pf->x, xmax);
619 ymax = MAX(pf->y, ymax);
620 }
621
622
HPGL_Pt_to_polygon(HPGL_Pt pf)623 void HPGL_Pt_to_polygon(HPGL_Pt pf)
624 {
625 if (record_off) /* Wrong page! */
626 return;
627
628 polygons[++vertices] = pf;
629 if (rotate_flag) {
630 double tmp = rot_cos * pf.x - rot_sin * pf.y;
631 pf.y = rot_sin * pf.x + rot_cos * pf.y;
632 pf.x = tmp;
633 }
634 xmin = MIN(pf.x, xmin);
635 ymin = MIN(pf.y, ymin);
636 xmax = MAX(pf.x, xmax);
637 ymax = MAX(pf.y, ymax);
638 }
639
640
641
642
643 /**
644 ** Low-level vector generation & file I/O
645 **/
646
647 static void
LPattern_Generator(HPGL_Pt * pa,double dx,double dy,double start_of_pat,double end_of_pat)648 LPattern_Generator(HPGL_Pt * pa,
649 double dx, double dy,
650 double start_of_pat, double end_of_pat)
651 /**
652 ** Generator of Line type patterns:
653 **
654 ** pa: Start point (ptr) of current line segment
655 ** dx, dy: Components of c * (*pb - *pa), c holding
656 ** dx^2 + dy^2 = pattern_length^2
657 ** start_of_pat: Fraction of start point within pattern
658 ** end_of_pat: Fraction of end point within pattern
659 ** Valid: 0 <= start_of_pat <= end_of_pat <= 1
660 **
661 ** A pattern consists of alternating "line"/"point" and "gap" elements,
662 ** always starting with a line/point. A point is a line of zero length.
663 ** The table below contains the relative lengths of the elements
664 ** of all line types except LT0; and LT; (7), which are treated separately.
665 ** These lengths always add up to 1. A negative value terminates a pattern.
666 **/
667 {
668 double length_of_ele, start_of_action, end_of_action;
669 static double *p_cur_pat;
670
671 p_cur_pat = lt[(LT_MIN * -1) + (int) CurrentLinePattern]; /* was CurrentLineType */
672
673 if (CurrentLineType == LT_adaptive)
674 for (;;) {
675 length_of_ele = (double) *p_cur_pat++ / 100; /* Line or point */
676 if (length_of_ele < 0.)
677 return;
678 if (length_of_ele < 1.e-5)
679 PlotCmd_to_tmpfile(PLOT_AT);
680 else
681 PlotCmd_to_tmpfile(DRAW_TO);
682
683 pa->x += dx * length_of_ele;
684 pa->y += dy * length_of_ele;
685 HPGL_Pt_to_tmpfile(pa);
686
687 length_of_ele = (double) *p_cur_pat++ / 100; /* Gap */
688 if (length_of_ele < 0.)
689 return;
690 pa->x += dx * length_of_ele;
691 pa->y += dy * length_of_ele;
692 PlotCmd_to_tmpfile(MOVE_TO);
693 HPGL_Pt_to_tmpfile(pa);
694 } else /* LT_fixed */
695 for (end_of_action = 0.0;;) {
696 /**
697 ** Line or point:
698 **/
699 start_of_action = end_of_action;
700 length_of_ele = (double) *p_cur_pat++ / 100;
701 if (length_of_ele < 0.)
702 return;
703
704 if (length_of_ele < 1.e-5) { /* Dot Only */
705 PlotCmd_to_tmpfile(PLOT_AT);
706 HPGL_Pt_to_tmpfile(pa);
707 } else { /* Line Segment */
708 end_of_action += length_of_ele;
709
710 if (end_of_action > start_of_pat) { /* If anything to do: */
711 if (start_of_pat <= start_of_action) { /* If start is valid */
712 if (end_of_action <= end_of_pat) { /* Draw full element */
713 pa->x +=
714 dx *
715 length_of_ele;
716 pa->y +=
717 dy *
718 length_of_ele;
719 PlotCmd_to_tmpfile
720 (DRAW_TO);
721 HPGL_Pt_to_tmpfile
722 (pa);
723 } else
724 /* End_of_action beyond End_of_pattern: */
725 { /* --> Draw only first part of element: */
726 pa->x +=
727 dx *
728 (end_of_pat -
729 start_of_action);
730 pa->y +=
731 dy *
732 (end_of_pat -
733 start_of_action);
734 PlotCmd_to_tmpfile
735 (DRAW_TO);
736 HPGL_Pt_to_tmpfile
737 (pa);
738 return;
739 }
740 } else
741 /* Start_of_action before Start_of_pattern: */
742 {
743 if (end_of_action <= end_of_pat) { /* Draw remainder of element */
744 pa->x +=
745 dx *
746 (end_of_action
747 -
748 start_of_pat);
749 pa->y +=
750 dy *
751 (end_of_action
752 -
753 start_of_pat);
754 PlotCmd_to_tmpfile
755 (DRAW_TO);
756 HPGL_Pt_to_tmpfile
757 (pa);
758 } else
759 /* End_of_action beyond End_of_pattern: */
760 /* Draw central part of element & leave */
761 {
762 if (end_of_pat ==
763 start_of_pat)
764 PlotCmd_to_tmpfile
765 (PLOT_AT);
766 else
767 PlotCmd_to_tmpfile
768 (DRAW_TO);
769 pa->x +=
770 dx *
771 (end_of_pat -
772 start_of_pat);
773 pa->y +=
774 dy *
775 (end_of_pat -
776 start_of_pat);
777
778 HPGL_Pt_to_tmpfile
779 (pa);
780 return;
781 }
782 }
783 }
784 }
785 /**
786 ** Gap (analogous to line/point):
787 **/
788 start_of_action = end_of_action;
789 length_of_ele = (double) *p_cur_pat++ / 100;
790 if (length_of_ele < 0)
791 return;
792 end_of_action += length_of_ele;
793 if (end_of_action > start_of_pat) { /* If anything to do: */
794 if (start_of_pat <= start_of_action) { /* If start is valid */
795 if (end_of_action <= end_of_pat) { /* Full gap */
796 pa->x +=
797 dx * length_of_ele;
798 pa->y +=
799 dy * length_of_ele;
800 PlotCmd_to_tmpfile
801 (MOVE_TO);
802 HPGL_Pt_to_tmpfile(pa);
803 } else
804 /* End_of_action beyond End_of_pattern: */
805 { /* --> Apply only first part of gap: */
806 pa->x +=
807 dx * (end_of_pat -
808 start_of_action);
809 pa->y +=
810 dy * (end_of_pat -
811 start_of_action);
812 PlotCmd_to_tmpfile
813 (MOVE_TO);
814 HPGL_Pt_to_tmpfile(pa);
815 return;
816 }
817 } else
818 /* Start_of_action before Start_of_pattern: */
819 {
820 if (end_of_action <= end_of_pat) { /* Apply remainder of gap */
821 pa->x +=
822 dx * (end_of_action -
823 start_of_pat);
824 pa->y +=
825 dy * (end_of_action -
826 start_of_pat);
827 PlotCmd_to_tmpfile
828 (MOVE_TO);
829 HPGL_Pt_to_tmpfile(pa);
830 } else
831 /* End_of_action beyond End_of_pattern: */
832 /* Apply central part of gap & leave */
833 {
834 if (end_of_pat ==
835 start_of_pat)
836 return; /* A null move */
837 pa->x +=
838 dx * (end_of_pat -
839 start_of_pat);
840 pa->y +=
841 dy * (end_of_pat -
842 start_of_pat);
843 PlotCmd_to_tmpfile
844 (MOVE_TO);
845 HPGL_Pt_to_tmpfile(pa);
846 return;
847 }
848 }
849 }
850 }
851 }
852
853 /**
854 ** Rectangles -- by Th. Hiller (hiller@tu-harburg.d400.de)
855 **/
856
rect(int relative,int filled,float cur_pensize,HPGL_Pt p)857 static void rect(int relative, int filled, float cur_pensize, HPGL_Pt p)
858 {
859 HPGL_Pt p1;
860
861 if (relative) { /* Process coordinates */
862 p.x += p_last.x;
863 p.y += p_last.y;
864 }
865 if (!filled) {
866 p1.x = p_last.x;
867 p1.y = p.y;
868 Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag);
869 p1.x = p.x;
870 p1.y = p.y;
871 Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag);
872 p1.x = p.x;
873 p1.y = p_last.y;
874 Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag);
875 p1.x = p_last.x;
876 p1.y = p_last.y;
877 Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag);
878 } else {
879 vertices = -1;
880 HPGL_Pt_to_polygon(p_last);
881 p1.x = p_last.x;
882 p1.y = p.y;
883 HPGL_Pt_to_polygon(p1);
884 HPGL_Pt_to_polygon(p1);
885 HPGL_Pt_to_polygon(p);
886 HPGL_Pt_to_polygon(p);
887 p1.x = p.x;
888 p1.y = p_last.y;
889 HPGL_Pt_to_polygon(p1);
890 HPGL_Pt_to_polygon(p1);
891 HPGL_Pt_to_polygon(p_last);
892 if (hatchspace == 0.)
893 hatchspace = cur_pensize;
894 if (filltype < 3 && thickness > 0.)
895 hatchspace = thickness;
896 if (ac_flag == 0) { /* not yet initialized */
897 anchor.x = P1.x;
898 anchor.y = P1.y;
899 /* fprintf(stderr,"anchor init to P1\n");*/
900
901 /* anchor.y=MIN(P1.y,ymin); */
902 }
903 fill(polygons, vertices, anchor, P2, scale_flag,
904 filltype, hatchspace, hatchangle);
905 }
906 Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag);
907 }
908
rects(int relative,int filled,float cur_pensize,FILE * hd)909 static void rects(int relative, int filled, float cur_pensize, FILE * hd)
910 {
911 HPGL_Pt p;
912 for (;;) {
913 if (read_float(&p.x, hd)) /* No number found */
914 return;
915
916 if (read_float(&p.y, hd)) /* x without y invalid! */
917 par_err_exit(2, EA, hd);
918 rect(relative, filled, cur_pensize, p);
919 }
920 }
921
922
923 /*
924 struct PE_flags{
925 int abs;
926 int up;
927 int sbmode;
928 int fract;
929 int pen;
930 } ;
931 */
read_PE_flags(GEN_PAR * pg,int c,FILE * hd,PE_flags * fl)932 int read_PE_flags(GEN_PAR * pg, int c, FILE * hd, PE_flags * fl)
933 {
934 short old_pen;
935 float ftmp;
936 int ctmp;
937 switch (c) {
938 case 183:
939 case '7':
940 /* seven bit mode */
941 fl->sbmode = 1;
942 break;
943
944 case 185:
945 case '9':
946 /* rectangle mode */
947 fl->rect = 1;
948 fl->up = 1;
949 break;
950
951 case 186:
952 case ':':
953 /* select pen */
954 if (EOF == (fl->pen = getc(hd))) {
955 par_err_exit(98, PE, hd);
956 }
957 old_pen = pen;
958 read_PE_coord(fl->pen, hd, fl, &ftmp);
959 pen = (short) ftmp;
960 if (pen < 0 || (int) pen > pg->maxpens) {
961 Eprintf
962 ("\nIllegal pen number %d: replaced by %d\n",
963 pen, pen % pg->maxpens);
964 n_unexpected++;
965 pen = pen % pg->maxpens;
966 }
967 if (pen == 0 && pg->mapzero > -1)
968 pen = pg->mapzero;
969 if (old_pen != pen) {
970 if ((fputc(SET_PEN, td) == EOF)
971 || (fputc(pen, td) == EOF)) {
972 PError("Writing to temporary file:");
973 Eprintf("Error @ Cmd %ld\n", vec_cntr_w);
974 exit(ERROR);
975 }
976 }
977 if (pen)
978 pens_in_use[pen] = 1;
979 pg->maxcolor = MAX(pg->maxcolor, (int) pen);
980 /*MK */
981 break;
982
983 case 190:
984 case '>':
985 /* fractional data */
986
987 if (EOF == (ctmp = getc(hd))) {
988 par_err_exit(98, PE, hd);
989 }
990 fl->fract = decode_PE_char(ctmp, fl);
991 fl->fract =
992 ((fl->fract >> 1) * ((fl->fract & 0x01) ? -1 : 1));
993 /* fprintf(stderr,"PE > flag, fract =%d (%d decimals) ",fl->fract, fl->fract/3); */
994 break;
995
996 case 188:
997 case '<':
998 /* pen up */
999 fl->up = 1;
1000 fl->rect = 0;
1001 break;
1002
1003 case 189:
1004 case '=':
1005 /* abs plotting */
1006
1007 fl->abs = 1;
1008 break;
1009
1010 default:
1011 return (0);
1012 }
1013 return (1);
1014 }
1015
isPEterm(int c,PE_flags * fl)1016 int isPEterm(int c, PE_flags * fl)
1017 {
1018 if ((fl->sbmode) && ((c > 94) || (c < 63)))
1019 return 1;
1020 if ((!fl->sbmode) && ((c > 190) || (c < 63)))
1021 return 1;
1022 return (0);
1023 }
1024
1025
decode_PE_char(int c,PE_flags * fl)1026 int decode_PE_char(int c, PE_flags * fl)
1027 {
1028 if (fl->sbmode) {
1029 c &= 0x7f;
1030 return ((c > 94) ? (c - 95) : (c - 63));
1031 } else {
1032 return ((c > 190) ? (c - 191) : (c - 63));
1033 }
1034 }
1035
read_PE_coord(int c,FILE * hd,PE_flags * fl,float * fv)1036 int read_PE_coord(int c, FILE * hd, PE_flags * fl, float *fv)
1037 {
1038 long lv = 0;
1039 int i = 0;
1040 int shft = (fl->sbmode) ? 5 : 6;
1041
1042 for (;;) {
1043 if (c < 63) {
1044 if (!i) { /* avoid endless getc/ungetc loop with broken files */
1045 Eprintf("error in PE data!\n");
1046 return 0;
1047 }
1048 ungetc(c, hd);
1049 break;
1050 }
1051 lv |= ((long) decode_PE_char(c, fl)) << (i * shft);
1052 i++;
1053 if (isPEterm(c, fl)) {
1054 break;
1055 }
1056 if (EOF == (c = getc(hd))) {
1057 par_err_exit(98, PE, hd);
1058 }
1059 }
1060 *fv = (float) (((lv >> 1) * ((lv & 0x01) ? -1 : 1)) << fl->fract);
1061 return (1);
1062 }
1063
1064
read_PE_pair(int c,FILE * hd,PE_flags * fl,HPGL_Pt * p)1065 int read_PE_pair(int c, FILE * hd, PE_flags * fl, HPGL_Pt * p)
1066 {
1067 if (!read_PE_coord(c, hd, fl, &(p->x)))
1068 return 0;
1069 if (EOF == (c = getc(hd))) {
1070 par_err_exit(98, PE, hd);
1071 }
1072 if (!read_PE_coord(c, hd, fl, &(p->y)))
1073 return 0;
1074 return (1);
1075 }
1076
1077
1078
1079
read_PE(GEN_PAR * pg,FILE * hd)1080 void read_PE(GEN_PAR * pg, FILE * hd)
1081 {
1082 int c;
1083
1084 HPGL_Pt p;
1085 PE_flags fl;
1086
1087 fl.fract = 0;
1088 fl.sbmode = 0;
1089 fl.abs = 0;
1090 fl.up = 0;
1091 fl.pen = 0;
1092
1093 for (c = getc(hd); (c != EOF) && (c != ';'); c = getc(hd)) {
1094 if (!read_PE_flags(pg, c, hd, &fl)) {
1095 if (!read_PE_pair(c, hd, &fl, &p))
1096 continue;
1097 switch (fl.rect) {
1098 case 1:
1099 pen_down = 0;
1100 line(!fl.abs, p);
1101 fl.rect = 2;
1102 break;
1103 case 2:
1104 pen_down = 1;
1105 rect(1, pg->nofill ? 0 : 1, pt.width[pen],
1106 p);
1107 fl.rect = 1;
1108 /* should be up when PE ends while */
1109 /* in PE mode */
1110 pen_down = 0;
1111 break;
1112 default:
1113 pen_down = (fl.up) ? FALSE : TRUE;
1114 line(!fl.abs, p);
1115 fl.up = 0;
1116 break;
1117 }
1118 fl.abs = 0;
1119 tp->CR_point = HP_pos;
1120 }
1121 }
1122 }
1123
1124
ceil_with_tolerance(double x,double tol)1125 double ceil_with_tolerance(double x, double tol)
1126 {
1127 double rounded;
1128
1129 /* rounded=rint(x);*/
1130 rounded = (double) (x + 0.5);
1131
1132 if (fabs(rounded - x) <= tol)
1133 return (rounded);
1134 else
1135 return (ceil(x));
1136 }
1137
Line_Generator(HPGL_Pt * pa,const HPGL_Pt * pb,int mv_flag)1138 static void Line_Generator(HPGL_Pt * pa, const HPGL_Pt * pb, int mv_flag)
1139 {
1140 double seg_len, dx, dy, quot;
1141 int n_pat, i;
1142
1143 dx = pb->x - pa->x;
1144 dy = pb->y - pa->y;
1145 seg_len = HYPOT(dx, dy);
1146
1147 switch (CurrentLineType) {
1148
1149 case LT_solid:
1150 if (seg_len < 1.e-8) {
1151 if (!silent_mode)
1152 Eprintf
1153 ("Warning: Zero line segment length -- skipped\n");
1154 return; /* No line to draw ?? */
1155 }
1156 PlotCmd_to_tmpfile(DRAW_TO);
1157 HPGL_Pt_to_tmpfile(pb);
1158 return;
1159
1160 case LT_adaptive:
1161 if (seg_len < 1.e-8) {
1162 if (!silent_mode)
1163 Eprintf
1164 ("Warning: Zero line segment length -- skipped\n");
1165 return; /* No line to draw ?? */
1166 }
1167 pat_pos = 0.0; /* Reset to start-of-pattern */
1168 n_pat =
1169 (int) ceil_with_tolerance(seg_len / CurrentLinePatLen,
1170 CurrentLinePatLen *
1171 LT_PATTERN_TOL);
1172 if (n_pat == 0) { /* sanity check for segment << pattern length */
1173 n_pat = 1;
1174 if (!silent_mode)
1175 fprintf(stderr,
1176 "very short pattern run encountered\n");
1177 }
1178 dx /= n_pat;
1179 dy /= n_pat;
1180 /* Now draw n_pat complete line patterns */
1181 for (i = 0; i < n_pat; i++)
1182 LPattern_Generator(pa, dx, dy, 0.0, 1.0);
1183 return;
1184
1185 case LT_plot_at:
1186 PlotCmd_to_tmpfile(PLOT_AT);
1187 HPGL_Pt_to_tmpfile(pb);
1188 return;
1189
1190 case LT_fixed:
1191 if (seg_len < 1.e-8) {
1192 if (!silent_mode)
1193 Eprintf
1194 ("Warning: Zero line segment length -- skipped\n");
1195 return; /* No line to draw ?? */
1196 }
1197 if (mv_flag) /* Last move ends old line pattern */
1198 pat_pos = 0.0;
1199 quot = seg_len / CurrentLinePatLen;
1200 dx /= quot;
1201 dy /= quot;
1202 while (quot >= 1.0) {
1203 LPattern_Generator(pa, dx, dy, pat_pos, 1.0);
1204 quot -= (1.0 - pat_pos);
1205 pat_pos = 0.0;
1206 }
1207 quot += pat_pos;
1208 if (quot >= 1.0) {
1209 LPattern_Generator(pa, dx, dy, pat_pos, 1.0);
1210 quot -= 1.0;
1211 pat_pos = 0.0;
1212 }
1213 if (quot > LT_PATTERN_TOL) {
1214 LPattern_Generator(pa, dx, dy, pat_pos, quot);
1215 pat_pos = quot;
1216 } else {
1217 PlotCmd_to_tmpfile(MOVE_TO);
1218 HPGL_Pt_to_tmpfile(pb);
1219 }
1220 return;
1221
1222 default:
1223 break;
1224 }
1225
1226 }
1227
1228
1229
1230
Pen_action_to_tmpfile(PlotCmd cmd,const HPGL_Pt * p,int scaled)1231 void Pen_action_to_tmpfile(PlotCmd cmd, const HPGL_Pt * p, int scaled)
1232 {
1233 static HPGL_Pt P_last;
1234 HPGL_Pt P;
1235 double tmp;
1236
1237 if (record_off) /* Wrong page! */
1238 return;
1239
1240 if (scaled) /* Rescaling */
1241 User_to_Plotter_coord(p, &P);
1242 else
1243 P = *p; /* Local copy */
1244
1245
1246 HP_pos = P; /* Actual plotter pos. in plotter coord */
1247 if (rotate_flag) { /* hp2xx-specific global rotation */
1248 tmp = rot_cos * P.x - rot_sin * P.y;
1249 P.y = rot_sin * P.x + rot_cos * P.y;
1250 P.x = tmp;
1251 }
1252
1253 /* Extreme values needed for later scaling: */
1254
1255 switch (cmd) {
1256 case MOVE_TO:
1257 mv_flag = TRUE;
1258 break;
1259
1260 /**
1261 ** Multiple-move suppression. In addition,
1262 ** a move only precedes a draw -- nothing else!
1263 **/
1264
1265 case DRAW_TO:
1266 if (mv_flag) {
1267 PlotCmd_to_tmpfile(MOVE_TO);
1268 HPGL_Pt_to_tmpfile(&P_last);
1269 }
1270 /* drop through */
1271 case PLOT_AT:
1272 Line_Generator(&P_last, &P, mv_flag);
1273 mv_flag = FALSE;
1274 break;
1275
1276 default:
1277 Eprintf("Illegal Pen Action: %d\n", cmd);
1278 Eprintf("Error @ Cmd %ld\n", vec_cntr_w);
1279 exit(ERROR);
1280 }
1281 P_last = P;
1282 }
1283
1284
1285
1286
1287
read_float(float * pnum,FILE * hd)1288 int read_float(float *pnum, FILE * hd)
1289 /**
1290 ** Main work-horse for parameter input:
1291 **
1292 ** Search for next number, skipping white space but return if mnemonic met.
1293 ** If found, read in number
1294 ** returns 0 if valid number
1295 ** 1 if command ended
1296 ** 2 if scanf failed (possibly corrupted file)
1297 ** EOF if EOF met
1298 **/
1299 {
1300 int c;
1301 char *ptr, numbuf[80];
1302
1303 for (c = getc(hd);
1304 (c != '.') && (c != '+') && (c != '-') && ((c < '0')
1305 || (c > '9'));
1306 c = getc(hd)) {
1307 if (c == EOF) /* Wait for number */
1308 return EOF; /* Should not happen */
1309 if (c == ';')
1310 return 1; /* Terminator reached */
1311 if (((c >= 'A') && (c <= 'Z')) ||
1312 ((c >= 'a') && (c <= 'a')) || (c == ESC)) {
1313 ungetc(c, hd);
1314 return 1; /* Next Mnemonic reached */
1315 }
1316 }
1317 /* Number found: Get it */
1318 ptr = numbuf;
1319 for (*ptr++ = c, c = getc(hd);
1320 ((c >= '0') && (c <= '9')) || (c == '.'); c = getc(hd))
1321 *ptr++ = c; /* Read number */
1322 *ptr = '\0';
1323 if (c != EOF)
1324 ungetc(c, hd);
1325
1326 if (sscanf(numbuf, "%f", pnum) != 1)
1327 return 11; /* Should never happen */
1328 return 0;
1329 }
1330
1331
1332
1333
read_string(char * buf,FILE * hd)1334 void read_string(char *buf, FILE * hd)
1335 {
1336 int c;
1337 unsigned int n;
1338
1339 for (n = 0, c = getc(hd); (c != EOF) && (c != StrTerm);
1340 c = getc(hd)) {
1341 if (n > strbufsize / 2) {
1342 strbufsize *= 2;
1343 strbuf = realloc(strbuf, strbufsize);
1344 if (strbuf == NULL) {
1345 fprintf(stderr, "\nNo memory !\n");
1346 exit(ERROR);
1347 }
1348 buf = strbuf + n;
1349 }
1350 if (c == '\0')
1351 continue; /* ignore \0 */
1352 if (n++ < strbufsize)
1353 *buf++ = c;
1354 }
1355 if (c != StrTerm || StrTermSilent == 0)
1356 *buf++ = c;
1357 *buf = '\0';
1358 }
1359
1360
1361
1362
read_symbol_char(FILE * hd)1363 static void read_symbol_char(FILE * hd)
1364 {
1365 int c;
1366
1367 for (c = getc(hd); /* ended by switch{} */ ; c = getc(hd))
1368 switch (c) {
1369 case ' ':
1370 case _HT:
1371 case _LF:
1372 break; /* Skip white space */
1373 case _CR:
1374 case EOF:
1375 case ';': /* CR or "term" end symbol mode */
1376 symbol_char = '\0';
1377 return;
1378 default:
1379 if (c < ' ' || c > '~')
1380 break; /* Ignore unprintable chars */
1381 else {
1382 symbol_char = c;
1383 return;
1384 }
1385 }
1386 }
1387
1388
1389
1390
read_ESC_HP7550A(FILE * hd)1391 static void read_ESC_HP7550A(FILE * hd)
1392 /*
1393 * Read & skip HP 7550A control commands (ESC.-Commands)
1394 */
1395 {
1396 int c;
1397
1398 switch (getc(hd)) {
1399 case EOF:
1400 n_unexpected++;
1401 Eprintf("\nUnexpected EOF!\n");
1402 return;
1403 break;
1404 case 'A':
1405 case 'B':
1406 case 'E':
1407 case 'J':
1408 case 'K':
1409 case 'L':
1410 case 'O':
1411 case 'U':
1412 case 'Y':
1413 case '(':
1414 case ')':
1415 return; /* Commands without parameters */
1416 case '@':
1417 case 'H':
1418 case 'I':
1419 case 'M':
1420 case 'N':
1421 case 'P':
1422 case 'Q':
1423 case 'S':
1424 case 'T':
1425 do { /* Search for terminator ':' */
1426 c = getc(hd);
1427 }
1428 while ((c != ':') && (c != EOF));
1429 if (c == EOF) {
1430 n_unexpected++;
1431 Eprintf("\nUnexpected EOF!\n");
1432 }
1433 return;
1434 default:
1435 n_unknown++;
1436 return;
1437 }
1438 }
1439
1440
read_PJL(FILE * hd)1441 static int read_PJL(FILE * hd)
1442 /*
1443 * a simple PJL parser
1444 * just reads PJL header and
1445 * return
1446 * TRUE if PJL enters HPGL context,
1447 * FALSE if not
1448 * *
1449 * PJL lines are like this:
1450 * @PJL[ command][ args][\r]\n
1451 * (however I've seen some wrong PJL files with \n\r )
1452 * @PJL must be uppercase, ther rest of string is not
1453 * case sensitive
1454 * The last line of a PJL header is like these:
1455 * @PJL ENTER LANGUAGE = HPGL2
1456 * @PJL EOJ [NAME = "something"]
1457 */
1458 {
1459 #define PJLBS 257
1460
1461 char strbuf[PJLBS];
1462 int i, j, ov, ctmp, qt, el = 0, nw = 0, rc = -2, nl = 0;
1463 for (;;) {
1464 /* read word */
1465 for (i = ov = qt = 0;; i++) {
1466 ctmp = getc(hd);
1467 if (ctmp == ESC) {
1468 while (ctmp != 'X')
1469 ctmp = getc(hd);
1470 ctmp = getc(hd);
1471 }
1472 if (PJLBS - 1 == i) {
1473 if (!silent_mode)
1474 Eprintf
1475 ("PJL buffer overflow, rest of token dropped\n");
1476 ov = 1;
1477 strbuf[i] = '\0';
1478 }
1479 if (!ov)
1480 strbuf[i] = (0 == nw
1481 || qt) ? ctmp : toupper(ctmp);
1482 if (EOF == ctmp) {
1483 if (!ov)
1484 strbuf[i] = 0;
1485 break;
1486 } else if ('=' == ctmp && 0 == i) {
1487 strbuf[i] = '=';
1488 strbuf[++i] = '\0';
1489 ctmp = ' ';
1490 break;
1491 } else if (strchr(" \t=", ctmp)) {
1492 if (!qt) {
1493 if (!ov)
1494 strbuf[i] = 0;
1495 break;
1496 }
1497 } else if ('\n' == ctmp || '\r' == ctmp) {
1498 if (!ov)
1499 strbuf[i] = 0;
1500 nl = 1;
1501 break;
1502 } else if ('"' == ctmp) {
1503 qt = !qt;
1504 }
1505 }
1506 /* handle word */
1507 if (i) {
1508 #ifdef DEBUG_ESC
1509 Eprintf("word %d: read %d bytes: '%s'\n", nw, i,
1510 strbuf);
1511 #endif
1512 if (0 == nw && strcmp(strbuf, "@PJL")) {
1513 Eprintf
1514 ("unexpected end of a PJL header!\n");
1515 return (TRUE);
1516 } else if (1 == nw && !strcmp(strbuf, "EOJ")) {
1517 if (!silent_mode)
1518 Eprintf("end of a PJL job\n");
1519 rc = TRUE;
1520 } else if (1 == nw && !strcmp(strbuf, "ENTER")) {
1521 el++;
1522 } else if (2 == nw && 1 == el
1523 && !strcmp(strbuf, "LANGUAGE")) {
1524 el++;
1525 } else if (3 == nw && 2 == el
1526 && !strcmp(strbuf, "=")) {
1527 el++;
1528 } else if (4 == nw && 3 == el) {
1529 if (!silent_mode)
1530 Eprintf("Entering %s context\n",
1531 strbuf);
1532 rc = strncmp(strbuf, "HPGL",
1533 4) ? FALSE : TRUE;
1534 }
1535 nw++;
1536 }
1537 /* read separator */
1538 for (j = 0; EOF != ctmp; j++) {
1539 if (!strchr(" \t\n\r", ctmp)) {
1540 ungetc(ctmp, hd);
1541 break;
1542 }
1543 ctmp = getc(hd);
1544 if ('\n' == ctmp) {
1545 nl = 1;
1546 }
1547 }
1548 #ifdef DEBUG_ESC
1549 if (j)
1550 Eprintf("separator: read %d bytes\n", j);
1551 #endif
1552
1553 if (nl) {
1554 nw = el = nl = 0;
1555 if (-2 != rc)
1556 return rc;
1557 }
1558 if (EOF == ctmp) {
1559 if (!silent_mode)
1560 Eprintf("EOF in PJL context\n");
1561 return (FALSE);
1562 }
1563 }
1564 }
1565
read_ESC_RTL(FILE * hd,int c1,int hp)1566 static void read_ESC_RTL(FILE * hd, int c1, int hp)
1567 /*
1568 *read and skip ESC% control commands
1569 */
1570 {
1571 /*
1572 * known escapes:
1573 * ESC%-12345X UEL (Universal Escape Language)
1574 * followed by @PJL..
1575 *
1576 * ESC%-1B Enter HPGL/2 context
1577 * ESC%0B -
1578 * ESC%1B -
1579 *
1580 * ESC%1A Exit HPGL/2 context
1581 * ESC%0A -
1582 * ESC%-1A -
1583
1584 * how a PCL escape looks like:
1585 * ESC, lowercase letters and digits, an Upper case letter
1586
1587 */
1588 int c0, c2, ctmp = 0, nf;
1589
1590 for (c0 = ESC, c2 = getc(hd), nf = 0;
1591 EOF != c2; c0 = c1, c1 = c2, c2 = getc(hd)) {
1592
1593 if ((ESC == c0) && (c1 == '%')) {
1594 if ('-' == c2) {
1595 c2 = getc(hd);
1596 nf = 1;
1597 }
1598 switch (c2) {
1599 case EOF:
1600 n_unexpected++;
1601 Eprintf("\nUnexpected EOF!\n");
1602 return;
1603 break;
1604 case '1':
1605 case '0':
1606 switch (ctmp = getc(hd)) {
1607 case 'A':
1608
1609 if (hp && !silent_mode) {
1610 #ifdef DEBUG_ESC
1611 Eprintf
1612 ("leaving HPGL context\n");
1613 #endif
1614 hp = FALSE;
1615 }
1616 continue;
1617 case 'B':
1618 #ifdef DEBUG_ESC
1619 if (!silent_mode && !hp)
1620 Eprintf
1621 ("entering HPGL context\n");
1622 #endif
1623 return;
1624 case '2':
1625 /* check for UEL */
1626 if (nf && '1' == c2 &&
1627 '3' == (c2 = getc(hd)) &&
1628 '4' == (c2 = getc(hd)) &&
1629 '5' == (c2 = getc(hd))
1630 && 'X' == (c2 = getc(hd))) {
1631 #ifdef DEBUG_ESC
1632 if (!silent_mode)
1633 Eprintf
1634 ("UEL found\n");
1635 #endif
1636 if (read_PJL(hd)) {
1637 return;
1638 } else {
1639 hp = 0;
1640 continue;
1641 }
1642 } else {
1643 ungetc(ctmp, hd);
1644 if (hp)
1645 return;
1646 }
1647 break;
1648 default:
1649 if (!silent_mode)
1650 Eprintf
1651 ("unknown escape: ESC%%%s%c%c\n",
1652 nf ? "-" : "", c2,
1653 ctmp);
1654 ungetc(ctmp, hd);
1655 if (hp)
1656 return;
1657 }
1658 break;
1659 default:
1660 if (!silent_mode)
1661 Eprintf
1662 ("unknown escape: ESC%%%s%c",
1663 nf ? "-" : "", c2);
1664 ungetc(ctmp, hd);
1665 if (hp)
1666 return;
1667 break;
1668 }
1669 }
1670 if (hp == TRUE && !nf && c1 != '%' && c1 != 'E') {
1671 ungetc(ctmp, hd);
1672 if (!silent_mode)
1673 Eprintf("invalid escape ESC%c%c\n", c1,
1674 c2);
1675 return;
1676 }
1677 }
1678 }
1679
read_ESC_cmd(FILE * hd,int hp)1680 static void read_ESC_cmd(FILE * hd, int hp)
1681 /*
1682 * Read & skip device control commands (ESC.-Commands)
1683
1684 */
1685 {
1686 int ctmp;
1687 switch (ctmp = getc(hd)) {
1688 case '.':
1689 read_ESC_HP7550A(hd);
1690 break;
1691 case EOF:
1692 n_unexpected++;
1693 Eprintf("\nUnexpected EOF!\n");
1694 return;
1695 default:
1696 read_ESC_RTL(hd, ctmp, hp);
1697 break;
1698 }
1699 }
1700
1701
1702
1703 /****************************************************************************/
1704
1705
1706
1707 /**
1708 ** lines: Process PA-, PR-, PU-, and PD- commands
1709 **/
lines(int relative,FILE * hd)1710 static void lines(int relative, FILE * hd)
1711 /**
1712 ** Examples of anticipated commands:
1713 **
1714 ** PA PD0,0,80,50,90,20PU140,30PD150,80;
1715 ** PU0,0;PD20.53,40.32,30.08,60.2,40,90,;PU100,300;PD120,340...
1716 **/
1717 {
1718 HPGL_Pt p;
1719 int numcmds = 0;
1720 int outside = 0;
1721 double p1x, p1y, p2x, p2y;
1722
1723 for (;;) {
1724 if (read_float(&p.x, hd)) { /* No number found */
1725 if (numcmds > 0)
1726 return;
1727 if (pen_down && mv_flag && pen > 0 && pt.width[pen] < 0.35) { /*simulate dot created by 'real' pen on PD;PU; */
1728 /*but not on PDPA */
1729 p.x = p_last.x + 0.01;
1730 p.y = p_last.y + 0.01;
1731 outside = 0;
1732 if (iwflag) {
1733 p1x =
1734 P1.x + (p_last.x - S1.x) * Q.x;
1735 p1y =
1736 P1.y + (p_last.y - S1.y) * Q.y;
1737 p2x = P1.x + (p.x - S1.x) * Q.x;
1738 p2y = P1.y + (p.y - S1.y) * Q.y;
1739
1740 outside =
1741 (DtClipLine
1742 (C1.x, C1.y, C2.x, C2.y, &p1x,
1743 &p1y, &p2x,
1744 &p2y) == CLIP_NODRAW);
1745 }
1746 if (!outside) {
1747 Pen_action_to_tmpfile(MOVE_TO, &p,
1748 scale_flag);
1749 Pen_action_to_tmpfile(DRAW_TO,
1750 &p_last,
1751 scale_flag);
1752 }
1753 }
1754 return;
1755 }
1756
1757 if (read_float(&p.y, hd)) /* x without y invalid! */
1758 par_err_exit(2, PA, hd);
1759 line(relative, p);
1760 numcmds++;
1761 }
1762 }
1763
1764
1765 /*
1766 * line : process a pair of coordinates
1767 */
line(int relative,HPGL_Pt p)1768 void line(int relative, HPGL_Pt p)
1769 {
1770 HPGL_Pt pl, porig;
1771 int outside = 0;
1772 double x1, y1, x2, y2;
1773
1774 if (relative) {
1775 p.x += p_last.x;
1776 p.y += p_last.y;
1777 }
1778
1779 porig.x = p.x;
1780 porig.y = p.y;
1781
1782 if (iwflag) {
1783 x1 = P1.x + (p_last.x - S1.x) * Q.x;
1784 y1 = P1.y + (p_last.y - S1.y) * Q.y;
1785 x2 = P1.x + (p.x - S1.x) * Q.x;
1786 y2 = P1.y + (p.y - S1.y) * Q.y;
1787
1788 outside =
1789 (DtClipLine(C1.x, C1.y, C2.x, C2.y, &x1, &y1, &x2, &y2)
1790 == CLIP_NODRAW);
1791
1792 if (!outside) {
1793 p.x = (x2 - P1.x) / Q.x + S1.x;
1794 p.y = (y2 - P1.y) / Q.y + S1.y;
1795 pl.x = (x1 - P1.x) / Q.x + S1.x;
1796 pl.y = (y1 - P1.y) / Q.y + S1.y;
1797 if (pl.x != p_last.x || pl.y != p_last.y)
1798 Pen_action_to_tmpfile(MOVE_TO, &pl,
1799 scale_flag);
1800
1801 }
1802
1803 } else
1804 pl = p_last;
1805
1806 if (polygon_mode && polygon_penup)
1807 pen_down = FALSE;
1808
1809 if (pen_down && !outside) {
1810 if (polygon_mode) {
1811 HPGL_Pt_to_polygon(pl);
1812 HPGL_Pt_to_polygon(p);
1813 /* fprintf(stderr,"polygon line1: %f %f - %f %f\n",p_last.x,p_last.y,p.x,p.y);*/
1814 } else {
1815 Pen_action_to_tmpfile(DRAW_TO, &p, scale_flag);
1816 /* fprintf(stderr,"std line1: %f %f - %f %f\n",p_last.x,p_last.y,p.x,p.y); */
1817 }
1818 } else {
1819 if (iwflag) {
1820 Pen_action_to_tmpfile(MOVE_TO, &porig, scale_flag);
1821 } else {
1822 Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag);
1823 }
1824 }
1825
1826 if (polygon_mode && polygon_penup) {
1827 polygon_penup = FALSE;
1828 polystart = p;
1829 pen_down = TRUE;
1830 }
1831
1832
1833 if (symbol_char) {
1834 plot_symbol_char(symbol_char);
1835 Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag);
1836 }
1837 outside = 0;
1838 p_last = porig;
1839
1840 }
1841
1842
1843 /**
1844 ** Arcs, circles and alike
1845 **/
1846
1847
arc_increment(HPGL_Pt * pcenter,double r,double phi)1848 static void arc_increment(HPGL_Pt * pcenter, double r, double phi)
1849 {
1850 HPGL_Pt p;
1851 int outside = 0;
1852 p.x = pcenter->x + r * cos(phi);
1853 p.y = pcenter->y + r * sin(phi);
1854
1855 if (iwflag) {
1856 if (P1.x + (p.x - S1.x) * Q.x > C2.x
1857 || P1.y + (p.y - S1.y) * Q.y > C2.y) {
1858 /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */
1859 outside = 1;
1860 }
1861 if (P1.x + (p.x - S1.x) * Q.x < C1.x
1862 || P1.y + (p.y - S1.y) * Q.y < C1.y) {
1863 /*fprintf(stderr,"IW set:point %f %f <P1\n",p.x,p.y); */
1864 outside = 1;
1865 }
1866 }
1867
1868 if (polygon_mode) {
1869 if (polygon_penup)
1870 polygon_penup = FALSE;
1871 else if (pen_down && !outside) {
1872 HPGL_Pt_to_polygon(p_last);
1873 HPGL_Pt_to_polygon(p);
1874 /*fprintf(stderr,"arcpoint %f %f\n",p.x,p.y);*/
1875
1876 } else if ((p.x != p_last.x) || (p.y != p_last.y)) {
1877 /*polygon_penup=TRUE; */
1878 HPGL_Pt_to_polygon(p_last);
1879 HPGL_Pt_to_polygon(p);
1880 /*fprintf(stderr,"final arcpoint %f %f\n",p.x,p.y);*/
1881 }
1882 } else {
1883 if (pen_down && !outside)
1884 Pen_action_to_tmpfile(DRAW_TO, &p, scale_flag);
1885 else if (!outside
1886 && ((p.x != p_last.x) || (p.y != p_last.y)))
1887 Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag);
1888 }
1889 p_last = p;
1890 }
1891
bezier(int relative,FILE * hd)1892 static void bezier(int relative, FILE * hd)
1893 {
1894 HPGL_Pt p, p1, p2, p3, polyp;
1895 int i, outside;
1896 float t;
1897 /* double SafeLinePatLen = CurrentLinePatLen;*/
1898
1899 for (;;) { /* parameter set may contain several bezier curves */
1900 if (read_float(&p1.x, hd)) /* No number found */
1901 return;
1902
1903 if (read_float(&p1.y, hd)) /* x without y invalid! */
1904 par_err_exit(2, BZ, hd);
1905
1906 if (read_float(&p2.x, hd)) /* No number found */
1907 return;
1908
1909 if (read_float(&p2.y, hd)) /* x without y invalid! */
1910 par_err_exit(2, BZ, hd);
1911
1912 if (read_float(&p3.x, hd)) /* No endpoint */
1913 par_err_exit(3, BZ, hd);
1914
1915 if (read_float(&p3.y, hd)) /* No endpoint */
1916 par_err_exit(3, BZ, hd);
1917
1918 if (relative) { /* Transform coordinates */
1919 p1.x = p1.x + p_last.x;
1920 p1.y = p1.y + p_last.y;
1921 p2.x = p2.x + p_last.x;
1922 p2.y = p2.y + p_last.y;
1923 p3.x = p3.x + p_last.x;
1924 p3.y = p3.y + p_last.y;
1925 }
1926
1927 /*
1928 p(t) = t^3*P3 + 3*t^2*(1-t)*P2 + 3*t*(1-t)^2* P1 + (1-t)^3 * P0
1929 */
1930
1931 polyp = p_last;
1932 outside = 0;
1933
1934 for (i = 0; i < 51; i++) {
1935 t = (float) i / 50.;
1936 p.x =
1937 t * t * t * p3.x + 3 * t * t * (1. -
1938 t) * p2.x +
1939 3 * t * (1. - t) * (1. - t) * p1.x + (1. -
1940 t) *
1941 (1. - t) * (1. - t) * p_last.x;
1942 p.y =
1943 t * t * t * p3.y + 3 * t * t * (1. -
1944 t) * p2.y +
1945 3 * t * (1. - t) * (1. - t) * p1.y + (1. -
1946 t) *
1947 (1. - t) * (1. - t) * p_last.y;
1948
1949 /*fprintf(stderr,"bezier point %f %f\n",p.x,p.y);*/
1950 if (iwflag) {
1951 if (P1.x + (p.x - S1.x) * Q.x > C2.x
1952 || P1.y + (p.y - S1.y) * Q.y > C2.y) {
1953 /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */
1954 outside = 1;
1955 }
1956 if (P1.x + (p.x - S1.x) * Q.x < C1.x
1957 || P1.y + (p.y - S1.y) * Q.y < C1.y) {
1958 /*fprintf(stderr,"IW set:point %f %f <P1\n",p.x,p.y); */
1959 outside = 1;
1960 }
1961 }
1962
1963 if (!outside) {
1964 if (polygon_mode) {
1965 HPGL_Pt_to_polygon(polyp);
1966 HPGL_Pt_to_polygon(p);
1967 polyp.x = p.x;
1968 polyp.y = p.y;
1969 } else {
1970 Pen_action_to_tmpfile(DRAW_TO, &p,
1971 scale_flag);
1972 }
1973 } else
1974 Pen_action_to_tmpfile(MOVE_TO, &p,
1975 scale_flag);
1976 outside = 0;
1977 }
1978
1979 p_last.x = p3.x;
1980 p_last.y = p3.y;
1981
1982 }
1983 }
1984
tarcs(int relative,FILE * hd)1985 static void tarcs(int relative, FILE * hd)
1986 {
1987 HPGL_Pt p, p2, p3, center, d;
1988 float alpha, eps;
1989 double phi, phi0, r;
1990 double SafeLinePatLen = CurrentLinePatLen;
1991
1992 if (read_float(&p2.x, hd)) /* No number found */
1993 return;
1994
1995 if (read_float(&p2.y, hd)) /* x without y invalid! */
1996 par_err_exit(2, AT, hd);
1997
1998 if (read_float(&p3.x, hd)) /* No endpoint */
1999 par_err_exit(3, AT, hd);
2000
2001 if (read_float(&p3.y, hd)) /* No endpoint */
2002 par_err_exit(3, AT, hd);
2003
2004 switch (read_float(&eps, hd)) { /* chord angle is optional */
2005 case 0:
2006 if (eps < 0.5)
2007 eps = 0.5;
2008 break;
2009 case 1: /* No resolution option */
2010 eps = 5.0; /* so use default! */
2011 break;
2012 case 2: /* Illegal state */
2013 par_err_exit(98, AT, hd);
2014 case EOF:
2015 return;
2016 default: /* Illegal state */
2017 par_err_exit(99, AT, hd);
2018 }
2019 if (ct_dist == FALSE)
2020 eps *= M_PI / 180.0; /* Deg-to-Rad */
2021
2022 d = p_last;
2023
2024 if (!relative) { /* Transform coordinates */
2025 p2.x = p2.x - p_last.x;
2026 p2.y = p2.y - p_last.y;
2027 p3.x = p3.x - p_last.x;
2028 p3.y = p3.y - p_last.y;
2029 }
2030
2031 /*
2032 2*p2.x*h+2*p2.y*k = p2.x^2 + p2.y^2
2033
2034 k= (p2.x^2 + p2.y^2 - 2*p2.x*h) /2*p2.y
2035
2036 2*p3.x*h+2*p3.y*k = p3.x^2 + p3.y^2
2037
2038
2039 2* p3.x*h +2*p3.y * (p2.x^2 + p2.y^2 -2*p2.x*h) / 2*p2.y = (p3.x^2 + p3.y^2)
2040 2* p3.x*h +2*p3.y * (p2.x^2 + p2.y^2 -2*p2.x*h) = (p3.x^2 + p3.y^2) *2*p2.y
2041
2042 2*p3.x*h + 2*p3.y*p2.x^2 + 2*p3.y*p2.y^2 - 4*p2.x*p3.y*h =...
2043 (2*p3.x-4*p2.y*p3.y)*h + 2*p3.y*p2.x^2 + 2*p3.y*p2.y^2 = ...
2044 h = ( 2*p2.y*(p2.x^2 + p2.y^2) -2*p3.y*p2.x^2 - 2*p3.y*p2.y^2 ) / 2*p3.x-4*p2.x*p3.y
2045 */
2046 center.x =
2047 (2. * p2.y * (p3.x * p3.x + p3.y * p3.y) -
2048 2. * p3.y * p2.x * p2.x -
2049 2. * p3.y * p2.y * p2.y) / (2. * p3.x - 4. * p2.x * p3.y);
2050 center.y =
2051 (p2.x * p2.x + p2.y * p2.y -
2052 2. * p2.x * center.x) / (2. * p2.y);
2053
2054 r = sqrt(center.x * center.x + center.y * center.y);
2055
2056 if (ct_dist == TRUE)
2057 eps = 2. * acos((r - eps) / r);
2058 center.x = center.x + p_last.x;
2059 center.y = center.y + p_last.y;
2060
2061
2062 d.x = p_last.x - center.x;
2063 d.y = p_last.y - center.y;
2064
2065 phi0 = atan2(d.y, d.x);
2066
2067 d.x = p3.x + p_last.x - center.x;
2068 d.y = p3.y + p_last.y - center.y;
2069
2070 alpha = 2. * atan2(d.y, d.x);
2071 /*
2072 fprintf(stderr,"AT: P1 at %f %f , P2 %f %f, P3 %f %f, center %f %f radius %f\n",
2073 p_last.x,p_last.y,p2.x+p_last.x,p2.y+p_last.y,p3.x+p_last.x,p3.y+p_last.y,
2074 center.x,center.y,r);
2075 */
2076 if (CurrentLineType == LT_adaptive) { /* Adaptive patterns: */
2077 p.x = r * cos(eps); /* A chord segment */
2078 p.y = r * sin(eps);
2079 if (scale_flag)
2080 User_to_Plotter_coord(&p, &p);
2081
2082 /* Pattern length = chord length */
2083 CurrentLinePatLen = HYPOT(p.x, p.y);
2084 }
2085
2086 if (alpha > 0.0) {
2087 for (phi = phi0 + MIN(eps, alpha); phi < phi0 + alpha;
2088 phi += eps)
2089 arc_increment(¢er, r, phi);
2090 arc_increment(¢er, r, phi0 + alpha); /* to endpoint */
2091 } else {
2092 for (phi = phi0 - MIN(eps, -alpha); phi > phi0 + alpha;
2093 phi -= eps)
2094 arc_increment(¢er, r, phi);
2095 arc_increment(¢er, r, phi0 + alpha); /* to endpoint */
2096 }
2097
2098 CurrentLinePatLen = SafeLinePatLen; /* Restore */
2099
2100 p_last.x = p_last.x + p3.x;
2101 p_last.y = p_last.y + p3.y;
2102
2103 }
2104
arcs(int relative,FILE * hd)2105 static void arcs(int relative, FILE * hd)
2106 {
2107 HPGL_Pt p, d, center;
2108 float alpha, eps;
2109 double phi, phi0, r;
2110 double SafeLinePatLen = CurrentLinePatLen;
2111
2112 if (read_float(&p.x, hd)) /* No number found */
2113 return;
2114
2115 if (read_float(&p.y, hd)) /* x without y invalid! */
2116 par_err_exit(2, AA, hd);
2117
2118 if (read_float(&alpha, hd)) /* Invalid without angle */
2119 par_err_exit(3, AA, hd);
2120 else
2121 alpha *= M_PI / 180.0; /* Deg-to-Rad */
2122
2123 switch (read_float(&eps, hd)) {
2124 case 0:
2125 if (eps < 0.5)
2126 eps = 0.5;
2127 break;
2128 case 1: /* No resolution option */
2129 eps = 5.0; /* so use default! */
2130 break;
2131 case 2: /* Illegal state */
2132 par_err_exit(98, AA, hd);
2133 case EOF:
2134 return;
2135 default: /* Illegal state */
2136 par_err_exit(99, AA, hd);
2137 }
2138
2139 if (ct_dist == FALSE)
2140 eps *= M_PI / 180.0; /* Deg-to-Rad */
2141
2142 if (relative) { /* Process coordinates */
2143 d = p; /* Difference vector */
2144 center.x = d.x + p_last.x;
2145 center.y = d.y + p_last.y;
2146 } else {
2147 d.x = p.x - p_last.x;
2148 d.y = p.y - p_last.y;
2149 center.x = p.x;
2150 center.y = p.y;
2151 }
2152
2153 if (((r = sqrt(d.x * d.x + d.y * d.y)) == 0.0) || (alpha == 0.0))
2154 return; /* Zero radius or zero arc angle given */
2155
2156 if (ct_dist == TRUE)
2157 eps = 2. * acos((r - eps) / r);
2158
2159 phi0 = atan2(-d.y, -d.x);
2160
2161 if (CurrentLineType == LT_adaptive) { /* Adaptive patterns: */
2162 p.x = r * cos(eps); /* A chord segment */
2163 p.y = r * sin(eps);
2164 if (scale_flag)
2165 User_to_Plotter_coord(&p, &p);
2166
2167 /* Pattern length = chord length */
2168 CurrentLinePatLen = HYPOT(p.x, p.y);
2169 }
2170
2171 if (alpha > 0.0) {
2172 for (phi = phi0 + MIN(eps, alpha); phi < phi0 + alpha;
2173 phi += eps)
2174 arc_increment(¢er, r, phi);
2175 arc_increment(¢er, r, phi0 + alpha); /* to endpoint */
2176 } else {
2177 for (phi = phi0 - MIN(eps, -alpha); phi > phi0 + alpha;
2178 phi -= eps)
2179 arc_increment(¢er, r, phi);
2180 arc_increment(¢er, r, phi0 + alpha); /* to endpoint */
2181 }
2182 CurrentLinePatLen = SafeLinePatLen; /* Restore */
2183 }
2184
fwedges(FILE * hd,float cur_pensize)2185 static void fwedges(FILE * hd, float cur_pensize)
2186 { /*derived from circles */
2187 HPGL_Pt p, oldp, center;
2188 float eps, r, start, sweep;
2189 double phi;
2190 double SafeLinePatLen = CurrentLinePatLen;
2191 int outside = 0;
2192 int i;
2193
2194 if (read_float(&r, hd)) /* No radius found */
2195 return;
2196 if (read_float(&start, hd)) /* No start angle found */
2197 return;
2198
2199 if (read_float(&sweep, hd)) /* No sweep angle found */
2200 return;
2201
2202 switch (read_float(&eps, hd)) { /* chord angle */
2203 case 0:
2204 if (eps < 0.5)
2205 eps = 0.5;
2206 break;
2207 case 1: /* No resolution option */
2208 eps = 5.0; /* so use default! */
2209 break;
2210 case 2: /* Illegal state */
2211 par_err_exit(98, EW, hd);
2212 case EOF:
2213 return;
2214 default: /* Illegal state */
2215 par_err_exit(99, EW, hd);
2216 }
2217
2218 if (ct_dist == TRUE)
2219 eps = 2. * acos((r - eps) / r);
2220 else
2221 eps *= M_PI / 180.0; /* Deg-to-Rad */
2222 start *= M_PI / 180.0; /* Deg-to-Rad */
2223 sweep *= M_PI / 180.0; /* Deg-to-Rad */
2224
2225
2226 center = p_last; /* reference point is last position */
2227 vertices = -1; /* clear the polygon buffer */
2228 if (r == 0.0) /* Zero radius given */
2229 return;
2230
2231 HPGL_Pt_to_polygon(p_last);
2232 p.x = center.x + r * cos(start);
2233 p.y = center.y + r * sin(start);
2234 HPGL_Pt_to_polygon(p);
2235
2236
2237 if (CurrentLineType == LT_adaptive) { /* Adaptive patterns */
2238 p.x = r * cos(eps); /* A chord segment */
2239 p.y = r * sin(eps);
2240 if (scale_flag)
2241 User_to_Plotter_coord(&p, &p);
2242
2243 /* Pattern length = chord length */
2244 CurrentLinePatLen = HYPOT(p.x, p.y);
2245 }
2246 i = 1;
2247 for (phi = eps; phi <= sweep; phi += eps) {
2248 oldp = p;
2249 p.x = center.x + r * cos(start + phi);
2250 p.y = center.y + r * sin(start + phi);
2251 if (iwflag) {
2252 if (P1.x + (p.x - S1.x) * Q.x > C2.x
2253 || P1.y + (p.y - S1.y) * Q.y > C2.y) {
2254 /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */
2255 outside = 1;
2256 }
2257 if (P1.x + (p.x - S1.x) * Q.x < C1.x
2258 || P1.y + (p.y - S1.y) * Q.y < C1.y) {
2259 /*fprintf(stderr,"IW set:point %f %f <P1\n",p.x,p.y); */
2260 outside = 1;
2261 }
2262 }
2263 if (!outside) {
2264 HPGL_Pt_to_polygon(oldp);
2265 HPGL_Pt_to_polygon(p);
2266 }
2267 outside = 0;
2268 }
2269 HPGL_Pt_to_polygon(p);
2270 HPGL_Pt_to_polygon(center);
2271 if (hatchspace == 0.)
2272 hatchspace = cur_pensize;
2273 if (filltype < 3 && thickness > 0.)
2274 hatchspace = thickness;
2275 if (!ac_flag) { /* not yet initialized */
2276 anchor.x = P1.x;
2277 anchor.y = P1.y;
2278 }
2279 fill(polygons, vertices, anchor, P2, scale_flag, filltype,
2280 hatchspace, hatchangle);
2281
2282
2283 CurrentLinePatLen = SafeLinePatLen; /* Restore */
2284
2285 }
2286
2287
2288
circles(FILE * hd)2289 static void circles(FILE * hd)
2290 {
2291 HPGL_Pt p, center, polyp;
2292 float eps, r;
2293 double phi;
2294 double SafeLinePatLen = CurrentLinePatLen;
2295 int outside = 0;
2296
2297 if (read_float(&r, hd)) /* No radius found */
2298 return;
2299
2300 switch (read_float(&eps, hd)) {
2301 case 0:
2302 if (eps < 0.5)
2303 eps = 0.5;
2304 break;
2305 case 1: /* No resolution option */
2306 eps = 5.0; /* so use default! */
2307 break;
2308 case 2: /* Illegal state */
2309 par_err_exit(98, CI, hd);
2310 case EOF:
2311 return;
2312 default: /* Illegal state */
2313 par_err_exit(99, CI, hd);
2314 }
2315
2316 if (ct_dist == TRUE)
2317 eps = 2. * acos((r - eps) / r);
2318 else
2319 eps *= M_PI / 180.0; /* Deg-to-Rad */
2320
2321
2322 center = p_last;
2323
2324 if (r == 0.0) /* Zero radius given */
2325 return;
2326
2327 p.x = center.x + r;
2328 p.y = center.y;
2329 Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag);
2330 if (polygon_mode) {
2331 polyp.x = p.x;
2332 polyp.y = p.y;
2333 }
2334 if (CurrentLineType == LT_adaptive) { /* Adaptive patterns */
2335 p.x = r * cos(eps); /* A chord segment */
2336 p.y = r * sin(eps);
2337 if (scale_flag)
2338 User_to_Plotter_coord(&p, &p);
2339
2340 /* Pattern length = chord length */
2341 CurrentLinePatLen = HYPOT(p.x, p.y);
2342 }
2343
2344 for (phi = eps; phi < 2.0 * M_PI; phi += eps) {
2345 p.x = center.x + r * cos(phi);
2346 p.y = center.y + r * sin(phi);
2347 if (iwflag) {
2348 if (P1.x + (p.x - S1.x) * Q.x > C2.x
2349 || P1.y + (p.y - S1.y) * Q.y > C2.y) {
2350 /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */
2351 outside = 1;
2352 }
2353 if (P1.x + (p.x - S1.x) * Q.x < C1.x
2354 || P1.y + (p.y - S1.y) * Q.y < C1.y) {
2355 /*fprintf(stderr,"IW set:point %f %f <P1\n",p.x,p.y); */
2356 outside = 1;
2357 }
2358 }
2359
2360 if (!outside) {
2361 if (polygon_mode) {
2362 HPGL_Pt_to_polygon(polyp);
2363 HPGL_Pt_to_polygon(p);
2364 polyp.x = p.x;
2365 polyp.y = p.y;
2366 } else {
2367 Pen_action_to_tmpfile(DRAW_TO, &p,
2368 scale_flag);
2369 }
2370 } else
2371 Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag);
2372 outside = 0;
2373 }
2374 p.x = center.x + r; /* Close circle at r * (1, 0) */
2375 p.y = center.y;
2376 if (polygon_mode) {
2377 HPGL_Pt_to_polygon(polyp);
2378 HPGL_Pt_to_polygon(p);
2379 } else
2380 Pen_action_to_tmpfile(DRAW_TO, &p, scale_flag);
2381
2382 if (!polygon_mode) {
2383 /* draw one overlapping segment to avoid leaving gap with wide pens */
2384 p.x = center.x + r * cos(eps);
2385 p.y = center.y + r * sin(eps);
2386 if (iwflag) {
2387 if (P1.x + (p.x - S1.x) * Q.x > C2.x
2388 || P1.y + (p.y - S1.y) * Q.y > C2.y) {
2389 /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */
2390 outside = 1;
2391 }
2392 if (P1.x + (p.x - S1.x) * Q.x < C1.x
2393 || P1.y + (p.y - S1.y) * Q.y < C1.y) {
2394 /*fprintf(stderr,"IW set:point %f %f <P1\n",p.x,p.y); */
2395 outside = 1;
2396 }
2397 }
2398
2399 if (!outside) {
2400 if (polygon_mode) {
2401 HPGL_Pt_to_polygon(polyp);
2402 HPGL_Pt_to_polygon(p);
2403 polyp.x = p.x;
2404 polyp.y = p.y;
2405 } else {
2406 Pen_action_to_tmpfile(DRAW_TO, &p,
2407 scale_flag);
2408 }
2409 }
2410 }
2411 Pen_action_to_tmpfile(MOVE_TO, ¢er, scale_flag);
2412
2413 CurrentLinePatLen = SafeLinePatLen; /* Restore */
2414 }
2415
wedges(FILE * hd)2416 static void wedges(FILE * hd)
2417 { /*derived from circles */
2418 HPGL_Pt p, center;
2419 float eps, r, start, sweep;
2420 double phi;
2421 double SafeLinePatLen = CurrentLinePatLen;
2422 int outside = 0;
2423
2424 if (read_float(&r, hd)) /* No radius found */
2425 return;
2426
2427 if (read_float(&start, hd)) /* No start angle found */
2428 return;
2429
2430 if (read_float(&sweep, hd)) /* No sweep angle found */
2431 return;
2432
2433 switch (read_float(&eps, hd)) { /* chord angle */
2434 case 0:
2435 if (eps < 0.5)
2436 eps = 0.5;
2437 break;
2438 case 1: /* No resolution option */
2439 eps = 5.0; /* so use default! */
2440 break;
2441 case 2: /* Illegal state */
2442 par_err_exit(98, EW, hd);
2443 case EOF:
2444 return;
2445 default: /* Illegal state */
2446 par_err_exit(99, EW, hd);
2447 }
2448
2449 if (ct_dist == TRUE)
2450 eps = 2. * acos((r - eps) / r);
2451 else
2452 eps *= M_PI / 180.0; /* Deg-to-Rad */
2453 start *= M_PI / 180.0; /* Deg-to-Rad */
2454 sweep *= M_PI / 180.0; /* Deg-to-Rad */
2455
2456
2457 center = p_last; /* reference point is last position */
2458
2459 if (r == 0.0) /* Zero radius given */
2460 return;
2461
2462 p.x = center.x + r * cos(start);
2463 p.y = center.y + r * sin(start);
2464 Pen_action_to_tmpfile(DRAW_TO, &p, scale_flag);
2465
2466 if (CurrentLineType == LT_adaptive) { /* Adaptive patterns */
2467 p.x = r * cos(eps); /* A chord segment */
2468 p.y = r * sin(eps);
2469 if (scale_flag)
2470 User_to_Plotter_coord(&p, &p);
2471
2472 /* Pattern length = chord length */
2473 CurrentLinePatLen = HYPOT(p.x, p.y);
2474 }
2475
2476 for (phi = eps; phi <= sweep; phi += eps) {
2477 p.x = center.x + r * cos(start + phi);
2478 p.y = center.y + r * sin(start + phi);
2479 if (iwflag) {
2480 if (P1.x + (p.x - S1.x) * Q.x > C2.x
2481 || P1.y + (p.y - S1.y) * Q.y > C2.y) {
2482 /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */
2483 outside = 1;
2484 }
2485 if (P1.x + (p.x - S1.x) * Q.x < C1.x
2486 || P1.y + (p.y - S1.y) * Q.y < C1.y) {
2487 /*fprintf(stderr,"IW set:point %f %f <P1\n",p.x,p.y); */
2488 outside = 1;
2489 }
2490 }
2491 if (!outside)
2492 Pen_action_to_tmpfile(DRAW_TO, &p, scale_flag);
2493 else
2494 Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag);
2495 outside = 0;
2496 }
2497
2498 Pen_action_to_tmpfile(DRAW_TO, ¢er, scale_flag);
2499
2500 CurrentLinePatLen = SafeLinePatLen; /* Restore */
2501 }
2502
2503
2504
ax_ticks(int mode)2505 static void ax_ticks(int mode)
2506 {
2507 HPGL_Pt p0, p1, p2;
2508 LineType SafeLineType = CurrentLineType;
2509
2510 p0 = p1 = p2 = p_last;
2511 /**
2512 ** According to the HP-GL manual,
2513 ** XT & YT are not affected by LT
2514 **/
2515 CurrentLineType = LT_solid;
2516
2517 if (mode == 0) { /* X tick */
2518 if (scale_flag) {
2519 p1.y -= neg_ticklen * (P2.y - P1.y) / Q.y;
2520 p2.y += pos_ticklen * (P2.y - P1.y) / Q.y;
2521 } else {
2522 p1.y -= neg_ticklen * (P2.y - P1.y);
2523 p2.y += pos_ticklen * (P2.y - P1.y);
2524 }
2525 } else
2526 /* Y tick */
2527 {
2528 if (scale_flag) {
2529 p1.x -= neg_ticklen * (P2.x - P1.x) / Q.x;
2530 p2.x += pos_ticklen * (P2.x - P1.x) / Q.x;
2531 } else {
2532 p1.x -= neg_ticklen * (P2.x - P1.x);
2533 p2.x += pos_ticklen * (P2.x - P1.x);
2534 }
2535 }
2536
2537 Pen_action_to_tmpfile(MOVE_TO, &p1, scale_flag);
2538 Pen_action_to_tmpfile(DRAW_TO, &p2, scale_flag);
2539 Pen_action_to_tmpfile(MOVE_TO, &p0, scale_flag);
2540
2541 CurrentLineType = SafeLineType;
2542 }
2543
2544
2545
2546 /**
2547 ** Process a single HPGL command
2548 **/
2549
read_HPGL_cmd(GEN_PAR * pg,int cmd,FILE * hd)2550 static void read_HPGL_cmd(GEN_PAR * pg, int cmd, FILE * hd)
2551 {
2552 short old_pen;
2553 HPGL_Pt p1 = { 0., 0. }, p2 = {
2554 0., 0.};
2555 float ftmp;
2556 float csfont;
2557 int mypen, myred, mygreen, myblue, i;
2558 float mywidth, myheight;
2559 char tmpstr[1024];
2560 char SafeTerm;
2561 static int FoundUserFill = 0;
2562 /**
2563 ** Each command consists of 2 characters. We unite them here to a single int
2564 ** to allow for easy processing within a big switch statement:
2565 **/
2566
2567 switch (cmd & 0xDFDF) { /* & forces to upper case */
2568 /**
2569 ** Commands appear in alphabetical order within each topic group
2570 ** except for command synonyms.
2571 **/
2572 case AA: /* Arc Absolute */
2573 arcs(FALSE, hd);
2574 tp->CR_point = HP_pos;
2575 break;
2576 case AR: /* Arc Relative */
2577 arcs(TRUE, hd);
2578 tp->CR_point = HP_pos;
2579 break;
2580 case AT: /* Arc Absolute, through Three points */
2581 tarcs(FALSE, hd);
2582 break;
2583 case BR: /* cubic bezier curve, relative control points */
2584 bezier(TRUE, hd);
2585 break;
2586 case BZ: /* cubic bezier curve, absolute control points */
2587 bezier(FALSE, hd);
2588 break;
2589 case AC: /* anchor corner of fill patterns */
2590 if (read_float(&ftmp, hd)) { /* just AC - default hard-clip limit */
2591 anchor.x = P1.x;
2592 anchor.y = P1.y;
2593 if (scale_flag)
2594 User_to_Plotter_coord(&anchor, &anchor);
2595 break;
2596 } else {
2597 ac_flag = 1;
2598 anchor.x = ftmp;
2599 }
2600 if (read_float(&ftmp, hd))
2601 anchor.y = 0.;
2602 else
2603 anchor.y = ftmp;
2604 if (scale_flag)
2605 User_to_Plotter_coord(&anchor, &anchor);
2606 break;
2607 case AD:
2608 if (read_float(&ftmp, hd)) /* just AD - defaults */
2609 tp->altfont = 0;
2610 else {
2611 switch ((int) ftmp) {
2612 case 1: /* charset */
2613 if (read_float(&csfont, hd))
2614 par_err_exit(2, cmd, hd);
2615 else
2616 tp->altfont = (int) csfont;
2617 break;
2618 case 2: /* fixed or variable spacing */
2619 if (read_float(&csfont, hd))
2620 par_err_exit(2, cmd, hd);
2621 else if ((int) csfont == 1 && !silent_mode)
2622 fprintf(stderr,
2623 "only fixed fonts available\n");
2624 break;
2625 case 3: /* font pitch */
2626 case 4: /* font height */
2627 case 5: /* posture */
2628 case 6: /* stroke weight */
2629 if (read_float(&ftmp, hd))
2630 par_err_exit(2, cmd, hd);
2631 if (ftmp == 9999)
2632 tp->astrokewidth = ftmp;
2633 else {
2634 if (ftmp < -7. || ftmp > 7.)
2635 ftmp = 0.;
2636 tp->astrokewidth = 0.11 + ftmp / 70.; /* 0.01 ... 0.21 mm */
2637 }
2638 break;
2639 case 7: /* typeface */
2640 if (read_float(&csfont, hd))
2641 par_err_exit(2, cmd, hd);
2642 else if (!silent_mode)
2643 fprintf(stderr,
2644 "pitch/height/posture/typeface unsupported\n");
2645 break;
2646 default:
2647 par_err_exit(1, cmd, hd);
2648 }
2649 }
2650 break;
2651 case CA: /* Alternate character set */
2652 if (read_float(&csfont, hd)) /* just CA; */
2653 tp->altfont = 0;
2654 else
2655 tp->altfont = (int) csfont;
2656 break;
2657 case CI: /* Circle */
2658 circles(hd);
2659 break;
2660 case CO: /* Comment */
2661 SafeTerm = StrTerm;
2662 StrTerm = ';';
2663 read_string(tmpstr, hd);
2664 StrTerm = SafeTerm;
2665 if (strlen(tmpstr) > 0)
2666 tmpstr[strlen(tmpstr) - 1] = '\0';
2667 if (!silent_mode)
2668 printf("\n%s\n", tmpstr);
2669 break;
2670 case CR: /* color range */
2671 if (read_float(&ftmp, hd)) {
2672 r_base = g_base = b_base = 0;
2673 r_max = g_max = b_max = 255;
2674 break;
2675 } else {
2676 r_base = (unsigned char) ftmp;
2677 }
2678 if (read_float(&ftmp, hd)) {
2679 r_max = 255;
2680 break;
2681
2682 } else {
2683 r_max = (unsigned char) ftmp;
2684 }
2685 if (read_float(&ftmp, hd)) {
2686 break;
2687
2688 } else {
2689 g_base = (unsigned char) ftmp;
2690 }
2691 if (read_float(&ftmp, hd)) {
2692 g_max = 255;
2693 break;
2694 } else {
2695 g_max = (unsigned char) ftmp;
2696 }
2697 if (read_float(&ftmp, hd)) {
2698 break;
2699 } else {
2700 b_base = (unsigned char) ftmp;
2701 }
2702 if (read_float(&ftmp, hd)) {
2703 b_max = 255;
2704 break;
2705 } else {
2706 b_max = (unsigned char) ftmp;
2707 break;
2708 }
2709 case CS: /*character set selection */
2710 if (read_float(&csfont, hd)) /* just CS; */
2711 tp->font = 0;
2712 else
2713 tp->font = (int) csfont;
2714 tp->stdfont = tp->font;
2715 break;
2716 case CT: /* chord tolerance */
2717 if (read_float(&ftmp, hd) || ftmp != 1.)
2718 ct_dist = FALSE;
2719 else
2720 ct_dist = TRUE;
2721 break;
2722 case EP: /* edge polygon */
2723 if (polygon_penup == TRUE)
2724 if (p_last.x != polystart.x
2725 || p_last.y != polystart.y)
2726 vertices -= 2;
2727
2728 for (i = 0; i < vertices; i = i + 2) { /*for all polygon edges */
2729 p1.x = polygons[i].x;
2730 p1.y = polygons[i].y;
2731 Pen_action_to_tmpfile(MOVE_TO, &p1, scale_flag);
2732 p1.x = polygons[i + 1].x;
2733 p1.y = polygons[i + 1].y;
2734 Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag);
2735 }
2736 Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag);
2737 break;
2738
2739 case EW: /* Edge Wedge */
2740 wedges(hd);
2741 break;
2742
2743 case EC:
2744 /* printf("cut paper\n"); */
2745 break;
2746
2747 case FP: /* fill polygon */
2748 if (pg->nofill) { /* treat like EP */
2749 if (!silent_mode)
2750 fprintf(stderr, "FP : suppressed\n");
2751 for (i = 0; i < vertices; i = i + 2) { /*for all polygon edges */
2752 p1.x = polygons[i].x;
2753 p1.y = polygons[i].y;
2754 Pen_action_to_tmpfile(MOVE_TO, &p1,
2755 scale_flag);
2756 p1.x = polygons[i + 1].x;
2757 p1.y = polygons[i + 1].y;
2758 Pen_action_to_tmpfile(DRAW_TO, &p1,
2759 scale_flag);
2760 }
2761 Pen_action_to_tmpfile(MOVE_TO, &p_last,
2762 scale_flag);
2763 break;
2764 }
2765 if (hatchspace == 0.)
2766 hatchspace = pt.width[pen];
2767 if (filltype < 3 && thickness > 0.)
2768 hatchspace = thickness;
2769 if (!ac_flag) { /* not yet initialized */
2770 anchor.x = P1.x;
2771 anchor.y = P1.y;
2772 }
2773 fill(polygons, vertices, anchor, P2, scale_flag, filltype,
2774 hatchspace, hatchangle);
2775 Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag);
2776 break;
2777 case FT: /* Fill Type */
2778 if (read_float(&ftmp, hd)) { /* just FT -> FT=1 */
2779 filltype = 1;
2780 break;
2781 } else {
2782 filltype = (int) ftmp;
2783 }
2784 if (filltype < 3)
2785 break;
2786
2787 if (filltype > 4) {
2788 if (FoundUserFill == 0) {
2789 FoundUserFill = 1;
2790 if (!silent_mode)
2791 fprintf(stderr,
2792 "\nNo support for user-defined fill types, using type 1 instead\n");
2793 }
2794 filltype = 1;
2795 break;
2796 }
2797
2798 if (read_float(&ftmp, hd)) {
2799 hatchspace = saved_hatchspace[filltype - 3];
2800 if (hatchspace == 0.)
2801 hatchspace = 0.01 * Diag_P1_P2;
2802 hatchangle = saved_hatchangle[filltype - 3];
2803 break;
2804 } else {
2805 if (ftmp <= 0.)
2806 ftmp = 0.01 * Diag_P1_P2;
2807 hatchspace = ftmp;
2808 saved_hatchspace[filltype - 3] = hatchspace;
2809 }
2810 if (read_float(&ftmp, hd)) {
2811 hatchangle = saved_hatchangle[filltype - 3];
2812 break;
2813 } else {
2814 hatchangle = ftmp;
2815 saved_hatchangle[filltype - 3] = hatchangle;
2816 }
2817 break;
2818 case NP: /* Number of Pens */
2819 if (read_float(&ftmp, hd) || ftmp > NUMPENS) /* invalid or missing */
2820 break;
2821 else {
2822 pg->maxpens = (int) ftmp;
2823 if (!silent_mode)
2824 fprintf(stderr, "NP: %d pens requested\n",
2825 pg->maxpens);
2826 }
2827 break;
2828 case NR: /*Not ready - pause plotter (noop) */
2829 if (read_float(&ftmp, hd))
2830 break;
2831 break;
2832 case PA: /* Plot Absolute */
2833 lines(plot_rel = FALSE, hd);
2834 tp->CR_point = HP_pos;
2835 break;
2836 case PC: /* Pen Color */
2837 if (read_float(&ftmp, hd) || fixedcolor || (int) ftmp > pg->maxpens) { /* invalid or missing */
2838 break;
2839 } else {
2840 mypen = (int) ftmp;
2841 if (pg->mapzero == mypen)
2842 break;
2843 /* this color is remapped for pen 0, ignore original definition */
2844 if (read_float(&ftmp, hd)) /* no red component */
2845 myred = 0;
2846 else
2847 myred = 255 * (ftmp - r_base) / r_max;
2848 if (read_float(&ftmp, hd)) /* no green component */
2849 mygreen = 0;
2850 else
2851 mygreen = 255 * (ftmp - g_base) / g_max;
2852 if (read_float(&ftmp, hd)) /* no blue component */
2853 myblue = 0;
2854 else
2855 myblue = 255 * (ftmp - b_base) / b_max;
2856 pg->is_color = TRUE;
2857 PlotCmd_to_tmpfile(DEF_PC);
2858 if (mypen == 0 && pg->mapzero > -1)
2859 mypen = pg->mapzero;
2860 Pen_Color_to_tmpfile(mypen, myred, mygreen,
2861 myblue);
2862 break;
2863 }
2864 case PD: /* Pen Down */
2865 pen_down = TRUE;
2866 lines(plot_rel, hd);
2867 tp->CR_point = HP_pos;
2868 break;
2869 case PE:
2870 read_PE(pg, hd);
2871 tp->CR_point = HP_pos;
2872 break;
2873 case PM:
2874 if (read_float(&ftmp, hd) || ftmp == 0) { /* no parameters or PM0 */
2875 polygon_mode = TRUE;
2876 polygon_penup = FALSE;
2877 saved_penstate = pen_down;
2878 vertices = -1;
2879 polystart = p_last;
2880 break;
2881 }
2882 if (ftmp == 1) {
2883 if (vertices > 0)
2884 polygon_penup = TRUE;
2885 pen_down = FALSE;
2886 break;
2887 }
2888 if (ftmp == 2) {
2889 polygon_mode = FALSE;
2890 pen_down = saved_penstate;
2891 if (p_last.x != polystart.x
2892 || p_last.y != polystart.y) {
2893 int outside = 0;
2894 double x1, y1, x2, y2;
2895 if (iwflag) {
2896 x1 = P1.x + (p_last.x -
2897 S1.x) * Q.x;
2898 y1 = P1.y + (p_last.y -
2899 S1.y) * Q.y;
2900 x2 = P1.x + (polystart.x -
2901 S1.x) * Q.x;
2902 y2 = P1.y + (polystart.y -
2903 S1.y) * Q.y;
2904
2905 outside =
2906 (DtClipLine
2907 (C1.x, C1.y, C2.x, C2.y, &x1,
2908 &y1, &x2,
2909 &y2) == CLIP_NODRAW);
2910
2911 if (!outside) {
2912 p_last.x =
2913 (x2 - P1.x) / Q.x +
2914 S1.x;
2915 p_last.y =
2916 (y2 - P1.y) / Q.y +
2917 S1.y;
2918 polystart.x =
2919 (x1 - P1.x) / Q.x +
2920 S1.x;
2921 polystart.y =
2922 (y1 - P1.y) / Q.y +
2923 S1.y;
2924 }
2925 }
2926 if (!outside) {
2927 HPGL_Pt_to_polygon(p_last);
2928 HPGL_Pt_to_polygon(polystart); /* force closing of open polygon */
2929 }
2930 }
2931 }
2932 break;
2933 case PR: /* Plot Relative */
2934 lines(plot_rel = TRUE, hd);
2935 tp->CR_point = HP_pos;
2936 break;
2937 case PS:
2938 if (read_float(&ftmp, hd) || ftmp == 0.) { /* no parameters or PS0; */
2939 break;
2940 } else {
2941 myheight = ftmp;
2942 }
2943 if (read_float(&ftmp, hd)) { /* no parameters */
2944 mywidth = P2.y;
2945 } else {
2946 mywidth = ftmp;
2947 if (mywidth > myheight) {
2948 mywidth = myheight;
2949 myheight = ftmp;
2950 }
2951 }
2952 if (pg->no_ps == TRUE) {
2953 if (!silent_mode)
2954 Eprintf("PS: suppressed\n");
2955 break;
2956 }
2957 ps_flag = 1;
2958 /* fprintf(stderr,"min,max vor PS: %f %f %f %f\n",xmin,ymin,xmax,ymax);*/
2959 M.x = myheight;
2960 M.y = mywidth;
2961 p1.x = 0;
2962 p1.y = 0;
2963
2964 if (scale_flag) /* Rescaling */
2965 User_to_Plotter_coord(&p1, &p2);
2966 else
2967 p2 = p1; /* Local copy */
2968 if (rotate_flag) { /* hp2xx-specific global rotation */
2969 ftmp = rot_cos * p2.x - rot_sin * p2.y;
2970 p2.y = rot_sin * p2.x + rot_cos * p2.y;
2971 p2.x = ftmp;
2972 }
2973 xmin = MIN(p2.x, xmin);
2974 ymin = MIN(p2.y, ymin);
2975 xmax = MAX(p2.x, xmax);
2976 ymax = MAX(p2.y, ymax);
2977
2978 p1.x = myheight;
2979 p1.y = mywidth;
2980 if (scale_flag) /* Rescaling */
2981 User_to_Plotter_coord(&p1, &p2);
2982 else
2983 p2 = p1; /* Local copy */
2984 if (rotate_flag) { /* hp2xx-specific global rotation */
2985 ftmp = rot_cos * p2.x - rot_sin * p2.y;
2986 p2.y = rot_sin * p2.x + rot_cos * p2.y;
2987 p2.x = ftmp;
2988 }
2989 xmin = MIN(p2.x, xmin);
2990 ymin = MIN(p2.y, ymin);
2991 xmax = MAX(p2.x, xmax);
2992 ymax = MAX(p2.y, ymax);
2993 /* fprintf(stderr,"min,max vor PS: %f %f %f %f\n",xmin,ymin,xmax,ymax);*/
2994
2995 /* add the following - to get the correct linetype scale etc */
2996 P1.x = 0.;
2997 P1.y = 0.;
2998 P2.x = myheight;
2999 P2.y = mywidth;
3000 if (rotate_flag) {
3001 P2.x = mywidth;
3002 P2.y = myheight;
3003 }
3004 Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y);
3005 CurrentLinePatLen = 0.04 * Diag_P1_P2;
3006 S1 = P1;
3007 S2 = P2;
3008 /* ajb */
3009 break;
3010 case PT: /* Pen thickness (for solid fills - current pen only */
3011 if (read_float(&ftmp, hd)) { /* no parameters */
3012 thickness = 0.3;
3013 break;
3014 } else {
3015 if (ftmp >= 0.1 && ftmp <= 5.)
3016 thickness = ftmp;
3017 }
3018 case PU: /* Pen Up */
3019 pen_down = FALSE;
3020 if (polygon_mode)
3021 polygon_penup = TRUE;
3022 lines(plot_rel, hd);
3023 tp->CR_point = HP_pos;
3024 break;
3025 case PW: /* Pen Width */
3026 if (fixedwidth) {
3027 if (!silent_mode)
3028 fprintf(stderr,
3029 "PW: ignored (hardware mode)\n");
3030 break;
3031 }
3032 if (read_float(&ftmp, hd)) { /* no parameters -> set defaults */
3033 mywidth = 0.35;
3034 /* FIXME - scaling here ! */
3035 if (wu_relative)
3036 mywidth = Diag_P1_P2 / 1000.;
3037 if (mywidth < 0.1)
3038 mywidth = 0.1;
3039 PlotCmd_to_tmpfile(DEF_PW);
3040 Pen_Width_to_tmpfile(0, mywidth);
3041 /*
3042 fprintf(stderr,"PW: defaulting to 0.35 for all pens\n");
3043 */
3044 break;
3045 } else {
3046 mywidth = ftmp; /* first or only parameter is width */
3047 if (wu_relative)
3048 mywidth = Diag_P1_P2 * ftmp / 1000.;
3049 if (mywidth < 0.1)
3050 mywidth = 0.1;
3051 }
3052
3053 if (read_float(&ftmp, hd)) { /* width only, applies to all pens */
3054 PlotCmd_to_tmpfile(DEF_PW);
3055 Pen_Width_to_tmpfile(0, mywidth);
3056 if (pg->maxpensize < mywidth)
3057 pg->maxpensize = mywidth;
3058 /*
3059 fprintf(stderr,"PW: defaulting to %f for all pens\n",mywidth);
3060 */
3061 } else { /* second parameter is pen */
3062 PlotCmd_to_tmpfile(DEF_PW);
3063 Pen_Width_to_tmpfile((int) ftmp, mywidth);
3064 if ((int) ftmp <= pg->maxpens) {
3065 if (pg->maxpensize < mywidth)
3066 pg->maxpensize = mywidth;
3067 }
3068 /*
3069 fprintf(stderr,"pen%d, size now %f\n",(int) ftmp,mywidth);
3070 */
3071 }
3072 break;
3073 case TL: /* Tick Length */
3074 if (read_float(&ftmp, hd)) { /* No number found */
3075 neg_ticklen = pos_ticklen = 0.005;
3076 return;
3077 } else
3078 pos_ticklen = ftmp / 100.0;
3079
3080 if (read_float(&ftmp, hd)) { /* pos, but not neg */
3081 neg_ticklen = 0.0;
3082 return;
3083 } else
3084 neg_ticklen = ftmp / 100.0;
3085 break;
3086 case WG: /* Filled Wedge */
3087 fwedges(hd, pt.width[pen]);
3088 break;
3089 case WU: /* pen Width Unit is relative */
3090 if (read_float(&ftmp, hd) || ftmp == 0.) /* Zero or no number */
3091 wu_relative = FALSE;
3092 else
3093 wu_relative = TRUE;
3094 break;
3095 case XT: /* X Tick */
3096 ax_ticks(0);
3097 break;
3098 case YT: /* Y Tick */
3099 ax_ticks(1);
3100 break;
3101
3102
3103 case IP: /* Input reference Points P1,P2 */
3104 tp->width /= (P2.x - P1.x);
3105 tp->height /= (P2.y - P1.y);
3106 if (read_float(&p1.x, hd)) { /* No number found */
3107 P1.x = P1X_default;
3108 P1.y = P1Y_default;
3109 P2.x = P2X_default;
3110 P2.y = P2Y_default;
3111 goto IP_Exit;
3112 }
3113 if (read_float(&p1.y, hd)) /* x without y! */
3114 par_err_exit(2, cmd, hd);
3115
3116 if (read_float(&p2.x, hd)) { /* No number found */
3117 P2.x += p1.x - P1.x;
3118 P2.y += p1.y - P1.y;
3119 P1 = p1;
3120 goto IP_Exit;
3121 }
3122 if (read_float(&p2.y, hd)) /* x without y! */
3123 par_err_exit(4, cmd, hd);
3124
3125 P1 = p1;
3126 P2 = p2;
3127
3128 IP_Exit:
3129 S1 = P1;
3130 S2 = P2;
3131 Q.x = (P2.x - P1.x) / (S2.x - S1.x);
3132 Q.y = (P2.y - P1.y) / (S2.y - S1.y);
3133 Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y);
3134 CurrentLinePatLen = 0.04 * Diag_P1_P2;
3135 tp->width *= (P2.x - P1.x);
3136 tp->height *= (P2.y - P1.y);
3137 adjust_text_par();
3138 return;
3139
3140 case IR: /* input reference points P1,P2 as percentages of defaults */
3141 if (read_float(&p1.x, hd)) /* No number found */
3142 return; /* keep defaults */
3143 if (read_float(&p1.y, hd)) /* x without y! */
3144 par_err_exit(2, cmd, hd);
3145
3146 /*fprintf(stderr,"P1,P2 vor IR: %f %f, %f %f\n",P1.x,P1.y,P2.x,P2.y);*/
3147
3148 mywidth = P2.x - P1.x;
3149 myheight = P2.y - P1.y;
3150 ftmp = p1.x;
3151 p1.x = P1.x; /* need old value for computation of new P2 */
3152 P1.x = p1.x + ftmp / 100. * mywidth;
3153 ftmp = p1.y;
3154 p1.y = P1.y;
3155 P1.y = p1.y + ftmp / 100. * myheight;
3156
3157 if (read_float(&p2.x, hd)) { /* No number found */
3158 P2.x = P1.x + mywidth; /* P2 tracks new P1 too keep constant size */
3159 P2.y = P1.y + myheight;
3160 /*fprintf(stderr,"P1,P2 nach IR: %f %f, %f %f\n",P1.x,P1.y,P2.x,P2.y);*/
3161 return;
3162 }
3163 if (read_float(&p2.y, hd)) /* x without y! */
3164 par_err_exit(4, cmd, hd);
3165
3166 P2.x = p1.x + p2.x / 100. * mywidth;
3167 P2.y = p1.y + p2.y / 100. * myheight;
3168 if (P1.x == P2.x)
3169 P2.x = P2.x + 1.;
3170 if (P1.y == P2.y)
3171 P2.y = P2.y + 1.;
3172 fprintf(stderr, "P1,P2 nach IR: %f %f, %f %f\n", P1.x,
3173 P1.y, P2.x, P2.y);
3174 Q.x = (P2.x - P1.x) / (S2.x - S1.x);
3175 Q.y = (P2.y - P1.y) / (S2.y - S1.y);
3176 Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y);
3177 CurrentLinePatLen = 0.04 * Diag_P1_P2;
3178 tp->width *= (P2.x - P1.x);
3179 tp->height *= (P2.y - P1.y);
3180 adjust_text_par();
3181 return;
3182
3183 case IW:
3184 iwflag = 1;
3185 if (read_float(&C1.x, hd)) { /* No number found */
3186 if (P1.x == P1X_default && P1.y == P1Y_default
3187 && P2.x == P2X_default
3188 && P2.y == P2Y_default) {
3189 iwflag = 0;
3190 break;
3191 }
3192 C1 = P1;
3193 C2 = P2;
3194 if (scale_flag) {
3195 C1 = S1;
3196 C2 = S2;
3197 }
3198 if (rotate_flag && !ps_flag) {
3199 switch ((int) fabs(rot_tmp)) {
3200 case 90:
3201 case 270:
3202 ftmp = C1.x;
3203 C1.x = C1.y;
3204 C1.y = ftmp;
3205 ftmp = C2.x;
3206 C2.x = C2.y;
3207 C2.y = ftmp;
3208 break;
3209 default:
3210 break;
3211 }
3212 }
3213 } else {
3214 if (read_float(&C1.y, hd)) /* x without y! */
3215 par_err_exit(2, cmd, hd);
3216 if (read_float(&C2.x, hd)) /* No number found */
3217 par_err_exit(3, cmd, hd);
3218 if (read_float(&C2.y, hd)) /* x without y! */
3219 par_err_exit(4, cmd, hd);
3220 }
3221 /*fprintf (stderr," clip limits (%f,%f)(%f,%f)\n",C1.x,C1.y,C2.x,C2.y);*/
3222
3223 if (scale_flag) {
3224 User_to_Plotter_coord(&C1, &C1);
3225 User_to_Plotter_coord(&C2, &C2);
3226 }
3227
3228
3229 if (C2.x < C1.x) {
3230 ftmp = C2.x;
3231 C2.x = C1.x;
3232 C1.x = ftmp;
3233 }
3234 if (C2.y < C1.y) {
3235 ftmp = C2.y;
3236 C2.y = C1.y;
3237 C1.y = ftmp;
3238 }
3239
3240 C1.x -= pg->extraclip;
3241 C1.y -= pg->extraclip;
3242 C2.x += pg->extraclip;
3243 C2.y += pg->extraclip;
3244
3245 break;
3246
3247 case OP: /* Output reference Points P1,P2 */
3248 if (!silent_mode) {
3249 Eprintf("\nP1 = (%g, %g)\n", P1.x, P1.y);
3250 Eprintf("P2 = (%g, %g)\n", P2.x, P2.y);
3251 }
3252 break;
3253 case OW: /* Output clip box */
3254 if (!silent_mode) {
3255 Eprintf("\nC1 = (%g, %g)\n", C1.x, C1.y);
3256 Eprintf("C2 = (%g, %g)\n", C2.x, C2.y);
3257 }
3258 break;
3259
3260 case AF:
3261 case AH:
3262 case PG: /* new PaGe */
3263 /* record ON happens only once! */
3264 page_number++;
3265 /* fprintf(stderr, "PG: page_number now %d\n", page_number);*/
3266 record_off = (first_page > page_number)
3267 || ((last_page < page_number) && (last_page > 0));
3268 pg_flag = TRUE;
3269 return;
3270 break;
3271
3272 case EA: /* Edge Rectangle absolute */
3273 rects(plot_rel = FALSE, 0, pt.width[pen], hd);
3274 tp->CR_point = HP_pos;
3275 break;
3276
3277 case ER: /* Edge Rectangle relative */
3278 rects(TRUE, 0, 0., hd);
3279 tp->CR_point = HP_pos;
3280 break;
3281
3282 case RA: /* Fill Rectangle absolute */
3283 rects(plot_rel = FALSE, 1, pt.width[pen], hd);
3284 tp->CR_point = HP_pos;
3285 break;
3286
3287 case RR: /* Fill Rectangle relative */
3288 rects(plot_rel = TRUE, 1, pt.width[pen], hd);
3289 tp->CR_point = HP_pos;
3290 break;
3291
3292 case RT: /* Relative arc, through Three points */
3293 tarcs(TRUE, hd);
3294 break;
3295
3296 case LT: /* Line Type: */
3297 if (read_float(&p1.x, hd)) /* just LT; */
3298 CurrentLineType = LT_solid;
3299 else {
3300 if ((((int) p1.x) >= LT_MIN)
3301 && (((int) p1.x) < LT_ZERO))
3302 CurrentLineType = LT_adaptive;
3303 else if (((int) p1.x) == LT_ZERO)
3304 CurrentLineType = LT_plot_at;
3305 else if ((((int) p1.x) > LT_ZERO)
3306 && (((int) p1.x) <= LT_MAX))
3307 CurrentLineType = LT_fixed;
3308 else {
3309 Eprintf("Illegal line type:\t%d\n",
3310 (int) p1.x);
3311 CurrentLineType = LT_solid; /* set to something sane */
3312 }
3313 CurrentLinePattern = (int) p1.x;
3314
3315 if (!read_float(&p1.y, hd)) { /* optional pattern length? */
3316 if (p1.y <= 0.0)
3317 Eprintf
3318 ("Illegal pattern length:\t%g\n",
3319 p1.y);
3320 else {
3321 Diag_P1_P2 =
3322 HYPOT(P2.x - P1.x,
3323 P2.y - P1.y);
3324
3325 if (!read_float(&ftmp, hd)) {
3326 if (ftmp == 1.0) {
3327 CurrentLinePatLen = p1.y * 40; /* absolute */
3328 } else {
3329 CurrentLinePatLen = Diag_P1_P2 * p1.y / 100.0; /* relative */
3330 }
3331 } else {
3332 CurrentLinePatLen = Diag_P1_P2 * p1.y / 100.0; /* relative */
3333 }
3334 }
3335 }
3336 }
3337
3338 break;
3339
3340 case SC: /* Input Scale Points S1,S2 */
3341 User_to_Plotter_coord(&p_last, &p_last);
3342 if (read_float(&p1.x, hd)) { /* No number found */
3343 S1.x = P1X_default;
3344 S1.y = P1Y_default;
3345 S2.x = P2X_default;
3346 S2.y = P2Y_default;
3347 scale_flag = FALSE;
3348 Q.x = Q.y = 1.0;
3349 break;
3350 }
3351 if (read_float(&p2.x, hd)) /* x without y! */
3352 par_err_exit(2, cmd, hd);
3353 if (read_float(&p1.y, hd)) /* No number found */
3354 par_err_exit(3, cmd, hd);
3355 if (read_float(&p2.y, hd)) /* x without y! */
3356 par_err_exit(4, cmd, hd);
3357
3358 if (p1.x == p2.x || p1.y == p2.y) { /* min must differ from max */
3359 if (!silent_mode)
3360 Eprintf
3361 ("Warning: Invalid SC command parameters -- ignored\n");
3362 Q.x = Q.y = 1.0;
3363 break;
3364 }
3365 S1.x = p1.x;
3366 S1.y = p1.y;
3367 S2.x = p2.x;
3368 S2.y = p2.y;
3369 if (read_float(&ftmp, hd))
3370 ftmp = 0; /*scaling defaults to type 0 */
3371 switch ((int) ftmp) {
3372 case 0: /* anisotropic scaling */
3373 Q.x = (P2.x - P1.x) / (S2.x - S1.x);
3374 Q.y = (P2.y - P1.y) / (S2.y - S1.y);
3375 break;
3376
3377 case 1: /* isotropic scaling */
3378 if (read_float(&ftmp, hd)) /* percentage of unused space on the left */
3379 ftmp = 50.0; /* of the isotropic area defaults to 50% */
3380 Q.x = (P2.x - P1.x) / (S2.x - S1.x);
3381 Q.y = (P2.y - P1.y) / (S2.y - S1.y);
3382 if (Q.x < Q.y) {
3383 if (read_float(&ftmp, hd))
3384 ftmp = 50.0; /* percentage of unused space below the plot */
3385 S1.y +=
3386 ftmp * ((P2.y - P1.y) / Q.y -
3387 (P2.y - P1.y) / Q.x) / 100.0;
3388 Q.y = Q.x;
3389 S2.y = S1.y + (P2.y - P1.y) / Q.y;
3390 } else {
3391 S1.x +=
3392 ftmp * ((P2.x - P1.x) / Q.x -
3393 (P2.x - P1.x) / Q.y) / 100.0;
3394 read_float(&ftmp, hd); /* mandatory 'bottom' value is unused */
3395 Q.x = Q.y;
3396 S2.x = S1.x + (P2.x - P1.x) / Q.x;
3397 }
3398 break;
3399 case 2: /* point factor scaling */
3400 Q.x = S2.x;
3401 Q.y = S2.y;
3402 S2.x = S1.x + (P2.x - P1.x) / Q.x;
3403 S2.y = S1.y + (P2.y - P1.y) / Q.y;
3404 break;
3405 default:
3406 par_err_exit(0, cmd, hd);
3407 }
3408 scale_flag = TRUE;
3409 Plotter_to_User_coord(&p_last, &p_last);
3410 break;
3411
3412 case SP: /* Select pen: none/0, or number */
3413 old_pen = pen;
3414 thickness = 0.; /* clear any PT setting (should we default to 0.3 here ??) */
3415 if (read_float(&p1.x, hd)) /* just SP; */
3416 pen = 0;
3417 else {
3418 pen = (short) p1.x;
3419 if (pen == 0 && pg->mapzero > -1)
3420 pen = pg->mapzero;
3421 }
3422 if (pen < 0 || (int) pen > pg->maxpens) {
3423 Eprintf
3424 ("\nIllegal pen number %d: replaced by %d\n",
3425 pen, pen % pg->maxpens);
3426 n_unexpected++;
3427 pen = pen % pg->maxpens;
3428 }
3429 if (old_pen != pen) {
3430 if ((fputc(SET_PEN, td) == EOF)
3431 || (fputc(pen, td) == EOF)) {
3432 PError("Writing to temporary file:");
3433 Eprintf("Error @ Cmd %ld\n", vec_cntr_w);
3434 exit(ERROR);
3435 }
3436 }
3437 if (pen)
3438 pens_in_use[pen] = 1;
3439 pg->maxcolor = MAX(pg->maxcolor, (int) pen);
3440 /* pens_in_use |= (1 << (pen-1)); */
3441 break;
3442
3443 case BP: /* Begin Plot */
3444 for (;;) {
3445 if (read_float(&ftmp, hd)) { /* No number found */
3446 break;
3447 } else {
3448 switch ((int) ftmp) {
3449 case 1: /* picture name follows */
3450 tmpstr[0] = fgetc(hd); /* skip comma */
3451 tmpstr[0] = fgetc(hd);
3452 if (!silent_mode)
3453 fprintf(stderr,
3454 "HPGL picture name: %c",
3455 tmpstr[0]);
3456 if (tmpstr[0] == '"') {
3457 tmpstr[0] = ' ';
3458 do {
3459 tmpstr[0] =
3460 fgetc(hd);
3461 if (!silent_mode)
3462 fputc
3463 (tmpstr
3464 [0],
3465 stderr);
3466 }
3467 while (tmpstr[0] != '"');
3468 }
3469 if (!silent_mode)
3470 fprintf(stderr, "\n");
3471 break;
3472 case 2: /* number of copies */
3473 case 3: /* disposition code */
3474 case 4: /* render unfinished */
3475 case 5: /* autorotation */
3476 if (read_float(&ftmp, hd))
3477 break;
3478 break;
3479 default:
3480 break;
3481 }
3482 }
3483 }
3484 /* fall through to initialization code now */
3485 case DF: /* Set to default */
3486 case IN: /* Initialize */
3487 reset_HPGL();
3488 tp->CR_point = HP_pos;
3489 break;
3490 case RO:
3491 if (read_float(&ftmp, hd)) { /* No number found */
3492 break;
3493 } else {
3494 /*if (!silent_mode)
3495 fprintf (stderr, "RO encountered, rotating P1,P2 by %f\n", ftmp);
3496 */
3497 rotate_flag = 1;
3498 rot_ang += ftmp;
3499 rot_tmp = ftmp;
3500 switch ((int) ftmp) {
3501 case 90:
3502 case 270:
3503 ftmp = M.x;
3504 M.x = M.y;
3505 M.y = ftmp;
3506 break;
3507 case 0:
3508 case 180:
3509 break;
3510 default:
3511 rotate_flag = 0;
3512 break;
3513 }
3514
3515 /* if (!silent_mode)
3516 fprintf (stderr, "cumulative rot_ang now %f\n", rot_ang); */
3517 rot_cos = cos(M_PI * rot_ang / 180.0);
3518 rot_sin = sin(M_PI * rot_ang / 180.0);
3519
3520 if (ps_flag) { /* transform extents from previous PS statement */
3521
3522 xmin = 1e10;
3523 ymin = 1e10;
3524 xmax = 1e-10;
3525 ymax = 1e-10;
3526
3527 p1.x = 0;
3528 p1.y = 0;
3529 if (scale_flag) /* Rescaling */
3530 User_to_Plotter_coord(&p1, &p2);
3531 else
3532 p2 = p1; /* Local copy */
3533 HP_pos = p2; /* Actual plotter pos. in plotter coord */
3534 ftmp = rot_cos * p2.x - rot_sin * p2.y;
3535 p2.y = rot_sin * p2.x + rot_cos * p2.y;
3536 p2.x = ftmp;
3537 xmin = MIN(p2.x, xmin);
3538 ymin = MIN(p2.y, ymin);
3539 xmax = MAX(p2.x, xmax);
3540 ymax = MAX(p2.y, ymax);
3541 p1.x = M.x;
3542 p1.y = M.y;
3543 if (scale_flag) /* Rescaling */
3544 User_to_Plotter_coord(&p1, &p2);
3545 else
3546 p2 = p1; /* Local copy */
3547 HP_pos = p2; /* Actual plotter pos. in plotter coord */
3548 ftmp = rot_cos * p2.x - rot_sin * p2.y;
3549 p2.y = rot_sin * p2.x + rot_cos * p2.y;
3550 p2.x = ftmp;
3551 xmin = MIN(p2.x, xmin);
3552 ymin = MIN(p2.y, ymin);
3553 xmax = MAX(p2.x, xmax);
3554 ymax = MAX(p2.y, ymax);
3555 }
3556 }
3557 break;
3558 case BL: /* Buffer label string */
3559 read_string(strbuf, hd);
3560 break;
3561 case CP: /* Char Plot (rather: move) */
3562 if (read_float(&p1.x, hd)) { /* No number found */
3563 plot_string("\n\r", LB_direct, pen);
3564 return;
3565 } else if (read_float(&p1.y, hd))
3566 par_err_exit(2, cmd, hd);
3567
3568 p2.x =
3569 p1.x * tp->chardiff.x - p1.y * tp->linediff.x +
3570 HP_pos.x;
3571 p2.y =
3572 p1.x * tp->chardiff.y - p1.y * tp->linediff.y +
3573 HP_pos.y;
3574 Pen_action_to_tmpfile(MOVE_TO, &p2, FALSE);
3575 break;
3576 case DI: /* Char plot Dir (absolute) */
3577 if (read_float(&p1.x, hd)) { /* No number found */
3578 tp->dir = 0.0;
3579 tp->CR_point = HP_pos;
3580 adjust_text_par();
3581 break;
3582 }
3583 if (read_float(&p1.y, hd)) /* x, but not y */
3584 par_err_exit(2, cmd, hd);
3585 if ((p1.x == 0.0) && (p1.y == 0.0))
3586 par_err_exit(0, cmd, hd);
3587 tp->dir = atan2(p1.y, p1.x);
3588 tp->CR_point = HP_pos;
3589 adjust_text_par();
3590 break;
3591 case DR: /* Char plot Dir (rel P1,P2) */
3592 if (read_float(&p1.x, hd)) { /* No number found */
3593 tp->dir = 0.0;
3594 tp->CR_point = HP_pos;
3595 adjust_text_par();
3596 break;
3597 }
3598 if (read_float(&p1.y, hd))
3599 par_err_exit(2, cmd, hd); /* x, but not y */
3600 if ((p1.x == 0.0) && (p1.y == 0.0))
3601 par_err_exit(0, cmd, hd);
3602 tp->dir =
3603 atan2(p1.y * (P2.y - P1.y), p1.x * (P2.x - P1.x));
3604 tp->CR_point = HP_pos;
3605 adjust_text_par();
3606 break;
3607 case DT: /* Define string terminator */
3608 StrTerm = getc(hd);
3609 if (StrTerm == ';') { /*just DT */
3610 StrTerm = ETX;
3611 StrTermSilent = 1;
3612 break;
3613 }
3614 if (read_float(&ftmp, hd)) {
3615 StrTermSilent = 1;
3616 } else
3617 StrTermSilent = (short) ftmp;
3618 break;
3619 case DV: /* Text direction vertical */
3620 if (read_float(&ftmp, hd) || ftmp == 0)
3621 mode_vert = 0;
3622 else
3623 mode_vert = 1;
3624 break;
3625 case ES: /* Extra Space */
3626 if (read_float(&tp->espace, hd)) { /* No number found */
3627 tp->espace = 0.0;
3628 tp->eline = 0.0;
3629 } else if (read_float(&tp->eline, hd))
3630 tp->eline = 0.0; /* Supply default */
3631 adjust_text_par();
3632 break;
3633 case LA: /* Line Attributes */
3634 set_line_attr(hd);
3635 break;
3636 case LB: /* Label string */
3637 read_string(strbuf, hd);
3638 plot_string(strbuf, LB_direct, pen);
3639 /*
3640 * Bug fix by W. Eric Norum:
3641 * Update the position so that subsequent `PR's will work.
3642 */
3643 if (scale_flag)
3644 Plotter_to_User_coord(&HP_pos, &p_last);
3645 else
3646 p_last = HP_pos;
3647 break;
3648 case LO: /* Label Origin */
3649 if (read_float(&p1.x, hd)) /* No number found */
3650 tp->orig = 1;
3651 else {
3652 tp->orig = (int) p1.x;
3653 if (tp->orig < 1 || tp->orig == 10
3654 || tp->orig > 19)
3655 tp->orig = 1; /* Error */
3656 }
3657 adjust_text_par();
3658 break;
3659 case PB: /* Plot Buffered label string */
3660 plot_string(strbuf, LB_buffered, pen);
3661 break;
3662 case SI: /* Char cell Sizes (absolute) */
3663 if (read_float(&tp->width, hd)) { /* No number found */
3664 tp->width = 0.187; /* [cm], A4 */
3665 tp->height = 0.269; /* [cm], A4 */
3666 } else {
3667 if (read_float(&tp->height, hd))
3668 par_err_exit(2, cmd, hd);
3669 if ((tp->width == 0.0) || (tp->height == 0.0))
3670 par_err_exit(0, cmd, hd);
3671 }
3672 tp->width *= 400.0; /* [cm] --> [plotter units] */
3673 tp->height *= 400.0; /* [cm] --> [plotter units] */
3674 adjust_text_par();
3675 break;
3676 case SL: /* Char Slant */
3677 if (read_float(&tp->slant, hd)) /* No number found */
3678 tp->slant = 0.0;
3679 adjust_text_par();
3680 break;
3681 case SM: /* Symbol Mode */
3682 read_symbol_char(hd);
3683 break;
3684 case SR: /* Character sizes (Rel P1,P2) */
3685 if (read_float(&tp->width, hd)) { /* No number found */
3686 tp->width = 0.75; /* % of (P2-P1)_x */
3687 tp->height = 1.5; /* % of (P2-P1)_y */
3688 } else {
3689 if (read_float(&tp->height, hd))
3690 par_err_exit(2, (short) cmd, hd);
3691 if ((tp->width == 0.0) || (tp->height == 0.0))
3692 par_err_exit(0, (short) cmd, hd);
3693 }
3694 tp->width *= (P2.x - P1.x) / 100.0; /* --> [pl. units] */
3695 tp->height *= (P2.y - P1.y) / 100.0;
3696 adjust_text_par();
3697 break;
3698 case SA: /* Select designated alternate charset */
3699 if (tp->altfont)
3700 tp->font = tp->altfont;
3701 else /* Was never designated, default to 0 */
3702 tp->font = 0;
3703 tp->strokewidth = tp->astrokewidth;
3704 break;
3705 case SD:
3706 if (read_float(&ftmp, hd)) /* just SD - defaults */
3707 tp->stdfont = 0;
3708 else {
3709 switch ((int) ftmp) {
3710 case 1: /* charset */
3711 if (read_float(&csfont, hd))
3712 par_err_exit(2, cmd, hd);
3713 else
3714 tp->stdfont = (int) csfont;
3715 break;
3716 case 2: /* fixed or variable spacing */
3717 if (read_float(&csfont, hd))
3718 par_err_exit(2, cmd, hd);
3719 else if ((int) csfont == 1 && !silent_mode)
3720 fprintf(stderr,
3721 "only fixed fonts available\n");
3722 break;
3723 case 3: /* font pitch */
3724 case 4: /* font height */
3725 case 5: /* posture */
3726 case 6: /* stroke weight */
3727 if (read_float(&ftmp, hd))
3728 par_err_exit(2, cmd, hd);
3729 if (ftmp == 9999)
3730 tp->sstrokewidth = ftmp;
3731 else {
3732 if (ftmp < -7. || ftmp > 7.)
3733 ftmp = 0.;
3734 tp->sstrokewidth = 0.11 + ftmp / 70.; /* 0.01 ... 0.21 mm */
3735 }
3736 break;
3737 case 7: /* typeface */
3738 if (read_float(&csfont, hd))
3739 par_err_exit(2, cmd, hd);
3740 else if (!silent_mode)
3741 fprintf(stderr,
3742 "pitch/height/posture/typeface unsupported\n");
3743 break;
3744 default:
3745 par_err_exit(1, cmd, hd);
3746 }
3747 }
3748 break;
3749 case SS: /* Select designated standard character set */
3750 if (tp->stdfont)
3751 tp->font = tp->stdfont;
3752 else /* Was never designated, default to 0 */
3753 tp->font = 0;
3754 tp->strokewidth = tp->sstrokewidth;
3755 break;
3756 case UC: /* User defined character */
3757 plot_user_char(hd, pen);
3758 break;
3759 case UL: /* User defined line style */
3760 set_line_style_by_UL(hd);
3761 break;
3762 case MG:
3763 case WD: /* Write string to display */
3764 read_string(strbuf, hd);
3765 if (!silent_mode)
3766 Eprintf("\nLABEL: %s\n", strbuf);
3767 break;
3768 case VS:
3769 if (read_float(&ftmp, hd)) /* Just VS */
3770 break;
3771 if (read_float(&ftmp, hd)) /* uniform speed */
3772 break;
3773 if (read_float(&ftmp, hd)) /* speed for given pen */
3774 break;
3775 default: /* Skip unknown HPGL command: */
3776 n_unknown++;
3777 if (!silent_mode)
3778 Eprintf(" %c%c: ignored ", cmd >> 8, cmd & 0xFF);
3779 if (cmd == EOF) {
3780 n_unexpected++;
3781 if (!silent_mode)
3782 Eprintf("\nUnexpected EOF!\t");
3783 }
3784 break;
3785 }
3786 }
3787
3788
read_HPGL(GEN_PAR * pg,const IN_PAR * pi)3789 void read_HPGL(GEN_PAR * pg, const IN_PAR * pi)
3790 /**
3791 ** This routine is the high-level entry for HP-GL processing.
3792 ** It reads the input stream character-by-character, identifies
3793 ** ESC. commands (device controls) and HP-GL mnemonics, reads
3794 ** parameters (if expected), and initiates processing of these
3795 ** commands. It finally reports on this parsing process.
3796 **/
3797 {
3798 int c;
3799 int cmd;
3800
3801 vec_cntr_r = 0L;
3802 vec_cntr_w = 0L;
3803 n_unexpected = 0;
3804 n_commands = 0;
3805 n_unknown = 0;
3806
3807 if ((c = getc(pi->hd)) == EOF)
3808 return;
3809 else
3810 ungetc(c, pi->hd);
3811
3812 if (!pg_flag)
3813 init_HPGL(pg, pi);
3814
3815 if (!pg->quiet)
3816 Eprintf("\nReading HPGL file\n");
3817
3818 /**
3819 ** MAIN parser LOOP!!
3820 **/
3821 while ((c = getc(pi->hd)) != EOF) {
3822 switch (c) {
3823 #ifdef MUTOH_KLUGE
3824 case '\a':
3825 Eprintf("Mutoh header found\n");
3826 read_ESC_cmd(pi->hd, FALSE); /* ESC sequence */
3827 break;
3828 #endif
3829 case ESC:
3830 read_ESC_cmd(pi->hd, TRUE); /* ESC sequence */
3831 break;
3832 default:
3833 if ((c < 'A') || (c > 'z')
3834 || ((c > 'Z') && (c < 'a')))
3835 break;
3836 if (c == 'P') {
3837 if ((cmd = getc(pi->hd)) == 'G') {
3838 page_number++;
3839 /* fprintf(stderr, "stream-reading PG: page_number now %d\n", page_number);*/
3840 record_off =
3841 (first_page > page_number)
3842 || ((last_page < page_number)
3843 && (last_page > 0));
3844 goto END;
3845 } else {
3846 if (cmd == EOF)
3847 return;
3848 ungetc(cmd, pi->hd);
3849 }
3850 }
3851 if (c == 'N') {
3852 if ((cmd = getc(pi->hd)) == 'R') {
3853 /* fprintf(stderr,"***NR***\n");'*/
3854 page_number++;
3855 /* fprintf(stderr, "stream-reading NR: page_number now %d\n", page_number);*/
3856 record_off =
3857 (first_page > page_number)
3858 || ((last_page < page_number)
3859 && (last_page > 0));
3860 goto END;
3861 } else {
3862 if (cmd == EOF)
3863 return;
3864 ungetc(cmd, pi->hd);
3865 }
3866 }
3867 if (c == 'A') {
3868 cmd = getc(pi->hd);
3869 if (cmd == 'F' || cmd == 'H') {
3870 /* fprintf(stderr,"***AF/AH***\n");*/
3871 page_number++;
3872 /* fprintf(stderr, "stream-reading AF/AH: page_number now %d\n", page_number);*/
3873 record_off =
3874 (first_page > page_number)
3875 || ((last_page < page_number)
3876 && (last_page > 0));
3877 goto END;
3878 } else {
3879 if (cmd == EOF)
3880 return;
3881 ungetc(cmd, pi->hd);
3882 }
3883 }
3884 cmd = c << 8;
3885 if ((c = getc(pi->hd)) == EOF)
3886 return;
3887 if ((c < 'A') || (c > 'z')
3888 || ((c > 'Z') && (c < 'a'))) {
3889 ungetc(c, pi->hd);
3890 break;
3891 }
3892 cmd |= (c & 0xFF);
3893 n_commands++;
3894 read_HPGL_cmd(pg, cmd, pi->hd);
3895 }
3896 }
3897 if (c == EOF) {
3898 page_number++;
3899 /* fprintf(stderr, "EOF : page_number now %d\n", page_number);*/
3900 }
3901 END:
3902 if (!pg->quiet && n_commands > 0) {
3903 Eprintf("Page number %d of range %d - %d\n",
3904 page_number - 1, pi->first_page, pi->last_page);
3905 Eprintf("\nHPGL commands read: %d\n", n_commands);
3906 Eprintf("HPGL command(s) ignored: %d\n", n_unknown);
3907 Eprintf("Unexpected event(s): %d\n", n_unexpected);
3908 Eprintf("Internal command(s): %ld\n", vec_cntr_w);
3909 if ((pi->first_page > page_number - 1)
3910 || ((pi->last_page < page_number - 1)
3911 && (pi->last_page > 0))) {
3912 n_commands = -1;
3913 Eprintf
3914 ("Page %d not drawn (outside selected range %d-%d)\n",
3915 page_number - 1, pi->first_page,
3916 pi->last_page);
3917 }
3918 Eprintf("Pens used: ");
3919 /* for (c=0; c < NUMPENS; c++, pens_in_use >>= 1)
3920 if (pens_in_use & 1)
3921 */
3922 for (c = 0; c < NUMPENS; c++)
3923 if (pens_in_use[c] == 1)
3924 Eprintf("%d ", c);
3925 /* Eprintf ("%d ", c+1); */
3926 Eprintf("\nMax. number of pages: %d\n", page_number - 1);
3927 }
3928 }
3929
3930
3931
3932
3933 void
adjust_input_transform(const GEN_PAR * pg,const IN_PAR * pi,OUT_PAR * po)3934 adjust_input_transform(const GEN_PAR * pg, const IN_PAR * pi, OUT_PAR * po)
3935 {
3936 /**
3937 ** The temporary input data of the temp. file may be re-used multiple
3938 ** times by calling this function with varying parameters,
3939 ** mainly in pi.
3940 **
3941 ** Some conversion factors for transformation from HP-GL coordinates
3942 ** (as given in the temp. file) into mm or pel numbers are set here.
3943 ** There are both global parameters and elemts of po set here.
3944 ** DPI-related factors only apply if the current mode is a raster mode.
3945 **
3946 ** # points (dots) in any direction = range [mm] * 1in/25.4mm * #dots/in
3947 **/
3948
3949 double dot_ratio, Dx, Dy, tmp_w, tmp_h;
3950 char *dir_str;
3951
3952 Dx = xmax - xmin;
3953 Dy = ymax - ymin;
3954 dot_ratio = (double) po->dpi_y / (double) po->dpi_x;
3955 po->width = pi->width;
3956 po->height = pi->height;
3957 po->xoff = pi->xoff;
3958 po->yoff = pi->yoff;
3959
3960 /* Width assuming given height: */
3961 tmp_w = pi->height * Dx / Dy * pi->aspectfactor;
3962 /* tmp_w = pi->height * Dx / Dx / pi->aspectfactor; */
3963 /* Height assuming given width: */
3964 tmp_h = pi->width * Dy / Dx / pi->aspectfactor;
3965
3966 /**
3967 ** EITHER width OR height MUST be the correct limit. The other will
3968 ** be adapted. Adaptation of both is inconsistent, except in truesize mode.
3969 **/
3970
3971 if (pi->truesize) {
3972 po->width = Dx / 40.0; /* Ignore -w, take natural HP-GL range */
3973 po->height = Dy / 40.0; /* Ignore -h, take natural HP-GL range */
3974 po->HP_to_xdots = (float) (po->dpi_x / 1016.0); /* dots per HP unit */
3975 po->HP_to_ydots = (float) (po->dpi_y / 1016.0); /* (1/40 mm) */
3976 dir_str = "true sizes";
3977 if (pi->center_mode) {
3978 if (!pg->quiet) {
3979 fprintf(stderr,
3980 "trying to center image\n");
3981 fprintf(stderr,
3982 "po->width ?<? tmp_w: %f %f\n",
3983 po->width, tmp_w);
3984 fprintf(stderr,
3985 "po->height ?<? tmp_h: %f %f\n",
3986 po->height, tmp_h);
3987 }
3988 if (po->width < tmp_w)
3989 po->xoff += (tmp_w - po->width) / 2.0;
3990 if (po->height < tmp_h)
3991 po->yoff += (tmp_h - po->height) / 2.0;
3992 }
3993
3994 } else {
3995 /* if (po->width > tmp_w) */
3996 if (Dy > Dx) {
3997 po->HP_to_ydots =
3998 (float) (po->dpi_y * po->height) / Dy / 25.4;
3999 po->HP_to_xdots =
4000 po->HP_to_ydots * pi->aspectfactor / dot_ratio;
4001 if (pi->center_mode)
4002 po->xoff += (po->width - tmp_w) / 2.0; /* by L. Lowe */
4003 po->width = tmp_w;
4004 dir_str = "width adapted"; /* Height fits, adjust width */
4005 } else {
4006 po->HP_to_xdots =
4007 (float) (po->dpi_x * po->width) / Dx / 25.4;
4008 po->HP_to_ydots =
4009 po->HP_to_xdots * dot_ratio / pi->aspectfactor;
4010 if (pi->center_mode)
4011 po->yoff += (po->height - tmp_h) / 2.0; /* by L. Lowe */
4012 po->height = tmp_h;
4013 dir_str = "height adapted"; /* Width fits, adjust height */
4014 }
4015 }
4016
4017 if (!pg->quiet) {
4018 Eprintf("\nWidth x height: %5.2f x %5.2f mm, %s\n",
4019 po->width, po->height, dir_str);
4020 Eprintf("Coordinate range: (%g, %g) ... (%g, %g)\n",
4021 xmin, ymin, xmax, ymax);
4022 }
4023
4024 po->xmin = xmin;
4025 po->xmax = xmax;
4026 po->ymin = ymin;
4027 po->ymax = ymax;
4028 }
4029
4030 #ifdef EMF
reset_tmpfile(void)4031 void reset_tmpfile(void)
4032 {
4033 (void) lseek(fileno(td), 0L, SEEK_SET);
4034 if (vec_cntr_r)
4035 again = TRUE;
4036 vec_cntr_r = 0;
4037 }
4038 #endif
4039
PlotCmd_from_tmpfile(void)4040 PlotCmd PlotCmd_from_tmpfile(void)
4041 {
4042 PlotCmd cmd;
4043
4044 if (!silent_mode && !again)
4045 switch (vec_cntr_r++) {
4046 case 0:
4047 Eprintf("\nProcessing Cmd: ");
4048 break;
4049 case 1:
4050 Eprintf("1 ");
4051 break;
4052 case 2:
4053 Eprintf("2 ");
4054 break;
4055 case 5:
4056 Eprintf("5 ");
4057 break;
4058 case 10:
4059 Eprintf("10 ");
4060 break;
4061 case 20:
4062 Eprintf("20 ");
4063 break;
4064 case 50:
4065 Eprintf("50 ");
4066 break;
4067 case 100:
4068 Eprintf("100 ");
4069 break;
4070 case 200:
4071 Eprintf("200 ");
4072 break;
4073 case 500:
4074 Eprintf("500 ");
4075 break;
4076 case 1000:
4077 Eprintf("1k ");
4078 break;
4079 case 2000:
4080 Eprintf("2k ");
4081 break;
4082 case 5000:
4083 Eprintf("5k ");
4084 break;
4085 case 10000:
4086 Eprintf("10k ");
4087 break;
4088 case 20000:
4089 Eprintf("20k ");
4090 break;
4091 case 50000L:
4092 Eprintf("50k ");
4093 break;
4094 case 100000L:
4095 Eprintf("100k ");
4096 break;
4097 case 200000L:
4098 Eprintf("200k ");
4099 break;
4100 case 500000L:
4101 Eprintf("500k ");
4102 break;
4103 }
4104
4105 switch (cmd = fgetc(td)) {
4106 case NOP:
4107 case MOVE_TO:
4108 case DRAW_TO:
4109 case PLOT_AT:
4110 case SET_PEN:
4111 case DEF_PW:
4112 case DEF_PC:
4113 case DEF_LA:
4114 return cmd;
4115 case (unsigned int) EOF:
4116 default:
4117 return CMD_EOF;
4118 }
4119 }
4120
4121
4122
HPGL_Pt_from_tmpfile(HPGL_Pt * pf)4123 void HPGL_Pt_from_tmpfile(HPGL_Pt * pf)
4124 {
4125 if (fread((VOID *) pf, sizeof(*pf), 1, td) != 1) {
4126 PError("HPGL_Pt_from_tmpfile");
4127 Eprintf("Error @ Cmd %ld\n", vec_cntr_r);
4128 exit(ERROR);
4129 }
4130 if (pf->x < xmin || pf->x > xmax)
4131 Eprintf
4132 ("HPGL_Pt_from_tmpfile: x out of range (%g not in [%g, %g])\n",
4133 pf->x, xmin, xmax);
4134 if (pf->y < ymin || pf->y > ymax)
4135 Eprintf
4136 ("HPGL_Pt_from_tmpfile: y out of range (%g not in [%g, %g])\n",
4137 pf->y, ymin, ymax);
4138 }
4139