mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-29 01:24:51 +02:00
previous behavior that had inadvertently been changed. In recent versions, "load <absolute_path> -dereference" would incorrectly apply the dereferencing to <absolute_path> rather than just its subcells. Cleaned up the code around DBCellRead() in the process, so everything is more straightforward (although probably more could be done in that regard).
485 lines
13 KiB
C
485 lines
13 KiB
C
/*
|
|
* ExtInteraction.c --
|
|
*
|
|
* Circuit extraction.
|
|
* Finds interaction areas.
|
|
*
|
|
* *********************************************************************
|
|
* * 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/extract/ExtInter.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "utils/geofast.h"
|
|
#include "utils/undo.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "utils/malloc.h"
|
|
#include "textio/textio.h"
|
|
#include "debug/debug.h"
|
|
#include "extract/extract.h"
|
|
#include "extract/extractInt.h"
|
|
#include "utils/signals.h"
|
|
#include "utils/styles.h"
|
|
|
|
/* Local data */
|
|
CellUse *extInterUse = (CellUse *) NULL; /* Subtree being processed */
|
|
Plane *extInterPlane; /* Paint into this plane */
|
|
int extInterHalo; /* Elements closer than this
|
|
* constitute an interaction.
|
|
*/
|
|
int extInterBloat; /* Bloat by this much when
|
|
* painting into result plane.
|
|
*/
|
|
|
|
/* Forward declarations */
|
|
int extInterOverlapSubtree();
|
|
int extInterOverlapTile();
|
|
int extInterSubtree();
|
|
int extInterSubtreeClip();
|
|
int extInterSubtreeElement();
|
|
int extInterSubtreeTile();
|
|
int extInterSubtreePaint();
|
|
|
|
#define BLOATBY(r, h) ( (r)->r_xbot -= (h), (r)->r_ybot -= (h), \
|
|
(r)->r_xtop += (h), (r)->r_ytop += (h) )
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* ExtFindInteractions --
|
|
*
|
|
* Paint into the supplied tile plane 'resultPlane' TT_ERROR_P tiles
|
|
* for each area in the CellDef 'def' that must be processed for
|
|
* interactions.
|
|
*
|
|
* Each interaction arises from paint in two different subtrees
|
|
* being less than (but not equal to) 'halo' units away from
|
|
* each other. In this definition, a subtree refers to a single
|
|
* CellUse, which may be either a single cell or an entire array.
|
|
*
|
|
* If 'bloat' is non-zero, each interaction area is bloated by
|
|
* this amount when being painted into the result plane.
|
|
*
|
|
* Results:
|
|
* None.
|
|
*
|
|
* Side effects:
|
|
* Paints into the plane 'resultPlane'.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
ExtFindInteractions(def, halo, bloatby, resultPlane)
|
|
CellDef *def; /* Find interactions among children of def */
|
|
int halo; /* Interaction is elements closer than halo */
|
|
int bloatby; /* Bloat each interaction area by this amount when
|
|
* painting into resultPlane.
|
|
*/
|
|
Plane *resultPlane; /* Paint interaction areas into this plane */
|
|
{
|
|
SearchContext scx;
|
|
|
|
UndoDisable();
|
|
extInterPlane = resultPlane;
|
|
extInterHalo = halo;
|
|
extInterBloat = bloatby;
|
|
extParentUse->cu_def = def;
|
|
scx.scx_use = extParentUse;
|
|
scx.scx_trans = GeoIdentityTransform;
|
|
scx.scx_area = def->cd_bbox;
|
|
|
|
/*
|
|
* Process each child subtree.
|
|
* This involves comparing all the paint in the subtree
|
|
* with all the paint in all other subtrees up to, but
|
|
* not including, the subtree under consideration.
|
|
*/
|
|
extInterUse = (CellUse *) NULL;
|
|
(void) DBCellSrArea(&scx, extInterSubtree, (ClientData) NULL);
|
|
|
|
/*
|
|
* Process parent paint if there were any subcells.
|
|
* We compare each paint rectangle with all the paint in
|
|
* all the subtrees, to see if there is an overlap.
|
|
*/
|
|
if (extInterUse)
|
|
{
|
|
extInterUse = (CellUse *) NULL;
|
|
(void) DBCellSrArea(&scx, extInterSubtreePaint, (ClientData) def);
|
|
}
|
|
UndoEnable();
|
|
}
|
|
|
|
int
|
|
extInterSubtreePaint(scx, def)
|
|
SearchContext *scx;
|
|
CellDef *def;
|
|
{
|
|
Rect r;
|
|
int pNum;
|
|
|
|
r = scx->scx_use->cu_bbox;
|
|
BLOATBY(&r, extInterHalo);
|
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
|
(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &r,
|
|
&DBAllButSpaceAndDRCBits, extInterSubtreeTile, (ClientData) NULL);
|
|
|
|
return (2);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* extInterSubtree --
|
|
*
|
|
* Called for each immediate child use of the cell being processed
|
|
* for interactions. Our job is to process all the paint in this
|
|
* use against all other subtrees overlapping this one.
|
|
*
|
|
* Results:
|
|
* Returns 2 to abort after the first array element.
|
|
*
|
|
* Side effects:
|
|
* Sets extInterUse to scx->scx_use.
|
|
* Children may paint into extInterPlane.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
extInterSubtree(scx)
|
|
SearchContext *scx;
|
|
{
|
|
CellUse *oldUse = extInterUse;
|
|
SearchContext parentScx;
|
|
|
|
extInterUse = scx->scx_use;
|
|
if (oldUse)
|
|
{
|
|
/* Find all other subtrees overlapping this cell */
|
|
parentScx.scx_area = scx->scx_use->cu_bbox;
|
|
BLOATBY(&parentScx.scx_area, extInterHalo);
|
|
parentScx.scx_trans = GeoIdentityTransform;
|
|
parentScx.scx_use = extParentUse;
|
|
(void) DBCellSrArea(&parentScx, extInterSubtreeClip, (ClientData) scx);
|
|
}
|
|
return (2);
|
|
}
|
|
|
|
int
|
|
extInterSubtreeClip(overlapScx, scx)
|
|
SearchContext *overlapScx, *scx;
|
|
{
|
|
Rect r, r2;
|
|
|
|
/* Only search as far as extInterUse */
|
|
if (overlapScx->scx_use == extInterUse)
|
|
return (2);
|
|
|
|
/*
|
|
* Only process the overlap between overlapScx and scx,
|
|
* bloating both by extInterHalo.
|
|
*/
|
|
r = overlapScx->scx_use->cu_bbox;
|
|
BLOATBY(&r, extInterHalo);
|
|
r2 = scx->scx_use->cu_bbox;
|
|
BLOATBY(&r2, extInterHalo);
|
|
GEOCLIP(&r, &r2);
|
|
|
|
(void) DBArraySr(scx->scx_use, &r, extInterSubtreeElement,
|
|
(ClientData) &r);
|
|
return (2);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* extInterSubtreeElement --
|
|
*
|
|
* Called for each element in the array forming the use passed to
|
|
* extInterSubtree(). See extInterSubtree() for comments.
|
|
*
|
|
* Results:
|
|
* Returns 0 always.
|
|
*
|
|
* Side effects:
|
|
* See ExtFindInteractions.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
extInterSubtreeElement(use, trans, x, y, r)
|
|
CellUse *use;
|
|
Transform *trans;
|
|
int x, y;
|
|
Rect *r;
|
|
{
|
|
SearchContext scx;
|
|
Transform tinv;
|
|
|
|
scx.scx_use = use;
|
|
scx.scx_trans = *trans;
|
|
scx.scx_x = x;
|
|
scx.scx_y = y;
|
|
GEOINVERTTRANS(trans, &tinv);
|
|
GEOTRANSRECT(&tinv, r, &scx.scx_area);
|
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
|
extInterSubtreeTile, (ClientData) NULL);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* extInterSubtreeTile --
|
|
*
|
|
* Called for each tile in the subtree being processed by
|
|
* extInterSubtree(). Transform this tile to root coordinates,
|
|
* bloating by extInterHalo, and then call extInterOverlapSubtree
|
|
* to process all the other subtrees for paint overlapping
|
|
* this bloated area. If the argument 'cxp' is non-NULL, we
|
|
* use cxp->tc_scx->scx_trans to transform the area of tile to
|
|
* root coordinates; otherwise, we don't transform it at all.
|
|
*
|
|
* Results:
|
|
* Returns 0 always.
|
|
*
|
|
* Side effects:
|
|
* See extInterOverlapTile.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
extInterSubtreeTile(tile, cxp)
|
|
Tile *tile;
|
|
TreeContext *cxp;
|
|
{
|
|
SearchContext newscx;
|
|
Rect r;
|
|
|
|
TITORECT(tile, &r);
|
|
BLOATBY(&r, extInterHalo);
|
|
if (cxp)
|
|
{
|
|
GEOTRANSRECT(&cxp->tc_scx->scx_trans, &r, &newscx.scx_area);
|
|
}
|
|
else newscx.scx_area = r;
|
|
newscx.scx_trans = GeoIdentityTransform;
|
|
newscx.scx_use = extParentUse;
|
|
(void) DBCellSrArea(&newscx, extInterOverlapSubtree, (ClientData) NULL);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* extInterOverlapSubtree --
|
|
*
|
|
* Called for each subcell of the root that overlaps the piece
|
|
* of paint found by extInterSubtreeTile() above. We stop
|
|
* as soon as we see extInterUse; otherwise, search all the
|
|
* cells in the subtree rooted at scx->scx_use for paint
|
|
* overlapping scx->scx_area.
|
|
*
|
|
* Results:
|
|
* Returns 2 if we see extInterUse; otherwise, returns 0.
|
|
*
|
|
* Side effects:
|
|
* Paints into the plane 'resultPlane'; see extInterOverlapTile.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
extInterOverlapSubtree(scx)
|
|
SearchContext *scx;
|
|
{
|
|
if (extInterUse == scx->scx_use)
|
|
return (2);
|
|
|
|
(void) extTreeSrPaintArea(scx, extInterOverlapTile, (ClientData) NULL);
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* extInterOverlapTile --
|
|
*
|
|
* Called for each piece of paint overlapping the piece found
|
|
* by extInterSubtreeTile(). Bloat the found piece by extInterHalo,
|
|
* then clip to the area of the overlapping piece of paint in root
|
|
* coordinates. If the result is non-empty, paint it into the
|
|
* plane extInterPlane.
|
|
*
|
|
* Results:
|
|
* Returns 0 always.
|
|
*
|
|
* Side effects:
|
|
* Paints into the plane 'resultPlane'.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
extInterOverlapTile(tile, cxp)
|
|
Tile *tile;
|
|
TreeContext *cxp;
|
|
{
|
|
SearchContext *scx = cxp->tc_scx;
|
|
Rect r, rootr;
|
|
|
|
TITORECT(tile, &r);
|
|
BLOATBY(&r, extInterHalo);
|
|
GEOCLIP(&r, &scx->scx_area);
|
|
if (GEO_RECTNULL(&r))
|
|
return (0);
|
|
|
|
GEOTRANSRECT(&scx->scx_trans, &r, &rootr);
|
|
BLOATBY(&rootr, extInterBloat);
|
|
DBPaintPlane(extInterPlane, &rootr, DBStdWriteTbl(TT_ERROR_P),
|
|
(PaintUndoInfo *) NULL);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* extTreeSrPaintArea --
|
|
*
|
|
* Recursively search downward from the supplied CellUse for
|
|
* all paint tiles.
|
|
*
|
|
* The procedure should be of the following form:
|
|
*
|
|
* int
|
|
* func(tile, scx, cdata)
|
|
* Tile *tile;
|
|
* SearchContext *scx;
|
|
* ClientData cdata;
|
|
* {
|
|
* }
|
|
*
|
|
* The SearchContext is stored in cxp->tc_scx, and the user's arg is stored
|
|
* in cxp->tc_filter->tf_arg.
|
|
*
|
|
* In the above, the scx transform is the net transform from the coordinates
|
|
* of tile to "world" coordinates (or whatever coordinates the initial
|
|
* transform supplied to extTreeSrTiles was a transform to). Func returns
|
|
* 0 under normal conditions. If 1 is returned, it is a request to
|
|
* abort the search.
|
|
*
|
|
* *** WARNING ***
|
|
*
|
|
* The client procedure should not modify any of the paint planes in
|
|
* the cells visited by extTreeSrTiles, because we use DBSrPaintArea
|
|
* as our paint-tile enumeration function.
|
|
*
|
|
* Results:
|
|
* 0 is returned if the search finished normally. 1 is returned
|
|
* if the search was aborted.
|
|
*
|
|
* Side effects:
|
|
* Whatever side effects are brought about by applying the
|
|
* procedure supplied.
|
|
*
|
|
*-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
extTreeSrPaintArea(scx, func, cdarg)
|
|
SearchContext *scx; /* Pointer to search context specifying
|
|
* a cell use to search, an area in the
|
|
* coordinates of the cell's def, and a
|
|
* transform back to "root" coordinates.
|
|
*/
|
|
int (*func)(); /* Function to apply at each qualifying tile */
|
|
ClientData cdarg; /* Client data for above function */
|
|
{
|
|
int extTreeSrFunc();
|
|
CellDef *def = scx->scx_use->cu_def;
|
|
TreeContext context;
|
|
TreeFilter filter;
|
|
int pNum;
|
|
|
|
if ((def->cd_flags & CDAVAILABLE) == 0)
|
|
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
|
return 0;
|
|
|
|
filter.tf_func = func;
|
|
filter.tf_arg = cdarg;
|
|
context.tc_scx = scx;
|
|
context.tc_filter = &filter;
|
|
|
|
/*
|
|
* Apply the function first to any of the tiles in the planes
|
|
* for this CellUse's CellDef that match the mask.
|
|
*/
|
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
|
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
|
|
&scx->scx_area, &DBAllButSpaceAndDRCBits, func,
|
|
(ClientData) &context))
|
|
return (1);
|
|
|
|
/* Visit our children recursively */
|
|
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) &filter));
|
|
}
|
|
|
|
/*
|
|
* extTreeSrFunc --
|
|
*
|
|
* Filter procedure applied to subcells by extTreeSrPaintArea().
|
|
*/
|
|
|
|
int
|
|
extTreeSrFunc(scx, fp)
|
|
SearchContext *scx;
|
|
TreeFilter *fp;
|
|
{
|
|
CellDef *def = scx->scx_use->cu_def;
|
|
TreeContext context;
|
|
int pNum;
|
|
|
|
if ((def->cd_flags & CDAVAILABLE) == 0)
|
|
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
|
return 0;
|
|
|
|
context.tc_scx = scx;
|
|
context.tc_filter = fp;
|
|
|
|
/*
|
|
* Apply the function first to any of the tiles in the planes
|
|
* for this CellUse's CellDef that match the mask.
|
|
*/
|
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
|
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum],
|
|
&scx->scx_area, &DBAllButSpaceAndDRCBits,
|
|
fp->tf_func, (ClientData) &context))
|
|
return (1);
|
|
|
|
/* Visit our children recursively */
|
|
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) fp));
|
|
}
|
|
|