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