1 /* -*- tab-width: 4 -*-
2  *
3  * Electric(tm) VLSI Design System
4  *
5  * File: iopsoutcolor.cpp
6  * Input/output tool: Color Postscript output
7  * Written by: David Harris, 4/20/01 (David_Harris@hmc.edu)
8  * Updated to speed up handling transparencies, 1/20/02 (David Harris)
9  * Integrated into Electric: 2/03 (Steven Rubin)
10  *
11  * Copyright (c) 2003 Static Free Software.
12  *
13  * Electric(tm) is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * Electric(tm) is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with Electric(tm); see the file COPYING.  If not, write to
25  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
26  * Boston, Mass 02111-1307, USA.
27  *
28  * Static Free Software
29  * 4119 Alpine Road
30  * Portola Valley, California 94028
31  * info@staticfreesoft.com
32  */
33 
34 /*
35  * Things still to do:
36  *    circles and arcs
37  *    rotation of the plot
38  *    eps
39  *    plot text (an option?)
40  */
41 
42 /*
43 	This code generates postscript plots of an IC layout in CIF format.
44 	It handles color better than existing freely available
45 	postscript generators.  It does not handle arbitrary rotations.
46 
47 	To use ICPLOT
48 	look at the output with RoPS
49 	To print from windows in E-sized format (34" wide) *** outdated
50 		use RoPS to print to the plotter (C3PO)
51 		Application Page Size: ANSI E
52 		set the options to Color, then under Advanced to E-sized sheet
53 		be sure plotter driver under Windows is set to E-size (a D-size driver also exists)
54 
55 	*** updated 12/10/01 for qbert
56 		use RoPS to print to the plotter (C3PO)
57 		Application Page Size: ANSI A, fit to page ANSI E
58 		Advanced tab: process document in computer
59 		be sure plotter driver under Windows is set to E-size (a D-size driver also exists)
60 
61 
62 	Limitations:
63 	the code to handle quad trees is rather messy now
64 
65 	ideas:
66 		draw highlights around edges
67 		center port labels
68 		give options about aspect ratio / page size
69 		put date in postscript and on caption
70 		print layers on caption
71 
72 	To do 1/28/03:
73 		draw outlines around edges
74 		handle black & white mode
75 		center labels
76 */
77 
78 #include "config.h"
79 #include "global.h"
80 #include "egraphics.h"
81 #include "efunction.h"
82 #include "eio.h"
83 #include "usr.h"
84 #include <math.h>
85 
86 /* macros */
87 
88 #define min(a,b) (((a) < (b)) ? (a) : (b))
89 #define max(a,b) (((a) > (b)) ? (a) : (b))
90 
91 /* Constants */
92 
93 #define MAXLAYERS 1000
94 #define TREETHRESHOLD 500
95 #define SMALL_NUM 0.000001
96 
97 /* Structures */
98 
99 typedef struct POLYL {
100 	INTBIG *coords;
101 	INTBIG numcoords;
102 	INTBIG layer;
103 	struct POLYL *next;
104 } POLYL;
105 
106 typedef struct OUTLINEL {
107 	struct OUTLINEL *next;
108 } OUTLINEL;
109 
110 typedef struct BOXL {
111 	INTBIG pos[4];  /* 0: dx, 1: dy, 2: left, 3: bot */
112 	INTSML layer;
113 	INTSML visible;
114 	struct BOXL *next;
115 } BOXL;
116 
117 typedef struct LINEL {
118 	INTBIG x[2];
119 	INTBIG y;
120 	INTSML visible;
121 	struct LINEL *next;
122 } LINEL;
123 
124 typedef struct LABELL {
125 	CHAR   *label;
126 	INTBIG  pos[4];
127 	INTBIG  style;
128 	UINTBIG descript[TEXTDESCRIPTSIZE];
129 	struct LABELL *next;
130 } LABELL;
131 
132 typedef struct CELLL {
133 	INTBIG	cellNum;
134 	BOXL   *box;
135 	POLYL  *poly;
136 	LABELL *label;
137 	CELLL  *next;
138 	struct CELLINSTL *inst;
139 } CELLL;
140 
141 typedef struct CELLINSTL {
142 	float      transform[9];
143 	CELLL     *inst;
144 	CELLINSTL *next;
145 } CELLINSTL;
146 
147 typedef struct {
148 	INTBIG pos[4]; /* 0: dx, 1: dy, 2: left, 3: bot */
149 	INTSML layer;
150 	INTSML visible;
151 } BOXELEM;
152 
153 typedef struct BOXQUADTREE {
154 	INTBIG numBoxes;
155 	BOXELEM *boxes;
156 	INTBIG bounds[4]; /* 0: dx, 1: dy, 2: left, 3: bot */
157 	struct BOXQUADTREE *tl;
158 	struct BOXQUADTREE *tr;
159 	struct BOXQUADTREE *bl;
160 	struct BOXQUADTREE *br;
161 	struct BOXQUADTREE *parent;
162 	INTBIG level;
163 } BOXQUADTREE;
164 
165 typedef struct LAYERMAP {
166 	INTBIG layernumber;
167 	TECHNOLOGY *tech;
168 	INTBIG mix1, mix2; /* layer made from mix of previous layers, or -1 if not */
169 	double r, g, b;
170 	double opacity;
171 	INTBIG foreground;
172 } LAYERMAP;
173 
174 typedef struct
175 {
176 	INTBIG layer;
177 	TECHNOLOGY *tech;
178 	float height;
179 	INTBIG r, g, b;
180 	float  opacity;
181 	INTBIG foreground;
182 } LAYERSORT;
183 
184 /* Globals */
185 static INTBIG       io_pscolor_cifBoundaries[4];
186 static CELLL       *io_pscolor_cells = NULL;
187 static LAYERMAP     io_pscolor_layers[MAXLAYERS];
188 static BOXL        *io_pscolor_flattenedbox[MAXLAYERS];
189 static BOXQUADTREE *io_pscolor_boxQuadTrees[MAXLAYERS];
190 static POLYL       *io_pscolor_flattenedpoly[MAXLAYERS];
191 static INTBIG       io_pscolor_numLayers;
192 static INTBIG       io_pscolor_numBoxes = 0;
193 static INTBIG       io_pscolor_numCells = 0;
194 static INTBIG       io_pscolor_numPolys = 0;
195 static INTBIG       io_pscolor_numInstances = 0;
196 static INTBIG       io_pscolor_cellnumber;
197 static BOOLEAN      io_pscolor_curvewarning;
198 static CHAR         io_pscolor_font[80];
199 static INTBIG       io_pscolor_totalBoxes = 0;
200 
201 /* not used yet */
202 #if 0
203 static LINEL       *io_pscolor_horizsegs[MAXLAYERS];
204 static OUTLINEL    *io_pscolor_flattenedoutline[MAXLAYERS];
205 
206 static LINEL       *io_pscolor_genSegments(BOXL *boxes, INTBIG dir);
207 static int          io_pscolor_lineCompare(const void *a, const void *b);
208 static INTBIG       io_pscolor_countBoxes(BOXL *boxes);
209 static OUTLINEL    *io_pscolor_combineSegments(LINEL *horiz, LINEL *vert);
210 static void         io_pscolor_checkOverlap(CELLL*, BOXL*, BOXL*, INTBIG);
211 static void			io_pscolor_printBoxes(void);
212 static void         io_pscolor_freeLine(LINEL*);
213 #endif
214 
215 /* Function Prototypes */
216 static void         io_pscolor_initICPlot(void);
217 static void         io_pscolor_getLayerMap(TECHNOLOGY *tech);
218 static void         io_pscolor_extractDatabase(NODEPROTO*);
219 static void         io_pscolor_genOverlapShapesAfterFlattening(void);
220 static void         io_pscolor_coaf1(BOXQUADTREE*, BOXQUADTREE*, INTBIG);
221 static void         io_pscolor_coaf2(BOXQUADTREE*, BOXQUADTREE*, INTBIG);
222 static void         io_pscolor_coaf3(BOXQUADTREE*, BOXQUADTREE*, INTBIG);
223 static void         io_pscolor_coaf4(BOXQUADTREE*, BOXQUADTREE*, INTBIG, INTBIG);
224 static void         io_pscolor_checkOverlapAfterFlattening(BOXQUADTREE*, BOXQUADTREE*, INTBIG);
225 static BOXQUADTREE *io_pscolor_makeBoxQuadTree(INTBIG);
226 static void         io_pscolor_recursivelyMakeBoxQuadTree(BOXQUADTREE*);
227 static void         io_pscolor_splitTree(INTBIG, BOXELEM*, BOXQUADTREE*, INTBIG, INTBIG, INTBIG, INTBIG);
228 static void         io_pscolor_flatten(void);
229 static void         io_pscolor_recursiveFlatten(CELLL*, float[]);
230 static void         io_pscolor_writePS(NODEPROTO*, BOOLEAN, INTBIG, INTBIG, INTBIG);
231 static void         io_pscolor_mergeBoxes(void);
232 static INTBIG       io_pscolor_mergeBoxPair(BOXL*, BOXL*);
233 static BOXL        *io_pscolor_copybox(BOXL*, float[]);
234 static POLYL       *io_pscolor_copypoly(POLYL*, float[]);
235 static CELLL       *io_pscolor_insertCell(CELLL*, CELLL*);
236 static BOXL        *io_pscolor_insertbox(BOXL*, BOXL*);
237 static POLYL       *io_pscolor_insertpoly(POLYL*, POLYL*);
238 static LABELL      *io_pscolor_insertlabel(LABELL*, LABELL*);
239 static CELLINSTL   *io_pscolor_insertInst(CELLINSTL*, CELLINSTL*);
240 static void         io_pscolor_matrixMul(float[], float[], float[]);
241 static void         io_pscolor_newIdentityMatrix(float[]);
242 static void         io_pscolor_transformBox(INTBIG*, INTBIG*, float[]);
243 static void         io_pscolor_transformPoly(POLYL*, POLYL*, float[]);
244 static void         io_pscolor_printStatistics(void);
245 static void         io_pscolor_freeMem(void);
246 static void         io_pscolor_freeBoxQuadTree(BOXQUADTREE*);
247 static void         io_pscolor_freeCell(CELLL*);
248 static void         io_pscolor_freeBox(BOXL*);
249 static void         io_pscolor_freePoly(POLYL*);
250 static void         io_pscolor_freeLabel(LABELL*);
251 static void         io_pscolor_freeCellInst(CELLINSTL*);
252 static void         io_pscolor_plotPolygon(POLYGON *poly, CELLL *curCell);
253 static INTBIG       io_pscolor_truefontsize(INTBIG font, TECHNOLOGY *tech);
254 static int          io_pscolor_sortlayers(const void *e1, const void *e2);
255 static void         io_pscolor_plotline(INTBIG layer, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, INTBIG texture, CELLL *curCell);
256 
257 /*
258  * Main entry point for color PostScript output.  The cell being written is "np".
259  * The size of the paper is "pagewid" wide and "pagehei" tall with a margin of
260  * "pagemargin" (in 1/75 of an inch).  If "useplotter" is TRUE, this is an infinitely-tall
261  * plotter, so height is not a consideration.  If "epsformat" is TRUE, write encapsulated
262  * PostScript.
263  */
264 /* extern "C" extern TECHNOLOGY *sch_tech, *gen_tech, *art_tech; */
io_pscolorplot(NODEPROTO * np,BOOLEAN epsformat,BOOLEAN useplotter,INTBIG pagewid,INTBIG pagehei,INTBIG pagemargin)265 void io_pscolorplot(NODEPROTO *np, BOOLEAN epsformat, BOOLEAN useplotter,
266 	INTBIG pagewid, INTBIG pagehei, INTBIG pagemargin)
267 {
268 	REGISTER TECHNOLOGY *tech;
269 
270 	strcpy(io_pscolor_font, x_("Helvetica"));
271 
272 	io_pscolor_initICPlot();
273 
274 	/* initialize layer maps for the current technology */
275 	io_pscolor_numLayers = 0;
276 	for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
277 		tech->temp1 = 0;
278 /* io_pscolor_getLayerMap(sch_tech); */
279 /* io_pscolor_getLayerMap(art_tech); */
280 /* io_pscolor_getLayerMap(gen_tech); */
281 	io_pscolor_getLayerMap(el_curtech);
282 
283 	io_pscolor_curvewarning = FALSE;
284 	io_pscolor_extractDatabase(np);
285 	io_pscolor_mergeBoxes();
286 /*	io_pscolor_printBoxes(); */
287 	io_pscolor_flatten();
288 /*	io_pscolor_printBoxes(); */
289 	io_pscolor_genOverlapShapesAfterFlattening();
290 /*	io_pscolor_printBoxes(); */
291 	io_pscolor_writePS(np, useplotter, pagewid, pagehei, pagemargin);
292 	io_pscolor_printStatistics();
293 	io_pscolor_freeMem();
294 }
295 
io_pscolor_initICPlot(void)296 void io_pscolor_initICPlot(void)
297 {
298 	INTBIG i;
299 	REGISTER LIBRARY *lib;
300 	REGISTER NODEPROTO *np;
301 
302 	io_pscolor_numBoxes = io_pscolor_numCells = io_pscolor_numPolys =
303 		io_pscolor_totalBoxes = io_pscolor_numInstances = 0;
304 	io_pscolor_cifBoundaries[0] = 1<<30;
305 	io_pscolor_cifBoundaries[1] = 1<<30;
306 	io_pscolor_cifBoundaries[2] = -1<<30;
307 	io_pscolor_cifBoundaries[3] = -1<<30;
308 
309 	for (i=0; i<MAXLAYERS; i++) {
310 		io_pscolor_boxQuadTrees[i] = NULL;
311 	}
312 
313 	/* mark all cells as "not written" */
314 	for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
315 		for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
316 			np->temp1 = 0;
317 	io_pscolor_cellnumber = 1;
318 }
319 
320 /*
321  * Routine to get the print colors and load them into the layer map.
322  */
io_pscolor_getLayerMap(TECHNOLOGY * tech)323 void io_pscolor_getLayerMap(TECHNOLOGY *tech)
324 {
325 	INTBIG i, j, k, fun, *printcolors, curLayer, startlayer;
326 	float thickness;
327 	REGISTER LAYERSORT *ls;
328 
329 	/* see if this technology has already been done */
330 	if (tech->temp1 != 0) return;
331 	tech->temp1 = 1;
332 
333 	/* read layer map */
334 	startlayer = io_pscolor_numLayers;
335 	printcolors = us_getprintcolors(tech);
336 	if (printcolors == 0) return;
337 	ls = (LAYERSORT *)emalloc(tech->layercount * (sizeof (LAYERSORT)), io_tool->cluster);
338 	if (ls == 0) return;
339 	j = 0;
340 	for(i=0; i<tech->layercount; i++)
341 	{
342 		fun = layerfunction(tech, i);
343 		if ((fun&LFPSEUDO) != 0) continue;
344 		if (get3dfactors(tech, i, &ls[j].height, &thickness)) break;
345 		ls[j].height += thickness/2;
346 		ls[j].layer = i;
347 		ls[j].tech = tech;
348 		ls[j].r = printcolors[i*5];
349 		ls[j].g = printcolors[i*5+1];
350 		ls[j].b = printcolors[i*5+2];
351 		ls[j].opacity = (float)printcolors[i*5+3]/WHOLE;
352 		ls[j].foreground = printcolors[i*5+4];
353 		j++;
354 	}
355 
356 	/* sort by layer height */
357 	esort(ls, j, sizeof (LAYERSORT), io_pscolor_sortlayers);
358 
359 	/* load the layer information */
360 	for(i=0; i<j; i++)
361 	{
362 		if (io_pscolor_numLayers >= MAXLAYERS)
363 		{
364 			ttyputerr("More than %ld layers", MAXLAYERS);
365 			break;
366 		}
367 		io_pscolor_layers[io_pscolor_numLayers].layernumber = ls[i].layer;
368 		io_pscolor_layers[io_pscolor_numLayers].tech = ls[i].tech;
369 		io_pscolor_layers[io_pscolor_numLayers].opacity = ls[i].opacity;
370 		io_pscolor_layers[io_pscolor_numLayers].foreground = ls[i].foreground;
371 		io_pscolor_layers[io_pscolor_numLayers].r = ls[i].r/255.0f;
372 		io_pscolor_layers[io_pscolor_numLayers].g = ls[i].g/255.0f;
373 		io_pscolor_layers[io_pscolor_numLayers].b = ls[i].b/255.0f;
374 		io_pscolor_layers[io_pscolor_numLayers].mix1 = -1;
375 		io_pscolor_layers[io_pscolor_numLayers].mix2 = -1;
376 		if (io_pscolor_layers[io_pscolor_numLayers].opacity < 1)
377 		{
378 			/* create new layers to provide transparency */
379 			curLayer = io_pscolor_numLayers;
380 			for (k=startlayer; k < curLayer; k++)
381 			{
382 				if (io_pscolor_layers[k].foreground == 1)
383 				{
384 					io_pscolor_layers[++io_pscolor_numLayers].opacity = 1;
385 					io_pscolor_layers[io_pscolor_numLayers].layernumber = io_pscolor_layers[k].layernumber + 1000*io_pscolor_layers[curLayer].layernumber+1000000;
386 					io_pscolor_layers[io_pscolor_numLayers].tech = io_pscolor_layers[k].tech;
387 					io_pscolor_layers[io_pscolor_numLayers].foreground = 1;
388 					io_pscolor_layers[io_pscolor_numLayers].r = io_pscolor_layers[curLayer].r*io_pscolor_layers[curLayer].opacity +
389 						io_pscolor_layers[k].r*(1-io_pscolor_layers[curLayer].opacity);
390 					io_pscolor_layers[io_pscolor_numLayers].g = io_pscolor_layers[curLayer].g*io_pscolor_layers[curLayer].opacity +
391 						io_pscolor_layers[k].g*(1-io_pscolor_layers[curLayer].opacity);
392 					io_pscolor_layers[io_pscolor_numLayers].b = io_pscolor_layers[curLayer].b*io_pscolor_layers[curLayer].opacity +
393 						io_pscolor_layers[k].b*(1-io_pscolor_layers[curLayer].opacity);
394 					io_pscolor_layers[io_pscolor_numLayers].mix1 = k;
395 					io_pscolor_layers[io_pscolor_numLayers].mix2 = curLayer;
396 				}
397 			}
398 		}
399 		io_pscolor_numLayers++;
400 	}
401 	efree((CHAR *)ls);
402 }
403 
404 /*
405  * Helper routine for "io_pscolor_getLayerMap()" to sort layers by height.
406  */
io_pscolor_sortlayers(const void * e1,const void * e2)407 int io_pscolor_sortlayers(const void *e1, const void *e2)
408 {
409 	LAYERSORT *ls1, *ls2;
410 	float diff;
411 
412 	ls1 = (LAYERSORT *)e1;
413 	ls2 = (LAYERSORT *)e2;
414 	diff = ls1->height - ls2->height;
415 	if (diff == 0.0) return(0);
416 	if (diff < 0.0) return(-1);
417 	return(1);
418 }
419 
io_pscolor_extractDatabase(NODEPROTO * cell)420 void io_pscolor_extractDatabase(NODEPROTO *cell)
421 {
422 	REGISTER NODEINST *ni;
423 	REGISTER NODEPROTO *np;
424 	REGISTER ARCINST *ai;
425 	REGISTER PORTPROTO *pp;
426 	CELLL *curCell, *subCell;
427 	CELLINSTL *curInst;
428 	BOXL *curbox;
429 	float transt[9], transr[9];
430 	LABELL *curlabel;
431 	INTBIG i;
432 	REGISTER INTBIG tot;
433 	INTBIG xp, yp;
434 	static POLYGON *poly = NOPOLYGON;
435 	XARRAY trans;
436 
437 	/* check for subcells that haven't been written yet */
438 	for(ni = cell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
439 	{
440 		if (ni->proto->primindex != 0) continue;
441 		if (ni->proto->temp1 != 0) continue;
442 		if ((ni->userbits&NEXPAND) == 0) continue;
443 		io_pscolor_extractDatabase(ni->proto);
444 	}
445 
446 	/* get polygon */
447 	(void)needstaticpolygon(&poly, 4, io_tool->cluster);
448 
449 	/* create a cell */
450 	curCell = (CELLL *)emalloc(sizeof(CELLL), io_tool->cluster);
451 	curCell->cellNum = io_pscolor_cellnumber++;
452 	curCell->box = NULL;
453 	curCell->poly = NULL;
454 	curCell->label = NULL;
455 	curCell->inst = NULL;
456 	curCell->next = NULL;
457 	io_pscolor_numCells++;
458 	cell->temp1 = (INTBIG)curCell;
459 
460 	/* examine all nodes in the cell */
461 	for(ni = cell->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
462 	{
463 		np = ni->proto;
464 		if (np->primindex == 0)
465 		{
466 			/* instance */
467 			if ((ni->userbits&NEXPAND) == 0)
468 			{
469 				/* look for a black layer */
470 				for(i=0; i<io_pscolor_numLayers; i++)
471 					if (io_pscolor_layers[i].r == 0 && io_pscolor_layers[i].g == 0 &&
472 						io_pscolor_layers[i].b == 0 && io_pscolor_layers[i].opacity == 1) break;
473 				if (i < io_pscolor_numLayers)
474 				{
475 					/* draw a box by plotting 4 lines */
476 					curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
477 					curbox->layer = (INTSML)i;
478 					curbox->next = NULL;
479 					curbox->visible = 1;
480 					curbox->pos[0] = 1;
481 					curbox->pos[1] = ni->geom->highy - ni->geom->lowy;
482 					curbox->pos[2] = ni->geom->lowx;
483 					curbox->pos[3] = ni->geom->lowy;
484 					curCell->box = io_pscolor_insertbox(curbox, curCell->box);
485 
486 					curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
487 					curbox->layer = (INTSML)i;
488 					curbox->next = NULL;
489 					curbox->visible = 1;
490 					curbox->pos[0] = ni->geom->highx - ni->geom->lowx;
491 					curbox->pos[1] = 1;
492 					curbox->pos[2] = ni->geom->lowx;
493 					curbox->pos[3] = ni->geom->lowy;
494 					curCell->box = io_pscolor_insertbox(curbox, curCell->box);
495 
496 					curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
497 					curbox->layer = (INTSML)i;
498 					curbox->next = NULL;
499 					curbox->visible = 1;
500 					curbox->pos[0] = 1;
501 					curbox->pos[1] = ni->geom->highy - ni->geom->lowy;
502 					curbox->pos[2] = ni->geom->highx;
503 					curbox->pos[3] = ni->geom->lowy;
504 					curCell->box = io_pscolor_insertbox(curbox, curCell->box);
505 
506 					curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
507 					curbox->layer = (INTSML)i;
508 					curbox->next = NULL;
509 					curbox->visible = 1;
510 					curbox->pos[0] = ni->geom->highx - ni->geom->lowx;
511 					curbox->pos[1] = 1;
512 					curbox->pos[2] = ni->geom->lowx;
513 					curbox->pos[3] = ni->geom->highy;
514 					curCell->box = io_pscolor_insertbox(curbox, curCell->box);
515 
516 					/* add the cell name */
517 					curlabel = (LABELL *)emalloc(sizeof(LABELL), io_tool->cluster);
518 					(void)allocstring(&curlabel->label, describenodeproto(ni->proto), io_tool->cluster);
519 					curlabel->pos[0] = ni->lowx;
520 					curlabel->pos[1] = ni->highx;
521 					curlabel->pos[2] = ni->lowy;
522 					curlabel->pos[3] = ni->highy;
523 					curlabel->style = TEXTBOX;
524 					TDCOPY(curlabel->descript, ni->textdescript);
525 					curCell->label = io_pscolor_insertlabel(curlabel, curCell->label);
526 				}
527 			} else
528 			{
529 				/* expanded instance: make the invocation */
530 				subCell = (CELLL *)np->temp1;
531 				curInst = (CELLINSTL *)emalloc(sizeof(CELLINSTL), io_tool->cluster);
532 				curInst->next = NULL;
533 				curInst->inst = subCell;
534 				io_pscolor_newIdentityMatrix(curInst->transform);
535 
536 				/* account for instance position */
537 				io_pscolor_newIdentityMatrix(transt);
538 				transt[2*3+0] -= (float)((np->lowx + np->highx) / 2);
539 				transt[2*3+1] -= (float)((np->lowy + np->highy) / 2);
540 				io_pscolor_matrixMul(curInst->transform, curInst->transform, transt);
541 
542 				/* account for instance rotation */
543 				io_pscolor_newIdentityMatrix(transr);
544 				float rotation;
545 				rotation = (float)(ni->rotation / 1800.0 * EPI);
546 				transr[0*3+0] = (float)cos(rotation); if (fabs(transr[0]) < SMALL_NUM) transr[0] = 0;
547 				transr[0*3+1] = (float)sin(rotation); if (fabs(transr[1]) < SMALL_NUM) transr[1] = 0;
548 				transr[1*3+0] = -(float)sin(rotation); if (fabs(transr[3]) < SMALL_NUM) transr[3] = 0;
549 				transr[1*3+1] = (float)cos(rotation); if (fabs(transr[4]) < SMALL_NUM) transr[4] = 0;
550 
551 				io_pscolor_matrixMul(curInst->transform, curInst->transform, transr);
552 
553 				/* account for instance transposition */
554 				if (ni->transpose != 0)
555 				{
556 					io_pscolor_newIdentityMatrix(transr);
557 					transr[0*3+0] = 0;
558 					transr[1*3+1] = 0;
559 					transr[0*3+1] = -1;
560 					transr[1*3+0] = -1;
561 					io_pscolor_matrixMul(curInst->transform, curInst->transform, transr);
562 				}
563 
564 				/* account for instance location */
565 				io_pscolor_newIdentityMatrix(transt);
566 				transt[2*3+0] = (float)((ni->lowx + ni->highx) / 2);
567 				transt[2*3+1] = (float)((ni->lowy + ni->highy) / 2);
568 				io_pscolor_matrixMul(curInst->transform, curInst->transform, transt);
569 				curCell->inst = io_pscolor_insertInst(curInst, curCell->inst);
570 			}
571 		} else
572 		{
573 			/* primitive: generate its layers */
574 			makerot(ni, trans);
575 			tot = nodepolys(ni, 0, NOWINDOWPART);
576 			for(i=0; i<tot; i++)
577 			{
578 				shapenodepoly(ni, i, poly);
579 				xformpoly(poly, trans);
580 				io_pscolor_plotPolygon(poly, curCell);
581 			}
582 		}
583 	}
584 
585 	/* add geometry for all arcs */
586 	for(ai = cell->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
587 	{
588 		tot = arcpolys(ai, NOWINDOWPART);
589 		for(i=0; i<tot; i++)
590 		{
591 			shapearcpoly(ai, i, poly);
592 			io_pscolor_plotPolygon(poly, curCell);
593 		}
594 	}
595 
596 	/* add the name of all exports */
597 	for(pp = cell->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
598 	{
599 		curlabel = (LABELL *)emalloc(sizeof(LABELL), io_tool->cluster);
600 		(void)allocstring(&curlabel->label, pp->protoname, io_tool->cluster);
601 		portposition(pp->subnodeinst, pp->subportproto, &xp, &yp);
602 		curlabel->pos[0] = curlabel->pos[1] = xp;
603 		curlabel->pos[2] = curlabel->pos[3] = yp;
604 		curlabel->style = TEXTCENT;
605 		TDCOPY(curlabel->descript, pp->textdescript);
606 		curCell->label = io_pscolor_insertlabel(curlabel, curCell->label);
607 	}
608 
609 	/* add the completed cell to the list */
610 	io_pscolor_cells = io_pscolor_insertCell(curCell, io_pscolor_cells);
611 }
612 
io_pscolor_plotPolygon(POLYGON * poly,CELLL * curCell)613 void io_pscolor_plotPolygon(POLYGON *poly, CELLL *curCell)
614 {
615 	BOXL *curbox;
616 	POLYL *curpoly;
617 	LABELL *curlabel;
618 	REGISTER INTBIG j, k, type;
619 	INTBIG lx, hx, ly, hy, x, y;
620 	REGISTER BOOLEAN isabox;
621 
622 	if (poly->tech == NOTECHNOLOGY) return;
623 	io_pscolor_getLayerMap(poly->tech);
624 	for(j=0; j<io_pscolor_numLayers; j++)
625 		if (io_pscolor_layers[j].layernumber == poly->layer &&
626 			io_pscolor_layers[j].tech == poly->tech) break;
627 	if (j >= io_pscolor_numLayers)
628 		return;
629 	isabox = isbox(poly, &lx, &hx, &ly, &hy);
630 	if (!isabox) getbbox(poly, &lx, &hx, &ly, &hy);
631 
632 	switch (poly->style)
633 	{
634 		case FILLED:
635 		case FILLEDRECT:
636 			if (isabox)
637 			{
638 				curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
639 				curbox->layer = (INTSML)j;
640 				curbox->next = NULL;
641 				curbox->visible = 1;
642 				curbox->pos[0] = hx-lx;
643 				curbox->pos[1] = hy-ly;
644 				curbox->pos[2] = (lx+hx)/2;
645 				curbox->pos[3] = (ly+hy)/2;
646 				curbox->pos[2] -= curbox->pos[0]/2; /* adjust center x to left edge; */
647 				curbox->pos[3] -= curbox->pos[1]/2; /* adjust center y to bottom edge */
648 				curCell->box = io_pscolor_insertbox(curbox, curCell->box);
649 			} else
650 			{
651 				curpoly = (POLYL *)emalloc(sizeof(POLYL), io_tool->cluster);
652 				if (curpoly == 0) return;
653 				curpoly->layer = (INTSML)j;
654 				curpoly->next = NULL;
655 				curpoly->numcoords = poly->count*2;
656 				curpoly->coords = (INTBIG *)emalloc(curpoly->numcoords * SIZEOFINTBIG, io_tool->cluster);
657 				if (curpoly->coords == 0) return;
658 				for(j=0; j<curpoly->numcoords; j++)
659 				{
660 					if ((j%2) == 0) curpoly->coords[j] = poly->xv[j/2]; else
661 						curpoly->coords[j] = poly->yv[j/2];
662 				}
663 				curCell->poly = io_pscolor_insertpoly(curpoly, curCell->poly);
664 			}
665 			break;
666 
667 		case CLOSED:
668 		case CLOSEDRECT:
669 			if (isabox)
670 			{
671 				io_pscolor_plotline(j, lx, ly, lx, hy, 0, curCell);
672 				io_pscolor_plotline(j, lx, hy, hx, hy, 0, curCell);
673 				io_pscolor_plotline(j, hx, hy, hx, ly, 0, curCell);
674 				io_pscolor_plotline(j, hx, ly, lx, ly, 0, curCell);
675 				break;
676 			}
677 			/* FALLTHROUGH */
678 
679 		case OPENED:
680 		case OPENEDT1:
681 		case OPENEDT2:
682 		case OPENEDT3:
683 			switch (poly->style)
684 			{
685 				case OPENEDT1: type = 1; break;
686 				case OPENEDT2: type = 2; break;
687 				case OPENEDT3: type = 3; break;
688 				default:       type = 0; break;
689 			}
690 			for (k = 1; k < poly->count; k++)
691 				io_pscolor_plotline(j, poly->xv[k-1], poly->yv[k-1], poly->xv[k], poly->yv[k], type, curCell);
692 			if (poly->style == CLOSED)
693 			{
694 				k = poly->count - 1;
695 				io_pscolor_plotline(j, poly->xv[k], poly->yv[k], poly->xv[0], poly->yv[0], type, curCell);
696 			}
697 			break;
698 
699 		case VECTORS:
700 			for(k=0; k<poly->count; k += 2)
701 				io_pscolor_plotline(j, poly->xv[k], poly->yv[k], poly->xv[k+1], poly->yv[k+1], 0, curCell);
702 			break;
703 
704 		case CROSS:
705 		case BIGCROSS:
706 			getcenter(poly, &x, &y);
707 			io_pscolor_plotline(j, x-5, y, x+5, y, 0, curCell);
708 			io_pscolor_plotline(j, x, y+5, x, y-5, 0, curCell);
709 			break;
710 
711 		case CROSSED:
712 			io_pscolor_plotline(j, lx, ly, lx, hy, 0, curCell);
713 			io_pscolor_plotline(j, lx, hy, hx, hy, 0, curCell);
714 			io_pscolor_plotline(j, hx, hy, hx, ly, 0, curCell);
715 			io_pscolor_plotline(j, hx, ly, lx, ly, 0, curCell);
716 			io_pscolor_plotline(j, hx, hy, lx, ly, 0, curCell);
717 			io_pscolor_plotline(j, hx, ly, lx, hy, 0, curCell);
718 			break;
719 
720 		case DISC:
721 		case CIRCLE:
722 		case THICKCIRCLE:
723 		case CIRCLEARC:
724 		case THICKCIRCLEARC:
725 			if (!io_pscolor_curvewarning)
726 				ttyputmsg(_("Warning: the 'merged color' PostScript option ignores curves.  Use other color options"));
727 			io_pscolor_curvewarning = TRUE;
728 			break;
729 
730 		case TEXTCENT:
731 		case TEXTTOP:
732 		case TEXTBOT:
733 		case TEXTLEFT:
734 		case TEXTRIGHT:
735 		case TEXTTOPLEFT:
736 		case TEXTBOTLEFT:
737 		case TEXTTOPRIGHT:
738 		case TEXTBOTRIGHT:
739 		case TEXTBOX:
740 			curlabel = (LABELL *)emalloc(sizeof(LABELL), io_tool->cluster);
741 			(void)allocstring(&curlabel->label, poly->string, io_tool->cluster);
742 			curlabel->pos[0] = lx;
743 			curlabel->pos[1] = hx;
744 			curlabel->pos[2] = ly;
745 			curlabel->pos[3] = hy;
746 			curlabel->style = poly->style;
747 			TDCOPY(curlabel->descript, poly->textdescript);
748 			curCell->label = io_pscolor_insertlabel(curlabel, curCell->label);
749 			break;
750 	}
751 }
752 
753 /*
754  * Routine to add a line from (fx,fy) to (tx,ty) on layer "layer" to the cell "curCell".
755  */
io_pscolor_plotline(INTBIG layer,INTBIG fx,INTBIG fy,INTBIG tx,INTBIG ty,INTBIG texture,CELLL * curCell)756 void io_pscolor_plotline(INTBIG layer, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, INTBIG texture, CELLL *curCell)
757 {
758 	POLYL *curpoly;
759 
760 	curpoly = (POLYL *)emalloc(sizeof(POLYL), io_tool->cluster);
761 	if (curpoly == 0) return;
762 	curpoly->layer = (INTSML)layer;
763 	curpoly->next = NULL;
764 	curpoly->numcoords = 4;
765 	curpoly->coords = (INTBIG *)emalloc(4 * SIZEOFINTBIG, io_tool->cluster);
766 	if (curpoly->coords == 0) return;
767 	curpoly->coords[0] = fx;
768 	curpoly->coords[1] = fy;
769 	curpoly->coords[2] = tx;
770 	curpoly->coords[3] = ty;
771 	curCell->poly = io_pscolor_insertpoly(curpoly, curCell->poly);
772 }
773 
io_pscolor_genOverlapShapesAfterFlattening(void)774 void io_pscolor_genOverlapShapesAfterFlattening(void)
775 {
776 	BOXQUADTREE *q1, *q2;
777 	INTBIG i;
778 
779 	/* traverse the list of boxes and create new layers where overlaps occur */
780 	ttyputmsg(_("Generating overlap after flattening for %ld layers..."), io_pscolor_numLayers);
781 	for (i=0; i<io_pscolor_numLayers; i++) {
782 		if (io_pscolor_layers[i].mix1 != -1 && io_pscolor_layers[i].mix2 != -1) {
783 			q1 = io_pscolor_makeBoxQuadTree(io_pscolor_layers[i].mix1);
784 			q2 = io_pscolor_makeBoxQuadTree(io_pscolor_layers[i].mix2);
785 			io_pscolor_coaf1(q1, q2, i);
786 		}
787 	}
788 }
789 
io_pscolor_makeBoxQuadTree(INTBIG layer)790 BOXQUADTREE *io_pscolor_makeBoxQuadTree(INTBIG layer)
791 {
792 	BOXL *g;
793 	INTBIG i, numBoxes = 0;
794 
795 	/* return if the quadtree is already generated */
796 	if (io_pscolor_boxQuadTrees[layer] != NULL) return io_pscolor_boxQuadTrees[layer];
797 
798 	/* otherwise find number of boxes on this layer */
799 	g = io_pscolor_flattenedbox[layer];
800 	while (g != NULL) {
801 		if (g->visible) numBoxes++;
802 		g = g->next;
803 	}
804 
805 	/* and convert the list into a quad tree for faster processing */
806 
807 	/* first allocate the quad tree */
808 	io_pscolor_boxQuadTrees[layer] = (BOXQUADTREE *)emalloc(sizeof(BOXQUADTREE), io_tool->cluster);
809 	io_pscolor_boxQuadTrees[layer]->bounds[0] = io_pscolor_cifBoundaries[0];
810 	io_pscolor_boxQuadTrees[layer]->bounds[1] = io_pscolor_cifBoundaries[1];
811 	io_pscolor_boxQuadTrees[layer]->bounds[2] = io_pscolor_cifBoundaries[2];
812 	io_pscolor_boxQuadTrees[layer]->bounds[3] = io_pscolor_cifBoundaries[3];
813 	io_pscolor_boxQuadTrees[layer]->tl = NULL;
814 	io_pscolor_boxQuadTrees[layer]->tr = NULL;
815 	io_pscolor_boxQuadTrees[layer]->bl = NULL;
816 	io_pscolor_boxQuadTrees[layer]->br = NULL;
817 	io_pscolor_boxQuadTrees[layer]->numBoxes = numBoxes;
818 	io_pscolor_boxQuadTrees[layer]->boxes = (BOXELEM *)emalloc(numBoxes*sizeof(BOXELEM), io_tool->cluster);
819 	io_pscolor_boxQuadTrees[layer]->parent = NULL;
820 	io_pscolor_boxQuadTrees[layer]->level = 0;
821 
822 	/* then copy the boxes into the tree */
823 	g = io_pscolor_flattenedbox[layer];
824 	i = 0;
825 	while (g != NULL) {
826 		if (g->visible) {
827 			io_pscolor_boxQuadTrees[layer]->boxes[i].pos[0] = g->pos[0];
828 			io_pscolor_boxQuadTrees[layer]->boxes[i].pos[1] = g->pos[1];
829 			io_pscolor_boxQuadTrees[layer]->boxes[i].pos[2] = g->pos[2];
830 			io_pscolor_boxQuadTrees[layer]->boxes[i].pos[3] = g->pos[3];
831 			io_pscolor_boxQuadTrees[layer]->boxes[i].layer = g->layer;
832 			io_pscolor_boxQuadTrees[layer]->boxes[i].visible = 1;
833 			i++;
834 		}
835 		g = g->next;
836 	}
837 
838 	/* if there are too many boxes in this layer of the tree, create subtrees */
839 	if (numBoxes > TREETHRESHOLD)
840 		io_pscolor_recursivelyMakeBoxQuadTree(io_pscolor_boxQuadTrees[layer]);
841 
842 	return io_pscolor_boxQuadTrees[layer];
843 }
844 
io_pscolor_recursivelyMakeBoxQuadTree(BOXQUADTREE * q)845 void io_pscolor_recursivelyMakeBoxQuadTree(BOXQUADTREE *q)
846 {
847 	INTBIG i, numBoxes;
848 
849 	q->tl = (BOXQUADTREE *)emalloc(sizeof(BOXQUADTREE), io_tool->cluster);
850 	q->tl->parent = q; q->tl->level = q->level*10+1;
851 	q->tr = (BOXQUADTREE *)emalloc(sizeof(BOXQUADTREE), io_tool->cluster);
852 	q->tr->parent = q; q->tr->level = q->level*10+2;
853 	q->bl = (BOXQUADTREE *)emalloc(sizeof(BOXQUADTREE), io_tool->cluster);
854 	q->bl->parent = q; q->bl->level = q->level*10+3;
855 	q->br = (BOXQUADTREE *)emalloc(sizeof(BOXQUADTREE), io_tool->cluster);
856 	q->br->parent = q; q->br->level = q->level*10+4;
857 
858 	/* split boxes into subtrees where they fit */
859 	io_pscolor_splitTree(q->numBoxes, q->boxes, q->bl, q->bounds[0], q->bounds[1],
860 		(q->bounds[0]+q->bounds[2])/2, (q->bounds[1]+q->bounds[3])/2);
861 	io_pscolor_splitTree(q->numBoxes, q->boxes, q->br, (q->bounds[0]+q->bounds[2])/2, q->bounds[1],
862 		q->bounds[2], (q->bounds[1]+q->bounds[3])/2);
863 	io_pscolor_splitTree(q->numBoxes, q->boxes, q->tl, q->bounds[0], (q->bounds[1]+q->bounds[3])/2,
864 		(q->bounds[0]+q->bounds[2])/2, q->bounds[3]);
865 	io_pscolor_splitTree(q->numBoxes, q->boxes, q->tr, (q->bounds[0]+q->bounds[2])/2,
866 		(q->bounds[1]+q->bounds[3])/2, q->bounds[2], q->bounds[3]);
867 
868 	/* and leave boxes that span the subtrees at the top level */
869 	numBoxes = 0;
870 	for (i=0; i<q->numBoxes; i++) {
871 		if (q->boxes[i].visible) {
872 			/* q->boxes[numBoxes] = q->boxes[i]; */
873 			q->boxes[numBoxes].layer = q->boxes[i].layer;
874 			q->boxes[numBoxes].visible = 1;
875 			q->boxes[numBoxes].pos[0] = q->boxes[i].pos[0];
876 			q->boxes[numBoxes].pos[1] = q->boxes[i].pos[1];
877 			q->boxes[numBoxes].pos[2] = q->boxes[i].pos[2];
878 			q->boxes[numBoxes].pos[3] = q->boxes[i].pos[3];
879 			numBoxes++;
880 		}
881 	}
882 
883 	q->numBoxes = numBoxes;
884 }
885 
io_pscolor_splitTree(INTBIG numBoxes,BOXELEM * boxes,BOXQUADTREE * q,INTBIG left,INTBIG bot,INTBIG right,INTBIG top)886 void io_pscolor_splitTree(INTBIG numBoxes, BOXELEM *boxes, BOXQUADTREE *q,
887 						  INTBIG left, INTBIG bot, INTBIG right, INTBIG top)
888 {
889 	INTBIG i;
890 	INTBIG count = 0;
891 
892 	/* count how many boxes are in subtree */
893 	for (i = 0; i<numBoxes; i++) {
894 		if (boxes[i].visible && boxes[i].pos[2] >= left && boxes[i].pos[3] >= bot &&
895 			(boxes[i].pos[2]+boxes[i].pos[0]) <= right && (boxes[i].pos[3]+boxes[i].pos[1]) <= top) count++;
896 	}
897 	/* and copy them into a new array for the subtree */
898 	q->boxes = (BOXELEM *)emalloc(count*sizeof(BOXELEM), io_tool->cluster);
899 	count = 0;
900 	for (i=0; i<numBoxes; i++) {
901 		if (boxes[i].visible && boxes[i].pos[2] >= left && boxes[i].pos[3] >= bot &&
902 			(boxes[i].pos[2]+boxes[i].pos[0]) <= right && (boxes[i].pos[3]+boxes[i].pos[1]) <= top) {
903 			/*q->boxes[count] = boxes[i]; */
904 			q->boxes[count].layer = boxes[i].layer;
905 			q->boxes[count].visible = 1;
906 			q->boxes[count].pos[0] = boxes[i].pos[0];
907 			q->boxes[count].pos[1] = boxes[i].pos[1];
908 			q->boxes[count].pos[2] = boxes[i].pos[2];
909 			q->boxes[count].pos[3] = boxes[i].pos[3];
910 			boxes[i].visible = 0; /* mark box for removal from upper level */
911 			count++;
912 		}
913 	}
914 
915 	q->numBoxes = count;
916 	q->bounds[0] = left;
917 	q->bounds[1] = bot;
918 	q->bounds[2] = right;
919 	q->bounds[3] = top;
920 	q->tl = NULL;
921 	q->tr = NULL;
922 	q->bl = NULL;
923 	q->br = NULL;
924 
925 	if (count > TREETHRESHOLD) {
926 		io_pscolor_recursivelyMakeBoxQuadTree(q);
927 	}
928 }
929 
930 #if 0
931 void io_pscolor_printBoxes(void)
932 {
933 	CELLL *c;
934 	BOXL *b1;
935 	int i;
936 
937 	c = io_pscolor_cells;
938 	while (c != NULL) {
939 		ttyputerr("cell\n");
940 		b1 = c->box;
941 		while (b1 != NULL) {
942 			ttyputerr("  box layer %d visible %d coords %d %d %d %d\n", b1->layer, b1->visible, b1->pos[0], b1->pos[1], b1->pos[2], b1->pos[3]);
943 			b1 = b1->next;
944 		}
945 		c = c->next;
946 	}
947 	for (i=0; i<MAXLAYERS; i++) {
948 		b1 = io_pscolor_flattenedbox[i];
949 		if (b1 != NULL) ttyputerr("BOX layer %d num %d \n", i, io_pscolor_layers[i].layernumber);
950 		while (b1 != NULL) {
951 			ttyputerr("  box layer %d visible %d coords %d %d %d %d\n", b1->layer, b1->visible, b1->pos[0], b1->pos[1], b1->pos[2], b1->pos[3]);
952 			b1 = b1->next;
953 		}
954 	}
955 }
956 #endif
957 
io_pscolor_mergeBoxes(void)958 void io_pscolor_mergeBoxes(void)
959 {
960 	CELLL *c;
961 	BOXL *b1, *b2;
962 	INTBIG changed;
963 	INTBIG numMerged = 0;
964 
965 	ttyputmsg(_("Merging boxes for %ld cells..."), io_pscolor_numCells);
966 	c = io_pscolor_cells;
967 	while (c != NULL) {
968 		do {
969 			changed = 0;
970 			b1 = c->box;
971 			while (b1 != NULL) {
972 				b2 = b1->next;
973 				while (b2 != NULL) {
974 					if (b1->layer == b2->layer && b1->visible && b2->visible)
975 						if (io_pscolor_mergeBoxPair(b1, b2)) changed = 1;
976 					b2 = b2->next;
977 				}
978 				b1 = b1->next;
979 			}
980 		} while (changed);
981 		c = c->next;
982 		numMerged++;
983 	}
984 }
985 
io_pscolor_mergeBoxPair(BOXL * b1,BOXL * b2)986 INTBIG io_pscolor_mergeBoxPair(BOXL *b1, BOXL *b2)
987 {
988 	INTBIG t[3], b[3], l[3], r[3];
989 
990 	t[0] = b1->pos[3] + b1->pos[1];
991 	b[0] = b1->pos[3];
992 	l[0] = b1->pos[2];
993 	r[0] = b1->pos[2] + b1->pos[0];
994 	t[1] = b2->pos[3] + b2->pos[1];
995 	b[1] = b2->pos[3];
996 	l[1] = b2->pos[2];
997 	r[1] = b2->pos[2] + b2->pos[0];
998 
999 	/* if the boxes coincide, expand the first one and hide the second one */
1000 
1001 	if (t[0] == t[1] && b[0] == b[1] && (min(r[0], r[1]) > max(l[0], l[1]))) {
1002 		l[2] = min(l[0], l[1]);
1003 		r[2] = max(r[0], r[1]);
1004 		b1->pos[0] = (r[2]-l[2]);
1005 		b1->pos[1] = (t[0]-b[0]);
1006 		b1->pos[2] = (l[2]);
1007 		b1->pos[3] = (b[0]);
1008 		b2->visible = 0;
1009 		return 1;
1010 	}
1011 	else if (r[0] == r[1] && l[0] == l[1] && (min(t[0], t[1]) > max(b[0], b[1]))) {
1012 		b[2] = min(b[0], b[1]);
1013 		t[2] = max(t[0], t[1]);
1014 		b1->pos[0] = (r[0]-l[0]);
1015 		b1->pos[1] = (t[2]-b[2]);
1016 		b1->pos[2] = (l[0]);
1017 		b1->pos[3] = (b[2]);
1018 		b2->visible = 0;
1019 		return 1;
1020 	}
1021 	/* if one completely covers another, hide the covered box */
1022 	else if (r[0] >= r[1] && l[0] <= l[1] && t[0] >= t[1] && b[0] <= b[1]) {
1023 		b2->visible = 0;
1024 		return 1;
1025 	}
1026 	else if (r[1] >= r[0] && l[1] <= l[0] && t[1] >= t[0] && b[1] <= b[0]) {
1027 		b1->visible = 0;
1028 		return 1;
1029 	}
1030 	return 0;
1031 }
1032 
1033 #if 0
1034 void io_pscolor_checkOverlap(CELLL *c, BOXL *b1, BOXL *b2, INTBIG layerNum)
1035 {
1036 	INTBIG t[3], b[3], l[3], r[3];
1037 	BOXL *curbox;
1038 
1039 	t[0] = b1->pos[3] + b1->pos[1];
1040 	b[0] = b1->pos[3];
1041 	l[0] = b1->pos[2];
1042 	r[0] = b1->pos[2] + b1->pos[0];
1043 	t[1] = b2->pos[3] + b2->pos[1];
1044 	b[1] = b2->pos[3];
1045 	l[1] = b2->pos[2];
1046 	r[1] = b2->pos[2] + b2->pos[0];
1047 
1048 	t[2] = t[0] < t[1] ? t[0] : t[1];
1049 	b[2] = b[0] > b[1] ? b[0] : b[1];
1050 	l[2] = l[0] > l[1] ? l[0] : l[1];
1051 	r[2] = r[0] < r[1] ? r[0] : r[1];
1052 
1053 	if (t[2] > b[2] && r[2] > l[2]) {
1054 		/* create overlap layer */
1055 		curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
1056 		curbox->layer = (INTSML)layerNum;
1057 		curbox->next = NULL;
1058 		curbox->pos[0] = (r[2]-l[2]);
1059 		curbox->pos[1] = (t[2]-b[2]);
1060 		curbox->pos[2] = (l[2]);
1061 		curbox->pos[3] = (b[2]);
1062 		curbox->visible = 1;
1063 		if (t[2] == t[0] && b[2] == b[0] && l[2] == l[0] && r[2] == r[0])
1064 			b1->visible = 0;
1065 		if (t[2] == t[1] && b[2] == b[1] && l[2] == l[1] && r[2] == r[1])
1066 			b2->visible = 0;
1067 		c->box = io_pscolor_insertbox(curbox, c->box);
1068 	}
1069 }
1070 #endif
1071 
io_pscolor_coaf1(BOXQUADTREE * q1,BOXQUADTREE * q2,INTBIG layernum)1072 void io_pscolor_coaf1(BOXQUADTREE *q1, BOXQUADTREE *q2, INTBIG layernum)
1073 {
1074 	io_pscolor_coaf2(q1, q2, layernum);
1075 	if (q1->tl != NULL) {
1076 		io_pscolor_coaf3(q1->tl, q2, layernum);
1077 		io_pscolor_coaf3(q1->tr, q2, layernum);
1078 		io_pscolor_coaf3(q1->bl, q2, layernum);
1079 		io_pscolor_coaf3(q1->br, q2, layernum);
1080 		if (q2->tl != NULL) {
1081 			io_pscolor_coaf1(q1->tl, q2->tl, layernum);
1082 			io_pscolor_coaf1(q1->tr, q2->tr, layernum);
1083 			io_pscolor_coaf1(q1->bl, q2->bl, layernum);
1084 			io_pscolor_coaf1(q1->br, q2->br, layernum);
1085 		}
1086 		else {
1087 			io_pscolor_coaf4(q1->tl, q2, layernum, 0);
1088 			io_pscolor_coaf4(q1->tr, q2, layernum, 0);
1089 			io_pscolor_coaf4(q1->bl, q2, layernum, 0);
1090 			io_pscolor_coaf4(q1->br, q2, layernum, 0);
1091 		}
1092 	}
1093 }
1094 
io_pscolor_coaf2(BOXQUADTREE * q1,BOXQUADTREE * q2,INTBIG layernum)1095 void io_pscolor_coaf2(BOXQUADTREE *q1, BOXQUADTREE *q2, INTBIG layernum)
1096 {
1097 	io_pscolor_checkOverlapAfterFlattening(q1, q2, layernum);
1098 	if (q2->tl != NULL) {
1099 		io_pscolor_coaf2(q1, q2->tl, layernum);
1100 		io_pscolor_coaf2(q1, q2->tr, layernum);
1101 		io_pscolor_coaf2(q1, q2->bl, layernum);
1102 		io_pscolor_coaf2(q1, q2->br, layernum);
1103 	}
1104 }
1105 
io_pscolor_coaf3(BOXQUADTREE * q1,BOXQUADTREE * q2,INTBIG layernum)1106 void io_pscolor_coaf3(BOXQUADTREE *q1, BOXQUADTREE *q2, INTBIG layernum)
1107 {
1108 	io_pscolor_checkOverlapAfterFlattening(q1, q2, layernum);
1109 	if (q2->parent != NULL)
1110 		io_pscolor_coaf3(q1, q2->parent, layernum);
1111 }
1112 
io_pscolor_coaf4(BOXQUADTREE * q1,BOXQUADTREE * q2,INTBIG layernum,INTBIG check)1113 void io_pscolor_coaf4(BOXQUADTREE *q1, BOXQUADTREE *q2, INTBIG layernum, INTBIG check)
1114 {
1115 	if (check) {
1116 		io_pscolor_coaf3(q1, q2, layernum);
1117 	}
1118 	if (q1->tl != NULL) {
1119 		io_pscolor_coaf4(q1->tl, q2, layernum, 1);
1120 		io_pscolor_coaf4(q1->tr, q2, layernum, 1);
1121 		io_pscolor_coaf4(q1->bl, q2, layernum, 1);
1122 		io_pscolor_coaf4(q1->br, q2, layernum, 1);
1123 	}
1124 }
1125 
io_pscolor_checkOverlapAfterFlattening(BOXQUADTREE * q1,BOXQUADTREE * q2,INTBIG layerNum)1126 void io_pscolor_checkOverlapAfterFlattening(BOXQUADTREE *q1, BOXQUADTREE *q2, INTBIG layerNum)
1127 {
1128 	INTBIG j, k;
1129 	INTBIG t[3], b[3], l[3], r[3];
1130 	BOXL *curbox;
1131 
1132 	/* check overlap of boxes at this level of the quad tree */
1133 	if (q1->numBoxes && q2->numBoxes) {
1134 		for (j=0; j<q1->numBoxes; j++) {
1135 			t[0] = q1->boxes[j].pos[3] + q1->boxes[j].pos[1];
1136 			b[0] = q1->boxes[j].pos[3];
1137 			l[0] = q1->boxes[j].pos[2];
1138 			r[0] = q1->boxes[j].pos[2] + q1->boxes[j].pos[0];
1139 
1140 			for (k=0; k < q2->numBoxes; k++) {
1141 				t[1] = q2->boxes[k].pos[3] + q2->boxes[k].pos[1];
1142 				b[1] = q2->boxes[k].pos[3];
1143 				l[1] = q2->boxes[k].pos[2];
1144 				r[1] = q2->boxes[k].pos[2] + q2->boxes[k].pos[0];
1145 
1146 				t[2] = t[0] < t[1] ? t[0] : t[1];
1147 				b[2] = b[0] > b[1] ? b[0] : b[1];
1148 				l[2] = l[0] > l[1] ? l[0] : l[1];
1149 				r[2] = r[0] < r[1] ? r[0] : r[1];
1150 
1151 				if (t[2] > b[2] && r[2] > l[2]) {
1152 					/* create overlap layer */
1153 					curbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
1154 					curbox->layer = (INTSML)layerNum;
1155 					curbox->next = NULL;
1156 					curbox->pos[0] = (r[2]-l[2]);
1157 					curbox->pos[1] = (t[2]-b[2]);
1158 					curbox->pos[2] = (l[2]);
1159 					curbox->pos[3] = (b[2]);
1160 					curbox->visible = 1;
1161 					if (t[2] == t[0] && b[2] == b[0] && l[2] == l[0] && r[2] == r[0]) q1->boxes[j].visible = 0;
1162 					if (t[2] == t[1] && b[2] == b[1] && l[2] == l[1] && r[2] == r[1]) q2->boxes[k].visible = 0;
1163 					io_pscolor_flattenedbox[layerNum] = io_pscolor_insertbox(curbox, io_pscolor_flattenedbox[layerNum]);
1164 				}
1165 			}
1166 		}
1167 	}
1168 }
1169 
io_pscolor_flatten(void)1170 void io_pscolor_flatten(void)
1171 {
1172 	float ident[9];
1173 	INTBIG i;
1174 
1175 	io_pscolor_newIdentityMatrix(ident);
1176 	for (i=0; i<io_pscolor_numLayers; i++) {
1177 		io_pscolor_flattenedbox[i] = NULL;
1178 	}
1179 
1180 	/* for now, assume last cell is top level.  Change this to recognize C *** at top of CIF */
1181 
1182 	ttyputmsg(_("Flattening..."));
1183 	io_pscolor_recursiveFlatten(io_pscolor_cells, ident);
1184 }
1185 
io_pscolor_recursiveFlatten(CELLL * top,float m[9])1186 void io_pscolor_recursiveFlatten(CELLL *top, float m[9])
1187 {
1188 	CELLINSTL *inst;
1189 	BOXL *box, *newbox;
1190 	POLYL *poly, *newpoly;
1191 	float tm[9];
1192 
1193 	/* add boxes from this cell */
1194 	box = top->box;
1195 	while (box != NULL) {
1196 		if (box->visible) {
1197 			newbox = io_pscolor_copybox(box, m);
1198 			io_pscolor_flattenedbox[newbox->layer] = io_pscolor_insertbox(newbox, io_pscolor_flattenedbox[newbox->layer]);
1199 		}
1200 		box = box->next;
1201 	}
1202 
1203 	/* add polygons from this cell */
1204 	poly = top->poly;
1205 	while (poly != NULL) {
1206 		newpoly = io_pscolor_copypoly(poly, m);
1207 		io_pscolor_flattenedpoly[newpoly->layer] = io_pscolor_insertpoly(newpoly, io_pscolor_flattenedpoly[newpoly->layer]);
1208 		poly = poly->next;
1209 	}
1210 
1211 	/* recursively traverse subinstances */
1212 	inst = top->inst;
1213 	while (inst != NULL) {
1214 		io_pscolor_numInstances++;
1215 		io_pscolor_matrixMul(tm, inst->transform, m);
1216 		io_pscolor_recursiveFlatten(inst->inst, tm);
1217 		inst = inst->next;
1218 	}
1219 }
1220 
io_pscolor_writePS(NODEPROTO * cell,BOOLEAN useplotter,INTBIG pageWidth,INTBIG pageHeight,INTBIG border)1221 void io_pscolor_writePS(NODEPROTO *cell, BOOLEAN useplotter,
1222 	INTBIG pageWidth, INTBIG pageHeight, INTBIG border)
1223 {
1224 	INTBIG i, j, pslx, pshx, psly, pshy, size, x, y, descenderoffset, rot, xoff, yoff,
1225 		reducedwidth, reducedheight;
1226 	CHAR *opname;
1227 	POLYL *p;
1228 	BOXL *g;
1229 	LABELL *l;
1230 	float scale;
1231 	INTBIG w, h;
1232 	time_t curdate;
1233 	extern CHAR *io_psstringheader[];
1234 
1235 	/* Header info */
1236 	io_pswrite(x_("%%!PS-Adobe-1.0\n"));
1237 	io_pswrite(x_("%%Title: %s\n"), describenodeproto(cell));
1238 	if ((us_useroptions&NODATEORVERSION) == 0)
1239 	{
1240 		io_pswrite(x_("%%%%Creator: Electric VLSI Design System (David Harris's color PostScript generator) version %s\n"), el_version);
1241 		curdate = getcurrenttime();
1242 		io_pswrite(x_("%%%%CreationDate: %s\n"), timetostring(curdate));
1243 	} else
1244 	{
1245 		io_pswrite(x_("%%%%Creator: Electric VLSI Design System (David Harris's color PostScript generator)\n"));
1246 	}
1247 	io_pswrite(x_("%%%%Pages: 1\n"));
1248 	io_pswrite(x_("%%%%BoundingBox: %ld %ld %ld %ld\n"), io_pscolor_cifBoundaries[0],
1249 		io_pscolor_cifBoundaries[1], io_pscolor_cifBoundaries[2], io_pscolor_cifBoundaries[3]);
1250 	io_pswrite(x_("%%%%DocumentFonts: %s\n"), io_pscolor_font);
1251 	io_pswrite(x_("%%%%EndComments\n"));
1252 
1253 	/* Coordinate system */
1254 	io_pswrite(x_("%% Min X: %d  min Y: %d  max X: %d  max Y: %d\n"), io_pscolor_cifBoundaries[0],
1255 		io_pscolor_cifBoundaries[1], io_pscolor_cifBoundaries[2], io_pscolor_cifBoundaries[3]);
1256 	reducedwidth = pageWidth - border*2;
1257 	reducedheight = pageHeight - border*2;
1258 	scale = reducedwidth/(float)(io_pscolor_cifBoundaries[2]-io_pscolor_cifBoundaries[0]);
1259 	if (useplotter)
1260 	{
1261 		/* plotter: infinite height */
1262 		io_pswrite(x_("%f %f scale\n"), scale, scale);
1263 		x = io_pscolor_cifBoundaries[0]+border - ((INTBIG)(pageWidth/scale) -
1264 			(io_pscolor_cifBoundaries[2]-io_pscolor_cifBoundaries[0])) / 2;
1265 		y = io_pscolor_cifBoundaries[1]+border;
1266 		io_pswrite(x_("%d neg %d neg translate\n"), x, y);
1267 	} else
1268 	{
1269 		/* printer: fixed height */
1270 		if (reducedheight/(float)(io_pscolor_cifBoundaries[3]-io_pscolor_cifBoundaries[1]) < scale)
1271 			scale = reducedheight/(float)(io_pscolor_cifBoundaries[3]-io_pscolor_cifBoundaries[1]);
1272 		io_pswrite(x_("%f %f scale\n"), scale, scale);
1273 		x = io_pscolor_cifBoundaries[0]+border - ((INTBIG)(pageWidth/scale) -
1274 			(io_pscolor_cifBoundaries[2]-io_pscolor_cifBoundaries[0])) / 2;
1275 		y = io_pscolor_cifBoundaries[1]+border - ((INTBIG)(pageHeight/scale) -
1276 			(io_pscolor_cifBoundaries[3]-io_pscolor_cifBoundaries[1])) / 2;
1277 		io_pswrite(x_("%d neg %d neg translate\n"), x, y);
1278 	}
1279 
1280 	/* set font */
1281 	io_pswrite(x_("/DefaultFont /%s def\n"), io_pscolor_font);
1282 	io_pswrite(x_("/scaleFont {\n"));
1283 	io_pswrite(x_("    DefaultFont findfont\n"));
1284 	io_pswrite(x_("    exch scalefont setfont} def\n"));
1285 
1286 	/* define box command to make rectangles more memory efficient */
1287 	io_pswrite(x_("\n/bx \n  { /h exch def /w exch def /x exch def /y exch def\n"));
1288 	io_pswrite(x_("    newpath x y moveto w 0 rlineto 0 h rlineto w neg 0 rlineto closepath fill } def\n"));
1289 
1290 	/* draw layers */
1291 	for (i=0; i<io_pscolor_numLayers; i++)
1292 	{
1293 		/* skip drawing layers that are white */
1294 		if (io_pscolor_layers[i].r != 1 || io_pscolor_layers[i].g != 1 || io_pscolor_layers[i].b != 1)
1295 		{
1296 			g = io_pscolor_flattenedbox[i];
1297 			p = io_pscolor_flattenedpoly[i];
1298 			if (g != NULL || p != NULL)
1299 			{
1300 				io_pswrite(x_("\n%% Layer %s:%d"), io_pscolor_layers[i].tech->techname,
1301 					io_pscolor_layers[i].layernumber);
1302 				if (io_pscolor_layers[i].mix1 != -1)
1303 					io_pswrite(x_(" mix of %d and %d"), io_pscolor_layers[io_pscolor_layers[i].mix1].layernumber,
1304 						io_pscolor_layers[io_pscolor_layers[i].mix2].layernumber);
1305 				io_pswrite(x_("\n%f %f %f setrgbcolor\n"), io_pscolor_layers[i].r,
1306 					io_pscolor_layers[i].g, io_pscolor_layers[i].b);
1307 			}
1308 			while (g != NULL)
1309 			{
1310 				if (g->visible)
1311 				{
1312 					w = g->pos[0];
1313 					h = g->pos[1];
1314 					io_pswrite(x_("%d %d %d %d bx\n"),	g->pos[3], g->pos[2], w, h);
1315 					io_pscolor_numBoxes++;
1316 				}
1317 				g = g->next;
1318 				io_pscolor_totalBoxes++;
1319 			}
1320 			while (p != NULL)
1321 			{
1322 				if (p->numcoords > 2)
1323 				{
1324 					io_pswrite(x_("newpath %d %d moveto\n"), p->coords[0], p->coords[1]);
1325 					for (j=2; j<p->numcoords; j+=2) {
1326 						io_pswrite(x_("        %d %d lineto\n"), p->coords[j], p->coords[j+1]);
1327 					}
1328 					io_pswrite(x_("closepath %s\n"), i==0 ? x_("stroke") : x_("fill"));
1329 					io_pscolor_numPolys++;
1330 				}
1331 				p = p->next;
1332 			}
1333 /*			LINEL *h = io_pscolor_horizsegs[i];
1334 			io_pswrite(x_("\n0 0 0 setrgbcolor\n newpath\n"));
1335 			while (h != NULL) {
1336 				io_pswrite(x_("%d %d moveto %d %d lineto\n"), h->x[0], h->y, h->x[1], h->y);
1337 				h = h->next;
1338 			}
1339 			io_pswrite(x_("closepath stroke\n"));
1340 */
1341 		}
1342 	}
1343 
1344 	/* label ports and cell instances */
1345 	l = io_pscolor_cells->label;
1346 	io_pswrite(x_("\n%% Port and Cell Instance Labels\n"));
1347 	io_pswrite(x_("0 0 0 setrgbcolor\n"));
1348 	for(i=0; io_psstringheader[i] != 0; i++)
1349 		io_pswrite(x_("%s\n"), io_psstringheader[i]);
1350 	while (l != NULL)
1351 	{
1352 		size = io_pscolor_truefontsize(TDGETSIZE(l->descript), el_curtech);
1353 		pslx = l->pos[0];   pshx = l->pos[1];
1354 		psly = l->pos[2];   pshy = l->pos[3];
1355 		if (l->style == TEXTBOX)
1356 		{
1357 			io_pswrite(x_("%ld %ld %ld %ld "), (pslx+pshx)/2, (psly+pshy)/2, pshx-pslx, pshy-psly);
1358 			io_pswritestring(l->label);
1359 			io_pswrite(x_(" %f Boxstring\n"), size/scale);
1360 		} else
1361 		{
1362 			switch (l->style)
1363 			{
1364 				case TEXTCENT:
1365 					x = (pslx+pshx)/2;   y = (psly+pshy)/2;
1366 					opname = x_("Centerstring");
1367 					break;
1368 				case TEXTTOP:
1369 					x = (pslx+pshx)/2;   y = pshy;
1370 					opname = x_("Topstring");
1371 					break;
1372 				case TEXTBOT:
1373 					x = (pslx+pshx)/2;   y = psly;
1374 					opname = x_("Botstring");
1375 					break;
1376 				case TEXTLEFT:
1377 					x = pslx;   y = (psly+pshy)/2;
1378 					opname = x_("Leftstring");
1379 					break;
1380 				case TEXTRIGHT:
1381 					x = pshx;   y = (psly+pshy)/2;
1382 					opname = x_("Rightstring");
1383 					break;
1384 				case TEXTTOPLEFT:
1385 					x = pslx;   y = pshy;
1386 					opname = x_("Topleftstring");
1387 					break;
1388 				case TEXTTOPRIGHT:
1389 					x = pshx;   y = pshy;
1390 					opname = x_("Toprightstring");
1391 					break;
1392 				case TEXTBOTLEFT:
1393 					x = pslx;   y = psly;
1394 					opname = x_("Botleftstring");
1395 					break;
1396 				case TEXTBOTRIGHT:
1397 					x = pshx;   y = psly;
1398 					opname = x_("Botrightstring");
1399 					break;
1400 			}
1401 			descenderoffset = size / 12;
1402 			rot = TDGETROTATION(l->descript);
1403 			switch (rot)
1404 			{
1405 				case 0: y += descenderoffset;   break;
1406 				case 1: x -= descenderoffset;   break;
1407 				case 2: y -= descenderoffset;   break;
1408 				case 3: x += descenderoffset;   break;
1409 			}
1410 			if (rot != 0)
1411 			{
1412 				if (rot == 1 || rot == 3)
1413 				{
1414 					switch (l->style)
1415 					{
1416 						case TEXTTOP:      opname = x_("Rightstring");     break;
1417 						case TEXTBOT:      opname = x_("Leftstring");      break;
1418 						case TEXTLEFT:     opname = x_("Botstring");       break;
1419 						case TEXTRIGHT:    opname = x_("Topstring");       break;
1420 						case TEXTTOPLEFT:  opname = x_("Botrightstring");  break;
1421 						case TEXTBOTRIGHT: opname = x_("Topleftstring");   break;
1422 					}
1423 				}
1424 				xoff = x;   yoff = y;
1425 				x = y = 0;
1426 				switch (rot)
1427 				{
1428 					case 1:		/* 90 degrees counterclockwise */
1429 						io_pswrite(x_("%ld %ld translate 90 rotate\n"), xoff, yoff);
1430 						break;
1431 					case 2:		/* 180 degrees */
1432 						io_pswrite(x_("%ld %ld translate 180 rotate\n"), xoff, yoff);
1433 						break;
1434 					case 3:		/* 90 degrees clockwise */
1435 						io_pswrite(x_("%ld %ld translate 270 rotate\n"), xoff, yoff);
1436 						break;
1437 				}
1438 			}
1439 			io_pswrite(x_("%ld %ld "), x, y);
1440 			io_pswritestring(l->label);
1441 			io_pswrite(x_(" %ld %s\n"), size, opname);
1442 			if (rot != 0)
1443 			{
1444 				switch (rot)
1445 				{
1446 					case 1:		/* 90 degrees counterclockwise */
1447 						io_pswrite(x_("270 rotate %ld %ld translate\n"), -xoff, -yoff);
1448 						break;
1449 					case 2:		/* 180 degrees */
1450 						io_pswrite(x_("180 rotate %ld %ld translate\n"), -xoff, -yoff);
1451 						break;
1452 					case 3:		/* 90 degrees clockwise */
1453 						io_pswrite(x_("90 rotate %ld %ld translate\n"), -xoff, -yoff);
1454 						break;
1455 				}
1456 			}
1457 		}
1458 		l = l->next;
1459 	}
1460 
1461 	/* Finish page */
1462 	io_pswrite(x_("\nshowpage\n"));
1463 }
1464 
io_pscolor_truefontsize(INTBIG font,TECHNOLOGY * tech)1465 INTBIG io_pscolor_truefontsize(INTBIG font, TECHNOLOGY *tech)
1466 {
1467 	REGISTER INTBIG  lambda, height;
1468 
1469 	/* absolute font sizes are easy */
1470 	if ((font&TXTPOINTS) != 0) return((font&TXTPOINTS) >> TXTPOINTSSH);
1471 
1472 	/* detemine default, min, and max size of font */
1473 	lambda = el_curlib->lambda[tech->techindex];
1474 	height = TXTGETQLAMBDA(font);
1475 	height = height * lambda / 4;
1476 	return(height);
1477 }
1478 
io_pscolor_copybox(BOXL * g,float m[9])1479 BOXL *io_pscolor_copybox(BOXL *g, float m[9])
1480 {
1481 	BOXL *newbox;
1482 	INTBIG dx, dy;
1483 
1484 	newbox = (BOXL *)emalloc(sizeof(BOXL), io_tool->cluster);
1485 	newbox->layer = g->layer;
1486 	newbox->next = NULL;
1487 	io_pscolor_transformBox(newbox->pos, g->pos, m);
1488 	newbox->visible = g->visible;
1489 
1490 	/* Update bounding box */
1491 	dx = newbox->pos[0];
1492 	dy = newbox->pos[1];
1493 	if (newbox->pos[2] < io_pscolor_cifBoundaries[0]) io_pscolor_cifBoundaries[0] = newbox->pos[2];
1494 	if (newbox->pos[3] < io_pscolor_cifBoundaries[1]) io_pscolor_cifBoundaries[1] = newbox->pos[3];
1495 	if (newbox->pos[2]+dx > io_pscolor_cifBoundaries[2]) io_pscolor_cifBoundaries[2] = newbox->pos[2]+dx;
1496 	if (newbox->pos[3]+dy > io_pscolor_cifBoundaries[3]) io_pscolor_cifBoundaries[3] = newbox->pos[3]+dy;
1497 	return newbox;
1498 }
1499 
io_pscolor_copypoly(POLYL * p,float m[9])1500 POLYL *io_pscolor_copypoly(POLYL *p, float m[9])
1501 {
1502 	POLYL *newpoly;
1503 	INTBIG i;
1504 
1505 	newpoly = (POLYL *)emalloc(sizeof(POLYL), io_tool->cluster);
1506 	if (newpoly == 0) return(0);
1507 	newpoly->layer = p->layer;
1508 	newpoly->next = NULL;
1509 	newpoly->numcoords = p->numcoords;
1510 	newpoly->coords = (INTBIG *)emalloc(newpoly->numcoords * SIZEOFINTBIG, io_tool->cluster);
1511 	if (newpoly->coords == 0) return(0);
1512 	io_pscolor_transformPoly(newpoly, p, m);
1513 
1514 	/* Update bounding box */
1515 	for(i=0; i<newpoly->numcoords; i++)
1516 	{
1517 		if ((i%2) == 0)
1518 		{
1519 			if (newpoly->coords[i] < io_pscolor_cifBoundaries[0]) io_pscolor_cifBoundaries[0] = newpoly->coords[i];
1520 			if (newpoly->coords[i] > io_pscolor_cifBoundaries[3]) io_pscolor_cifBoundaries[3] = newpoly->coords[i];
1521 		} else
1522 		{
1523 			if (newpoly->coords[i] < io_pscolor_cifBoundaries[1]) io_pscolor_cifBoundaries[1] = newpoly->coords[i];
1524 			if (newpoly->coords[i] > io_pscolor_cifBoundaries[2]) io_pscolor_cifBoundaries[2] = newpoly->coords[i];
1525 		}
1526 	}
1527 	return newpoly;
1528 }
1529 
io_pscolor_insertCell(CELLL * c,CELLL * list)1530 CELLL* io_pscolor_insertCell(CELLL *c, CELLL *list)
1531 {
1532 	c->next = list;
1533 	list = c;
1534 	return list;
1535 }
1536 
io_pscolor_insertbox(BOXL * g,BOXL * list)1537 BOXL* io_pscolor_insertbox(BOXL *g, BOXL *list)
1538 {
1539 	g->next = list;
1540 	list = g;
1541 	return list;
1542 }
1543 
io_pscolor_insertpoly(POLYL * p,POLYL * list)1544 POLYL* io_pscolor_insertpoly(POLYL *p, POLYL *list)
1545 {
1546 	p->next = list;
1547 	list = p;
1548 	return list;
1549 }
1550 
io_pscolor_insertlabel(LABELL * p,LABELL * list)1551 LABELL* io_pscolor_insertlabel(LABELL *p, LABELL *list)
1552 {
1553 	p->next = list;
1554 	list = p;
1555 	return list;
1556 }
1557 
io_pscolor_insertInst(CELLINSTL * i,CELLINSTL * list)1558 CELLINSTL* io_pscolor_insertInst(CELLINSTL *i, CELLINSTL *list)
1559 {
1560 	i->next = list;
1561 	list = i;
1562 	return list;
1563 }
1564 
io_pscolor_matrixMul(float r[9],float a[9],float b[9])1565 void io_pscolor_matrixMul(float r[9], float a[9], float b[9])
1566 {
1567 	INTBIG i, j, k;
1568 	float tmp[9];
1569 
1570 	for (i=0; i<3; i++) {
1571 		for (j=0; j<3; j++) {
1572 			tmp[i*3+j] = 0;
1573 			for (k=0; k<3; k++) {
1574 				tmp[i*3+j] += a[i*3+k] * b[k*3+j];
1575 			}
1576 		}
1577 	}
1578 	for (i=0; i<3; i++) {
1579 		for (j=0; j<3; j++) {
1580 			r[i*3+j] = tmp[i*3+j];
1581 		}
1582 	}
1583 }
1584 
io_pscolor_newIdentityMatrix(float m[9])1585 void io_pscolor_newIdentityMatrix(float m[9])
1586 {
1587 	INTBIG i,j;
1588 
1589 	for (i=0; i<3; i++) {
1590 		for (j=0; j<3; j++) {
1591 			m[i*3+j] = (i==j);
1592 		}
1593 	}
1594 }
1595 
io_pscolor_transformBox(INTBIG final[4],INTBIG initial[4],float m[9])1596 void io_pscolor_transformBox(INTBIG final[4], INTBIG initial[4], float m[9])
1597 {
1598 	INTBIG i,j;
1599 	INTBIG pos[2];
1600 
1601 	pos[0] = initial[2]+initial[0]/2;
1602 	pos[1] = initial[3]+initial[1]/2;
1603 
1604 	for (i=0; i < 2; i++) {
1605 		final[i+2] = (INTBIG)m[6+i];
1606 		for (j=0; j<2; j++) {
1607 			final[i+2] += (INTBIG)m[i+j*3]*pos[j];
1608 		}
1609 	}
1610 
1611 	if (m[1] == 0) { /* rotation */
1612 		final[0] = initial[0];
1613 		final[1] = initial[1];
1614 	}
1615 	else {
1616 		final[0] = initial[1];
1617 		final[1] = initial[0];
1618 	}
1619 	final[2] -= final[0]/2;
1620 	final[3] -= final[1]/2;
1621 }
1622 
io_pscolor_transformPoly(POLYL * final,POLYL * initial,float m[9])1623 void io_pscolor_transformPoly(POLYL *final, POLYL *initial, float m[9])
1624 {
1625 	INTBIG p, i,j;
1626 
1627 	for (p=0; p<initial->numcoords/2; p++) {
1628 		for (i=0; i <2; i++) {
1629 			final->coords[p*2+i] = (INTBIG)m[6+i];
1630 			for (j=0; j<2; j++) {
1631 				final->coords[p*2+i] += (INTBIG)m[i+j*3]*initial->coords[p*2+j];
1632 			}
1633 		}
1634 	}
1635 }
1636 
io_pscolor_printStatistics(void)1637 void io_pscolor_printStatistics(void)
1638 {
1639 	ttyputmsg("Plotting statistics:");
1640 	ttyputmsg("  %ld layers defined or transparencies implied in layer map", io_pscolor_numLayers);
1641 	ttyputmsg("  %ld cells", io_pscolor_numCells);
1642 	ttyputmsg("  %ld instances used", io_pscolor_numInstances);
1643 	ttyputmsg("  %ld boxes generated", io_pscolor_numBoxes);
1644 	ttyputmsg("  %ld polygons generated", io_pscolor_numPolys);
1645 }
1646 
io_pscolor_freeMem(void)1647 void io_pscolor_freeMem(void)
1648 {
1649 	INTBIG i;
1650 
1651 	io_pscolor_freeCell(io_pscolor_cells);
1652 	for (i=0; i<io_pscolor_numLayers; i++) {
1653 		io_pscolor_freeBox(io_pscolor_flattenedbox[i]);
1654 		io_pscolor_flattenedbox[i] = NULL;
1655 		io_pscolor_freePoly(io_pscolor_flattenedpoly[i]);
1656 		io_pscolor_flattenedpoly[i] = NULL;
1657 		io_pscolor_freeBoxQuadTree(io_pscolor_boxQuadTrees[i]);
1658 		io_pscolor_boxQuadTrees[i] = NULL;
1659 	}
1660 	io_pscolor_cells = NULL;
1661 }
1662 
io_pscolor_freeBoxQuadTree(BOXQUADTREE * q)1663 void io_pscolor_freeBoxQuadTree(BOXQUADTREE *q)
1664 {
1665 	if (q != NULL) {
1666 		io_pscolor_freeBoxQuadTree(q->tl);
1667 		io_pscolor_freeBoxQuadTree(q->tr);
1668 		io_pscolor_freeBoxQuadTree(q->bl);
1669 		io_pscolor_freeBoxQuadTree(q->br);
1670 		efree((CHAR *)q->boxes);
1671 		efree((CHAR *)q);
1672 	}
1673 }
1674 
io_pscolor_freeCell(CELLL * c)1675 void io_pscolor_freeCell(CELLL *c)
1676 {
1677 	CELLL *c2;
1678 
1679 	while (c != NULL) {
1680 		io_pscolor_freeCellInst(c->inst);
1681 		io_pscolor_freeBox(c->box);
1682 		io_pscolor_freePoly(c->poly);
1683 		io_pscolor_freeLabel(c->label);
1684 		c2 = c;
1685 		c = c->next;
1686 		efree((CHAR *)c2);
1687 	}
1688 }
1689 
io_pscolor_freeBox(BOXL * b)1690 void io_pscolor_freeBox(BOXL *b)
1691 {
1692 	BOXL *b2;
1693 
1694 	while (b != NULL) {
1695 		b2 = b;
1696 		b = b->next;
1697 		efree((CHAR *)b2);
1698 	}
1699 }
1700 
io_pscolor_freePoly(POLYL * b)1701 void io_pscolor_freePoly(POLYL *b)
1702 {
1703 	POLYL *b2;
1704 
1705 	while (b != NULL) {
1706 		b2 = b;
1707 		b = b->next;
1708 		efree((CHAR *)b2->coords);
1709 		efree((CHAR *)b2);
1710 	}
1711 }
1712 
io_pscolor_freeLabel(LABELL * b)1713 void io_pscolor_freeLabel(LABELL *b)
1714 {
1715 	LABELL *b2;
1716 
1717 	while (b != NULL) {
1718 		b2 = b;
1719 		b = b->next;
1720 		efree((CHAR *)b2->label);
1721 		efree((CHAR *)b2);
1722 	}
1723 }
1724 
io_pscolor_freeCellInst(CELLINSTL * b)1725 void io_pscolor_freeCellInst(CELLINSTL *b)
1726 {
1727 	CELLINSTL *b2;
1728 
1729 	while (b != NULL) {
1730 		b2 = b;
1731 		b = b->next;
1732 		efree((CHAR *)b2);
1733 	}
1734 }
1735 
1736 #if 0
1737 void io_pscolor_freeLine(LINEL *b)
1738 {
1739 	LINEL *b2;
1740 
1741 	while (b != NULL) {
1742 		b2 = b;
1743 		b = b->next;
1744 		efree((CHAR *)b2);
1745 	}
1746 }
1747 #endif
1748 
1749 /********************************* OUTLINE HANDLING *********************************/
1750 
1751 #if 0
1752 void genOutlines(void)
1753 {
1754 	INTBIG i;
1755 	LINEL *horiz, *vert;
1756 
1757 	ttyputmsg("Generating layer outlines...");
1758 	for (i=0; i<io_pscolor_numLayers; i++) {
1759 		if (io_pscolor_layers[i].mix1 == -1 && io_pscolor_layers[i].mix2 == -1) {
1760 			horiz = io_pscolor_genSegments(io_pscolor_flattenedbox[i], 0);
1761 			vert = io_pscolor_genSegments(io_pscolor_flattenedbox[i], 1);
1762 			/*eliminateSegments(horiz); */
1763 			/*eliminateSegments(vert); */
1764 			io_pscolor_flattenedoutline[i] = io_pscolor_combineSegments(horiz, vert);
1765 			io_pscolor_horizsegs[i] = horiz;
1766 		}
1767 	}
1768 }
1769 
1770 LINEL *io_pscolor_genSegments(BOXL *boxes, INTBIG dir)
1771 {
1772 	INTBIG numBoxes;
1773 	INTBIG i;
1774 	BOXL *b;
1775 	LINEL *lines;
1776 	LINEL *segs, *s2;
1777 
1778 	numBoxes = io_pscolor_countBoxes(boxes);
1779 	lines = (LINEL *)emalloc(2*numBoxes*sizeof(LINEL), io_tool->cluster);
1780 	for (i=0, b=boxes; i<numBoxes; i++) {
1781 		lines[2*i].visible = 1;
1782 		lines[2*i].x[0] = b->pos[2+dir];
1783 		lines[2*i].x[1] = b->pos[2+dir] + b->pos[0+dir];
1784 		lines[2*i].y = b->pos[3-dir];
1785 		lines[2*i+1].visible = 1;
1786 		lines[2*i+1].x[0] = b->pos[2+dir];
1787 		lines[2*i+1].x[1] = b->pos[2+dir] + b->pos[0+dir];
1788 		lines[2*i+1].y = b->pos[3-dir] + b->pos[1-dir];
1789 		b = b->next;
1790 	}
1791 	qsort(lines, 2*numBoxes, sizeof(LINEL), io_pscolor_lineCompare);
1792 /*	for (i=0; i<2*numBoxes; i++) */
1793 /*		ttyputmsg("seg %d: %d-%d, %d", i, lines[i].x[0], lines[i].x[1], lines[i].y); */
1794 
1795 	/* eliminate segments (not implemented yet) */
1796 	/* this may be difficult because boxes from different cells may overlap. */
1797 	/* at this point I give up and drop it.  dh 1/31/03 */
1798 	segs = NULL;
1799 	for (i=0; i<2*numBoxes; i++) {
1800 		s2 = (LINEL *)emalloc(sizeof(LINEL), io_tool->cluster);
1801 		s2->x[0] = lines[i].x[0];
1802 		s2->x[1] = lines[i].x[1];
1803 		s2->y = lines[i].y;
1804 		s2->visible = lines[i].visible;
1805 		s2->next = segs;
1806 		segs = s2;
1807 	}
1808 
1809 	/* free array */
1810 	efree((CHAR *)lines);
1811 
1812 	return segs;
1813 }
1814 
1815 int io_pscolor_lineCompare(const void *a, const void *b)
1816 {
1817 	return (((LINEL*)a)->y - ((LINEL*)b)->y);
1818 }
1819 
1820 INTBIG io_pscolor_countBoxes(BOXL *boxes)
1821 {
1822 	INTBIG i;
1823 	BOXL *b;
1824 
1825 	b = boxes; i = 0;
1826 	while (b != NULL) {
1827 		i++;
1828 		b = b->next;
1829 	}
1830 
1831 	return i;
1832 }
1833 
1834 OUTLINEL *io_pscolor_combineSegments(LINEL *horiz, LINEL *vert)
1835 {
1836 	return NULL;
1837 }
1838 #endif
1839