/* Copyright (c) 1991 - 1994 Heinz W. Werntges. All rights reserved. Parts Copyright (c) 1999 - 2001 Martin Kroeker All rights reserved. Distributed by Free Software Foundation, Inc. This file is part of HP2xx. HP2xx is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License, Version 2 or later, for full details. Everyone is granted permission to copy, modify and redistribute HP2xx, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with HP2xx so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /** HPGL.c: HPGL parser & i/o part of HP2xx (based on D. Donath's "HPtoGF.c") ** ** 91/01/13 V 1.00 HWW Originating ** 91/01/19 V 1.01 HWW reorganized ** 91/01/24 V 1.02 HWW ESC.-Sequences acknowledged (preliminary!!) ** 91/01/29 V 1.03 HWW Incl. SUN portation ** 91/01/31 V 1.04 HWW Parser: ESC sequences should be skipped now ** 91/02/10 V 1.05 HWW Parser renewed ** 91/02/15 V 1.06 HWW stdlib.h supported ** 91/02/19 V 1.07a HWW parser refined, bugs fixed ** 91/06/09 V 1.08 HWW New options added; some restructuring ** 91/06/16 V 1.09 HWW VGA mode added; some renaming; silent_mode! ** 91/06/20 V 1.10 HWW Rotation added ** 91/10/15 V 1.11 HWW ANSI_C; header files reorganized ** 91/10/20 V 1.11a HWW VAX_C support ** 91/10/25 V 1.11b HWW Support of LT; and LT0; (line type, partial) ** 91/11/20 V 1.12 HWW SPn; support: many changes! ** 91/11/21 V 1.12b HWW First comma in "PA,xxxx,yyyy..." accepted ** 91/12/22 V 1.13 HWW Multiple MOVE compression; "plot_rel", "old_pen" ** 92/01/13 V 1.13c HWW VAX problem with ungetc()/fscanf() fixed; bug fixed ** 92/01/15 V 1.13d HWW "vga" --> "pre" ** 92/01/30 V 1.14c HWW Parser: no need of ';', better portable ** 92/02/06 V 1.15a HWW Parser: AR, AA, CI, read_float() added; ** toupper() removed (MACH problems) ** 92/02/19 V 1.16c HWW LB etc. supported ** 92/02/23 V 1.17b HWW LB etc. improved, PG supported ** 92/02/25 V 1.17c HWW Parser improved: SP, LT, multi-mv suppression ** 92/03/01 V 1.17d HWW Char sizes: debugged ** 92/03/03 V 1.17e HWW LB_Mode introduced ** 92/04/15 V 1.17f HWW Width x Height limit assumed ** 92/05/21 V 1.18a HWW Multiple-file usage ** 92/05/28 V 1.19a HWW XT, YT, TL, SM added ** 92/10/20 V 1.20c HWW More line types added (debugged) ** 92/11/08 V 1.20d HWW Interval of active pages ** 92/12/13 V 1.20e HWW truesize option added ** 93/02/10 V 1.21a HWW Arcs & circles now properly closed; ** Bug fixed: SC does not interfere with last move ** 93/03/10 V 1.21b HWW Bug fixed in LT scanner part ** 93/03/22, V 1.21c HWW HYPOT() workaround for a weird BCC behavior; ** 93/04/02 Line_Generator(): Case *pb==*pa caught ** 93/04/13 V 1.22a HWW UC supported (code by Alois Treindl) ** 93/04/25 V 1.22b HWW LB/PR bug fix by E. Norum included ** 93/05/20 V 1.22c HWW LT1 pattern adjustment (report by E. Frambach) ** 93/09/02 V 1.22d HWW EA (rect) added (by Th. Hiller) ** 94/01/01 V 1.22e HWW Misc. additions suggested by L. Lowe: ** 1) PlotCmd_from_tmpfile(): int --> PlotCmd ** 2) ES: 2nd parameter now optional ** 3) evaluate_HPGL(): center_mode introduced ** 94/02/14 V 1.30a HWW Re-organized; many changes; min/max bug fixed ** 99/02/28 MK IW,CA,CS,SA,SS commands added ** 99/04/24 MK PC,PW commands added ** 99/05/10 MK RO command added (code by rs@daveg.com) ** 99/05/18 MK partial PE support (by Eugene Doudine) ** 99/06/05 MK PC improvements and fixes ** 99/11/30 MK support for fractional PE; PS/RO fixes ** 00/02/06 MK allow commandline overrides for PC/PW ** 00/02/13 MK DV support (backport from delayed 3.4.prealpha) ** 00/02/26 MK ER,EP,FP,FT,PM,PT,RA,RR,WG commands added ** 00/02/27 MK WU command added ** 00/03/02 MK SC types 1 and 2, more robust handling of PE, ** removed PE_line(), split lines() into file reader ** and common linedrawing backend for PD/PA and PE ** added PJL parser and RTL escape sequences ** (all these patches provided by Eugene Doudine) ** 00/03/03 MK convert IW parameters if scaling is in effect ** 00/03/05 MK AT/RT (arc through three points) added ** 01/01/01 MK UL added and PW rewritten (Andrew J.Bird) ** empty PUPD sequence now draws a small dot ** linedrawing fixed (added two moves when IW was ** in effect, ever since IW support was added) ** 01/04/01 MK BR/BZ added ** 01/04/22 MK reset PW and RO flags/values on reinitialization ** (Yuri Strelenko) ** 01/12/04 MK moved reinitialization of n_unknown and n_unexpected ** from reset_HPGL to init_HPGL so that they are not overwritten ** when a single drawing contains several IN statements ** 02/06/02 AJB Moved HYPOT macro to hpgl.h - so we can use it in murphy.c **/ #include #include #ifndef _NO_VCL #include #endif #include #include #include #include "bresnham.h" #include "hp2xx.h" #include "chardraw.h" #include "clip.h" #include "pendef.h" #include "lindef.h" #include "hpgl.h" #define ETX '\003' /* #define P1X_default 603.0 #define P1Y_default 521.0 #define P2X_default 10603.0 #define P2Y_default 7721.0 */ #define P1X_default 0.0 /* drop margins */ #define P1Y_default 0.0 /* #define P2X_default 11880. #define P2Y_default 16800. */ #define P2X_default 33600. /* A0 media */ #define P2Y_default 47520. #ifdef NORINT #define rint(a) (long)(a+0.5) #endif /** ** Globals needed in other source files: **/ LineType CurrentLineType = LT_solid; short scale_flag = FALSE; short record_off = FALSE; long vec_cntr_w = 0L; long n_commands = 0L; short silent_mode = FALSE; FILE *td; HPGL_Pt HP_pos = { 0, 0 }; /* Actual plotter pen position */ HPGL_Pt P1 = { P1X_default, P1Y_default }; /* Scaling points */ HPGL_Pt P2 = { P2X_default, P2Y_default }; int iwflag = 0; /*MK */ int mode_vert = 0; HPGL_Pt C1 = { P1X_default, P1Y_default }; /* Clipping points */ HPGL_Pt C2 = { P2X_default, P2Y_default }; HPGL_Pt S1 = { P1X_default, P1Y_default }; /* Scaled */ HPGL_Pt S2 = { P2X_default, P2Y_default }; /* points */ HPGL_Pt Q = { 1., 1. }; /* Delta-P/Delta-S: Initialized with first SC */ HPGL_Pt M; /* maximum coordinates set by PS instruction */ /** ** Global from chardraw.c: **/ extern TextPar tp; /** ** "Local" globals (I know this is messy...) : **/ static float xmin, xmax, ymin, ymax, neg_ticklen, pos_ticklen; static double Diag_P1_P2, pat_pos; static HPGL_Pt p_last = { M_PI, M_PI }; /* Init. to "impossible" values */ static HPGL_Pt polygons[MAXPOLY]; static int vertices = -1; static short polygon_mode = FALSE; static int filltype = 1; static float hatchspace = 0.; static float hatchangle = 0.; static float saved_hatchspace[2] = { 0., 0. }; static float saved_hatchangle[2] = { 0., 0. }; static float thickness = 0.; static short polygon_penup = FALSE; static HPGL_Pt anchor = { 100000.0, 100000.0 }; static HPGL_Pt polystart = { 0.0, 0.0 }; static float rot_cos, rot_sin; static short rotate_flag = FALSE; /* Flags tec external to HP-GL */ static short ps_flag = FALSE; static short ac_flag = FALSE; static double rot_ang = 0.; static double rot_tmp = 0.; /* saved RO value for resetting after drawing */ static short mv_flag = FALSE; static short pg_flag = FALSE; static short ct_dist = FALSE; static short fixedcolor = FALSE; static short fixedwidth = FALSE; static int first_page = 0; static int last_page = 0; static int n_unexpected = 0; static int n_unknown = 0; static int page_number = 1; static long vec_cntr_r = 0L; static short pen = -1; static short pens_in_use[NUMPENS]; static short pen_down = FALSE; /* Internal HP-GL book-keeping: */ static short plot_rel = FALSE; static short saved_penstate = FALSE; /* to track penstate over polygon mode */ static short wu_relative = FALSE; static int again = FALSE; static char StrTerm = ETX; /* String terminator char */ static short StrTermSilent = 1; /* only terminates, or prints too */ static char *strbuf = NULL; static unsigned int strbufsize = MAX_LB_LEN + 1; static char symbol_char = '\0'; /* Char in Symbol Mode (0=off) */ static unsigned char r_base = 0; static unsigned char g_base = 0; static unsigned char b_base = 0; static unsigned char r_max = 255; static unsigned char g_max = 255; static unsigned char b_max = 255; /* Known HPGL commands, ASCII-coded as High-byte/low-byte int's */ #define AA 0x4141 #define AC 0x4143 #define AD 0x4144 #define AF 0x4146 #define AH 0x4148 #define AR 0x4152 #define AT 0x4154 #define BL 0x424C #define BP 0x4250 #define BR 0x4252 #define BZ 0x425A #define CA 0x4341 /*MK */ #define CI 0x4349 #define CO 0x434F /*AJB*/ #define CP 0x4350 #define CR 0x4352 #define CS 0x4353 /*MK */ #define CT 0x4354 #define DF 0x4446 #define DI 0x4449 #define DR 0x4452 #define DT 0x4454 #define DV 0x4456 #define EA 0x4541 #define EC 0x4543 /*AJB*/ #define EP 0x4550 #define ER 0x4552 #define ES 0x4553 #define EW 0x4557 /*MK */ #define FP 0x4650 #define FT 0x4654 #define IN 0x494E #define IP 0x4950 #define IR 0x4952 #define IW 0x4957 /*MK */ #define LA 0x4C41 /*AJB*/ #define LB 0x4C42 #define LO 0x4C4F #define LT 0x4C54 #define MG 0x4D47 #define NP 0x4E50 #define NR 0x4E52 #define OP 0x4F50 #define OW 0x4F57 #define PA 0x5041 #define PB 0x5042 #define PC 0x5043 /*MK */ #define PD 0x5044 #define PE 0x5045 #define PG 0x5047 #define PM 0x504D #define PR 0x5052 #define PS 0x5053 #define PT 0x5054 #define PU 0x5055 #define PW 0x5057 /*MK */ #define RA 0x5241 #define RO 0x524F /*RS */ #define RR 0x5252 #define RT 0x5254 #define SA 0x5341 /*MK */ #define SC 0x5343 #define SD 0x5344 #define SI 0x5349 #define SL 0x534C #define SM 0x534D #define SP 0x5350 #define SR 0x5352 #define SS 0x5353 /*MK */ #define TL 0x544C #define UC 0x5543 #define UL 0x554C /*AJB*/ #define VS 0x5653 #define WD 0x5744 #define WG 0x5747 #define WU 0x5755 #define XT 0x5854 #define YT 0x5954 static void par_err_exit(int code, int cmd, FILE * hd) { const char *msg; char tmpstr[21]; switch (code) { case 0: msg = "Illegal parameters"; break; case 1: msg = "Error in first parameter"; break; case 2: msg = "No second parameter"; break; case 3: msg = "No third parameter"; break; case 4: msg = "No fourth parameter"; break; case 98: msg = "sscanf error: corrupted file?"; break; case 99: default: msg = "Internal error"; break; } Eprintf("\nError in command %c%c: %s\n", cmd >> 8, cmd & 0xFF, msg); Eprintf(" @ Cmd %ld\n", vec_cntr_w); fseek(hd, -10L, SEEK_CUR); read_string(tmpstr, hd); tmpstr[20] = '\0'; Eprintf(" lately read: %s\n", tmpstr); exit(ERROR); } static void reset_HPGL(void) { int i; p_last.x = p_last.y = M_PI; pen_down = FALSE; plot_rel = FALSE; pen = -1; /* n_unexpected = 0; n_unknown = 0;*/ mv_flag = FALSE; wu_relative = FALSE; pg_flag = FALSE; iwflag = FALSE; ps_flag = FALSE; ac_flag = FALSE; filltype = 1; saved_hatchangle[0] = saved_hatchangle[1] = 0.; saved_hatchspace[0] = saved_hatchspace[1] = 0.; ct_dist = FALSE; CurrentLineType = LT_solid; set_line_style_defaults(); /* set_line_attr_defaults();*/ CurrentLineAttr.Join = LAJ_plain_miter; CurrentLineAttr.End = LAE_butt; CurrentLineAttr.Limit = 5; tp->sstrokewidth = tp->astrokewidth = tp->strokewidth = 0.11; StrTerm = ETX; StrTermSilent = 1; if (strbuf == NULL) { strbuf = malloc(strbufsize); if (strbuf == NULL) { fprintf(stderr, "\nNo memory !\n"); exit(ERROR); } } strbuf[0] = '\0'; P1.x = P1X_default; P1.y = P1Y_default; Diag_P1_P2 = /*@-unrecog@ */ HYPOT(P2.x - P1.x, P2.y - P1.y); CurrentLinePatLen = 0.04 * Diag_P1_P2; pat_pos = 0.0; scale_flag = FALSE; S1 = P1; S2 = P2; Q.x = Q.y = 1.0; HP_pos.x = HP_pos.y = 0.0; neg_ticklen = 0.005; /* 0.5 % */ pos_ticklen = 0.005; symbol_char = '\0'; rot_ang -= rot_tmp; rot_tmp = 0.; if (rot_ang == 0.) rotate_flag = FALSE; if (rotate_flag) { rot_cos = cos(M_PI * rot_ang / 180.0); rot_sin = sin(M_PI * rot_ang / 180.0); } init_text_par(); if (fixedcolor == FALSE) { set_color_rgb(xxBackground, 255, 255, 255); set_color_rgb(xxForeground, 0, 0, 0); set_color_rgb(xxRed, 255, 0, 0); set_color_rgb(xxGreen, 0, 255, 0); set_color_rgb(xxBlue, 0, 0, 255); set_color_rgb(xxCyan, 0, 255, 255); set_color_rgb(xxMagenta, 255, 0, 255); set_color_rgb(xxYellow, 255, 255, 0); pt.color[0] = xxBackground; pt.color[1] = xxForeground; pt.color[2] = xxRed; pt.color[3] = xxGreen; pt.color[4] = xxBlue; pt.color[5] = xxCyan; pt.color[6] = xxMagenta; pt.color[7] = xxYellow; } if (fixedwidth == FALSE) for (i = 0; i < 8; i++) pt.width[i] = 0.1; record_off = (first_page > page_number) || ((last_page < page_number) && (last_page > 0)); } static void init_HPGL(GEN_PAR * pg, const IN_PAR * pi) { /** ** Re-init. global var's for multiple-file applications **/ /*fprintf(stderr,"init_HPGL\n");*/ td = pg->td; silent_mode = (short) pg->quiet; xmin = pi->x0; ymin = pi->y0; xmax = pi->x1; ymax = pi->y1; fixedcolor = (short) pi->hwcolor; fixedwidth = (short) pi->hwsize; r_base = g_base = b_base = 0; r_max = g_max = b_max = 255; /* pens_in_use = 0; */ pg->maxpens = 8; pg->maxcolor = 1; memset(pens_in_use, 0, NUMPENS * sizeof(short)); /** ** Record ON if no page selected (pg->page == 0)! **/ first_page = pi->first_page; /* May be 0 */ last_page = pi->last_page; /* May be 0 */ record_off = (first_page > page_number) || ((last_page < page_number) && (last_page > 0)); rot_ang = pi->rotation; rotate_flag = (rot_ang != 0.0) ? TRUE : FALSE; if (rotate_flag) { rot_cos = cos(M_PI * rot_ang / 180.0); rot_sin = sin(M_PI * rot_ang / 180.0); } vec_cntr_r = 0L; vec_cntr_w = 0L; n_unexpected = 0; n_commands = 0; n_unknown = 0; if (pi->hwlimit.x > 0.) P2.x = S2.x = pi->hwlimit.x; if (pi->hwlimit.y > 0.) P2.y = S2.y = pi->hwlimit.y; reset_HPGL(); } static void User_to_Plotter_coord(const HPGL_Pt * p_usr, HPGL_Pt * p_plot) /** ** Utility: Transformation from (scaled) user coordinates ** to plotter coordinates **/ { p_plot->x = P1.x + (p_usr->x - S1.x) * Q.x; p_plot->y = P1.y + (p_usr->y - S1.y) * Q.y; } static void Plotter_to_User_coord(const HPGL_Pt * p_plot, HPGL_Pt * p_usr) /** ** Utility: Transformation from plotter coordinates ** to (scaled) user coordinates **/ { p_usr->x = S1.x + (p_plot->x - P1.x) / Q.x; p_usr->y = S1.y + (p_plot->y - P1.y) / Q.y; } void PlotCmd_to_tmpfile(PlotCmd cmd) { if (record_off) /* Wrong page! */ return; if (!silent_mode) switch (vec_cntr_w++) { case 0: Eprintf("Writing Cmd: "); break; case 1: Eprintf("1 "); break; case 2: Eprintf("2 "); break; case 5: Eprintf("5 "); break; case 10: Eprintf("10 "); break; case 20: Eprintf("20 "); break; case 50: Eprintf("50 "); break; case 100: Eprintf("100 "); break; case 200: Eprintf("200 "); break; case 500: Eprintf("500 "); break; case 1000: Eprintf("1k "); break; case 2000: Eprintf("2k "); break; case 5000: Eprintf("5k "); break; case 10000: Eprintf("10k "); break; case 20000: Eprintf("20k "); break; case 50000L: Eprintf("50k "); break; case 100000L: Eprintf("100k "); break; case 200000L: Eprintf("200k "); break; case 500000L: Eprintf("500k "); break; case 1000000L: Eprintf("1000k "); break; case 2000000L: Eprintf("2000k "); break; case 3000000L: Eprintf("3000k "); break; case 4000000L: Eprintf("4000k "); break; case 5000000L: Eprintf("5000k... "); break; case 10000000L: Eprintf("10000k "); break; } if (fputc((int) cmd, td) == EOF) { PError("PlotCmd_to_tmpfile"); Eprintf("Error @ Cmd %ld\n", vec_cntr_w); exit(ERROR); } } void HPGL_Pt_to_tmpfile(const HPGL_Pt * pf) { if (record_off) /* Wrong page! */ return; if (fwrite((VOID *) pf, sizeof(*pf), 1, td) != 1) { PError("HPGL_Pt_to_tmpfile"); Eprintf("Error @ Cmd %ld\n", vec_cntr_w); exit(ERROR); } xmin = MIN(pf->x, xmin); ymin = MIN(pf->y, ymin); xmax = MAX(pf->x, xmax); ymax = MAX(pf->y, ymax); } void HPGL_Pt_to_polygon(HPGL_Pt pf) { if (record_off) /* Wrong page! */ return; polygons[++vertices] = pf; if (rotate_flag) { double tmp = rot_cos * pf.x - rot_sin * pf.y; pf.y = rot_sin * pf.x + rot_cos * pf.y; pf.x = tmp; } xmin = MIN(pf.x, xmin); ymin = MIN(pf.y, ymin); xmax = MAX(pf.x, xmax); ymax = MAX(pf.y, ymax); } /** ** Low-level vector generation & file I/O **/ static void LPattern_Generator(HPGL_Pt * pa, double dx, double dy, double start_of_pat, double end_of_pat) /** ** Generator of Line type patterns: ** ** pa: Start point (ptr) of current line segment ** dx, dy: Components of c * (*pb - *pa), c holding ** dx^2 + dy^2 = pattern_length^2 ** start_of_pat: Fraction of start point within pattern ** end_of_pat: Fraction of end point within pattern ** Valid: 0 <= start_of_pat <= end_of_pat <= 1 ** ** A pattern consists of alternating "line"/"point" and "gap" elements, ** always starting with a line/point. A point is a line of zero length. ** The table below contains the relative lengths of the elements ** of all line types except LT0; and LT; (7), which are treated separately. ** These lengths always add up to 1. A negative value terminates a pattern. **/ { double length_of_ele, start_of_action, end_of_action; static double *p_cur_pat; p_cur_pat = lt[(LT_MIN * -1) + (int) CurrentLinePattern]; /* was CurrentLineType */ if (CurrentLineType == LT_adaptive) for (;;) { length_of_ele = (double) *p_cur_pat++ / 100; /* Line or point */ if (length_of_ele < 0.) return; if (length_of_ele < 1.e-5) PlotCmd_to_tmpfile(PLOT_AT); else PlotCmd_to_tmpfile(DRAW_TO); pa->x += dx * length_of_ele; pa->y += dy * length_of_ele; HPGL_Pt_to_tmpfile(pa); length_of_ele = (double) *p_cur_pat++ / 100; /* Gap */ if (length_of_ele < 0.) return; pa->x += dx * length_of_ele; pa->y += dy * length_of_ele; PlotCmd_to_tmpfile(MOVE_TO); HPGL_Pt_to_tmpfile(pa); } else /* LT_fixed */ for (end_of_action = 0.0;;) { /** ** Line or point: **/ start_of_action = end_of_action; length_of_ele = (double) *p_cur_pat++ / 100; if (length_of_ele < 0.) return; if (length_of_ele < 1.e-5) { /* Dot Only */ PlotCmd_to_tmpfile(PLOT_AT); HPGL_Pt_to_tmpfile(pa); } else { /* Line Segment */ end_of_action += length_of_ele; if (end_of_action > start_of_pat) { /* If anything to do: */ if (start_of_pat <= start_of_action) { /* If start is valid */ if (end_of_action <= end_of_pat) { /* Draw full element */ pa->x += dx * length_of_ele; pa->y += dy * length_of_ele; PlotCmd_to_tmpfile (DRAW_TO); HPGL_Pt_to_tmpfile (pa); } else /* End_of_action beyond End_of_pattern: */ { /* --> Draw only first part of element: */ pa->x += dx * (end_of_pat - start_of_action); pa->y += dy * (end_of_pat - start_of_action); PlotCmd_to_tmpfile (DRAW_TO); HPGL_Pt_to_tmpfile (pa); return; } } else /* Start_of_action before Start_of_pattern: */ { if (end_of_action <= end_of_pat) { /* Draw remainder of element */ pa->x += dx * (end_of_action - start_of_pat); pa->y += dy * (end_of_action - start_of_pat); PlotCmd_to_tmpfile (DRAW_TO); HPGL_Pt_to_tmpfile (pa); } else /* End_of_action beyond End_of_pattern: */ /* Draw central part of element & leave */ { if (end_of_pat == start_of_pat) PlotCmd_to_tmpfile (PLOT_AT); else PlotCmd_to_tmpfile (DRAW_TO); pa->x += dx * (end_of_pat - start_of_pat); pa->y += dy * (end_of_pat - start_of_pat); HPGL_Pt_to_tmpfile (pa); return; } } } } /** ** Gap (analogous to line/point): **/ start_of_action = end_of_action; length_of_ele = (double) *p_cur_pat++ / 100; if (length_of_ele < 0) return; end_of_action += length_of_ele; if (end_of_action > start_of_pat) { /* If anything to do: */ if (start_of_pat <= start_of_action) { /* If start is valid */ if (end_of_action <= end_of_pat) { /* Full gap */ pa->x += dx * length_of_ele; pa->y += dy * length_of_ele; PlotCmd_to_tmpfile (MOVE_TO); HPGL_Pt_to_tmpfile(pa); } else /* End_of_action beyond End_of_pattern: */ { /* --> Apply only first part of gap: */ pa->x += dx * (end_of_pat - start_of_action); pa->y += dy * (end_of_pat - start_of_action); PlotCmd_to_tmpfile (MOVE_TO); HPGL_Pt_to_tmpfile(pa); return; } } else /* Start_of_action before Start_of_pattern: */ { if (end_of_action <= end_of_pat) { /* Apply remainder of gap */ pa->x += dx * (end_of_action - start_of_pat); pa->y += dy * (end_of_action - start_of_pat); PlotCmd_to_tmpfile (MOVE_TO); HPGL_Pt_to_tmpfile(pa); } else /* End_of_action beyond End_of_pattern: */ /* Apply central part of gap & leave */ { if (end_of_pat == start_of_pat) return; /* A null move */ pa->x += dx * (end_of_pat - start_of_pat); pa->y += dy * (end_of_pat - start_of_pat); PlotCmd_to_tmpfile (MOVE_TO); HPGL_Pt_to_tmpfile(pa); return; } } } } } /** ** Rectangles -- by Th. Hiller (hiller@tu-harburg.d400.de) **/ static void rect(int relative, int filled, float cur_pensize, HPGL_Pt p) { HPGL_Pt p1; if (relative) { /* Process coordinates */ p.x += p_last.x; p.y += p_last.y; } if (!filled) { p1.x = p_last.x; p1.y = p.y; Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag); p1.x = p.x; p1.y = p.y; Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag); p1.x = p.x; p1.y = p_last.y; Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag); p1.x = p_last.x; p1.y = p_last.y; Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag); } else { vertices = -1; HPGL_Pt_to_polygon(p_last); p1.x = p_last.x; p1.y = p.y; HPGL_Pt_to_polygon(p1); HPGL_Pt_to_polygon(p1); HPGL_Pt_to_polygon(p); HPGL_Pt_to_polygon(p); p1.x = p.x; p1.y = p_last.y; HPGL_Pt_to_polygon(p1); HPGL_Pt_to_polygon(p1); HPGL_Pt_to_polygon(p_last); if (hatchspace == 0.) hatchspace = cur_pensize; if (filltype < 3 && thickness > 0.) hatchspace = thickness; if (ac_flag == 0) { /* not yet initialized */ anchor.x = P1.x; anchor.y = P1.y; /* fprintf(stderr,"anchor init to P1\n");*/ /* anchor.y=MIN(P1.y,ymin); */ } fill(polygons, vertices, anchor, P2, scale_flag, filltype, hatchspace, hatchangle); } Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag); } static void rects(int relative, int filled, float cur_pensize, FILE * hd) { HPGL_Pt p; for (;;) { if (read_float(&p.x, hd)) /* No number found */ return; if (read_float(&p.y, hd)) /* x without y invalid! */ par_err_exit(2, EA, hd); rect(relative, filled, cur_pensize, p); } } /* struct PE_flags{ int abs; int up; int sbmode; int fract; int pen; } ; */ int read_PE_flags(GEN_PAR * pg, int c, FILE * hd, PE_flags * fl) { short old_pen; float ftmp; int ctmp; switch (c) { case 183: case '7': /* seven bit mode */ fl->sbmode = 1; break; case 185: case '9': /* rectangle mode */ fl->rect = 1; fl->up = 1; break; case 186: case ':': /* select pen */ if (EOF == (fl->pen = getc(hd))) { par_err_exit(98, PE, hd); } old_pen = pen; read_PE_coord(fl->pen, hd, fl, &ftmp); pen = (short) ftmp; if (pen < 0 || (int) pen > pg->maxpens) { Eprintf ("\nIllegal pen number %d: replaced by %d\n", pen, pen % pg->maxpens); n_unexpected++; pen = pen % pg->maxpens; } if (pen == 0 && pg->mapzero > -1) pen = pg->mapzero; if (old_pen != pen) { if ((fputc(SET_PEN, td) == EOF) || (fputc(pen, td) == EOF)) { PError("Writing to temporary file:"); Eprintf("Error @ Cmd %ld\n", vec_cntr_w); exit(ERROR); } } if (pen) pens_in_use[pen] = 1; pg->maxcolor = MAX(pg->maxcolor, (int) pen); /*MK */ break; case 190: case '>': /* fractional data */ if (EOF == (ctmp = getc(hd))) { par_err_exit(98, PE, hd); } fl->fract = decode_PE_char(ctmp, fl); fl->fract = ((fl->fract >> 1) * ((fl->fract & 0x01) ? -1 : 1)); /* fprintf(stderr,"PE > flag, fract =%d (%d decimals) ",fl->fract, fl->fract/3); */ break; case 188: case '<': /* pen up */ fl->up = 1; fl->rect = 0; break; case 189: case '=': /* abs plotting */ fl->abs = 1; break; default: return (0); } return (1); } int isPEterm(int c, PE_flags * fl) { if ((fl->sbmode) && ((c > 94) || (c < 63))) return 1; if ((!fl->sbmode) && ((c > 190) || (c < 63))) return 1; return (0); } int decode_PE_char(int c, PE_flags * fl) { if (fl->sbmode) { c &= 0x7f; return ((c > 94) ? (c - 95) : (c - 63)); } else { return ((c > 190) ? (c - 191) : (c - 63)); } } int read_PE_coord(int c, FILE * hd, PE_flags * fl, float *fv) { long lv = 0; int i = 0; int shft = (fl->sbmode) ? 5 : 6; for (;;) { if (c < 63) { if (!i) { /* avoid endless getc/ungetc loop with broken files */ Eprintf("error in PE data!\n"); return 0; } ungetc(c, hd); break; } lv |= ((long) decode_PE_char(c, fl)) << (i * shft); i++; if (isPEterm(c, fl)) { break; } if (EOF == (c = getc(hd))) { par_err_exit(98, PE, hd); } } *fv = (float) (((lv >> 1) * ((lv & 0x01) ? -1 : 1)) << fl->fract); return (1); } int read_PE_pair(int c, FILE * hd, PE_flags * fl, HPGL_Pt * p) { if (!read_PE_coord(c, hd, fl, &(p->x))) return 0; if (EOF == (c = getc(hd))) { par_err_exit(98, PE, hd); } if (!read_PE_coord(c, hd, fl, &(p->y))) return 0; return (1); } void read_PE(GEN_PAR * pg, FILE * hd) { int c; HPGL_Pt p; PE_flags fl; fl.fract = 0; fl.sbmode = 0; fl.abs = 0; fl.up = 0; fl.pen = 0; for (c = getc(hd); (c != EOF) && (c != ';'); c = getc(hd)) { if (!read_PE_flags(pg, c, hd, &fl)) { if (!read_PE_pair(c, hd, &fl, &p)) continue; switch (fl.rect) { case 1: pen_down = 0; line(!fl.abs, p); fl.rect = 2; break; case 2: pen_down = 1; rect(1, pg->nofill ? 0 : 1, pt.width[pen], p); fl.rect = 1; /* should be up when PE ends while */ /* in PE mode */ pen_down = 0; break; default: pen_down = (fl.up) ? FALSE : TRUE; line(!fl.abs, p); fl.up = 0; break; } fl.abs = 0; tp->CR_point = HP_pos; } } } double ceil_with_tolerance(double x, double tol) { double rounded; /* rounded=rint(x);*/ rounded = (double) (x + 0.5); if (fabs(rounded - x) <= tol) return (rounded); else return (ceil(x)); } static void Line_Generator(HPGL_Pt * pa, const HPGL_Pt * pb, int mv_flag) { double seg_len, dx, dy, quot; int n_pat, i; dx = pb->x - pa->x; dy = pb->y - pa->y; seg_len = HYPOT(dx, dy); switch (CurrentLineType) { case LT_solid: if (seg_len < 1.e-8) { if (!silent_mode) Eprintf ("Warning: Zero line segment length -- skipped\n"); return; /* No line to draw ?? */ } PlotCmd_to_tmpfile(DRAW_TO); HPGL_Pt_to_tmpfile(pb); return; case LT_adaptive: if (seg_len < 1.e-8) { if (!silent_mode) Eprintf ("Warning: Zero line segment length -- skipped\n"); return; /* No line to draw ?? */ } pat_pos = 0.0; /* Reset to start-of-pattern */ n_pat = (int) ceil_with_tolerance(seg_len / CurrentLinePatLen, CurrentLinePatLen * LT_PATTERN_TOL); if (n_pat == 0) { /* sanity check for segment << pattern length */ n_pat = 1; if (!silent_mode) fprintf(stderr, "very short pattern run encountered\n"); } dx /= n_pat; dy /= n_pat; /* Now draw n_pat complete line patterns */ for (i = 0; i < n_pat; i++) LPattern_Generator(pa, dx, dy, 0.0, 1.0); return; case LT_plot_at: PlotCmd_to_tmpfile(PLOT_AT); HPGL_Pt_to_tmpfile(pb); return; case LT_fixed: if (seg_len < 1.e-8) { if (!silent_mode) Eprintf ("Warning: Zero line segment length -- skipped\n"); return; /* No line to draw ?? */ } if (mv_flag) /* Last move ends old line pattern */ pat_pos = 0.0; quot = seg_len / CurrentLinePatLen; dx /= quot; dy /= quot; while (quot >= 1.0) { LPattern_Generator(pa, dx, dy, pat_pos, 1.0); quot -= (1.0 - pat_pos); pat_pos = 0.0; } quot += pat_pos; if (quot >= 1.0) { LPattern_Generator(pa, dx, dy, pat_pos, 1.0); quot -= 1.0; pat_pos = 0.0; } if (quot > LT_PATTERN_TOL) { LPattern_Generator(pa, dx, dy, pat_pos, quot); pat_pos = quot; } else { PlotCmd_to_tmpfile(MOVE_TO); HPGL_Pt_to_tmpfile(pb); } return; default: break; } } void Pen_action_to_tmpfile(PlotCmd cmd, const HPGL_Pt * p, int scaled) { static HPGL_Pt P_last; HPGL_Pt P; double tmp; if (record_off) /* Wrong page! */ return; if (scaled) /* Rescaling */ User_to_Plotter_coord(p, &P); else P = *p; /* Local copy */ HP_pos = P; /* Actual plotter pos. in plotter coord */ if (rotate_flag) { /* hp2xx-specific global rotation */ tmp = rot_cos * P.x - rot_sin * P.y; P.y = rot_sin * P.x + rot_cos * P.y; P.x = tmp; } /* Extreme values needed for later scaling: */ switch (cmd) { case MOVE_TO: mv_flag = TRUE; break; /** ** Multiple-move suppression. In addition, ** a move only precedes a draw -- nothing else! **/ case DRAW_TO: if (mv_flag) { PlotCmd_to_tmpfile(MOVE_TO); HPGL_Pt_to_tmpfile(&P_last); } /* drop through */ case PLOT_AT: Line_Generator(&P_last, &P, mv_flag); mv_flag = FALSE; break; default: Eprintf("Illegal Pen Action: %d\n", cmd); Eprintf("Error @ Cmd %ld\n", vec_cntr_w); exit(ERROR); } P_last = P; } int read_float(float *pnum, FILE * hd) /** ** Main work-horse for parameter input: ** ** Search for next number, skipping white space but return if mnemonic met. ** If found, read in number ** returns 0 if valid number ** 1 if command ended ** 2 if scanf failed (possibly corrupted file) ** EOF if EOF met **/ { int c; char *ptr, numbuf[80]; for (c = getc(hd); (c != '.') && (c != '+') && (c != '-') && ((c < '0') || (c > '9')); c = getc(hd)) { if (c == EOF) /* Wait for number */ return EOF; /* Should not happen */ if (c == ';') return 1; /* Terminator reached */ if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'a')) || (c == ESC)) { ungetc(c, hd); return 1; /* Next Mnemonic reached */ } } /* Number found: Get it */ ptr = numbuf; for (*ptr++ = c, c = getc(hd); ((c >= '0') && (c <= '9')) || (c == '.'); c = getc(hd)) *ptr++ = c; /* Read number */ *ptr = '\0'; if (c != EOF) ungetc(c, hd); if (sscanf(numbuf, "%f", pnum) != 1) return 11; /* Should never happen */ return 0; } void read_string(char *buf, FILE * hd) { int c; unsigned int n; for (n = 0, c = getc(hd); (c != EOF) && (c != StrTerm); c = getc(hd)) { if (n > strbufsize / 2) { strbufsize *= 2; strbuf = realloc(strbuf, strbufsize); if (strbuf == NULL) { fprintf(stderr, "\nNo memory !\n"); exit(ERROR); } buf = strbuf + n; } if (c == '\0') continue; /* ignore \0 */ if (n++ < strbufsize) *buf++ = c; } if (c != StrTerm || StrTermSilent == 0) *buf++ = c; *buf = '\0'; } static void read_symbol_char(FILE * hd) { int c; for (c = getc(hd); /* ended by switch{} */ ; c = getc(hd)) switch (c) { case ' ': case _HT: case _LF: break; /* Skip white space */ case _CR: case EOF: case ';': /* CR or "term" end symbol mode */ symbol_char = '\0'; return; default: if (c < ' ' || c > '~') break; /* Ignore unprintable chars */ else { symbol_char = c; return; } } } static void read_ESC_HP7550A(FILE * hd) /* * Read & skip HP 7550A control commands (ESC.-Commands) */ { int c; switch (getc(hd)) { case EOF: n_unexpected++; Eprintf("\nUnexpected EOF!\n"); return; break; case 'A': case 'B': case 'E': case 'J': case 'K': case 'L': case 'O': case 'U': case 'Y': case '(': case ')': return; /* Commands without parameters */ case '@': case 'H': case 'I': case 'M': case 'N': case 'P': case 'Q': case 'S': case 'T': do { /* Search for terminator ':' */ c = getc(hd); } while ((c != ':') && (c != EOF)); if (c == EOF) { n_unexpected++; Eprintf("\nUnexpected EOF!\n"); } return; default: n_unknown++; return; } } static int read_PJL(FILE * hd) /* * a simple PJL parser * just reads PJL header and * return * TRUE if PJL enters HPGL context, * FALSE if not * * * PJL lines are like this: * @PJL[ command][ args][\r]\n * (however I've seen some wrong PJL files with \n\r ) * @PJL must be uppercase, ther rest of string is not * case sensitive * The last line of a PJL header is like these: * @PJL ENTER LANGUAGE = HPGL2 * @PJL EOJ [NAME = "something"] */ { #define PJLBS 257 char strbuf[PJLBS]; int i, j, ov, ctmp, qt, el = 0, nw = 0, rc = -2, nl = 0; for (;;) { /* read word */ for (i = ov = qt = 0;; i++) { ctmp = getc(hd); if (ctmp == ESC) { while (ctmp != 'X') ctmp = getc(hd); ctmp = getc(hd); } if (PJLBS - 1 == i) { if (!silent_mode) Eprintf ("PJL buffer overflow, rest of token dropped\n"); ov = 1; strbuf[i] = '\0'; } if (!ov) strbuf[i] = (0 == nw || qt) ? ctmp : toupper(ctmp); if (EOF == ctmp) { if (!ov) strbuf[i] = 0; break; } else if ('=' == ctmp && 0 == i) { strbuf[i] = '='; strbuf[++i] = '\0'; ctmp = ' '; break; } else if (strchr(" \t=", ctmp)) { if (!qt) { if (!ov) strbuf[i] = 0; break; } } else if ('\n' == ctmp || '\r' == ctmp) { if (!ov) strbuf[i] = 0; nl = 1; break; } else if ('"' == ctmp) { qt = !qt; } } /* handle word */ if (i) { #ifdef DEBUG_ESC Eprintf("word %d: read %d bytes: '%s'\n", nw, i, strbuf); #endif if (0 == nw && strcmp(strbuf, "@PJL")) { Eprintf ("unexpected end of a PJL header!\n"); return (TRUE); } else if (1 == nw && !strcmp(strbuf, "EOJ")) { if (!silent_mode) Eprintf("end of a PJL job\n"); rc = TRUE; } else if (1 == nw && !strcmp(strbuf, "ENTER")) { el++; } else if (2 == nw && 1 == el && !strcmp(strbuf, "LANGUAGE")) { el++; } else if (3 == nw && 2 == el && !strcmp(strbuf, "=")) { el++; } else if (4 == nw && 3 == el) { if (!silent_mode) Eprintf("Entering %s context\n", strbuf); rc = strncmp(strbuf, "HPGL", 4) ? FALSE : TRUE; } nw++; } /* read separator */ for (j = 0; EOF != ctmp; j++) { if (!strchr(" \t\n\r", ctmp)) { ungetc(ctmp, hd); break; } ctmp = getc(hd); if ('\n' == ctmp) { nl = 1; } } #ifdef DEBUG_ESC if (j) Eprintf("separator: read %d bytes\n", j); #endif if (nl) { nw = el = nl = 0; if (-2 != rc) return rc; } if (EOF == ctmp) { if (!silent_mode) Eprintf("EOF in PJL context\n"); return (FALSE); } } } static void read_ESC_RTL(FILE * hd, int c1, int hp) /* *read and skip ESC% control commands */ { /* * known escapes: * ESC%-12345X UEL (Universal Escape Language) * followed by @PJL.. * * ESC%-1B Enter HPGL/2 context * ESC%0B - * ESC%1B - * * ESC%1A Exit HPGL/2 context * ESC%0A - * ESC%-1A - * how a PCL escape looks like: * ESC, lowercase letters and digits, an Upper case letter */ int c0, c2, ctmp = 0, nf; for (c0 = ESC, c2 = getc(hd), nf = 0; EOF != c2; c0 = c1, c1 = c2, c2 = getc(hd)) { if ((ESC == c0) && (c1 == '%')) { if ('-' == c2) { c2 = getc(hd); nf = 1; } switch (c2) { case EOF: n_unexpected++; Eprintf("\nUnexpected EOF!\n"); return; break; case '1': case '0': switch (ctmp = getc(hd)) { case 'A': if (hp && !silent_mode) { #ifdef DEBUG_ESC Eprintf ("leaving HPGL context\n"); #endif hp = FALSE; } continue; case 'B': #ifdef DEBUG_ESC if (!silent_mode && !hp) Eprintf ("entering HPGL context\n"); #endif return; case '2': /* check for UEL */ if (nf && '1' == c2 && '3' == (c2 = getc(hd)) && '4' == (c2 = getc(hd)) && '5' == (c2 = getc(hd)) && 'X' == (c2 = getc(hd))) { #ifdef DEBUG_ESC if (!silent_mode) Eprintf ("UEL found\n"); #endif if (read_PJL(hd)) { return; } else { hp = 0; continue; } } else { ungetc(ctmp, hd); if (hp) return; } break; default: if (!silent_mode) Eprintf ("unknown escape: ESC%%%s%c%c\n", nf ? "-" : "", c2, ctmp); ungetc(ctmp, hd); if (hp) return; } break; default: if (!silent_mode) Eprintf ("unknown escape: ESC%%%s%c", nf ? "-" : "", c2); ungetc(ctmp, hd); if (hp) return; break; } } if (hp == TRUE && !nf && c1 != '%' && c1 != 'E') { ungetc(ctmp, hd); if (!silent_mode) Eprintf("invalid escape ESC%c%c\n", c1, c2); return; } } } static void read_ESC_cmd(FILE * hd, int hp) /* * Read & skip device control commands (ESC.-Commands) */ { int ctmp; switch (ctmp = getc(hd)) { case '.': read_ESC_HP7550A(hd); break; case EOF: n_unexpected++; Eprintf("\nUnexpected EOF!\n"); return; default: read_ESC_RTL(hd, ctmp, hp); break; } } /****************************************************************************/ /** ** lines: Process PA-, PR-, PU-, and PD- commands **/ static void lines(int relative, FILE * hd) /** ** Examples of anticipated commands: ** ** PA PD0,0,80,50,90,20PU140,30PD150,80; ** PU0,0;PD20.53,40.32,30.08,60.2,40,90,;PU100,300;PD120,340... **/ { HPGL_Pt p; int numcmds = 0; int outside = 0; double p1x, p1y, p2x, p2y; for (;;) { if (read_float(&p.x, hd)) { /* No number found */ if (numcmds > 0) return; if (pen_down && mv_flag && pen > 0 && pt.width[pen] < 0.35) { /*simulate dot created by 'real' pen on PD;PU; */ /*but not on PDPA */ p.x = p_last.x + 0.01; p.y = p_last.y + 0.01; outside = 0; if (iwflag) { p1x = P1.x + (p_last.x - S1.x) * Q.x; p1y = P1.y + (p_last.y - S1.y) * Q.y; p2x = P1.x + (p.x - S1.x) * Q.x; p2y = P1.y + (p.y - S1.y) * Q.y; outside = (DtClipLine (C1.x, C1.y, C2.x, C2.y, &p1x, &p1y, &p2x, &p2y) == CLIP_NODRAW); } if (!outside) { Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag); Pen_action_to_tmpfile(DRAW_TO, &p_last, scale_flag); } } return; } if (read_float(&p.y, hd)) /* x without y invalid! */ par_err_exit(2, PA, hd); line(relative, p); numcmds++; } } /* * line : process a pair of coordinates */ void line(int relative, HPGL_Pt p) { HPGL_Pt pl, porig; int outside = 0; double x1, y1, x2, y2; if (relative) { p.x += p_last.x; p.y += p_last.y; } porig.x = p.x; porig.y = p.y; if (iwflag) { x1 = P1.x + (p_last.x - S1.x) * Q.x; y1 = P1.y + (p_last.y - S1.y) * Q.y; x2 = P1.x + (p.x - S1.x) * Q.x; y2 = P1.y + (p.y - S1.y) * Q.y; outside = (DtClipLine(C1.x, C1.y, C2.x, C2.y, &x1, &y1, &x2, &y2) == CLIP_NODRAW); if (!outside) { p.x = (x2 - P1.x) / Q.x + S1.x; p.y = (y2 - P1.y) / Q.y + S1.y; pl.x = (x1 - P1.x) / Q.x + S1.x; pl.y = (y1 - P1.y) / Q.y + S1.y; if (pl.x != p_last.x || pl.y != p_last.y) Pen_action_to_tmpfile(MOVE_TO, &pl, scale_flag); } } else pl = p_last; if (polygon_mode && polygon_penup) pen_down = FALSE; if (pen_down && !outside) { if (polygon_mode) { HPGL_Pt_to_polygon(pl); HPGL_Pt_to_polygon(p); /* fprintf(stderr,"polygon line1: %f %f - %f %f\n",p_last.x,p_last.y,p.x,p.y);*/ } else { Pen_action_to_tmpfile(DRAW_TO, &p, scale_flag); /* fprintf(stderr,"std line1: %f %f - %f %f\n",p_last.x,p_last.y,p.x,p.y); */ } } else { if (iwflag) { Pen_action_to_tmpfile(MOVE_TO, &porig, scale_flag); } else { Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag); } } if (polygon_mode && polygon_penup) { polygon_penup = FALSE; polystart = p; pen_down = TRUE; } if (symbol_char) { plot_symbol_char(symbol_char); Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag); } outside = 0; p_last = porig; } /** ** Arcs, circles and alike **/ static void arc_increment(HPGL_Pt * pcenter, double r, double phi) { HPGL_Pt p; int outside = 0; p.x = pcenter->x + r * cos(phi); p.y = pcenter->y + r * sin(phi); if (iwflag) { if (P1.x + (p.x - S1.x) * Q.x > C2.x || P1.y + (p.y - S1.y) * Q.y > C2.y) { /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */ outside = 1; } if (P1.x + (p.x - S1.x) * Q.x < C1.x || P1.y + (p.y - S1.y) * Q.y < C1.y) { /*fprintf(stderr,"IW set:point %f %f C2.x || P1.y + (p.y - S1.y) * Q.y > C2.y) { /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */ outside = 1; } if (P1.x + (p.x - S1.x) * Q.x < C1.x || P1.y + (p.y - S1.y) * Q.y < C1.y) { /*fprintf(stderr,"IW set:point %f %f 0.0) { for (phi = phi0 + MIN(eps, alpha); phi < phi0 + alpha; phi += eps) arc_increment(¢er, r, phi); arc_increment(¢er, r, phi0 + alpha); /* to endpoint */ } else { for (phi = phi0 - MIN(eps, -alpha); phi > phi0 + alpha; phi -= eps) arc_increment(¢er, r, phi); arc_increment(¢er, r, phi0 + alpha); /* to endpoint */ } CurrentLinePatLen = SafeLinePatLen; /* Restore */ p_last.x = p_last.x + p3.x; p_last.y = p_last.y + p3.y; } static void arcs(int relative, FILE * hd) { HPGL_Pt p, d, center; float alpha, eps; double phi, phi0, r; double SafeLinePatLen = CurrentLinePatLen; if (read_float(&p.x, hd)) /* No number found */ return; if (read_float(&p.y, hd)) /* x without y invalid! */ par_err_exit(2, AA, hd); if (read_float(&alpha, hd)) /* Invalid without angle */ par_err_exit(3, AA, hd); else alpha *= M_PI / 180.0; /* Deg-to-Rad */ switch (read_float(&eps, hd)) { case 0: if (eps < 0.5) eps = 0.5; break; case 1: /* No resolution option */ eps = 5.0; /* so use default! */ break; case 2: /* Illegal state */ par_err_exit(98, AA, hd); case EOF: return; default: /* Illegal state */ par_err_exit(99, AA, hd); } if (ct_dist == FALSE) eps *= M_PI / 180.0; /* Deg-to-Rad */ if (relative) { /* Process coordinates */ d = p; /* Difference vector */ center.x = d.x + p_last.x; center.y = d.y + p_last.y; } else { d.x = p.x - p_last.x; d.y = p.y - p_last.y; center.x = p.x; center.y = p.y; } if (((r = sqrt(d.x * d.x + d.y * d.y)) == 0.0) || (alpha == 0.0)) return; /* Zero radius or zero arc angle given */ if (ct_dist == TRUE) eps = 2. * acos((r - eps) / r); phi0 = atan2(-d.y, -d.x); if (CurrentLineType == LT_adaptive) { /* Adaptive patterns: */ p.x = r * cos(eps); /* A chord segment */ p.y = r * sin(eps); if (scale_flag) User_to_Plotter_coord(&p, &p); /* Pattern length = chord length */ CurrentLinePatLen = HYPOT(p.x, p.y); } if (alpha > 0.0) { for (phi = phi0 + MIN(eps, alpha); phi < phi0 + alpha; phi += eps) arc_increment(¢er, r, phi); arc_increment(¢er, r, phi0 + alpha); /* to endpoint */ } else { for (phi = phi0 - MIN(eps, -alpha); phi > phi0 + alpha; phi -= eps) arc_increment(¢er, r, phi); arc_increment(¢er, r, phi0 + alpha); /* to endpoint */ } CurrentLinePatLen = SafeLinePatLen; /* Restore */ } static void fwedges(FILE * hd, float cur_pensize) { /*derived from circles */ HPGL_Pt p, oldp, center; float eps, r, start, sweep; double phi; double SafeLinePatLen = CurrentLinePatLen; int outside = 0; int i; if (read_float(&r, hd)) /* No radius found */ return; if (read_float(&start, hd)) /* No start angle found */ return; if (read_float(&sweep, hd)) /* No sweep angle found */ return; switch (read_float(&eps, hd)) { /* chord angle */ case 0: if (eps < 0.5) eps = 0.5; break; case 1: /* No resolution option */ eps = 5.0; /* so use default! */ break; case 2: /* Illegal state */ par_err_exit(98, EW, hd); case EOF: return; default: /* Illegal state */ par_err_exit(99, EW, hd); } if (ct_dist == TRUE) eps = 2. * acos((r - eps) / r); else eps *= M_PI / 180.0; /* Deg-to-Rad */ start *= M_PI / 180.0; /* Deg-to-Rad */ sweep *= M_PI / 180.0; /* Deg-to-Rad */ center = p_last; /* reference point is last position */ vertices = -1; /* clear the polygon buffer */ if (r == 0.0) /* Zero radius given */ return; HPGL_Pt_to_polygon(p_last); p.x = center.x + r * cos(start); p.y = center.y + r * sin(start); HPGL_Pt_to_polygon(p); if (CurrentLineType == LT_adaptive) { /* Adaptive patterns */ p.x = r * cos(eps); /* A chord segment */ p.y = r * sin(eps); if (scale_flag) User_to_Plotter_coord(&p, &p); /* Pattern length = chord length */ CurrentLinePatLen = HYPOT(p.x, p.y); } i = 1; for (phi = eps; phi <= sweep; phi += eps) { oldp = p; p.x = center.x + r * cos(start + phi); p.y = center.y + r * sin(start + phi); if (iwflag) { if (P1.x + (p.x - S1.x) * Q.x > C2.x || P1.y + (p.y - S1.y) * Q.y > C2.y) { /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */ outside = 1; } if (P1.x + (p.x - S1.x) * Q.x < C1.x || P1.y + (p.y - S1.y) * Q.y < C1.y) { /*fprintf(stderr,"IW set:point %f %f 0.) hatchspace = thickness; if (!ac_flag) { /* not yet initialized */ anchor.x = P1.x; anchor.y = P1.y; } fill(polygons, vertices, anchor, P2, scale_flag, filltype, hatchspace, hatchangle); CurrentLinePatLen = SafeLinePatLen; /* Restore */ } static void circles(FILE * hd) { HPGL_Pt p, center, polyp; float eps, r; double phi; double SafeLinePatLen = CurrentLinePatLen; int outside = 0; if (read_float(&r, hd)) /* No radius found */ return; switch (read_float(&eps, hd)) { case 0: if (eps < 0.5) eps = 0.5; break; case 1: /* No resolution option */ eps = 5.0; /* so use default! */ break; case 2: /* Illegal state */ par_err_exit(98, CI, hd); case EOF: return; default: /* Illegal state */ par_err_exit(99, CI, hd); } if (ct_dist == TRUE) eps = 2. * acos((r - eps) / r); else eps *= M_PI / 180.0; /* Deg-to-Rad */ center = p_last; if (r == 0.0) /* Zero radius given */ return; p.x = center.x + r; p.y = center.y; Pen_action_to_tmpfile(MOVE_TO, &p, scale_flag); if (polygon_mode) { polyp.x = p.x; polyp.y = p.y; } if (CurrentLineType == LT_adaptive) { /* Adaptive patterns */ p.x = r * cos(eps); /* A chord segment */ p.y = r * sin(eps); if (scale_flag) User_to_Plotter_coord(&p, &p); /* Pattern length = chord length */ CurrentLinePatLen = HYPOT(p.x, p.y); } for (phi = eps; phi < 2.0 * M_PI; phi += eps) { p.x = center.x + r * cos(phi); p.y = center.y + r * sin(phi); if (iwflag) { if (P1.x + (p.x - S1.x) * Q.x > C2.x || P1.y + (p.y - S1.y) * Q.y > C2.y) { /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */ outside = 1; } if (P1.x + (p.x - S1.x) * Q.x < C1.x || P1.y + (p.y - S1.y) * Q.y < C1.y) { /*fprintf(stderr,"IW set:point %f %f C2.x || P1.y + (p.y - S1.y) * Q.y > C2.y) { /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */ outside = 1; } if (P1.x + (p.x - S1.x) * Q.x < C1.x || P1.y + (p.y - S1.y) * Q.y < C1.y) { /*fprintf(stderr,"IW set:point %f %f C2.x || P1.y + (p.y - S1.y) * Q.y > C2.y) { /*fprintf(stderr,"IW set:point %f %f >P2\n",p.x,p.y); */ outside = 1; } if (P1.x + (p.x - S1.x) * Q.x < C1.x || P1.y + (p.y - S1.y) * Q.y < C1.y) { /*fprintf(stderr,"IW set:point %f %f CR_point = HP_pos; break; case AR: /* Arc Relative */ arcs(TRUE, hd); tp->CR_point = HP_pos; break; case AT: /* Arc Absolute, through Three points */ tarcs(FALSE, hd); break; case BR: /* cubic bezier curve, relative control points */ bezier(TRUE, hd); break; case BZ: /* cubic bezier curve, absolute control points */ bezier(FALSE, hd); break; case AC: /* anchor corner of fill patterns */ if (read_float(&ftmp, hd)) { /* just AC - default hard-clip limit */ anchor.x = P1.x; anchor.y = P1.y; if (scale_flag) User_to_Plotter_coord(&anchor, &anchor); break; } else { ac_flag = 1; anchor.x = ftmp; } if (read_float(&ftmp, hd)) anchor.y = 0.; else anchor.y = ftmp; if (scale_flag) User_to_Plotter_coord(&anchor, &anchor); break; case AD: if (read_float(&ftmp, hd)) /* just AD - defaults */ tp->altfont = 0; else { switch ((int) ftmp) { case 1: /* charset */ if (read_float(&csfont, hd)) par_err_exit(2, cmd, hd); else tp->altfont = (int) csfont; break; case 2: /* fixed or variable spacing */ if (read_float(&csfont, hd)) par_err_exit(2, cmd, hd); else if ((int) csfont == 1 && !silent_mode) fprintf(stderr, "only fixed fonts available\n"); break; case 3: /* font pitch */ case 4: /* font height */ case 5: /* posture */ case 6: /* stroke weight */ if (read_float(&ftmp, hd)) par_err_exit(2, cmd, hd); if (ftmp == 9999) tp->astrokewidth = ftmp; else { if (ftmp < -7. || ftmp > 7.) ftmp = 0.; tp->astrokewidth = 0.11 + ftmp / 70.; /* 0.01 ... 0.21 mm */ } break; case 7: /* typeface */ if (read_float(&csfont, hd)) par_err_exit(2, cmd, hd); else if (!silent_mode) fprintf(stderr, "pitch/height/posture/typeface unsupported\n"); break; default: par_err_exit(1, cmd, hd); } } break; case CA: /* Alternate character set */ if (read_float(&csfont, hd)) /* just CA; */ tp->altfont = 0; else tp->altfont = (int) csfont; break; case CI: /* Circle */ circles(hd); break; case CO: /* Comment */ SafeTerm = StrTerm; StrTerm = ';'; read_string(tmpstr, hd); StrTerm = SafeTerm; if (strlen(tmpstr) > 0) tmpstr[strlen(tmpstr) - 1] = '\0'; if (!silent_mode) printf("\n%s\n", tmpstr); break; case CR: /* color range */ if (read_float(&ftmp, hd)) { r_base = g_base = b_base = 0; r_max = g_max = b_max = 255; break; } else { r_base = (unsigned char) ftmp; } if (read_float(&ftmp, hd)) { r_max = 255; break; } else { r_max = (unsigned char) ftmp; } if (read_float(&ftmp, hd)) { break; } else { g_base = (unsigned char) ftmp; } if (read_float(&ftmp, hd)) { g_max = 255; break; } else { g_max = (unsigned char) ftmp; } if (read_float(&ftmp, hd)) { break; } else { b_base = (unsigned char) ftmp; } if (read_float(&ftmp, hd)) { b_max = 255; break; } else { b_max = (unsigned char) ftmp; break; } case CS: /*character set selection */ if (read_float(&csfont, hd)) /* just CS; */ tp->font = 0; else tp->font = (int) csfont; tp->stdfont = tp->font; break; case CT: /* chord tolerance */ if (read_float(&ftmp, hd) || ftmp != 1.) ct_dist = FALSE; else ct_dist = TRUE; break; case EP: /* edge polygon */ if (polygon_penup == TRUE) if (p_last.x != polystart.x || p_last.y != polystart.y) vertices -= 2; for (i = 0; i < vertices; i = i + 2) { /*for all polygon edges */ p1.x = polygons[i].x; p1.y = polygons[i].y; Pen_action_to_tmpfile(MOVE_TO, &p1, scale_flag); p1.x = polygons[i + 1].x; p1.y = polygons[i + 1].y; Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag); } Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag); break; case EW: /* Edge Wedge */ wedges(hd); break; case EC: /* printf("cut paper\n"); */ break; case FP: /* fill polygon */ if (pg->nofill) { /* treat like EP */ if (!silent_mode) fprintf(stderr, "FP : suppressed\n"); for (i = 0; i < vertices; i = i + 2) { /*for all polygon edges */ p1.x = polygons[i].x; p1.y = polygons[i].y; Pen_action_to_tmpfile(MOVE_TO, &p1, scale_flag); p1.x = polygons[i + 1].x; p1.y = polygons[i + 1].y; Pen_action_to_tmpfile(DRAW_TO, &p1, scale_flag); } Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag); break; } if (hatchspace == 0.) hatchspace = pt.width[pen]; if (filltype < 3 && thickness > 0.) hatchspace = thickness; if (!ac_flag) { /* not yet initialized */ anchor.x = P1.x; anchor.y = P1.y; } fill(polygons, vertices, anchor, P2, scale_flag, filltype, hatchspace, hatchangle); Pen_action_to_tmpfile(MOVE_TO, &p_last, scale_flag); break; case FT: /* Fill Type */ if (read_float(&ftmp, hd)) { /* just FT -> FT=1 */ filltype = 1; break; } else { filltype = (int) ftmp; } if (filltype < 3) break; if (filltype > 4) { if (FoundUserFill == 0) { FoundUserFill = 1; if (!silent_mode) fprintf(stderr, "\nNo support for user-defined fill types, using type 1 instead\n"); } filltype = 1; break; } if (read_float(&ftmp, hd)) { hatchspace = saved_hatchspace[filltype - 3]; if (hatchspace == 0.) hatchspace = 0.01 * Diag_P1_P2; hatchangle = saved_hatchangle[filltype - 3]; break; } else { if (ftmp <= 0.) ftmp = 0.01 * Diag_P1_P2; hatchspace = ftmp; saved_hatchspace[filltype - 3] = hatchspace; } if (read_float(&ftmp, hd)) { hatchangle = saved_hatchangle[filltype - 3]; break; } else { hatchangle = ftmp; saved_hatchangle[filltype - 3] = hatchangle; } break; case NP: /* Number of Pens */ if (read_float(&ftmp, hd) || ftmp > NUMPENS) /* invalid or missing */ break; else { pg->maxpens = (int) ftmp; if (!silent_mode) fprintf(stderr, "NP: %d pens requested\n", pg->maxpens); } break; case NR: /*Not ready - pause plotter (noop) */ if (read_float(&ftmp, hd)) break; break; case PA: /* Plot Absolute */ lines(plot_rel = FALSE, hd); tp->CR_point = HP_pos; break; case PC: /* Pen Color */ if (read_float(&ftmp, hd) || fixedcolor || (int) ftmp > pg->maxpens) { /* invalid or missing */ break; } else { mypen = (int) ftmp; if (pg->mapzero == mypen) break; /* this color is remapped for pen 0, ignore original definition */ if (read_float(&ftmp, hd)) /* no red component */ myred = 0; else myred = 255 * (ftmp - r_base) / r_max; if (read_float(&ftmp, hd)) /* no green component */ mygreen = 0; else mygreen = 255 * (ftmp - g_base) / g_max; if (read_float(&ftmp, hd)) /* no blue component */ myblue = 0; else myblue = 255 * (ftmp - b_base) / b_max; pg->is_color = TRUE; PlotCmd_to_tmpfile(DEF_PC); if (mypen == 0 && pg->mapzero > -1) mypen = pg->mapzero; Pen_Color_to_tmpfile(mypen, myred, mygreen, myblue); break; } case PD: /* Pen Down */ pen_down = TRUE; lines(plot_rel, hd); tp->CR_point = HP_pos; break; case PE: read_PE(pg, hd); tp->CR_point = HP_pos; break; case PM: if (read_float(&ftmp, hd) || ftmp == 0) { /* no parameters or PM0 */ polygon_mode = TRUE; polygon_penup = FALSE; saved_penstate = pen_down; vertices = -1; polystart = p_last; break; } if (ftmp == 1) { if (vertices > 0) polygon_penup = TRUE; pen_down = FALSE; break; } if (ftmp == 2) { polygon_mode = FALSE; pen_down = saved_penstate; if (p_last.x != polystart.x || p_last.y != polystart.y) { int outside = 0; double x1, y1, x2, y2; if (iwflag) { x1 = P1.x + (p_last.x - S1.x) * Q.x; y1 = P1.y + (p_last.y - S1.y) * Q.y; x2 = P1.x + (polystart.x - S1.x) * Q.x; y2 = P1.y + (polystart.y - S1.y) * Q.y; outside = (DtClipLine (C1.x, C1.y, C2.x, C2.y, &x1, &y1, &x2, &y2) == CLIP_NODRAW); if (!outside) { p_last.x = (x2 - P1.x) / Q.x + S1.x; p_last.y = (y2 - P1.y) / Q.y + S1.y; polystart.x = (x1 - P1.x) / Q.x + S1.x; polystart.y = (y1 - P1.y) / Q.y + S1.y; } } if (!outside) { HPGL_Pt_to_polygon(p_last); HPGL_Pt_to_polygon(polystart); /* force closing of open polygon */ } } } break; case PR: /* Plot Relative */ lines(plot_rel = TRUE, hd); tp->CR_point = HP_pos; break; case PS: if (read_float(&ftmp, hd) || ftmp == 0.) { /* no parameters or PS0; */ break; } else { myheight = ftmp; } if (read_float(&ftmp, hd)) { /* no parameters */ mywidth = P2.y; } else { mywidth = ftmp; if (mywidth > myheight) { mywidth = myheight; myheight = ftmp; } } if (pg->no_ps == TRUE) { if (!silent_mode) Eprintf("PS: suppressed\n"); break; } ps_flag = 1; /* fprintf(stderr,"min,max vor PS: %f %f %f %f\n",xmin,ymin,xmax,ymax);*/ M.x = myheight; M.y = mywidth; p1.x = 0; p1.y = 0; if (scale_flag) /* Rescaling */ User_to_Plotter_coord(&p1, &p2); else p2 = p1; /* Local copy */ if (rotate_flag) { /* hp2xx-specific global rotation */ ftmp = rot_cos * p2.x - rot_sin * p2.y; p2.y = rot_sin * p2.x + rot_cos * p2.y; p2.x = ftmp; } xmin = MIN(p2.x, xmin); ymin = MIN(p2.y, ymin); xmax = MAX(p2.x, xmax); ymax = MAX(p2.y, ymax); p1.x = myheight; p1.y = mywidth; if (scale_flag) /* Rescaling */ User_to_Plotter_coord(&p1, &p2); else p2 = p1; /* Local copy */ if (rotate_flag) { /* hp2xx-specific global rotation */ ftmp = rot_cos * p2.x - rot_sin * p2.y; p2.y = rot_sin * p2.x + rot_cos * p2.y; p2.x = ftmp; } xmin = MIN(p2.x, xmin); ymin = MIN(p2.y, ymin); xmax = MAX(p2.x, xmax); ymax = MAX(p2.y, ymax); /* fprintf(stderr,"min,max vor PS: %f %f %f %f\n",xmin,ymin,xmax,ymax);*/ /* add the following - to get the correct linetype scale etc */ P1.x = 0.; P1.y = 0.; P2.x = myheight; P2.y = mywidth; if (rotate_flag) { P2.x = mywidth; P2.y = myheight; } Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y); CurrentLinePatLen = 0.04 * Diag_P1_P2; S1 = P1; S2 = P2; /* ajb */ break; case PT: /* Pen thickness (for solid fills - current pen only */ if (read_float(&ftmp, hd)) { /* no parameters */ thickness = 0.3; break; } else { if (ftmp >= 0.1 && ftmp <= 5.) thickness = ftmp; } case PU: /* Pen Up */ pen_down = FALSE; if (polygon_mode) polygon_penup = TRUE; lines(plot_rel, hd); tp->CR_point = HP_pos; break; case PW: /* Pen Width */ if (fixedwidth) { if (!silent_mode) fprintf(stderr, "PW: ignored (hardware mode)\n"); break; } if (read_float(&ftmp, hd)) { /* no parameters -> set defaults */ mywidth = 0.35; /* FIXME - scaling here ! */ if (wu_relative) mywidth = Diag_P1_P2 / 1000.; if (mywidth < 0.1) mywidth = 0.1; PlotCmd_to_tmpfile(DEF_PW); Pen_Width_to_tmpfile(0, mywidth); /* fprintf(stderr,"PW: defaulting to 0.35 for all pens\n"); */ break; } else { mywidth = ftmp; /* first or only parameter is width */ if (wu_relative) mywidth = Diag_P1_P2 * ftmp / 1000.; if (mywidth < 0.1) mywidth = 0.1; } if (read_float(&ftmp, hd)) { /* width only, applies to all pens */ PlotCmd_to_tmpfile(DEF_PW); Pen_Width_to_tmpfile(0, mywidth); if (pg->maxpensize < mywidth) pg->maxpensize = mywidth; /* fprintf(stderr,"PW: defaulting to %f for all pens\n",mywidth); */ } else { /* second parameter is pen */ PlotCmd_to_tmpfile(DEF_PW); Pen_Width_to_tmpfile((int) ftmp, mywidth); if ((int) ftmp <= pg->maxpens) { if (pg->maxpensize < mywidth) pg->maxpensize = mywidth; } /* fprintf(stderr,"pen%d, size now %f\n",(int) ftmp,mywidth); */ } break; case TL: /* Tick Length */ if (read_float(&ftmp, hd)) { /* No number found */ neg_ticklen = pos_ticklen = 0.005; return; } else pos_ticklen = ftmp / 100.0; if (read_float(&ftmp, hd)) { /* pos, but not neg */ neg_ticklen = 0.0; return; } else neg_ticklen = ftmp / 100.0; break; case WG: /* Filled Wedge */ fwedges(hd, pt.width[pen]); break; case WU: /* pen Width Unit is relative */ if (read_float(&ftmp, hd) || ftmp == 0.) /* Zero or no number */ wu_relative = FALSE; else wu_relative = TRUE; break; case XT: /* X Tick */ ax_ticks(0); break; case YT: /* Y Tick */ ax_ticks(1); break; case IP: /* Input reference Points P1,P2 */ tp->width /= (P2.x - P1.x); tp->height /= (P2.y - P1.y); if (read_float(&p1.x, hd)) { /* No number found */ P1.x = P1X_default; P1.y = P1Y_default; P2.x = P2X_default; P2.y = P2Y_default; goto IP_Exit; } if (read_float(&p1.y, hd)) /* x without y! */ par_err_exit(2, cmd, hd); if (read_float(&p2.x, hd)) { /* No number found */ P2.x += p1.x - P1.x; P2.y += p1.y - P1.y; P1 = p1; goto IP_Exit; } if (read_float(&p2.y, hd)) /* x without y! */ par_err_exit(4, cmd, hd); P1 = p1; P2 = p2; IP_Exit: S1 = P1; S2 = P2; Q.x = (P2.x - P1.x) / (S2.x - S1.x); Q.y = (P2.y - P1.y) / (S2.y - S1.y); Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y); CurrentLinePatLen = 0.04 * Diag_P1_P2; tp->width *= (P2.x - P1.x); tp->height *= (P2.y - P1.y); adjust_text_par(); return; case IR: /* input reference points P1,P2 as percentages of defaults */ if (read_float(&p1.x, hd)) /* No number found */ return; /* keep defaults */ if (read_float(&p1.y, hd)) /* x without y! */ par_err_exit(2, cmd, hd); /*fprintf(stderr,"P1,P2 vor IR: %f %f, %f %f\n",P1.x,P1.y,P2.x,P2.y);*/ mywidth = P2.x - P1.x; myheight = P2.y - P1.y; ftmp = p1.x; p1.x = P1.x; /* need old value for computation of new P2 */ P1.x = p1.x + ftmp / 100. * mywidth; ftmp = p1.y; p1.y = P1.y; P1.y = p1.y + ftmp / 100. * myheight; if (read_float(&p2.x, hd)) { /* No number found */ P2.x = P1.x + mywidth; /* P2 tracks new P1 too keep constant size */ P2.y = P1.y + myheight; /*fprintf(stderr,"P1,P2 nach IR: %f %f, %f %f\n",P1.x,P1.y,P2.x,P2.y);*/ return; } if (read_float(&p2.y, hd)) /* x without y! */ par_err_exit(4, cmd, hd); P2.x = p1.x + p2.x / 100. * mywidth; P2.y = p1.y + p2.y / 100. * myheight; if (P1.x == P2.x) P2.x = P2.x + 1.; if (P1.y == P2.y) P2.y = P2.y + 1.; fprintf(stderr, "P1,P2 nach IR: %f %f, %f %f\n", P1.x, P1.y, P2.x, P2.y); Q.x = (P2.x - P1.x) / (S2.x - S1.x); Q.y = (P2.y - P1.y) / (S2.y - S1.y); Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y); CurrentLinePatLen = 0.04 * Diag_P1_P2; tp->width *= (P2.x - P1.x); tp->height *= (P2.y - P1.y); adjust_text_par(); return; case IW: iwflag = 1; if (read_float(&C1.x, hd)) { /* No number found */ if (P1.x == P1X_default && P1.y == P1Y_default && P2.x == P2X_default && P2.y == P2Y_default) { iwflag = 0; break; } C1 = P1; C2 = P2; if (scale_flag) { C1 = S1; C2 = S2; } if (rotate_flag && !ps_flag) { switch ((int) fabs(rot_tmp)) { case 90: case 270: ftmp = C1.x; C1.x = C1.y; C1.y = ftmp; ftmp = C2.x; C2.x = C2.y; C2.y = ftmp; break; default: break; } } } else { if (read_float(&C1.y, hd)) /* x without y! */ par_err_exit(2, cmd, hd); if (read_float(&C2.x, hd)) /* No number found */ par_err_exit(3, cmd, hd); if (read_float(&C2.y, hd)) /* x without y! */ par_err_exit(4, cmd, hd); } /*fprintf (stderr," clip limits (%f,%f)(%f,%f)\n",C1.x,C1.y,C2.x,C2.y);*/ if (scale_flag) { User_to_Plotter_coord(&C1, &C1); User_to_Plotter_coord(&C2, &C2); } if (C2.x < C1.x) { ftmp = C2.x; C2.x = C1.x; C1.x = ftmp; } if (C2.y < C1.y) { ftmp = C2.y; C2.y = C1.y; C1.y = ftmp; } C1.x -= pg->extraclip; C1.y -= pg->extraclip; C2.x += pg->extraclip; C2.y += pg->extraclip; break; case OP: /* Output reference Points P1,P2 */ if (!silent_mode) { Eprintf("\nP1 = (%g, %g)\n", P1.x, P1.y); Eprintf("P2 = (%g, %g)\n", P2.x, P2.y); } break; case OW: /* Output clip box */ if (!silent_mode) { Eprintf("\nC1 = (%g, %g)\n", C1.x, C1.y); Eprintf("C2 = (%g, %g)\n", C2.x, C2.y); } break; case AF: case AH: case PG: /* new PaGe */ /* record ON happens only once! */ page_number++; /* fprintf(stderr, "PG: page_number now %d\n", page_number);*/ record_off = (first_page > page_number) || ((last_page < page_number) && (last_page > 0)); pg_flag = TRUE; return; break; case EA: /* Edge Rectangle absolute */ rects(plot_rel = FALSE, 0, pt.width[pen], hd); tp->CR_point = HP_pos; break; case ER: /* Edge Rectangle relative */ rects(TRUE, 0, 0., hd); tp->CR_point = HP_pos; break; case RA: /* Fill Rectangle absolute */ rects(plot_rel = FALSE, 1, pt.width[pen], hd); tp->CR_point = HP_pos; break; case RR: /* Fill Rectangle relative */ rects(plot_rel = TRUE, 1, pt.width[pen], hd); tp->CR_point = HP_pos; break; case RT: /* Relative arc, through Three points */ tarcs(TRUE, hd); break; case LT: /* Line Type: */ if (read_float(&p1.x, hd)) /* just LT; */ CurrentLineType = LT_solid; else { if ((((int) p1.x) >= LT_MIN) && (((int) p1.x) < LT_ZERO)) CurrentLineType = LT_adaptive; else if (((int) p1.x) == LT_ZERO) CurrentLineType = LT_plot_at; else if ((((int) p1.x) > LT_ZERO) && (((int) p1.x) <= LT_MAX)) CurrentLineType = LT_fixed; else { Eprintf("Illegal line type:\t%d\n", (int) p1.x); CurrentLineType = LT_solid; /* set to something sane */ } CurrentLinePattern = (int) p1.x; if (!read_float(&p1.y, hd)) { /* optional pattern length? */ if (p1.y <= 0.0) Eprintf ("Illegal pattern length:\t%g\n", p1.y); else { Diag_P1_P2 = HYPOT(P2.x - P1.x, P2.y - P1.y); if (!read_float(&ftmp, hd)) { if (ftmp == 1.0) { CurrentLinePatLen = p1.y * 40; /* absolute */ } else { CurrentLinePatLen = Diag_P1_P2 * p1.y / 100.0; /* relative */ } } else { CurrentLinePatLen = Diag_P1_P2 * p1.y / 100.0; /* relative */ } } } } break; case SC: /* Input Scale Points S1,S2 */ User_to_Plotter_coord(&p_last, &p_last); if (read_float(&p1.x, hd)) { /* No number found */ S1.x = P1X_default; S1.y = P1Y_default; S2.x = P2X_default; S2.y = P2Y_default; scale_flag = FALSE; Q.x = Q.y = 1.0; break; } if (read_float(&p2.x, hd)) /* x without y! */ par_err_exit(2, cmd, hd); if (read_float(&p1.y, hd)) /* No number found */ par_err_exit(3, cmd, hd); if (read_float(&p2.y, hd)) /* x without y! */ par_err_exit(4, cmd, hd); if (p1.x == p2.x || p1.y == p2.y) { /* min must differ from max */ if (!silent_mode) Eprintf ("Warning: Invalid SC command parameters -- ignored\n"); Q.x = Q.y = 1.0; break; } S1.x = p1.x; S1.y = p1.y; S2.x = p2.x; S2.y = p2.y; if (read_float(&ftmp, hd)) ftmp = 0; /*scaling defaults to type 0 */ switch ((int) ftmp) { case 0: /* anisotropic scaling */ Q.x = (P2.x - P1.x) / (S2.x - S1.x); Q.y = (P2.y - P1.y) / (S2.y - S1.y); break; case 1: /* isotropic scaling */ if (read_float(&ftmp, hd)) /* percentage of unused space on the left */ ftmp = 50.0; /* of the isotropic area defaults to 50% */ Q.x = (P2.x - P1.x) / (S2.x - S1.x); Q.y = (P2.y - P1.y) / (S2.y - S1.y); if (Q.x < Q.y) { if (read_float(&ftmp, hd)) ftmp = 50.0; /* percentage of unused space below the plot */ S1.y += ftmp * ((P2.y - P1.y) / Q.y - (P2.y - P1.y) / Q.x) / 100.0; Q.y = Q.x; S2.y = S1.y + (P2.y - P1.y) / Q.y; } else { S1.x += ftmp * ((P2.x - P1.x) / Q.x - (P2.x - P1.x) / Q.y) / 100.0; read_float(&ftmp, hd); /* mandatory 'bottom' value is unused */ Q.x = Q.y; S2.x = S1.x + (P2.x - P1.x) / Q.x; } break; case 2: /* point factor scaling */ Q.x = S2.x; Q.y = S2.y; S2.x = S1.x + (P2.x - P1.x) / Q.x; S2.y = S1.y + (P2.y - P1.y) / Q.y; break; default: par_err_exit(0, cmd, hd); } scale_flag = TRUE; Plotter_to_User_coord(&p_last, &p_last); break; case SP: /* Select pen: none/0, or number */ old_pen = pen; thickness = 0.; /* clear any PT setting (should we default to 0.3 here ??) */ if (read_float(&p1.x, hd)) /* just SP; */ pen = 0; else { pen = (short) p1.x; if (pen == 0 && pg->mapzero > -1) pen = pg->mapzero; } if (pen < 0 || (int) pen > pg->maxpens) { Eprintf ("\nIllegal pen number %d: replaced by %d\n", pen, pen % pg->maxpens); n_unexpected++; pen = pen % pg->maxpens; } if (old_pen != pen) { if ((fputc(SET_PEN, td) == EOF) || (fputc(pen, td) == EOF)) { PError("Writing to temporary file:"); Eprintf("Error @ Cmd %ld\n", vec_cntr_w); exit(ERROR); } } if (pen) pens_in_use[pen] = 1; pg->maxcolor = MAX(pg->maxcolor, (int) pen); /* pens_in_use |= (1 << (pen-1)); */ break; case BP: /* Begin Plot */ for (;;) { if (read_float(&ftmp, hd)) { /* No number found */ break; } else { switch ((int) ftmp) { case 1: /* picture name follows */ tmpstr[0] = fgetc(hd); /* skip comma */ tmpstr[0] = fgetc(hd); if (!silent_mode) fprintf(stderr, "HPGL picture name: %c", tmpstr[0]); if (tmpstr[0] == '"') { tmpstr[0] = ' '; do { tmpstr[0] = fgetc(hd); if (!silent_mode) fputc (tmpstr [0], stderr); } while (tmpstr[0] != '"'); } if (!silent_mode) fprintf(stderr, "\n"); break; case 2: /* number of copies */ case 3: /* disposition code */ case 4: /* render unfinished */ case 5: /* autorotation */ if (read_float(&ftmp, hd)) break; break; default: break; } } } /* fall through to initialization code now */ case DF: /* Set to default */ case IN: /* Initialize */ reset_HPGL(); tp->CR_point = HP_pos; break; case RO: if (read_float(&ftmp, hd)) { /* No number found */ break; } else { /*if (!silent_mode) fprintf (stderr, "RO encountered, rotating P1,P2 by %f\n", ftmp); */ rotate_flag = 1; rot_ang += ftmp; rot_tmp = ftmp; switch ((int) ftmp) { case 90: case 270: ftmp = M.x; M.x = M.y; M.y = ftmp; break; case 0: case 180: break; default: rotate_flag = 0; break; } /* if (!silent_mode) fprintf (stderr, "cumulative rot_ang now %f\n", rot_ang); */ rot_cos = cos(M_PI * rot_ang / 180.0); rot_sin = sin(M_PI * rot_ang / 180.0); if (ps_flag) { /* transform extents from previous PS statement */ xmin = 1e10; ymin = 1e10; xmax = 1e-10; ymax = 1e-10; p1.x = 0; p1.y = 0; if (scale_flag) /* Rescaling */ User_to_Plotter_coord(&p1, &p2); else p2 = p1; /* Local copy */ HP_pos = p2; /* Actual plotter pos. in plotter coord */ ftmp = rot_cos * p2.x - rot_sin * p2.y; p2.y = rot_sin * p2.x + rot_cos * p2.y; p2.x = ftmp; xmin = MIN(p2.x, xmin); ymin = MIN(p2.y, ymin); xmax = MAX(p2.x, xmax); ymax = MAX(p2.y, ymax); p1.x = M.x; p1.y = M.y; if (scale_flag) /* Rescaling */ User_to_Plotter_coord(&p1, &p2); else p2 = p1; /* Local copy */ HP_pos = p2; /* Actual plotter pos. in plotter coord */ ftmp = rot_cos * p2.x - rot_sin * p2.y; p2.y = rot_sin * p2.x + rot_cos * p2.y; p2.x = ftmp; xmin = MIN(p2.x, xmin); ymin = MIN(p2.y, ymin); xmax = MAX(p2.x, xmax); ymax = MAX(p2.y, ymax); } } break; case BL: /* Buffer label string */ read_string(strbuf, hd); break; case CP: /* Char Plot (rather: move) */ if (read_float(&p1.x, hd)) { /* No number found */ plot_string("\n\r", LB_direct, pen); return; } else if (read_float(&p1.y, hd)) par_err_exit(2, cmd, hd); p2.x = p1.x * tp->chardiff.x - p1.y * tp->linediff.x + HP_pos.x; p2.y = p1.x * tp->chardiff.y - p1.y * tp->linediff.y + HP_pos.y; Pen_action_to_tmpfile(MOVE_TO, &p2, FALSE); break; case DI: /* Char plot Dir (absolute) */ if (read_float(&p1.x, hd)) { /* No number found */ tp->dir = 0.0; tp->CR_point = HP_pos; adjust_text_par(); break; } if (read_float(&p1.y, hd)) /* x, but not y */ par_err_exit(2, cmd, hd); if ((p1.x == 0.0) && (p1.y == 0.0)) par_err_exit(0, cmd, hd); tp->dir = atan2(p1.y, p1.x); tp->CR_point = HP_pos; adjust_text_par(); break; case DR: /* Char plot Dir (rel P1,P2) */ if (read_float(&p1.x, hd)) { /* No number found */ tp->dir = 0.0; tp->CR_point = HP_pos; adjust_text_par(); break; } if (read_float(&p1.y, hd)) par_err_exit(2, cmd, hd); /* x, but not y */ if ((p1.x == 0.0) && (p1.y == 0.0)) par_err_exit(0, cmd, hd); tp->dir = atan2(p1.y * (P2.y - P1.y), p1.x * (P2.x - P1.x)); tp->CR_point = HP_pos; adjust_text_par(); break; case DT: /* Define string terminator */ StrTerm = getc(hd); if (StrTerm == ';') { /*just DT */ StrTerm = ETX; StrTermSilent = 1; break; } if (read_float(&ftmp, hd)) { StrTermSilent = 1; } else StrTermSilent = (short) ftmp; break; case DV: /* Text direction vertical */ if (read_float(&ftmp, hd) || ftmp == 0) mode_vert = 0; else mode_vert = 1; break; case ES: /* Extra Space */ if (read_float(&tp->espace, hd)) { /* No number found */ tp->espace = 0.0; tp->eline = 0.0; } else if (read_float(&tp->eline, hd)) tp->eline = 0.0; /* Supply default */ adjust_text_par(); break; case LA: /* Line Attributes */ set_line_attr(hd); break; case LB: /* Label string */ read_string(strbuf, hd); plot_string(strbuf, LB_direct, pen); /* * Bug fix by W. Eric Norum: * Update the position so that subsequent `PR's will work. */ if (scale_flag) Plotter_to_User_coord(&HP_pos, &p_last); else p_last = HP_pos; break; case LO: /* Label Origin */ if (read_float(&p1.x, hd)) /* No number found */ tp->orig = 1; else { tp->orig = (int) p1.x; if (tp->orig < 1 || tp->orig == 10 || tp->orig > 19) tp->orig = 1; /* Error */ } adjust_text_par(); break; case PB: /* Plot Buffered label string */ plot_string(strbuf, LB_buffered, pen); break; case SI: /* Char cell Sizes (absolute) */ if (read_float(&tp->width, hd)) { /* No number found */ tp->width = 0.187; /* [cm], A4 */ tp->height = 0.269; /* [cm], A4 */ } else { if (read_float(&tp->height, hd)) par_err_exit(2, cmd, hd); if ((tp->width == 0.0) || (tp->height == 0.0)) par_err_exit(0, cmd, hd); } tp->width *= 400.0; /* [cm] --> [plotter units] */ tp->height *= 400.0; /* [cm] --> [plotter units] */ adjust_text_par(); break; case SL: /* Char Slant */ if (read_float(&tp->slant, hd)) /* No number found */ tp->slant = 0.0; adjust_text_par(); break; case SM: /* Symbol Mode */ read_symbol_char(hd); break; case SR: /* Character sizes (Rel P1,P2) */ if (read_float(&tp->width, hd)) { /* No number found */ tp->width = 0.75; /* % of (P2-P1)_x */ tp->height = 1.5; /* % of (P2-P1)_y */ } else { if (read_float(&tp->height, hd)) par_err_exit(2, (short) cmd, hd); if ((tp->width == 0.0) || (tp->height == 0.0)) par_err_exit(0, (short) cmd, hd); } tp->width *= (P2.x - P1.x) / 100.0; /* --> [pl. units] */ tp->height *= (P2.y - P1.y) / 100.0; adjust_text_par(); break; case SA: /* Select designated alternate charset */ if (tp->altfont) tp->font = tp->altfont; else /* Was never designated, default to 0 */ tp->font = 0; tp->strokewidth = tp->astrokewidth; break; case SD: if (read_float(&ftmp, hd)) /* just SD - defaults */ tp->stdfont = 0; else { switch ((int) ftmp) { case 1: /* charset */ if (read_float(&csfont, hd)) par_err_exit(2, cmd, hd); else tp->stdfont = (int) csfont; break; case 2: /* fixed or variable spacing */ if (read_float(&csfont, hd)) par_err_exit(2, cmd, hd); else if ((int) csfont == 1 && !silent_mode) fprintf(stderr, "only fixed fonts available\n"); break; case 3: /* font pitch */ case 4: /* font height */ case 5: /* posture */ case 6: /* stroke weight */ if (read_float(&ftmp, hd)) par_err_exit(2, cmd, hd); if (ftmp == 9999) tp->sstrokewidth = ftmp; else { if (ftmp < -7. || ftmp > 7.) ftmp = 0.; tp->sstrokewidth = 0.11 + ftmp / 70.; /* 0.01 ... 0.21 mm */ } break; case 7: /* typeface */ if (read_float(&csfont, hd)) par_err_exit(2, cmd, hd); else if (!silent_mode) fprintf(stderr, "pitch/height/posture/typeface unsupported\n"); break; default: par_err_exit(1, cmd, hd); } } break; case SS: /* Select designated standard character set */ if (tp->stdfont) tp->font = tp->stdfont; else /* Was never designated, default to 0 */ tp->font = 0; tp->strokewidth = tp->sstrokewidth; break; case UC: /* User defined character */ plot_user_char(hd, pen); break; case UL: /* User defined line style */ set_line_style_by_UL(hd); break; case MG: case WD: /* Write string to display */ read_string(strbuf, hd); if (!silent_mode) Eprintf("\nLABEL: %s\n", strbuf); break; case VS: if (read_float(&ftmp, hd)) /* Just VS */ break; if (read_float(&ftmp, hd)) /* uniform speed */ break; if (read_float(&ftmp, hd)) /* speed for given pen */ break; default: /* Skip unknown HPGL command: */ n_unknown++; if (!silent_mode) Eprintf(" %c%c: ignored ", cmd >> 8, cmd & 0xFF); if (cmd == EOF) { n_unexpected++; if (!silent_mode) Eprintf("\nUnexpected EOF!\t"); } break; } } void read_HPGL(GEN_PAR * pg, const IN_PAR * pi) /** ** This routine is the high-level entry for HP-GL processing. ** It reads the input stream character-by-character, identifies ** ESC. commands (device controls) and HP-GL mnemonics, reads ** parameters (if expected), and initiates processing of these ** commands. It finally reports on this parsing process. **/ { int c; int cmd; vec_cntr_r = 0L; vec_cntr_w = 0L; n_unexpected = 0; n_commands = 0; n_unknown = 0; if ((c = getc(pi->hd)) == EOF) return; else ungetc(c, pi->hd); if (!pg_flag) init_HPGL(pg, pi); if (!pg->quiet) Eprintf("\nReading HPGL file\n"); /** ** MAIN parser LOOP!! **/ while ((c = getc(pi->hd)) != EOF) { switch (c) { #ifdef MUTOH_KLUGE case '\a': Eprintf("Mutoh header found\n"); read_ESC_cmd(pi->hd, FALSE); /* ESC sequence */ break; #endif case ESC: read_ESC_cmd(pi->hd, TRUE); /* ESC sequence */ break; default: if ((c < 'A') || (c > 'z') || ((c > 'Z') && (c < 'a'))) break; if (c == 'P') { if ((cmd = getc(pi->hd)) == 'G') { page_number++; /* fprintf(stderr, "stream-reading PG: page_number now %d\n", page_number);*/ record_off = (first_page > page_number) || ((last_page < page_number) && (last_page > 0)); goto END; } else { if (cmd == EOF) return; ungetc(cmd, pi->hd); } } if (c == 'N') { if ((cmd = getc(pi->hd)) == 'R') { /* fprintf(stderr,"***NR***\n");'*/ page_number++; /* fprintf(stderr, "stream-reading NR: page_number now %d\n", page_number);*/ record_off = (first_page > page_number) || ((last_page < page_number) && (last_page > 0)); goto END; } else { if (cmd == EOF) return; ungetc(cmd, pi->hd); } } if (c == 'A') { cmd = getc(pi->hd); if (cmd == 'F' || cmd == 'H') { /* fprintf(stderr,"***AF/AH***\n");*/ page_number++; /* fprintf(stderr, "stream-reading AF/AH: page_number now %d\n", page_number);*/ record_off = (first_page > page_number) || ((last_page < page_number) && (last_page > 0)); goto END; } else { if (cmd == EOF) return; ungetc(cmd, pi->hd); } } cmd = c << 8; if ((c = getc(pi->hd)) == EOF) return; if ((c < 'A') || (c > 'z') || ((c > 'Z') && (c < 'a'))) { ungetc(c, pi->hd); break; } cmd |= (c & 0xFF); n_commands++; read_HPGL_cmd(pg, cmd, pi->hd); } } if (c == EOF) { page_number++; /* fprintf(stderr, "EOF : page_number now %d\n", page_number);*/ } END: if (!pg->quiet && n_commands > 0) { Eprintf("Page number %d of range %d - %d\n", page_number - 1, pi->first_page, pi->last_page); Eprintf("\nHPGL commands read: %d\n", n_commands); Eprintf("HPGL command(s) ignored: %d\n", n_unknown); Eprintf("Unexpected event(s): %d\n", n_unexpected); Eprintf("Internal command(s): %ld\n", vec_cntr_w); if ((pi->first_page > page_number - 1) || ((pi->last_page < page_number - 1) && (pi->last_page > 0))) { n_commands = -1; Eprintf ("Page %d not drawn (outside selected range %d-%d)\n", page_number - 1, pi->first_page, pi->last_page); } Eprintf("Pens used: "); /* for (c=0; c < NUMPENS; c++, pens_in_use >>= 1) if (pens_in_use & 1) */ for (c = 0; c < NUMPENS; c++) if (pens_in_use[c] == 1) Eprintf("%d ", c); /* Eprintf ("%d ", c+1); */ Eprintf("\nMax. number of pages: %d\n", page_number - 1); } } void adjust_input_transform(const GEN_PAR * pg, const IN_PAR * pi, OUT_PAR * po) { /** ** The temporary input data of the temp. file may be re-used multiple ** times by calling this function with varying parameters, ** mainly in pi. ** ** Some conversion factors for transformation from HP-GL coordinates ** (as given in the temp. file) into mm or pel numbers are set here. ** There are both global parameters and elemts of po set here. ** DPI-related factors only apply if the current mode is a raster mode. ** ** # points (dots) in any direction = range [mm] * 1in/25.4mm * #dots/in **/ double dot_ratio, Dx, Dy, tmp_w, tmp_h; char *dir_str; Dx = xmax - xmin; Dy = ymax - ymin; dot_ratio = (double) po->dpi_y / (double) po->dpi_x; po->width = pi->width; po->height = pi->height; po->xoff = pi->xoff; po->yoff = pi->yoff; /* Width assuming given height: */ tmp_w = pi->height * Dx / Dy * pi->aspectfactor; /* tmp_w = pi->height * Dx / Dx / pi->aspectfactor; */ /* Height assuming given width: */ tmp_h = pi->width * Dy / Dx / pi->aspectfactor; /** ** EITHER width OR height MUST be the correct limit. The other will ** be adapted. Adaptation of both is inconsistent, except in truesize mode. **/ if (pi->truesize) { po->width = Dx / 40.0; /* Ignore -w, take natural HP-GL range */ po->height = Dy / 40.0; /* Ignore -h, take natural HP-GL range */ po->HP_to_xdots = (float) (po->dpi_x / 1016.0); /* dots per HP unit */ po->HP_to_ydots = (float) (po->dpi_y / 1016.0); /* (1/40 mm) */ dir_str = "true sizes"; if (pi->center_mode) { if (!pg->quiet) { fprintf(stderr, "trying to center image\n"); fprintf(stderr, "po->width ?width, tmp_w); fprintf(stderr, "po->height ?height, tmp_h); } if (po->width < tmp_w) po->xoff += (tmp_w - po->width) / 2.0; if (po->height < tmp_h) po->yoff += (tmp_h - po->height) / 2.0; } } else { /* if (po->width > tmp_w) */ if (Dy > Dx) { po->HP_to_ydots = (float) (po->dpi_y * po->height) / Dy / 25.4; po->HP_to_xdots = po->HP_to_ydots * pi->aspectfactor / dot_ratio; if (pi->center_mode) po->xoff += (po->width - tmp_w) / 2.0; /* by L. Lowe */ po->width = tmp_w; dir_str = "width adapted"; /* Height fits, adjust width */ } else { po->HP_to_xdots = (float) (po->dpi_x * po->width) / Dx / 25.4; po->HP_to_ydots = po->HP_to_xdots * dot_ratio / pi->aspectfactor; if (pi->center_mode) po->yoff += (po->height - tmp_h) / 2.0; /* by L. Lowe */ po->height = tmp_h; dir_str = "height adapted"; /* Width fits, adjust height */ } } if (!pg->quiet) { Eprintf("\nWidth x height: %5.2f x %5.2f mm, %s\n", po->width, po->height, dir_str); Eprintf("Coordinate range: (%g, %g) ... (%g, %g)\n", xmin, ymin, xmax, ymax); } po->xmin = xmin; po->xmax = xmax; po->ymin = ymin; po->ymax = ymax; } #ifdef EMF void reset_tmpfile(void) { (void) lseek(fileno(td), 0L, SEEK_SET); if (vec_cntr_r) again = TRUE; vec_cntr_r = 0; } #endif PlotCmd PlotCmd_from_tmpfile(void) { PlotCmd cmd; if (!silent_mode && !again) switch (vec_cntr_r++) { case 0: Eprintf("\nProcessing Cmd: "); break; case 1: Eprintf("1 "); break; case 2: Eprintf("2 "); break; case 5: Eprintf("5 "); break; case 10: Eprintf("10 "); break; case 20: Eprintf("20 "); break; case 50: Eprintf("50 "); break; case 100: Eprintf("100 "); break; case 200: Eprintf("200 "); break; case 500: Eprintf("500 "); break; case 1000: Eprintf("1k "); break; case 2000: Eprintf("2k "); break; case 5000: Eprintf("5k "); break; case 10000: Eprintf("10k "); break; case 20000: Eprintf("20k "); break; case 50000L: Eprintf("50k "); break; case 100000L: Eprintf("100k "); break; case 200000L: Eprintf("200k "); break; case 500000L: Eprintf("500k "); break; } switch (cmd = fgetc(td)) { case NOP: case MOVE_TO: case DRAW_TO: case PLOT_AT: case SET_PEN: case DEF_PW: case DEF_PC: case DEF_LA: return cmd; case (unsigned int) EOF: default: return CMD_EOF; } } void HPGL_Pt_from_tmpfile(HPGL_Pt * pf) { if (fread((VOID *) pf, sizeof(*pf), 1, td) != 1) { PError("HPGL_Pt_from_tmpfile"); Eprintf("Error @ Cmd %ld\n", vec_cntr_r); exit(ERROR); } if (pf->x < xmin || pf->x > xmax) Eprintf ("HPGL_Pt_from_tmpfile: x out of range (%g not in [%g, %g])\n", pf->x, xmin, xmax); if (pf->y < ymin || pf->y > ymax) Eprintf ("HPGL_Pt_from_tmpfile: y out of range (%g not in [%g, %g])\n", pf->y, ymin, ymax); }