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