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 
23 #include <GDSstructs.h>
24 #include <GDSconsts.h>
25 #include <GDStransf.h>
26 #include <GDSsref.h>
27 #include <GDSaux.h>
28 
29 bbox
GDSgetArefBBox(arefEl * aref,transform * transf)30 GDSgetArefBBox(arefEl *aref, transform *transf)
31 {
32   bbox bbx, bbx1;
33   srefEl sref;
34   transform *newtransf;
35   point refpoint;
36   int i, j;
37 
38   bbx.ll.x = BIGVAL;
39   bbx.ll.y = BIGVAL;
40   bbx.ur.x = -BIGVAL;
41   bbx.ur.y = -BIGVAL;
42 
43   for(i = 0; i < aref->cols; i++)
44     for(j = 0; j < aref->rows; j++)
45     {
46       sref.strptr = aref->strptr;
47       sref.refname = aref->refname;
48 
49       refpoint.x = i * aref->colspacing;
50       refpoint.y = j * aref->rowspacing;
51       sref.transfptr = GDStranslateTransf(&Ident, refpoint);
52       newtransf = GDStransfTransf(aref->transfptr, transf);
53       bbx1 = GDSgetSrefBBox(&sref, newtransf);
54 
55       GDSfreeTransf(sref.transfptr);
56       GDSfreeTransf(newtransf);
57 
58       if(bbx.ll.x > bbx1.ll.x)
59         bbx.ll.x = bbx1.ll.x;
60       if(bbx.ll.y > bbx1.ll.y)
61         bbx.ll.y = bbx1.ll.y;
62       if(bbx.ur.x < bbx1.ur.x)
63         bbx.ur.x = bbx1.ur.x;
64       if(bbx.ur.y < bbx1.ur.y)
65         bbx.ur.y = bbx1.ur.y;
66     }
67   return bbx;
68 }
69 
70 void
ArefToPS(FILE * psfile,arefEl * aref,transform * transf,PSStyle psStyle)71 ArefToPS(FILE *psfile, arefEl *aref, transform *transf, PSStyle psStyle)
72 {
73   srefEl sref;
74   transform *newtransf;
75   point refpoint;
76   int i, j;
77 
78   for(i = 0; i < aref->cols; i++)
79     for(j = 0; j < aref->rows; j++)
80     {
81       sref.strptr = aref->strptr;
82       sref.refname = aref->refname;
83 
84       refpoint.x = i * aref->colspacing;
85       refpoint.y = j * aref->rowspacing;
86       sref.transfptr = GDStranslateTransf(&Ident, refpoint);
87       newtransf = GDStransfTransf(aref->transfptr, transf);
88       SrefToPS(psfile, &sref, newtransf, psStyle);
89       GDSfreeTransf(sref.transfptr);
90       GDSfreeTransf(newtransf);
91     }
92 }
93 
94 void
ArefToPOV(FILE * povfile,arefEl * aref,transform * transf,PSStyle psStyle)95 ArefToPOV(FILE *povfile, arefEl *aref, transform *transf, PSStyle psStyle)
96 {
97   srefEl sref;
98   transform *newtransf;
99   point refpoint;
100   int i, j;
101   fprintf(stderr,"Rendering Aref->POV\n"
102     "  Rows: %d\n  Cols: %d\n  RowSpace: %d\n  ColSpace: %d\n",
103     aref->rows,aref->cols,aref->rowspacing,aref->colspacing
104    );
105   for(i = 0; i < aref->cols; i++)
106     for(j = 0; j < aref->rows; j++)
107     {
108       sref.strptr = aref->strptr;
109       sref.refname = aref->refname;
110 
111       refpoint.x = i * aref->colspacing;
112       refpoint.y = j * aref->rowspacing;
113       sref.transfptr = GDStranslateTransf(&Ident, refpoint);
114       newtransf = GDStransfTransf(aref->transfptr, transf);
115       /* Here we have a sref being instanced with additional
116                translations. */
117       SrefToPOV(povfile, &sref, newtransf, psStyle);
118       GDSfreeTransf(sref.transfptr);
119       GDSfreeTransf(newtransf);
120     }
121 }
122 
123 void
ArefToHPGL(FILE * hpglfile,arefEl * aref,transform * transf,PSStyle psStyle)124 ArefToHPGL(FILE *hpglfile, arefEl *aref, transform *transf, PSStyle psStyle)
125 {
126   srefEl sref;
127   transform *transfptr, *tp1;
128   point refpoint;
129   int i, j;
130 
131   for(i = 0; i < aref->cols; i++)
132     for(j = 0; j < aref->rows; j++)
133     {
134       sref.strptr = aref->strptr;
135       sref.refname = aref->refname;
136 
137       refpoint.x = i * aref->colspacing;
138       refpoint.y = j * aref->rowspacing;
139       tp1 = GDStranslateTransf(&Ident, refpoint);
140       transfptr = GDStransfTransf(tp1, aref->transfptr);
141       sref.transfptr = GDStransfTransf(transfptr, transf);
142       SrefToHPGL(hpglfile, &sref, sref.transfptr, psStyle);
143       GDSfreeTransf(sref.transfptr);
144       GDSfreeTransf(transfptr);
145       GDSfreeTransf(tp1);
146     }
147 }
148 
149 GDScell *
GDSreadAref(int gdsfildes,GDSstruct * structptr)150 GDSreadAref(int gdsfildes, GDSstruct *structptr)
151 {
152   unsigned char *record, chunk;
153   int rectype, nbytes;
154   point ref, col, row;
155   double angle, mag;
156   int mirror = 0;
157   GDScell *newcell;
158   arefEl *arefptr;
159 
160   arefptr = (arefEl *)MALLOC(sizeof(arefEl));
161   arefptr->strptr = NULL; /* to be inserted after all structs have been read */
162   newcell = (GDScell *)MALLOC(sizeof(GDScell));
163   newcell->type = AREF;
164   newcell->detail.aref = arefptr;
165   if(GDSreadRecord(gdsfildes, &record, &nbytes) != SNAME)
166   {
167     fprintf(stderr, "Missing SNAME field in AREF element. Abort!\n");
168     /* exit(1); */
169   }
170   if((arefptr->refname = GDSreadString(record + 2, nbytes - 4)) == NULL)
171   {
172     fprintf(stderr, "Bad STRING field in AREF element. Abort!\n");
173     exit(1);
174   }
175   FREE(record);
176 
177   rectype = GDSreadRecord(gdsfildes, &record, &nbytes);
178   if(rectype == STRANS)
179   {
180     chunk = record[2];
181     if(chunk & 0x80)
182       mirror = 1;
183 
184     FREE(record);
185     switch(GDSreadRecord(gdsfildes, &record, &nbytes))
186     {
187       case MAG:
188         mag = GDSreadReal8(record + 2);
189         if(!(chunk & 0x02))
190           mag *= CURRENTMAG;
191         FREE(record);
192         switch(GDSreadRecord(gdsfildes, &record, &nbytes))
193         {
194           case ANGLE:
195             angle = GDSreadReal8(record + 2);
196             if(!(chunk & 0x01))
197               angle += CURRENTANGLE;
198             FREE(record);
199             if(GDSreadRecord(gdsfildes, &record, &nbytes) != COLROW)
200             {
201               fprintf(stderr, "Missing COLROW field in AREF element. Abort!\n");
202               exit(1);
203             }
204             arefptr->cols = GDSreadInt2(record + 2);
205             arefptr->rows = GDSreadInt2(record + 4);
206             FREE(record);
207             break;
208           case COLROW:
209             angle = CURRENTANGLE;
210             arefptr->cols = GDSreadInt2(record + 2);
211             arefptr->rows = GDSreadInt2(record + 4);
212             FREE(record);
213             break;
214           default:
215             fprintf(stderr, "Missing COLROW field in AREF element. Abort!\n");
216             exit(1);
217         }
218         break;
219       case ANGLE:
220         mag = CURRENTMAG;
221         angle = GDSreadReal8(record + 2);
222         if(!(chunk & 0x01))
223           angle += CURRENTANGLE;
224         FREE(record);
225         if(GDSreadRecord(gdsfildes, &record, &nbytes) != COLROW)
226         {
227           fprintf(stderr, "Missing COLROW field in AREF element. Abort!\n");
228           exit(1);
229         }
230         arefptr->cols = GDSreadInt2(record + 2);
231         arefptr->rows = GDSreadInt2(record + 4);
232         FREE(record);
233         break;
234       case COLROW:
235         mag = CURRENTMAG;
236         angle = CURRENTANGLE;
237         arefptr->cols = GDSreadInt2(record + 2);
238         arefptr->rows = GDSreadInt2(record + 4);
239         FREE(record);
240         break;
241       default:
242         fprintf(stderr,
243                 "Missing MAG, ANGLE or COLROW field in AREF element. Abort!\n");
244         exit(1);
245     }
246   }
247   else if(rectype == COLROW)
248   {
249     mag = CURRENTMAG;
250     angle = CURRENTANGLE;
251     arefptr->cols = GDSreadInt2(record + 2);
252     arefptr->rows = GDSreadInt2(record + 4);
253     FREE(record);
254   }
255   else
256   {
257     fprintf(stderr, "Missing STRANS or COLROW field in AREF element. Abort!\n");
258     exit(1);
259   }
260 
261   if(GDSreadRecord(gdsfildes, &record, &nbytes) != XY)
262   {
263     fprintf(stderr, "Missing XY field in AREF element. Abort!\n");
264     exit(1);
265   }
266   if(arefptr->rows == 0 || arefptr->cols == 0)
267   {
268     fprintf(stderr, "AREF element with 0 rows/cols.  Abort!\n");
269     exit(1);
270   }
271 
272   ref.x = GDSreadInt4(record + 2);
273   ref.y = GDSreadInt4(record + 6);
274   col.x = GDSreadInt4(record + 10);
275   col.y = GDSreadInt4(record + 14);
276   row.x = GDSreadInt4(record + 18);
277   row.y = GDSreadInt4(record + 22);
278   FREE(record);
279 
280   arefptr->transfptr = GDSgetTransf(ref, angle, mag, mirror);
281 
282 /* Since GDSinvtransfPoint performs also the translation, the unused dimension
283    must be equal to 0 (i.e. the original one was identical to the reference
284    point one) and the useful one is exactly the spacing multiplied by the number
285    of cells in that direction */
286 
287   col = GDSinvtransfPoint(&col, arefptr->transfptr);
288 
289   if(col.x < 0)
290   {
291     fprintf(stdout, "Error in AREF! Found a y-axis mirrored array. This is impossible so I'm exiting.\n");
292     exit(1);
293   }
294   if(col.y != 0)
295   {
296     fprintf(stdout, "Error in AREF! The second point in XY is broken.\n");
297     exit(1);
298   }
299 
300   row = GDSinvtransfPoint(&row, arefptr->transfptr);
301 
302   if(row.x != 0)
303   {
304     fprintf(stdout, "Error in AREF! The third point in XY is broken.\n");
305     exit(1);
306   }
307 
308   arefptr->colspacing =
309     col.x / arefptr->cols;
310   arefptr->rowspacing =
311     row.y / arefptr->rows;
312 
313   if(row.y < 0)
314     arefptr->rowspacing *=-1.0;
315 /*    arefptr->transfptr->c -= arefptr->rowspacing; */
316   if(GDSreadRecord(gdsfildes, &record, &nbytes) != ENDEL)
317   {
318     fprintf(stderr, "Missing ENDEL field in AREF element. Abort!\n");
319     exit(1);
320   }
321   FREE(record);
322 
323   fprintf(stdout, "Aref at %d,%d/ of cell named \"%s\", c/r  = %d/%d, spacing = %d/%d, mirror = %d\n",
324           ref.x, ref.y, arefptr->refname, arefptr->cols, arefptr->rows,
325           arefptr->colspacing, arefptr->rowspacing, mirror);
326   return newcell;
327 }
328