1 /*
2    Copyright (c) 1991 - 1994 Heinz W. Werntges.  All rights reserved.
3    Distributed by Free Software Foundation, Inc.
4 
5 This file is part of HP2xx.
6 
7 HP2xx is distributed in the hope that it will be useful, but
8 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
9 to anyone for the consequences of using it or for whether it serves any
10 particular purpose or works at all, unless he says so in writing.  Refer
11 to the GNU General Public License, Version 2 or later, for full details.
12 
13 Everyone is granted permission to copy, modify and redistribute
14 HP2xx, but only under the conditions described in the GNU General Public
15 License.  A copy of this license is supposed to have been
16 given to you along with HP2xx so you can know your rights and
17 responsibilities.  It should be in a file named COPYING.  Among other
18 things, the copyright notice and this notice must be preserved on all
19 copies.
20 
21 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22 */
23 
24 /** to_rgip.c:   Converter to Uniplex RGIP format;
25  **    (very loosely derived from "to_eps.c")
26  **
27  ** By Gilles Gravier (corwin@ensta.fr)
28  ** 93/07/19  V 1.00       Derived from to_eps.c
29  ** 94/02/14  V 1.10a HWW  Adapted to changes in hp2xx.h
30  **/
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <math.h>
37 #include "bresnham.h"
38 #include "pendef.h"
39 #include "hp2xx.h"
40 
41 static float ax, ay;
42 static int startx, starty, endx, endy;
43 static int lwid, lsty, lcol;
44 static int firstmove;
45 
46 #define RGIPXMAX 10000.0
47 #define RGIPYMAX 10000.0
48 
49 /**
50  ** Convert HP to RGIP coordinates
51  **/
rgipx(float x)52 static int rgipx(float x)
53 {
54 	return (int) (x * ax);
55 }
56 
rgipy(float y)57 static int rgipy(float y)
58 {
59 	return (int) (y * ay);
60 }
61 
62 /**
63  ** Set line width
64  **/
rgip_set_linewidth(int width)65 static void rgip_set_linewidth(int width)
66 {
67 	lwid = width;
68 }
69 
70 /**
71  ** Set line style
72  **/
rgip_set_linestyle(int style)73 static void rgip_set_linestyle(int style)
74 {
75 	lsty = style;
76 }
77 
78 /**
79  ** Set RGB color
80  **/
rgip_set_color(double red,double green,double blue)81 static void rgip_set_color(double red, double green, double blue)
82 {
83 	float max, min, delta, r, g, b, h, s, v;
84   /**
85    ** Of course, here, in HP format, colors go from:
86    **   0<red<1
87    **   0<green<1
88    **   0<blue<1
89    ** Whereas in RGIP, colors are numbered 16, and are:
90    **    1 RED
91    **    2 YELLOW
92    **    3 GREEN
93    **    4 CYAN
94    **    5 BLUE
95    **    6 MAGENTA
96    **    7 WHITE
97    **    8 BLACK
98    **    9 LRED
99    **   10 LYELLOW
100    **   11 LGREEN
101    **   12 LCYAN
102    **   13 LBLUE
103    **   14 LMAGENTA
104    **   15 LGREY
105    **   16 DGREY
106    ** Some conversion needed...
107    **/
108 
109   /**
110    ** RGB to HSV conversion routine inspired from John Bradley
111    ** (bradley@cis.upenn.edu) XV version 3.0
112    **/
113 
114 	if (red >= green) {
115 		if (red >= blue)
116 			max = (float) red;
117 		else
118 			max = (float) blue;
119 	} else {
120 		if (green >= blue)
121 			max = (float) green;
122 		else
123 			max = (float) blue;
124 	}
125 	if (red <= green) {
126 		if (red <= blue)
127 			min = (float) red;
128 		else
129 			min = (float) blue;
130 	} else {
131 		if (green <= blue)
132 			min = (float) green;
133 		else
134 			min = (float) blue;
135 	}
136 	delta = max - min;
137 	v = max;
138 	h = (-1);
139 	s = 0.0;
140 	if (max != 0.0) {
141 		s = delta / max;
142 		if (s != 0.0) {
143 			r = (max - red) / delta;
144 			g = (max - green) / delta;
145 			b = (max - blue) / delta;
146 			if (red == max)
147 				h = b - g;
148 			else if (green == max)
149 				h = 2 + r - b;
150 			else
151 				h = 4 + g - r;
152 			h = h * 60;
153 			if (h < 0)
154 				h = h + 360;
155 		}
156 	}
157   /**
158    ** Assign correct RGIP color...
159    ** First case: if saturation reasonably high, then try for one of the
160    ** main colors... then check if it's light... or dark...
161    ** In case, prepare a default color...
162    **/
163 	lcol = 7;
164 	if (s >= .2) {
165 		if (((h >= 0) && (h < 30)) || (h >= 330))
166 			lcol = 1;
167 		else if ((h >= 30) && (h < 90))
168 			lcol = 2;
169 		else if ((h >= 90) && (h < 150))
170 			lcol = 3;
171 		else if ((h >= 150) && (h < 210))
172 			lcol = 4;
173 		else if ((h >= 210) && (h < 270))
174 			lcol = 5;
175 		else
176 			lcol = 6;
177 	}
178   /**
179    ** If not enough saturated, try for black, greys or white
180    **/
181 	else {
182     /**
183      ** If only one color and this color is not saturated, then it
184      ** is the default (black on white)...
185      **/
186 		if (delta == 0)
187 			lcol = 7;
188 		else {
189 			if (v < 0.15)
190 				lcol = 8;
191 			else if (v < 0.5)
192 				lcol = 16;
193 			else if (v < 0.75)
194 				lcol = 15;
195 			else
196 				lcol = 7;
197 		}
198 	}
199 }
200 
201 /**
202  ** Higher-level interface: Output Uniplex RGIP format
203  **/
204 
to_rgip(const GEN_PAR * pg,const OUT_PAR * po)205 int to_rgip(const GEN_PAR * pg, const OUT_PAR * po)
206 {
207 	PlotCmd cmd;
208 	HPGL_Pt pt1 = { 0, 0 };
209 	FILE *md;
210 	PEN_W pensize;
211 	PEN_C pencolor;
212 	int pen_no = 0, err = 0;
213 
214 	/* Give some news... */
215 	if (!pg->quiet) {
216 		Eprintf("\n\n- Writing RGIP code to \"%s\"\n",
217 			*po->outfile == '-' ? "stdout" : po->outfile);
218 	}
219 
220 	/* Init. of RGIP file: */
221 	if (*po->outfile != '-') {
222 		if ((md = fopen(po->outfile, "w")) == NULL) {
223 			PError("hp2xx (rgip)");
224 			err = ERROR;
225 			goto RGIP_exit;
226 		}
227 	} else {
228 		md = stdout;
229 	}
230 
231 	/* A begining is a very delicate time */
232 	firstmove = 1;
233 
234 	/* Factor for transformation of HP coordinates to RGIP */
235 	ax = RGIPXMAX / (po->xmax - po->xmin);
236 	ay = RGIPYMAX / (po->ymax - po->ymin);
237 
238 	/* RGIP header */
239 	fprintf(md, "%%RGIP_METAFILE  :1.0a\n");
240 	pensize = pt.width[DEFAULT_PEN_NO];
241 	if (pensize > 0.05) {
242 		rgip_set_linewidth((int)
243 				   (1 +
244 				    pensize * po->HP_to_xdots / 0.025));
245 	}
246 	rgip_set_linestyle(1);
247 	rgip_set_color(1.0, 1.0, 1.0);
248 
249 /**
250  ** Command loop: While temporary file not empty process command.
251  **/
252 
253 	while ((cmd = PlotCmd_from_tmpfile()) != CMD_EOF) {
254 		switch (cmd) {
255 		case NOP:
256 			break;
257 
258 		case SET_PEN:
259 			if ((pen_no = fgetc(pg->td)) == EOF) {
260 				PError("Unexpected end of temp. file: ");
261 				exit(ERROR);
262 			}
263 			pensize = pt.width[pen_no];
264 			if (pensize > 0.05) {
265 				rgip_set_linewidth((int)
266 						   (1 +
267 						    pensize *
268 						    po->HP_to_xdots /
269 						    0.025));
270 			}
271 			pencolor = pt.color[pen_no];
272 			rgip_set_color(pt.clut[pencolor][0] / 255.0,
273 				       pt.clut[pencolor][1] / 255.0,
274 				       pt.clut[pencolor][2] / 255.0);
275 			break;
276 
277 		case DEF_PC:
278 			if (!load_pen_color_table(pg->td)) {
279 				PError("Unexpected end of temp. file");
280 				exit(ERROR);
281 			}
282 			pencolor = pt.color[pen_no];
283 			rgip_set_color(pt.clut[pencolor][0] / 255.0,
284 				       pt.clut[pencolor][1] / 255.0,
285 				       pt.clut[pencolor][2] / 255.0);
286 			break;
287 		case DEF_PW:
288 			if (!load_pen_width_table(pg->td)) {
289 				PError("Unexpected end of temp. file");
290 				exit(ERROR);
291 			}
292 			pensize = pt.width[pen_no];
293 			if (pensize > 0.05) {
294 				rgip_set_linewidth((int)
295 						   (1 +
296 						    pensize *
297 						    po->HP_to_xdots /
298 						    0.025));
299 			}
300 			break;
301 
302 		case MOVE_TO:
303 			HPGL_Pt_from_tmpfile(&pt1);
304 			if (firstmove == 1) {
305 				firstmove = 0;
306 			} else {
307 				fprintf(md, "%%%%RI_GROUPEND\n");
308 			}
309 			startx = rgipx(((&pt1)->x) - po->xmin);
310 			starty = rgipy(((&pt1)->y) - po->ymin);
311 			fprintf(md, "%%%%RI_GROUPSTART\n");
312 			break;
313 
314 		case DRAW_TO:
315 			HPGL_Pt_from_tmpfile(&pt1);
316 			if (pensize != 0) {
317 				endx = rgipx(((&pt1)->x) - po->xmin);
318 				endy = rgipy(((&pt1)->y) - po->ymin);
319 				fprintf(md,
320 					"%d %d %d %d %d %d %d LINE\n",
321 					startx, starty, endx, endy, lwid,
322 					lsty, lcol);
323 				startx = endx;
324 				starty = endy;
325 			}
326 			break;
327 
328 		case PLOT_AT:
329 			HPGL_Pt_from_tmpfile(&pt1);
330 			if (pensize != 0) {
331 				startx = rgipx(((&pt1)->x) - po->xmin);
332 				starty = rgipy(((&pt1)->y) - po->ymin);
333 				fprintf(md,
334 					"[ %d %d ] %d DOTS\n",
335 					startx, starty, lcol);
336 
337 			}
338 			break;
339 
340 		default:
341 			Eprintf("Illegal cmd in temp. file!");
342 			err = ERROR;
343 			goto RGIP_exit;
344 		}
345 	}
346 
347 	/* Finish up */
348 	fprintf(md, "%%%%RI_GROUPEND\n");
349 
350       RGIP_exit:
351 	if (md != NULL && md != stdout)
352 		fclose(md);
353 	if (!pg->quiet)
354 		Eprintf("\n");
355 	return err;
356 }
357