1 /* CIFsee.c -
2 *
3 * This file provides procedures for displaying CIF layers on
4 * the screen using the highlight facilities.
5 *
6 * *********************************************************************
7 * * Copyright (C) 1985, 1990 Regents of the University of California. *
8 * * Permission to use, copy, modify, and distribute this *
9 * * software and its documentation for any purpose and without *
10 * * fee is hereby granted, provided that the above copyright *
11 * * notice appear in all copies. The University of California *
12 * * makes no representations about the suitability of this *
13 * * software for any purpose. It is provided "as is" without *
14 * * express or implied warranty. Export of this software outside *
15 * * of the United States of America may require an export license. *
16 * *********************************************************************
17 */
18
19 #ifndef lint
20 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFsee.c,v 1.5 2010/06/24 12:37:15 tim Exp $";
21 #endif /* not lint */
22
23 #include <stdio.h>
24 #include "tcltk/tclmagic.h"
25 #include "utils/magic.h"
26 #include "utils/geometry.h"
27 #include "tiles/tile.h"
28 #include "utils/hash.h"
29 #include "database/database.h"
30 #include "windows/windows.h"
31 #include "graphics/graphics.h"
32 #include "dbwind/dbwind.h"
33 #include "utils/styles.h"
34 #include "cif/CIFint.h"
35 #include "textio/textio.h"
36 #include "utils/undo.h"
37
38 /* The following variable holds the CellDef into which feedback
39 * is to be placed for displaying CIF.
40 */
41
42 static CellDef *cifSeeDef;
43
44 /* Verbosity of warning messages */
45 global int CIFWarningLevel = CIF_WARN_DEFAULT;
46
47 typedef struct {
48 CellDef *paintDef;
49 int layer;
50 } PaintLayerData;
51
52 typedef struct {
53 char *text;
54 int layer;
55 int style;
56 } SeeLayerData;
57
58 /*
59 * ----------------------------------------------------------------------------
60 *
61 * cifPaintDBFunc --
62 *
63 * This routine paints CIF back into the database at the inverse
64 * scale at which it was generated. Otherwise, it is very much like
65 * cifPaintCurrentFunc() in CIFrdcl.c.
66 *
67 * Results:
68 * Always returns 0 to keep the search alive.
69 *
70 * Side effects:
71 * Paint is generated in the cell.
72 * ----------------------------------------------------------------------------
73 */
74
75 int
cifPaintDBFunc(tile,pld)76 cifPaintDBFunc(tile, pld)
77 Tile *tile; /* Tile of CIF information. */
78 PaintLayerData *pld;
79 {
80 Rect area;
81 int pNum;
82 TileType type = pld->layer; /* Magic type to be painted. */
83 CellDef *paintDef = pld->paintDef; /* Cell to draw into. */
84 int cifScale = CIFCurStyle->cs_scaleFactor;
85 PaintUndoInfo ui;
86
87 /* Compute the area of the CIF tile, then scale it into
88 * Magic coordinates.
89 */
90
91 TiToRect(tile, &area);
92 area.r_xtop /= cifScale;
93 area.r_xbot /= cifScale;
94 area.r_ytop /= cifScale;
95 area.r_ybot /= cifScale;
96
97 /* Check for degenerate areas (from rescale limiting) before painting */
98 if ((area.r_xbot == area.r_xtop) || (area.r_ybot == area.r_ytop))
99 return 0;
100
101 ui.pu_def = paintDef;
102 for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
103 if (DBPaintOnPlane(type, pNum))
104 {
105 ui.pu_pNum = pNum;
106 DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
107 &area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
108 }
109
110 return 0; /* To keep the search alive. */
111 }
112
113 /*
114 * ----------------------------------------------------------------------------
115 *
116 * CIFPaintLayer --
117 *
118 * Generates CIF over a given area of a given cell, then
119 * paints the CIF layer back into the cell (or optionally,
120 * into a separate cell) as a magic layer.
121 *
122 * Results:
123 * None.
124 *
125 * Side effects:
126 * Highlight information is drawn on the screen.
127 *
128 * ----------------------------------------------------------------------------
129 */
130
131 void
CIFPaintLayer(rootDef,area,cifLayer,magicLayer,paintDef)132 CIFPaintLayer(rootDef, area, cifLayer, magicLayer, paintDef)
133 CellDef *rootDef; /* Cell for which to generate CIF. Must be
134 * the rootDef of a window.
135 */
136 Rect *area; /* Area in which to generate CIF. */
137 char *cifLayer; /* CIF layer to highlight on the screen. */
138 int magicLayer; /* Magic layer to paint with the result */
139 CellDef *paintDef; /* CellDef to paint into (may be NULL) */
140 {
141 int oldCount, i;
142 char msg[100];
143 SearchContext scx;
144 PaintLayerData pld;
145 TileTypeBitMask mask, depend;
146
147 /* Make sure the desired layer exists. */
148
149 if (!CIFNameToMask(cifLayer, &mask, &depend)) return;
150
151 /* Paint directly into the root cellDef if passed a NULL paintDef*/
152 pld.paintDef = (paintDef == NULL) ? rootDef : paintDef;
153 pld.layer = magicLayer;
154
155 /* Flatten the area and generate CIF for it. */
156
157 CIFErrorDef = rootDef;
158 CIFInitCells();
159 UndoDisable();
160 CIFDummyUse->cu_def = rootDef;
161 GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area);
162 scx.scx_use = CIFDummyUse;
163 scx.scx_trans = GeoIdentityTransform;
164 (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
165 cifHierCopyFunc, (ClientData) CIFComponentDef);
166 CIFCopyMaskHints(rootDef, CIFComponentDef);
167 DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
168 (ClientData)CIFComponentDef);
169
170 oldCount = DBWFeedbackCount;
171
172 CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, FALSE,
173 (ClientData)NULL);
174 DBCellClearDef(CIFComponentDef);
175
176 /* Report any errors that occurred. */
177
178 if (DBWFeedbackCount != oldCount)
179 {
180 TxPrintf("%d problems occurred. See feedback entries.\n",
181 DBWFeedbackCount-oldCount);
182 }
183
184 /* Paint back the chosen layer. */
185
186 UndoEnable();
187 for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
188 if (TTMaskHasType(&mask, i))
189 DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
190 &CIFSolidBits, cifPaintDBFunc, (ClientData)&pld);
191
192 DBWAreaChanged(rootDef, area, DBW_ALLWINDOWS, &mask);
193 DBReComputeBbox(rootDef);
194 DRCCheckThis(rootDef, TT_CHECKPAINT, area);
195 }
196
197 /*
198 * ----------------------------------------------------------------------------
199 *
200 * cifSeeFunc --
201 *
202 * Called once for each tile that is to be displayed as feedback.
203 * This procedure enters the tile as feedback. Note: the caller
204 * must arrange for cifSeeDef to contain a pointer to the cell
205 * def where feedback is to be displayed.
206 *
207 * Results:
208 * Always returns 0 to keep the search alive.
209 *
210 * Side effects:
211 * A new feedback area is created over the tile. The parameter
212 * "text" is associated with the feedback.
213 * ----------------------------------------------------------------------------
214 */
215
216 int
cifSeeFunc(tile,sld)217 cifSeeFunc(tile, sld)
218 Tile *tile; /* Tile to be entered as feedback. */
219 SeeLayerData *sld; /* Layer and explanation for the feedback. */
220 {
221 Rect area;
222
223 TiToRect(tile, &area);
224
225 if (((area.r_xbot & 0x1) || (area.r_ybot & 0x1))
226 && (CIFWarningLevel == CIF_WARN_ALIGN))
227 {
228 TxError("Warning: Corner (%.1f, %.1f) has half-lambda placement.\n",
229 (float)area.r_xbot / (float)CIFCurStyle->cs_scaleFactor,
230 (float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
231 }
232
233 DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
234 sld->style |
235 (TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
236 /* (preserve information about the geometry of a diagonal tile) */
237 return 0;
238 }
239
240 /*
241 * ----------------------------------------------------------------------------
242 *
243 * CIFSeeLayer --
244 *
245 * Generates CIF over a given area of a given cell, then
246 * highlights a particular CIF layer on the screen.
247 *
248 * Results:
249 * None.
250 *
251 * Side effects:
252 * Highlight information is drawn on the screen.
253 *
254 * ----------------------------------------------------------------------------
255 */
256
257 void
CIFSeeLayer(rootDef,area,layer)258 CIFSeeLayer(rootDef, area, layer)
259 CellDef *rootDef; /* Cell for which to generate CIF. Must be
260 * the rootDef of a window.
261 */
262 Rect *area; /* Area in which to generate CIF. */
263 char *layer; /* CIF layer to highlight on the screen. */
264 {
265 int oldCount, i;
266 char msg[100];
267 SearchContext scx;
268 SeeLayerData sld;
269 TileTypeBitMask mask, depend;
270
271 /* Make sure the desired layer exists. */
272
273 if (!CIFNameToMask(layer, &mask, &depend)) return;
274
275 /* Flatten the area and generate CIF for it. */
276
277 CIFErrorDef = rootDef;
278 CIFInitCells();
279 UndoDisable();
280 CIFDummyUse->cu_def = rootDef;
281 GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area);
282 scx.scx_use = CIFDummyUse;
283 scx.scx_trans = GeoIdentityTransform;
284 (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
285 cifHierCopyFunc, (ClientData) CIFComponentDef);
286 CIFCopyMaskHints(rootDef, CIFComponentDef);
287 DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
288 (ClientData)CIFComponentDef);
289
290 oldCount = DBWFeedbackCount;
291 CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
292 FALSE, (ClientData)NULL);
293 DBCellClearDef(CIFComponentDef);
294
295 /* Report any errors that occurred. */
296
297 if (DBWFeedbackCount != oldCount)
298 {
299 TxPrintf("%d problems occurred. See feedback entries.\n",
300 DBWFeedbackCount-oldCount);
301 }
302
303 /* Display the chosen layer. */
304
305 (void) sprintf(msg, "CIF layer \"%s\"", layer);
306 cifSeeDef = rootDef;
307 sld.text = msg;
308
309 for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
310 {
311 if (TTMaskHasType(&mask, i))
312 {
313 sld.layer = i;
314 #ifdef THREE_D
315 sld.style = CIFCurStyle->cs_layers[i]->cl_renderStyle
316 + TECHBEGINSTYLES;
317 #else
318 sld.style = STYLE_PALEHIGHLIGHTS;
319 #endif
320 DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
321 &CIFSolidBits, cifSeeFunc, (ClientData)&sld);
322 }
323 }
324 UndoEnable();
325 }
326
327 /*
328 * ----------------------------------------------------------------------------
329 *
330 * CIFSeeHierLayer --
331 *
332 * This procedure is similar to CIFSeeLayer except that it only
333 * generates hierarchical interaction information.
334 *
335 * Results:
336 * None.
337 *
338 * Side effects:
339 * CIF information is highlighed on the screen. If arrays is
340 * TRUE, then CIF that stems from array interactions is displayed.
341 * if subcells is TRUE, then CIF stemming from subcell interactions
342 * is displayed. If both are TRUE, then both are displayed.
343 *
344 * ----------------------------------------------------------------------------
345 */
346
347 void
CIFSeeHierLayer(rootDef,area,layer,arrays,subcells)348 CIFSeeHierLayer(rootDef, area, layer, arrays, subcells)
349 CellDef *rootDef; /* Def in which to compute CIF. Must be
350 * the root definition of a window.
351 */
352 Rect *area; /* Area in which to generate CIF. */
353 char *layer; /* CIF layer to be highlighted. */
354 bool arrays; /* TRUE means show array interactions. */
355 bool subcells; /* TRUE means show subcell interactions. */
356 {
357 int i, oldCount;
358 SeeLayerData sld;
359 char msg[100];
360 TileTypeBitMask mask;
361
362 /* Check out the CIF layer name. */
363
364 if (!CIFNameToMask(layer, &mask, NULL)) return;
365
366 CIFErrorDef = rootDef;
367 oldCount = DBWFeedbackCount;
368 CIFClearPlanes(CIFPlanes);
369 if (subcells)
370 CIFGenSubcells(rootDef, area, CIFPlanes);
371 if (arrays)
372 CIFGenArrays(rootDef, area, CIFPlanes);
373
374 /* Report any errors that occurred. */
375
376 if (DBWFeedbackCount != oldCount)
377 {
378 TxPrintf("%d problems occurred. See feedback entries.\n",
379 DBWFeedbackCount - oldCount);
380 }
381
382 (void) sprintf(msg, "CIF layer \"%s\"", layer);
383 cifSeeDef = rootDef;
384 sld.text = msg;
385
386 for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
387 {
388 if (TTMaskHasType(&mask, i))
389 {
390 sld.layer = i;
391 #ifdef THREE_D
392 sld.style = CIFCurStyle->cs_layers[i]->cl_renderStyle
393 + TECHBEGINSTYLES;
394 #else
395 sld.style = STYLE_PALEHIGHLIGHTS;
396 #endif
397 DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
398 &CIFSolidBits, cifSeeFunc, (ClientData)&sld);
399 }
400 }
401 }
402
403 /*
404 * ----------------------------------------------------------------------------
405 *
406 * CIFCoverageLayer --
407 *
408 * This procedure reports the total area coverage of a CIF layer
409 * within the bounding box of the root CellDef.
410 *
411 * Results:
412 * None.
413 *
414 * Side effects:
415 * Prints results.
416 *
417 * ----------------------------------------------------------------------------
418 */
419
420 typedef struct {
421 long long coverage;
422 Rect bounds;
423 } coverstats;
424
425 void
CIFCoverageLayer(rootDef,area,layer,dolist)426 CIFCoverageLayer(rootDef, area, layer, dolist)
427 CellDef *rootDef; /* Def in which to compute CIF coverage */
428 Rect *area; /* Area in which to compute coverage */
429 char *layer; /* CIF layer for coverage computation. */
430 bool dolist; /* If TRUE, report only the value, in decimal */
431 {
432 coverstats cstats;
433 int i, scale;
434 long long atotal, btotal;
435 SearchContext scx;
436 TileTypeBitMask mask, depend;
437 float fcover;
438 int cifCoverageFunc();
439 bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
440
441 /* Check out the CIF layer name. */
442
443 if (!CIFNameToMask(layer, &mask, &depend)) return;
444
445 CIFErrorDef = rootDef;
446 CIFInitCells();
447 UndoDisable();
448 CIFDummyUse->cu_def = rootDef;
449
450 GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area);
451
452 scx.scx_use = CIFDummyUse;
453 scx.scx_trans = GeoIdentityTransform;
454 (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
455 cifHierCopyFunc, (ClientData) CIFComponentDef);
456 CIFCopyMaskHints(rootDef, CIFComponentDef);
457 DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
458 (ClientData)CIFComponentDef);
459
460 CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
461 FALSE, (ClientData)NULL);
462 DBCellClearDef(CIFComponentDef);
463
464 cstats.coverage = 0;
465 cstats.bounds.r_xbot = cstats.bounds.r_xtop = 0;
466 cstats.bounds.r_ybot = cstats.bounds.r_ytop = 0;
467
468 for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
469 if (TTMaskHasType(&mask, i))
470 DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
471 &CIFSolidBits, cifCoverageFunc,
472 (ClientData) &cstats);
473
474 /* Print results */
475
476 scale = CIFCurStyle->cs_scaleFactor;
477
478 btotal = (long long)(area->r_xtop - area->r_xbot);
479 btotal *= (long long)(area->r_ytop - area->r_ybot);
480 btotal *= (long long)(scale * scale);
481 fcover = 0.0;
482 if (btotal > 0.0) fcover = (float)cstats.coverage / (float)btotal;
483
484 atotal = (long long)(cstats.bounds.r_xtop - cstats.bounds.r_xbot);
485 atotal *= (long long)(cstats.bounds.r_ytop - cstats.bounds.r_ybot);
486
487 if (dolist)
488 {
489 #ifdef MAGIC_WRAPPER
490 Tcl_Obj *pobj;
491
492 pobj = Tcl_NewDoubleObj((double)fcover);
493 Tcl_SetObjResult(magicinterp, pobj);
494 #else
495 TxPrintf("%g\n", fcover);
496 #endif
497 }
498 else
499 {
500 TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
501 "Cell", btotal);
502 TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
503 TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
504 TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
505 "cell", 100.0 * fcover);
506 }
507 }
508
509 int
cifCoverageFunc(tile,arg)510 cifCoverageFunc(tile, arg)
511 Tile *tile;
512 ClientData *arg;
513 {
514 coverstats *cstats = (coverstats *)arg;
515 Rect r;
516
517 TiToRect(tile, &r);
518 cstats->coverage += (long long)(r.r_xtop - r.r_xbot) * (long long)(r.r_ytop - r.r_ybot);
519 GeoInclude(&r, &cstats->bounds);
520
521 return(0);
522 }
523