526 lines
15 KiB
C
526 lines
15 KiB
C
/* CIFsee.c -
|
|
*
|
|
* This file provides procedures for displaying CIF layers on
|
|
* the screen using the highlight facilities.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
* * software and its documentation for any purpose and without *
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
* * notice appear in all copies. The University of California *
|
|
* * makes no representations about the suitability of this *
|
|
* * software for any purpose. It is provided "as is" without *
|
|
* * express or implied warranty. Export of this software outside *
|
|
* * of the United States of America may require an export license. *
|
|
* *********************************************************************
|
|
*/
|
|
|
|
#ifndef lint
|
|
static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFsee.c,v 1.5 2010/06/24 12:37:15 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include "tcltk/tclmagic.h"
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "windows/windows.h"
|
|
#include "graphics/graphics.h"
|
|
#include "dbwind/dbwind.h"
|
|
#include "utils/styles.h"
|
|
#include "cif/CIFint.h"
|
|
#include "textio/textio.h"
|
|
#include "utils/undo.h"
|
|
|
|
/* C99 compat */
|
|
#include "drc/drc.h"
|
|
|
|
/* The following variable holds the CellDef into which feedback
|
|
* is to be placed for displaying CIF.
|
|
*/
|
|
|
|
static CellDef *cifSeeDef;
|
|
|
|
/* Verbosity of warning messages */
|
|
global int CIFWarningLevel = CIF_WARN_DEFAULT;
|
|
|
|
typedef struct {
|
|
CellDef *paintDef;
|
|
int layer;
|
|
} PaintLayerData;
|
|
|
|
typedef struct {
|
|
char *text;
|
|
int layer;
|
|
int style;
|
|
} SeeLayerData;
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* cifPaintDBFunc --
|
|
*
|
|
* This routine paints CIF back into the database at the inverse
|
|
* scale at which it was generated. Otherwise, it is very much like
|
|
* cifPaintCurrentFunc() in CIFrdcl.c.
|
|
*
|
|
* Results:
|
|
* Always returns 0 to keep the search alive.
|
|
*
|
|
* Side effects:
|
|
* Paint is generated in the cell.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
cifPaintDBFunc(
|
|
Tile *tile, /* Tile of CIF information. */
|
|
PaintLayerData *pld)
|
|
{
|
|
Rect area;
|
|
int pNum;
|
|
TileType type = pld->layer; /* Magic type to be painted. */
|
|
CellDef *paintDef = pld->paintDef; /* Cell to draw into. */
|
|
int cifScale = CIFCurStyle->cs_scaleFactor;
|
|
PaintUndoInfo ui;
|
|
|
|
/* Compute the area of the CIF tile, then scale it into
|
|
* Magic coordinates.
|
|
*/
|
|
|
|
TiToRect(tile, &area);
|
|
area.r_xtop /= cifScale;
|
|
area.r_xbot /= cifScale;
|
|
area.r_ytop /= cifScale;
|
|
area.r_ybot /= cifScale;
|
|
|
|
/* Check for degenerate areas (from rescale limiting) before painting */
|
|
if ((area.r_xbot == area.r_xtop) || (area.r_ybot == area.r_ytop))
|
|
return 0;
|
|
|
|
ui.pu_def = paintDef;
|
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
|
if (DBPaintOnPlane(type, pNum))
|
|
{
|
|
ui.pu_pNum = pNum;
|
|
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
|
|
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
|
|
}
|
|
|
|
return 0; /* To keep the search alive. */
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CIFPaintLayer --
|
|
*
|
|
* Generates CIF over a given area of a given cell, then
|
|
* paints the CIF layer back into the cell (or optionally,
|
|
* into a separate cell) as a magic layer.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Highlight information is drawn on the screen.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
CIFPaintLayer(
|
|
CellDef *rootDef, /* Cell for which to generate CIF. Must be
|
|
* the rootDef of a window.
|
|
*/
|
|
Rect *area, /* Area in which to generate CIF. */
|
|
char *cifLayer, /* CIF layer to highlight on the screen. */
|
|
int magicLayer, /* Magic layer to paint with the result */
|
|
CellDef *paintDef) /* CellDef to paint into (may be NULL) */
|
|
{
|
|
int oldCount, i;
|
|
char msg[100];
|
|
SearchContext scx;
|
|
PaintLayerData pld;
|
|
TileTypeBitMask mask, depend;
|
|
|
|
/* Make sure the desired layer exists. */
|
|
|
|
if (!CIFNameToMask(cifLayer, &mask, &depend)) return;
|
|
|
|
/* Paint directly into the root cellDef if passed a NULL paintDef*/
|
|
pld.paintDef = (paintDef == NULL) ? rootDef : paintDef;
|
|
pld.layer = magicLayer;
|
|
|
|
/* Flatten the area and generate CIF for it. */
|
|
|
|
CIFErrorDef = rootDef;
|
|
CIFInitCells();
|
|
UndoDisable();
|
|
CIFDummyUse->cu_def = rootDef;
|
|
GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area);
|
|
scx.scx_use = CIFDummyUse;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
|
(ClientData)CIFComponentDef);
|
|
|
|
oldCount = DBWFeedbackCount;
|
|
|
|
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, FALSE,
|
|
(ClientData)NULL);
|
|
DBCellClearDef(CIFComponentDef);
|
|
|
|
/* Report any errors that occurred. */
|
|
|
|
if (DBWFeedbackCount != oldCount)
|
|
{
|
|
TxPrintf("%d problems occurred. See feedback entries.\n",
|
|
DBWFeedbackCount-oldCount);
|
|
}
|
|
|
|
/* Paint back the chosen layer. */
|
|
|
|
UndoEnable();
|
|
for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
|
|
if (TTMaskHasType(&mask, i))
|
|
DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
|
|
&CIFSolidBits, cifPaintDBFunc, (ClientData)&pld);
|
|
|
|
DBWAreaChanged(rootDef, area, DBW_ALLWINDOWS, &mask);
|
|
DBReComputeBbox(rootDef);
|
|
DRCCheckThis(rootDef, TT_CHECKPAINT, area);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* cifSeeFunc --
|
|
*
|
|
* Called once for each tile that is to be displayed as feedback.
|
|
* This procedure enters the tile as feedback. Note: the caller
|
|
* must arrange for cifSeeDef to contain a pointer to the cell
|
|
* def where feedback is to be displayed.
|
|
*
|
|
* Results:
|
|
* Always returns 0 to keep the search alive.
|
|
*
|
|
* Side effects:
|
|
* A new feedback area is created over the tile. The parameter
|
|
* "text" is associated with the feedback.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
cifSeeFunc(
|
|
Tile *tile, /* Tile to be entered as feedback. */
|
|
SeeLayerData *sld) /* Layer and explanation for the feedback. */
|
|
{
|
|
Rect area;
|
|
|
|
TiToRect(tile, &area);
|
|
|
|
if (((area.r_xbot & 0x1) || (area.r_ybot & 0x1))
|
|
&& (CIFWarningLevel == CIF_WARN_ALIGN))
|
|
{
|
|
TxError("Warning: Corner (%.1f, %.1f) has half-lambda placement.\n",
|
|
(float)area.r_xbot / (float)CIFCurStyle->cs_scaleFactor,
|
|
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
|
|
}
|
|
|
|
DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
|
|
sld->style |
|
|
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
|
/* (preserve information about the geometry of a diagonal tile) */
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CIFSeeLayer --
|
|
*
|
|
* Generates CIF over a given area of a given cell, then
|
|
* highlights a particular CIF layer on the screen.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Highlight information is drawn on the screen.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
CIFSeeLayer(
|
|
CellDef *rootDef, /* Cell for which to generate CIF. Must be
|
|
* the rootDef of a window.
|
|
*/
|
|
Rect *area, /* Area in which to generate CIF. */
|
|
char *layer) /* CIF layer to highlight on the screen. */
|
|
{
|
|
int oldCount, i;
|
|
char msg[100];
|
|
SearchContext scx;
|
|
SeeLayerData sld;
|
|
TileTypeBitMask mask, depend;
|
|
|
|
/* Make sure the desired layer exists. */
|
|
|
|
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
|
|
|
/* Flatten the area and generate CIF for it. */
|
|
|
|
CIFErrorDef = rootDef;
|
|
CIFInitCells();
|
|
UndoDisable();
|
|
CIFDummyUse->cu_def = rootDef;
|
|
GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area);
|
|
scx.scx_use = CIFDummyUse;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
|
(ClientData)CIFComponentDef);
|
|
|
|
oldCount = DBWFeedbackCount;
|
|
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
|
FALSE, (ClientData)NULL);
|
|
DBCellClearDef(CIFComponentDef);
|
|
|
|
/* Report any errors that occurred. */
|
|
|
|
if (DBWFeedbackCount != oldCount)
|
|
{
|
|
TxPrintf("%d problems occurred. See feedback entries.\n",
|
|
DBWFeedbackCount-oldCount);
|
|
}
|
|
|
|
/* Display the chosen layer. */
|
|
|
|
(void) sprintf(msg, "CIF layer \"%s\"", layer);
|
|
cifSeeDef = rootDef;
|
|
sld.text = msg;
|
|
|
|
for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
|
|
{
|
|
if (TTMaskHasType(&mask, i))
|
|
{
|
|
sld.layer = i;
|
|
#ifdef THREE_D
|
|
sld.style = CIFCurStyle->cs_layers[i]->cl_renderStyle
|
|
+ TECHBEGINSTYLES;
|
|
#else
|
|
sld.style = STYLE_PALEHIGHLIGHTS;
|
|
#endif
|
|
DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
|
|
&CIFSolidBits, cifSeeFunc, (ClientData)&sld);
|
|
}
|
|
}
|
|
UndoEnable();
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CIFSeeHierLayer --
|
|
*
|
|
* This procedure is similar to CIFSeeLayer except that it only
|
|
* generates hierarchical interaction information.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* CIF information is highlighed on the screen. If arrays is
|
|
* TRUE, then CIF that stems from array interactions is displayed.
|
|
* if subcells is TRUE, then CIF stemming from subcell interactions
|
|
* is displayed. If both are TRUE, then both are displayed.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
CIFSeeHierLayer(
|
|
CellDef *rootDef, /* Def in which to compute CIF. Must be
|
|
* the root definition of a window.
|
|
*/
|
|
Rect *area, /* Area in which to generate CIF. */
|
|
char *layer, /* CIF layer to be highlighted. */
|
|
bool arrays, /* TRUE means show array interactions. */
|
|
bool subcells) /* TRUE means show subcell interactions. */
|
|
{
|
|
int i, oldCount;
|
|
SeeLayerData sld;
|
|
char msg[100];
|
|
TileTypeBitMask mask;
|
|
|
|
/* Check out the CIF layer name. */
|
|
|
|
if (!CIFNameToMask(layer, &mask, NULL)) return;
|
|
|
|
CIFErrorDef = rootDef;
|
|
oldCount = DBWFeedbackCount;
|
|
CIFClearPlanes(CIFPlanes);
|
|
if (subcells)
|
|
CIFGenSubcells(rootDef, area, CIFPlanes);
|
|
if (arrays)
|
|
CIFGenArrays(rootDef, area, CIFPlanes);
|
|
|
|
/* Report any errors that occurred. */
|
|
|
|
if (DBWFeedbackCount != oldCount)
|
|
{
|
|
TxPrintf("%d problems occurred. See feedback entries.\n",
|
|
DBWFeedbackCount - oldCount);
|
|
}
|
|
|
|
(void) sprintf(msg, "CIF layer \"%s\"", layer);
|
|
cifSeeDef = rootDef;
|
|
sld.text = msg;
|
|
|
|
for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
|
|
{
|
|
if (TTMaskHasType(&mask, i))
|
|
{
|
|
sld.layer = i;
|
|
#ifdef THREE_D
|
|
sld.style = CIFCurStyle->cs_layers[i]->cl_renderStyle
|
|
+ TECHBEGINSTYLES;
|
|
#else
|
|
sld.style = STYLE_PALEHIGHLIGHTS;
|
|
#endif
|
|
DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
|
|
&CIFSolidBits, cifSeeFunc, (ClientData)&sld);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* CIFCoverageLayer --
|
|
*
|
|
* This procedure reports the total area coverage of a CIF layer
|
|
* within the bounding box of the root CellDef.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Prints results.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
typedef struct {
|
|
long long coverage;
|
|
Rect bounds;
|
|
} coverstats;
|
|
|
|
void
|
|
CIFCoverageLayer(
|
|
CellDef *rootDef, /* Def in which to compute CIF coverage */
|
|
Rect *area, /* Area in which to compute coverage */
|
|
char *layer, /* CIF layer for coverage computation. */
|
|
bool dolist) /* If TRUE, report only the value, in decimal */
|
|
{
|
|
coverstats cstats;
|
|
int i, scale;
|
|
long long atotal, btotal;
|
|
SearchContext scx;
|
|
TileTypeBitMask mask, depend;
|
|
float fcover;
|
|
int cifCoverageFunc(Tile *tile, ClientData *arg);
|
|
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
|
|
|
|
/* Check out the CIF layer name. */
|
|
|
|
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
|
|
|
CIFErrorDef = rootDef;
|
|
CIFInitCells();
|
|
UndoDisable();
|
|
CIFDummyUse->cu_def = rootDef;
|
|
|
|
GEO_EXPAND(area, CIFCurStyle->cs_radius, &scx.scx_area);
|
|
|
|
scx.scx_use = CIFDummyUse;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
|
(ClientData)CIFComponentDef);
|
|
|
|
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
|
FALSE, (ClientData)NULL);
|
|
DBCellClearDef(CIFComponentDef);
|
|
|
|
cstats.coverage = 0;
|
|
cstats.bounds.r_xbot = cstats.bounds.r_xtop = 0;
|
|
cstats.bounds.r_ybot = cstats.bounds.r_ytop = 0;
|
|
|
|
for (i = 0; i < CIFCurStyle->cs_nLayers; i++)
|
|
if (TTMaskHasType(&mask, i))
|
|
DBSrPaintArea((Tile *)NULL, CIFPlanes[i], &TiPlaneRect,
|
|
&CIFSolidBits, cifCoverageFunc,
|
|
(ClientData) &cstats);
|
|
|
|
/* Print results */
|
|
|
|
scale = CIFCurStyle->cs_scaleFactor;
|
|
|
|
btotal = (long long)(area->r_xtop - area->r_xbot);
|
|
btotal *= (long long)(area->r_ytop - area->r_ybot);
|
|
btotal *= (long long)(scale * scale);
|
|
fcover = 0.0;
|
|
if (btotal > 0.0) fcover = (float)cstats.coverage / (float)btotal;
|
|
|
|
atotal = (long long)(cstats.bounds.r_xtop - cstats.bounds.r_xbot);
|
|
atotal *= (long long)(cstats.bounds.r_ytop - cstats.bounds.r_ybot);
|
|
|
|
if (dolist)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_Obj *pobj;
|
|
|
|
pobj = Tcl_NewDoubleObj((double)fcover);
|
|
Tcl_SetObjResult(magicinterp, pobj);
|
|
#else
|
|
TxPrintf("%g\n", fcover);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
|
|
"Cell", btotal);
|
|
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
|
|
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
|
|
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
|
"cell", 100.0 * fcover);
|
|
}
|
|
}
|
|
|
|
int
|
|
cifCoverageFunc(
|
|
Tile *tile,
|
|
ClientData *arg)
|
|
{
|
|
coverstats *cstats = (coverstats *)arg;
|
|
Rect r;
|
|
|
|
TiToRect(tile, &r);
|
|
cstats->coverage += (long long)(r.r_xtop - r.r_xbot) * (long long)(r.r_ytop - r.r_ybot);
|
|
GeoInclude(&r, &cstats->bounds);
|
|
|
|
return(0);
|
|
}
|