1 /*
2 * gdsreader - simple Calma parser/printer tool
3 * Copyright (C) 1999 Serban-Mihai Popescu, serbanp@ix.netcom.com
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <strings.h>
22 #include <math.h>
23
24 #include <GDSstructs.h>
25 #include <GDSconsts.h>
26 #include <GDSglobals.h>
27 #include <GDSaux.h>
28 #include <GDStransf.h>
29
30 /*
31 * Both PostScript and HPGL interpreters are faster when dealing with rectangles
32 */
33 static int
BoundaryIsRectangle(boundaryEl * boundary)34 BoundaryIsRectangle(boundaryEl *boundary)
35 {
36 if(boundary->numpoints != 5)
37 return 0;
38
39 if(boundary->points[0].x != boundary->points[1].x)
40 {
41 if(boundary->points[0].y != boundary->points[1].y)
42 return 0;
43 if(boundary->points[0].x != boundary->points[3].x)
44 return 0;
45 if(boundary->points[2].x != boundary->points[1].x)
46 return 0;
47 if(boundary->points[2].y != boundary->points[3].y)
48 return 0;
49 }
50 else
51 {
52 if(boundary->points[0].y != boundary->points[3].y)
53 return 0;
54 if(boundary->points[2].y != boundary->points[1].y)
55 return 0;
56 if(boundary->points[2].x != boundary->points[3].x)
57 return 0;
58 }
59 return 1;
60 }
61
62 bbox
GDSgetBoundaryBBox(boundaryEl * boundary)63 GDSgetBoundaryBBox(boundaryEl *boundary)
64 {
65 int i;
66 bbox bbx;
67
68 bbx.ll.x = BIGVAL;
69 bbx.ll.y = BIGVAL;
70 bbx.ur.x = -BIGVAL;
71 bbx.ur.y = -BIGVAL;
72
73 for(i = 0; i < boundary->numpoints; i++)
74 {
75 if(boundary->points[i].x < bbx.ll.x)
76 bbx.ll.x = boundary->points[i].x;
77 if(boundary->points[i].x > bbx.ur.x)
78 bbx.ur.x = boundary->points[i].x;
79
80 if(boundary->points[i].y < bbx.ll.y)
81 bbx.ll.y = boundary->points[i].y;
82 if(boundary->points[i].y > bbx.ur.y)
83 bbx.ur.y = boundary->points[i].y;
84 }
85
86 return bbx;
87 }
88
89 void
BoundaryToHPGL(FILE * hpglfile,boundaryEl * boundary,PSStyle psStyle)90 BoundaryToHPGL(FILE *hpglfile, boundaryEl *boundary, PSStyle psStyle)
91 {
92 int i;
93
94 if(boundary->layerptr->layerno != psStyle.gdsno)
95 return;
96
97 if(BoundaryIsRectangle(boundary))
98 {
99 fprintf(hpglfile, "PU%d,%dER%d,%d",
100 boundary->points[0].x / InternalScaleFactor,
101 boundary->points[0].y / InternalScaleFactor,
102 (boundary->points[2].x - boundary->points[0].x) /
103 InternalScaleFactor,
104 (boundary->points[2].y - boundary->points[0].y) /
105 InternalScaleFactor);
106 if(psStyle.fill || psStyle.hatch)
107 fprintf(hpglfile, "PU%d,%dRR%d,%d",
108 boundary->points[0].x / InternalScaleFactor,
109 boundary->points[0].y / InternalScaleFactor,
110 (boundary->points[2].x - boundary->points[0].x) /
111 InternalScaleFactor,
112 (boundary->points[2].y - boundary->points[0].y) /
113 InternalScaleFactor);
114 }
115 else
116 {
117 fprintf(hpglfile, "PU%d,%dPM0",
118 boundary->points[0].x / InternalScaleFactor,
119 boundary->points[0].y / InternalScaleFactor);
120 for(i = 1; i < boundary->numpoints; i++)
121 fprintf(hpglfile, "PD%d,%d",
122 boundary->points[i].x / InternalScaleFactor,
123 boundary->points[i].y / InternalScaleFactor);
124 fprintf(hpglfile, "PM2EP");
125 if(psStyle.fill || psStyle.hatch)
126 fprintf(hpglfile, "FP");
127 }
128 fprintf(hpglfile, "\n");
129 }
130
131 int
GDSgetBoundaryWinding(boundaryEl * boundary)132 GDSgetBoundaryWinding(boundaryEl *boundary)
133 {
134 bbox bbx;
135 coord xmin, ymin, ycut, x1, x2, y1, y2;
136 int i, imin;
137
138 ymin = BIGVAL;
139
140 bbx = GDSgetBoundaryBBox(boundary);
141
142 xmin = bbx.ll.x + (bbx.ur.x - bbx.ll.x) / 2;
143 for(i = 0; i < boundary->numpoints - 1; i++)
144 {
145 x1 = boundary->points[i].x;
146 y1 = boundary->points[i].y;
147 x2 = boundary->points[i + 1].x;
148 y2 = boundary->points[i + 1].y;
149
150 if(x1 == x2)
151 continue;
152 else if(boundary->points[i].x > boundary->points[i + 1].x)
153 {
154 x1 = boundary->points[i + 1].x;
155 y1 = boundary->points[i + 1].y;
156 x2 = boundary->points[i].x;
157 y2 = boundary->points[i].y;
158 }
159 else
160 {
161 x1 = boundary->points[i].x;
162 y1 = boundary->points[i].y;
163 x2 = boundary->points[i + 1].x;
164 y2 = boundary->points[i + 1].y;
165 }
166 if(x1 <= xmin && x2 >= xmin)
167 ycut = y1 + (coord)(((double)(y2 - y1)) * (xmin - x1) / (x2 - x1));
168 else
169 continue;
170 if(ycut < ymin)
171 {
172 ymin = ycut;
173 imin = i;
174 }
175 }
176 if(boundary->points[imin].x > boundary->points[imin + 1].x)
177 return 1;
178 else
179 return -1;
180 }
181
182
183 void
BoundaryToPS(FILE * psfile,boundaryEl * boundary,PSStyle psStyle)184 BoundaryToPS(FILE *psfile, boundaryEl *boundary, PSStyle psStyle)
185 {
186 int i;
187
188 if(boundary->layerptr->layerno != psStyle.gdsno)
189 return;
190
191 if(BoundaryIsRectangle(boundary))
192 {
193 fprintf(psfile, "%d %d %d %d rectstroke\n",
194 boundary->points[0].x / InternalScaleFactor,
195 boundary->points[0].y / InternalScaleFactor,
196 (boundary->points[2].x - boundary->points[0].x) / InternalScaleFactor,
197 (boundary->points[2].y - boundary->points[0].y) / InternalScaleFactor);
198 }
199 else
200 {
201 fprintf(psfile, "%d %d m\n",
202 boundary->points[boundary->numpoints - 1].x / InternalScaleFactor,
203 boundary->points[boundary->numpoints - 1].y / InternalScaleFactor);
204 for(i = boundary->numpoints - 2; i >= 0; i--)
205 fprintf(psfile, "%d %d l\n",
206 boundary->points[i].x / InternalScaleFactor,
207 boundary->points[i].y / InternalScaleFactor);
208 fprintf(psfile, "closepath stroke\n");
209 }
210 fprintf(psfile, "%d %d m\n",
211 boundary->points[boundary->numpoints - 1].x / InternalScaleFactor,
212 boundary->points[boundary->numpoints - 1].y / InternalScaleFactor);
213 for(i = boundary->numpoints - 2; i >= 0; i--)
214 fprintf(psfile, "%d %d l\n",
215 boundary->points[i].x / InternalScaleFactor,
216 boundary->points[i].y / InternalScaleFactor);
217 fprintf(psfile, "closepath\n");
218
219 if(psStyle.fill)
220 fprintf(psfile, "fill\n");
221 if(psStyle.hatch)
222 fprintf(psfile, "/FONT%s findfont patternfill\n", psStyle.layername);
223
224 return;
225 }
226
227 void
BoundaryToPOV(FILE * povfile,boundaryEl * boundary,PSStyle psStyle)228 BoundaryToPOV(FILE *povfile, boundaryEl *boundary, PSStyle psStyle)
229 {
230 int i;
231 char *ts;
232 if(BoundaryIsRectangle(boundary)) /* Basically a box */
233 {
234 fprintf(povfile, " box { <%f,%f,%f> <%f,%f,%f>\n",
235 (double)(boundary->points[2].x),
236 psStyle.depth,
237 (double)(boundary->points[2].y),
238 (double)(boundary->points[0].x),
239 psStyle.depth-psStyle.thickness,
240 (double)(boundary->points[0].y));
241 fprintf(povfile," texture { %s }\n",
242 ts=GDSLayerToTEXName(boundary->layerptr));
243 fprintf(povfile, " }\n");
244 FREE(ts);
245 }
246 else
247 {
248
249 fprintf(povfile, " prism {\n linear_spline %f,%f,%d\n",psStyle.depth,
250 psStyle.depth-psStyle.thickness,boundary->numpoints);
251 for(i=0 ;i < (boundary->numpoints)-1 ; i++)
252 fprintf(povfile, " <%f,%f>,\n",
253 (double)(boundary->points[i].x),
254 (double)(boundary->points[i].y));
255 fprintf(povfile, " <%f,%f>\n",
256 (double)(boundary->points[(boundary->numpoints)-1].x),
257 (double)(boundary->points[(boundary->numpoints)-1].y));
258 fprintf(povfile," texture { %s }\n",
259 ts=GDSLayerToTEXName(boundary->layerptr));
260 fprintf(povfile,"}\n");
261 FREE(ts);
262 }
263 return;
264 }
265
266
267 /*
268 * Frees the cell contents and removes the layer list reference.
269 * The structure list reference has to be removed at the upper level.
270 */
271 void
GDSfreeBoundary(GDScell * cell)272 GDSfreeBoundary(GDScell *cell)
273 {
274 GDScell *cellptr;
275
276 if(cell == NULL)
277 return;
278 if(cell->type != BOUNDARY)
279 return;
280
281 if(cell == cell->detail.boundary->layerptr->cells)
282 cell->detail.boundary->layerptr->cells = cell->next;
283 else
284 {
285 for(cellptr = cell->detail.boundary->layerptr->cells;
286 cellptr->next != NULL; cellptr = cellptr->next)
287 {
288 if(cellptr->next == cell)
289 {
290 cellptr->next = cellptr->next->next;
291 break;
292 }
293 }
294 if(cellptr == NULL)
295 fprintf(stderr, "Oops! GDSfreeBoundary(): Missing cell in layerptr\n");
296 }
297 FREE(cell->detail.boundary->points);
298 FREE(cell->detail.boundary);
299 return;
300 }
301
302 GDScell *
GDSdupBoundary(boundaryEl * boundary)303 GDSdupBoundary(boundaryEl *boundary)
304 {
305 int i;
306 GDScell *newcell;
307 boundaryEl *boundaryptr;
308
309 if(boundary == NULL)
310 return NULL;
311
312 boundaryptr = (boundaryEl *)MALLOC(sizeof(boundaryEl));
313 newcell = (GDScell *)MALLOC(sizeof(GDScell));
314 newcell->type = BOUNDARY;
315 newcell->detail.boundary = boundaryptr;
316
317 newcell->next = boundary->layerptr->cells;
318 boundary->layerptr->cells = newcell;
319
320 boundaryptr->layerptr = boundary->layerptr;
321 boundaryptr->numpoints = boundary->numpoints;
322 boundaryptr->points = (point *)MALLOC(boundaryptr->numpoints * sizeof(point));
323 for(i = 0; i < boundaryptr->numpoints; i ++)
324 {
325 (boundaryptr->points[i]).x = (boundary->points[i]).x;
326 (boundaryptr->points[i]).y = (boundary->points[i]).y;
327 }
328
329 return newcell;
330 }
331
332 /*
333 * Apply the transform transf to all points in boundary.
334 */
335 void
GDStransfBoundary(boundaryEl * boundary,transform * transf)336 GDStransfBoundary(boundaryEl *boundary, transform *transf)
337 {
338 int i;
339
340 for(i = 0; i < boundary->numpoints; i++)
341 boundary->points[i] = GDStransfPoint(&(boundary->points[i]), transf);
342
343 return;
344 }
345
346 GDScell *
GDSreadBoundary(int gdsfildes,GDSstruct * structptr)347 GDSreadBoundary(int gdsfildes, GDSstruct *structptr)
348 {
349 unsigned char *record;
350 int i, nbytes, layerno, datatype;
351 layer *layerptr;
352 GDScell *newcell;
353 boundaryEl *boundaryptr;
354
355 boundaryptr = (boundaryEl *)MALLOC(sizeof(boundaryEl));
356 newcell = (GDScell *)MALLOC(sizeof(GDScell));
357 newcell->type = BOUNDARY;
358 newcell->detail.boundary = boundaryptr;
359
360 if(GDSreadRecord(gdsfildes, &record, &nbytes) != LAYER)
361 {
362 fprintf(stderr, "Missing LAYER field in BOUNDARY element. Abort!\n");
363 exit(1);
364 }
365 layerno = GDSreadInt2(record + 2);
366 FREE(record);
367
368 if(GDSreadRecord(gdsfildes, &record, &nbytes) != DATATYPE)
369 {
370 fprintf(stderr, "Missing DATATYPE field in BOUNDARY element. Abort!\n");
371 exit(1);
372 }
373 datatype = GDSreadInt2(record + 2);
374 FREE(record);
375
376 for(layerptr = structptr->layers;
377 layerptr != NULL; layerptr = layerptr->next)
378 if(layerptr->layerno == layerno && layerptr->datatype==datatype)
379 break;
380 if(layerptr == NULL)
381 {
382 layerptr = (layer *)MALLOC(sizeof(layer));
383 layerptr->layerno = layerno;
384 layerptr->datatype = datatype;
385 layerptr->name = NULL; /* to be added later */
386 layerptr->cells = newcell;
387 layerptr->next = structptr->layers;
388 structptr->layers = layerptr;
389 }
390 else
391 {
392 newcell->next = layerptr->cells;
393 layerptr->cells = newcell;
394 }
395 boundaryptr->layerptr = layerptr;
396
397
398 if(GDSreadRecord(gdsfildes, &record, &nbytes) != XY)
399 {
400 fprintf(stderr, "Missing XY field in BOUNDARY element. Abort!\n");
401 exit(1);
402 }
403 boundaryptr->numpoints = (nbytes - 2) / 8;
404 boundaryptr->points = (point *)MALLOC(boundaryptr->numpoints * sizeof(point));
405
406 for(i = 0; i < boundaryptr->numpoints; i ++)
407 {
408 (boundaryptr->points[i]).x = GDSreadInt4(record + 8 * i + 2);
409 (boundaryptr->points[i]).y = GDSreadInt4(record + 8 * i + 6);
410 }
411 FREE(record);
412
413 if(GDSreadRecord(gdsfildes, &record, &nbytes) != ENDEL)
414 {
415 fprintf(stderr, "Missing ENDEL field in BOUNDARY element. Abort!\n");
416 exit(1);
417 }
418 FREE(record);
419
420 fprintf(stdout, "Boundary on layer %d, datatype %d:\n", layerno,
421 layerptr->datatype);
422 for(i = 0; i < boundaryptr->numpoints; i++)
423 fprintf(stdout, "point[%d] = %d %d\n",
424 i, (boundaryptr->points[i]).x, (boundaryptr->points[i]).y);
425 return newcell;
426 }
427
428