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