magic/cif/CIFsee.c

491 lines
14 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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 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 "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"
/* 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, pld)
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(rootDef, area, cifLayer, magicLayer, paintDef)
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);
oldCount = DBWFeedbackCount;
CIFGen(CIFComponentDef, area, CIFPlanes, &depend, TRUE, TRUE);
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, sld)
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(rootDef, area, layer)
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);
oldCount = DBWFeedbackCount;
CIFGen(CIFComponentDef, area, CIFPlanes, &depend, TRUE, TRUE);
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(rootDef, area, layer, arrays, subcells)
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(rootDef, area, layer)
CellDef *rootDef; /* Def in which to compute CIF coverage */
Rect *area; /* Area in which to compute coverage */
char *layer; /* CIF layer for coverage computation. */
{
coverstats cstats;
int i, scale;
long long atotal, btotal;
SearchContext scx;
TileTypeBitMask mask, depend;
float fcover;
int cifCoverageFunc();
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);
CIFGen(CIFComponentDef, area, CIFPlanes, &depend, TRUE, TRUE);
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);
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, arg)
Tile *tile;
ClientData *arg;
{
coverstats *cstats = (coverstats *)arg;
Rect r;
TiToRect(tile, &r);
cstats->coverage += (long long)((r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot));
GeoInclude(&r, &cstats->bounds);
return(0);
}