/* 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 #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); }