Added a "bridge" operator to the set of operators used for CIF layer
generation in the "cifoutput" section of the techfile. This operator solves the problems with the catecorner position of geometry when attempting to automatically close up gaps between islands of a layer.
This commit is contained in:
parent
7540854184
commit
56250c907d
643
cif/CIFgen.c
643
cif/CIFgen.c
|
|
@ -1254,6 +1254,627 @@ cifBloatAllFunc(tile, bls)
|
|||
return 0; /* Keep the search alive. . . */
|
||||
}
|
||||
|
||||
/* Data structure to pass plane and minimum width to the callback function */
|
||||
typedef struct _bridgeStruct {
|
||||
Plane *plane;
|
||||
BridgeData *bridge;
|
||||
} BridgeStruct;
|
||||
|
||||
/* Bridge Check data structure */
|
||||
typedef struct _bridgeCheckStruct {
|
||||
Tile *tile; /* Tile that triggered search (ignore this tile) */
|
||||
int direction; /* What outside corner to look for */
|
||||
Tile *violator; /* Return the violator tile in this space */
|
||||
TileType checktype; /* Type to check for, either TT_SPACE or CIF_SOLIDTYPE */
|
||||
} BridgeCheckStruct;
|
||||
|
||||
/* Direction flags */
|
||||
#define BRIDGE_NW 1
|
||||
#define BRIDGE_SW 2
|
||||
#define BRIDGE_SE 3
|
||||
#define BRIDGE_NE 4
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* Function that returns the Euclidean distance corresponding to a manhattan
|
||||
* distance of the given width, at 45 degrees.
|
||||
*
|
||||
* This is used by the bridging method to keep the amount of extra material
|
||||
* added to a minimum.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
GetEuclideanWidthGrid(width)
|
||||
int width;
|
||||
{
|
||||
int weuclid;
|
||||
int delta;
|
||||
|
||||
weuclid = (int)(ceil((double)width * 0.70711));
|
||||
if (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1))
|
||||
{
|
||||
delta = weuclid % CIFCurStyle->cs_gridLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
weuclid -= delta;
|
||||
weuclid += CIFCurStyle->cs_gridLimit;
|
||||
}
|
||||
}
|
||||
return weuclid;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* cifBridgeFunc1 --
|
||||
*
|
||||
* Called for each relevant tile during bridge operations. The
|
||||
* bridge operation is responsible for preventing a grow-shrink
|
||||
* pair of operations from leaving width or spacing DRC errors,
|
||||
* which happens when tiles are in a catecorner position from
|
||||
* each other. The bridge operation adds a bridge of material
|
||||
* between the two tiles that solves spacing requirements between
|
||||
* the two tiles while satisfying the minimum width requirements,
|
||||
* adding a minimum amount of material to do so.
|
||||
*
|
||||
* The current version of this routine adds material on a stair-step
|
||||
* pattern; preferably this should be extended to create material
|
||||
* at allowed angles, where the allowed angles (90, 45, or any) are
|
||||
* specified as an option to the bridge statement in the tech file.
|
||||
*
|
||||
* GrowDistance is equal to the spacing rule distance needing to be
|
||||
* satisfied.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0 to keep the search alive.
|
||||
*
|
||||
* Side effects:
|
||||
* Paints into cifNewPlane. Tiles in old plane are tagged with
|
||||
* a static value in ClientData, which does not need to be reset
|
||||
* since the old plane will be free'd.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
cifBridgeFunc1(tile, brs)
|
||||
Tile *tile;
|
||||
BridgeStruct *brs;
|
||||
{
|
||||
Plane *plane = brs->plane;
|
||||
Rect area;
|
||||
Tile *tp1, *tp2, *tpx;
|
||||
int width = brs->bridge->br_width;
|
||||
int spacing = growDistance;
|
||||
int weuclid;
|
||||
BridgeCheckStruct brcs;
|
||||
int cifBridgeCheckFunc(); /* Forward reference */
|
||||
|
||||
/* If tile is marked, then it has been handled, so ignore it */
|
||||
if (tile->ti_client != (ClientData)CIF_UNPROCESSED) return 0;
|
||||
|
||||
/* Find each tile outside corner (up to four) */
|
||||
|
||||
/* Check for NE outside corner */
|
||||
tp1 = TR(tile); /* Tile on right side at the top of this tile */
|
||||
tp2 = RT(tile); /* Tile on top side at the right of this tile */
|
||||
if ((TiGetLeftType(tp1) == TT_SPACE) &&
|
||||
(TiGetBottomType(tp2) == TT_SPACE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = RIGHT(tile) - width;
|
||||
area.r_xtop = RIGHT(tile) + spacing;
|
||||
area.r_ybot = TOP(tile) - width;
|
||||
area.r_ytop = TOP(tile) + spacing;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_SW;
|
||||
brcs.checktype = TT_SPACE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&CIFSolidBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx) + weuclid);
|
||||
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx) + weuclid);
|
||||
|
||||
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile) - weuclid);
|
||||
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile) - weuclid);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for SW outside corner */
|
||||
tp1 = BL(tile); /* Tile on left side at the bottom of this tile */
|
||||
tp2 = LB(tile); /* Tile on bottom side at the left of this tile */
|
||||
if ((TiGetRightType(tp1) == TT_SPACE) &&
|
||||
(TiGetTopType(tp2) == TT_SPACE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = LEFT(tile) - spacing;
|
||||
area.r_xtop = LEFT(tile) + width;
|
||||
area.r_ybot = BOTTOM(tile) - spacing;
|
||||
area.r_ytop = BOTTOM(tile) + width;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_NE;
|
||||
brcs.checktype = TT_SPACE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&CIFSolidBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx) - weuclid);
|
||||
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx) - weuclid);
|
||||
|
||||
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile) + weuclid);
|
||||
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile) + weuclid);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for SE outside corner */
|
||||
for (tp1 = TR(tile); BOTTOM(tp1) > BOTTOM(tile); tp1 = LB(tp1));
|
||||
for (tp2 = LB(tile); RIGHT(tp1) < RIGHT(tile); tp2 = TR(tp2));
|
||||
if ((TiGetLeftType(tp1) == TT_SPACE) &&
|
||||
(TiGetTopType(tp2) == TT_SPACE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = RIGHT(tile) - width;
|
||||
area.r_xtop = RIGHT(tile) + spacing;
|
||||
area.r_ybot = BOTTOM(tile) - spacing;
|
||||
area.r_ytop = BOTTOM(tile) + width;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_NW;
|
||||
brcs.checktype = TT_SPACE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&CIFSolidBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx) + weuclid);
|
||||
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx) - weuclid);
|
||||
|
||||
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile) - weuclid);
|
||||
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile) + weuclid);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for NW outside corner */
|
||||
for (tp1 = BL(tile); TOP(tp1) < TOP(tile); tp1 = RT(tp1));
|
||||
for (tp2 = RT(tile); LEFT(tp1) > LEFT(tile); tp2 = BL(tp1));
|
||||
if ((TiGetRightType(tp1) == TT_SPACE) &&
|
||||
(TiGetBottomType(tp2) == TT_SPACE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = LEFT(tile) - spacing;
|
||||
area.r_xtop = LEFT(tile) + width;
|
||||
area.r_ybot = TOP(tile) - width;
|
||||
area.r_ytop = TOP(tile) + spacing;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_SE;
|
||||
brcs.checktype = TT_SPACE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&CIFSolidBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx) - weuclid);
|
||||
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx) + weuclid);
|
||||
|
||||
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile) + weuclid);
|
||||
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile) - weuclid);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* SetMinBoxGrid ---
|
||||
*
|
||||
* Adjust the given area by expanding evenly on both sides so that it
|
||||
* has a width and heigth no less than the given width. Then further
|
||||
* expand the box to ensure that it falls on the CIF minimum grid.
|
||||
*
|
||||
* Returns: Nothing
|
||||
*
|
||||
* Side Effects: Point to Rect "area" may be modified.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
SetMinBoxGrid(area, width)
|
||||
Rect *area;
|
||||
int width;
|
||||
{
|
||||
int wtest;
|
||||
int wtot;
|
||||
int delta;
|
||||
|
||||
wtest = (area->r_xtop - area->r_xbot);
|
||||
wtot = area->r_xtop + area->r_xbot;
|
||||
if (wtest < width)
|
||||
{
|
||||
area->r_xbot = (wtot - width) / 2;
|
||||
area->r_xtop = (wtot + width) / 2;
|
||||
}
|
||||
wtest = (area->r_ytop - area->r_ybot);
|
||||
wtot = area->r_ytop + area->r_ybot;
|
||||
if (wtest < width)
|
||||
{
|
||||
area->r_ybot = (wtot - width) / 2;
|
||||
area->r_ytop = (wtot + width) / 2;
|
||||
}
|
||||
|
||||
if (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1))
|
||||
{
|
||||
delta = abs(area->r_xbot) % CIFCurStyle->cs_gridLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
if (area->r_xbot < 0)
|
||||
{
|
||||
area->r_xbot += delta;
|
||||
area->r_xbot -= CIFCurStyle->cs_gridLimit;
|
||||
}
|
||||
else
|
||||
area->r_xbot -= delta;
|
||||
}
|
||||
|
||||
delta = abs(area->r_xtop) % CIFCurStyle->cs_gridLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
if (area->r_xtop < 0)
|
||||
area->r_xtop += delta;
|
||||
else
|
||||
{
|
||||
area->r_xtop -= delta;
|
||||
area->r_xtop += CIFCurStyle->cs_gridLimit;
|
||||
}
|
||||
}
|
||||
|
||||
delta = abs(area->r_ybot) % CIFCurStyle->cs_gridLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
if (area->r_ybot < 0)
|
||||
{
|
||||
area->r_ybot += delta;
|
||||
area->r_ybot -= CIFCurStyle->cs_gridLimit;
|
||||
}
|
||||
else
|
||||
area->r_ybot -= delta;
|
||||
}
|
||||
|
||||
delta = abs(area->r_ytop) % CIFCurStyle->cs_gridLimit;
|
||||
if (delta > 0)
|
||||
{
|
||||
if (area->r_ytop < 0)
|
||||
area->r_ytop += delta;
|
||||
else
|
||||
{
|
||||
area->r_ytop -= delta;
|
||||
area->r_ytop += CIFCurStyle->cs_gridLimit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* cifBridgeFunc2 --
|
||||
*
|
||||
* Called for each relevant tile during bridge operations. The
|
||||
* bridge operation is responsible for preventing a grow-shrink
|
||||
* pair of operations from leaving width or spacing DRC errors,
|
||||
* which happens when tiles are overlapping at a corner with the
|
||||
* overlap failing to meet the minimum width requirement. The
|
||||
* bridge operation adds a bridge of material over the pinch
|
||||
* point that solves the minimum width requirement, adding a
|
||||
* minimum amount of material to do so.
|
||||
*
|
||||
* The current version of this routine adds material on a stair-step
|
||||
* pattern; preferably this should be extended to create material
|
||||
* at allowed angles, where the allowed angles (90, 45, or any) are
|
||||
* specified as an option to the bridge statement in the tech file.
|
||||
*
|
||||
* growDistance is equal to the spacing rule distance needing to be
|
||||
* satisfied.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0 to keep the search alive.
|
||||
*
|
||||
* Side effects:
|
||||
* Paints into cifNewPlane. Tiles in old plane are tagged with
|
||||
* a static value in ClientData, which does not need to be reset
|
||||
* since the old plane will be free'd.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
cifBridgeFunc2(tile, brs)
|
||||
Tile *tile;
|
||||
BridgeStruct *brs;
|
||||
{
|
||||
Plane *plane = brs->plane;
|
||||
Rect area;
|
||||
Tile *tp1, *tp2, *tpx;
|
||||
int width = brs->bridge->br_width;
|
||||
int weuclid, wtest;
|
||||
int spacing = growDistance;
|
||||
BridgeCheckStruct brcs;
|
||||
int cifBridgeCheckFunc(); /* Forward reference */
|
||||
|
||||
/* If tile is marked, then it has been handled, so ignore it */
|
||||
if (tile->ti_client != (ClientData)CIF_UNPROCESSED) return 0;
|
||||
|
||||
/* Find each tile outside corner (up to four) */
|
||||
|
||||
/* Check for NE outside corner */
|
||||
tp1 = TR(tile); /* Tile on right side at the top of this tile */
|
||||
tp2 = RT(tile); /* Tile on top side at the right of this tile */
|
||||
if ((TiGetLeftType(tp1) == CIF_SOLIDTYPE) &&
|
||||
(TiGetBottomType(tp2) == CIF_SOLIDTYPE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = RIGHT(tile) - spacing;
|
||||
area.r_xtop = RIGHT(tile) + width;
|
||||
area.r_ybot = TOP(tile) - spacing;
|
||||
area.r_ytop = TOP(tile) + width;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_SW;
|
||||
brcs.checktype = TT_SPACE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&DBSpaceBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xbot = LEFT(tpx) - weuclid;
|
||||
area.r_ytop = TOP(tile) + weuclid;
|
||||
|
||||
area.r_xtop = RIGHT(tile) + weuclid;
|
||||
area.r_ybot = BOTTOM(tpx) - weuclid;
|
||||
|
||||
/* Box must meet width and height requirements */
|
||||
SetMinBoxGrid(&area, width);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for SW outside corner */
|
||||
tp1 = BL(tile); /* Tile on left side at the bottom of this tile */
|
||||
tp2 = LB(tile); /* Tile on bottom side at the left of this tile */
|
||||
if ((TiGetRightType(tp1) == CIF_SOLIDTYPE) &&
|
||||
(TiGetTopType(tp2) == CIF_SOLIDTYPE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = LEFT(tile) - width;
|
||||
area.r_xtop = LEFT(tile) + spacing;
|
||||
area.r_ybot = BOTTOM(tile) - width;
|
||||
area.r_ytop = BOTTOM(tile) + spacing;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_NE;
|
||||
brcs.checktype = CIF_SOLIDTYPE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&DBSpaceBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xbot = LEFT(tile) - weuclid;
|
||||
area.r_ytop = TOP(tpx) + weuclid;
|
||||
|
||||
area.r_xtop = RIGHT(tpx) + weuclid;
|
||||
area.r_ybot = BOTTOM(tile) - weuclid;
|
||||
|
||||
/* Box must meet width and height requirements */
|
||||
SetMinBoxGrid(&area, width);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for SE outside corner */
|
||||
for (tp1 = TR(tile); BOTTOM(tp1) > BOTTOM(tile); tp1 = LB(tp1));
|
||||
for (tp2 = LB(tile); RIGHT(tp2) < RIGHT(tile); tp2 = TR(tp2));
|
||||
if ((TiGetLeftType(tp1) == CIF_SOLIDTYPE) &&
|
||||
(TiGetTopType(tp2) == CIF_SOLIDTYPE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = RIGHT(tile) - spacing;
|
||||
area.r_xtop = RIGHT(tile) + width;
|
||||
area.r_ybot = BOTTOM(tile) - width;
|
||||
area.r_ytop = BOTTOM(tile) + spacing;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_NW;
|
||||
brcs.checktype = CIF_SOLIDTYPE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&DBSpaceBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
area.r_xbot = LEFT(tpx) - weuclid;
|
||||
area.r_ytop = TOP(tpx) + weuclid;
|
||||
|
||||
area.r_xtop = RIGHT(tile) + weuclid;
|
||||
area.r_ybot = BOTTOM(tile) - weuclid;
|
||||
|
||||
/* Box must meet width and height requirements */
|
||||
SetMinBoxGrid(&area, width);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for NW outside corner */
|
||||
for (tp1 = BL(tile); TOP(tp1) < TOP(tile); tp1 = RT(tp1));
|
||||
for (tp2 = RT(tile); LEFT(tp2) > LEFT(tile); tp2 = BL(tp2));
|
||||
if ((TiGetRightType(tp1) == CIF_SOLIDTYPE) &&
|
||||
(TiGetBottomType(tp2) == CIF_SOLIDTYPE))
|
||||
{
|
||||
/* Set search box */
|
||||
area.r_xbot = LEFT(tile) - width;
|
||||
area.r_xtop = LEFT(tile) + spacing;
|
||||
area.r_ybot = TOP(tile) - spacing;
|
||||
area.r_ytop = TOP(tile) + width;
|
||||
|
||||
/* Find violator tiles */
|
||||
brcs.tile = tile;
|
||||
brcs.direction = BRIDGE_SE;
|
||||
brcs.checktype = CIF_SOLIDTYPE;
|
||||
if (DBSrPaintArea((Tile *) NULL, plane, &area,
|
||||
&DBSpaceBits, cifBridgeCheckFunc, (ClientData)&brcs) == 1)
|
||||
{
|
||||
tpx = brcs.violator;
|
||||
weuclid = GetEuclideanWidthGrid(width);
|
||||
|
||||
/* Resize box to satisfy width requirement on both ends */
|
||||
area.r_xbot = LEFT(tile) - weuclid;
|
||||
area.r_ytop = TOP(tile) + weuclid;
|
||||
|
||||
area.r_xtop = RIGHT(tpx) + weuclid;
|
||||
area.r_ybot = BOTTOM(tpx) - weuclid;
|
||||
|
||||
/* Box must meet width and height requirements */
|
||||
SetMinBoxGrid(&area, width);
|
||||
|
||||
/* Trivial implementation: fill box */
|
||||
/* (to do: use stairstep to avoid filling unnecessary areas) */
|
||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------
|
||||
* Callback function for cifBridgeFunc1 and cifBridgeFunc2 to find if
|
||||
* there are violator cells in the search area. If a violator cell is
|
||||
* found, then put the tile pointer in the BridgeCheckStruct and return
|
||||
* value 1 to stop the search. Otherwise return 0 to keep going.
|
||||
*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
cifBridgeCheckFunc(tile, brcs)
|
||||
Tile *tile;
|
||||
BridgeCheckStruct *brcs;
|
||||
{
|
||||
int dir = brcs->direction;
|
||||
Tile *self = brcs->tile;
|
||||
Tile *tp1, *tp2;
|
||||
TileType checktype = brcs->checktype;
|
||||
|
||||
if (self == tile) return 0; /* Ignore the triggering tile */
|
||||
|
||||
switch (dir) {
|
||||
case BRIDGE_NW:
|
||||
/* Ignore tile if split, and SE corner is clipped */
|
||||
if (TiGetRightType(tile) == checktype || TiGetBottomType(tile) == checktype)
|
||||
break;
|
||||
for (tp1 = RT(tile); LEFT(tp1) > LEFT(tile); tp1 = BL(tp1));
|
||||
for (tp2 = BL(tile); TOP(tp2) < TOP(tile); tp2 = RT(tp2));
|
||||
if ((TiGetBottomType(tp1) == checktype) &&
|
||||
(TiGetRightType(tp2) == checktype))
|
||||
{
|
||||
brcs->violator = tile;
|
||||
return 1; /* Violator found */
|
||||
}
|
||||
break;
|
||||
case BRIDGE_NE:
|
||||
/* Ignore tile if split, and SW corner is clipped */
|
||||
if (TiGetLeftType(tile) == checktype || TiGetBottomType(tile) == checktype)
|
||||
break;
|
||||
tp1 = RT(tile);
|
||||
tp2 = TR(tile);
|
||||
if ((TiGetBottomType(tp1) == checktype) &&
|
||||
(TiGetLeftType(tp2) == checktype))
|
||||
{
|
||||
brcs->violator = tile;
|
||||
return 1; /* Violator found */
|
||||
}
|
||||
break;
|
||||
case BRIDGE_SW:
|
||||
/* Ignore tile if split, and NE corner is clipped */
|
||||
if (TiGetRightType(tile) == checktype || TiGetTopType(tile) == checktype)
|
||||
break;
|
||||
tp1 = LB(tile);
|
||||
tp2 = BL(tile);
|
||||
if ((TiGetTopType(tp1) == checktype) &&
|
||||
(TiGetRightType(tp2) == checktype))
|
||||
{
|
||||
brcs->violator = tile;
|
||||
return 1; /* Violator found */
|
||||
}
|
||||
break;
|
||||
case BRIDGE_SE:
|
||||
/* Ignore tile if split, and NW corner is clipped */
|
||||
if (TiGetLeftType(tile) == checktype || TiGetTopType(tile) == checktype)
|
||||
break;
|
||||
for (tp1 = LB(tile); RIGHT(tp1) < RIGHT(tile); tp1 = TR(tp1));
|
||||
for (tp2 = TR(tile); BOTTOM(tp2) > BOTTOM(tile); tp2 = LB(tp2));
|
||||
if ((TiGetTopType(tp1) == checktype) &&
|
||||
(TiGetLeftType(tp2) == checktype))
|
||||
{
|
||||
brcs->violator = tile;
|
||||
return 1; /* Violator found */
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0; /* Nothing found here, so keep going */
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -3191,6 +3812,8 @@ CIFGenLayer(op, area, cellDef, origDef, temps, clientdata)
|
|||
TileType ttype;
|
||||
char *netname;
|
||||
BloatStruct bls;
|
||||
BridgeStruct brs;
|
||||
BridgeData *bridge;
|
||||
int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ?
|
||||
cifGrowEuclideanFunc : cifGrowFunc;
|
||||
|
||||
|
|
@ -3394,6 +4017,26 @@ CIFGenLayer(op, area, cellDef, origDef, temps, clientdata)
|
|||
nextPlane = temp;
|
||||
break;
|
||||
|
||||
case CIFOP_BRIDGE:
|
||||
growDistance = op->co_distance;
|
||||
DBClearPaintPlane(nextPlane);
|
||||
cifPlane = nextPlane;
|
||||
cifScale = 1;
|
||||
/* First copy the existing paint into the target plane */
|
||||
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
|
||||
&CIFSolidBits, cifPaintFunc, (ClientData)CIFPaintTable);
|
||||
|
||||
brs.plane = curPlane;
|
||||
brs.bridge = (BridgeData *)op->co_client;
|
||||
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
|
||||
&CIFSolidBits, cifBridgeFunc1, (ClientData)&brs);
|
||||
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
|
||||
&DBSpaceBits, cifBridgeFunc2, (ClientData)&brs);
|
||||
temp = curPlane;
|
||||
curPlane = nextPlane;
|
||||
nextPlane = temp;
|
||||
break;
|
||||
|
||||
case CIFOP_BLOAT:
|
||||
cifPlane = curPlane;
|
||||
cifSrTiles(op, area, cellDef, temps,
|
||||
|
|
|
|||
3980
cif/CIFgen.c.test
3980
cif/CIFgen.c.test
File diff suppressed because it is too large
Load Diff
12
cif/CIFint.h
12
cif/CIFint.h
|
|
@ -52,6 +52,11 @@ typedef struct bloat_data
|
|||
int bl_distance[TT_MAXTYPES];
|
||||
} BloatData;
|
||||
|
||||
typedef struct bridge_data
|
||||
{
|
||||
int br_width; /* Minimum width rule for bridge */
|
||||
} BridgeData;
|
||||
|
||||
typedef struct squares_data
|
||||
{
|
||||
int sq_border;
|
||||
|
|
@ -81,8 +86,9 @@ typedef struct cifop
|
|||
* below for the legal ones.
|
||||
*/
|
||||
int co_distance; /* Grow or shrink distance (if needed). */
|
||||
ClientData co_client; /* Pointer to a BloatData, SquaresData, or
|
||||
* SlotsData structure, or NULL.
|
||||
ClientData co_client; /* Pointer to a BloatData, SquaresData,
|
||||
* SlotsData, or BridgeData structure,
|
||||
* or NULL.
|
||||
*/
|
||||
struct cifop *co_next; /* Next in list of operations to perform. */
|
||||
} CIFOp;
|
||||
|
|
@ -134,6 +140,7 @@ typedef struct cifop
|
|||
* which will be painted into parent cells instead of the
|
||||
* current cell. This replaces the "fault" method.
|
||||
* CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated
|
||||
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
|
||||
*/
|
||||
|
||||
#define CIFOP_AND 1
|
||||
|
|
@ -156,6 +163,7 @@ typedef struct cifop
|
|||
#define CIFOP_MAXRECT 18
|
||||
#define CIFOP_COPYUP 19
|
||||
#define CIFOP_CLOSE 20
|
||||
#define CIFOP_BRIDGE 21
|
||||
|
||||
/* Added by Tim 10/21/2004 */
|
||||
/* The following structure is used to pass information on how to draw
|
||||
|
|
|
|||
|
|
@ -531,6 +531,7 @@ CIFTechLine(sectionName, argc, argv)
|
|||
CIFKeep *newStyle, *p;
|
||||
char **bloatArg;
|
||||
BloatData *bloats;
|
||||
BridgeData *bridge;
|
||||
SquaresData *squares;
|
||||
SlotsData *slots;
|
||||
|
||||
|
|
@ -1055,6 +1056,8 @@ CIFTechLine(sectionName, argc, argv)
|
|||
newOp->co_opcode = CIFOP_BOUNDARY;
|
||||
else if (strcmp(argv[0], "close") == 0)
|
||||
newOp->co_opcode = CIFOP_CLOSE;
|
||||
else if (strcmp(argv[0], "bridge") == 0)
|
||||
newOp->co_opcode = CIFOP_BRIDGE;
|
||||
else
|
||||
{
|
||||
TechError("Unknown statement \"%s\".\n", argv[0]);
|
||||
|
|
@ -1085,6 +1088,25 @@ CIFTechLine(sectionName, argc, argv)
|
|||
}
|
||||
break;
|
||||
|
||||
case CIFOP_BRIDGE:
|
||||
if (argc != 3) goto wrongNumArgs;
|
||||
newOp->co_distance = atoi(argv[1]);
|
||||
if (newOp->co_distance <= 0)
|
||||
{
|
||||
TechError("Bridge distance must be greater than zero.\n");
|
||||
goto errorReturn;
|
||||
}
|
||||
bridge = (BridgeData *)mallocMagic(sizeof(BridgeData));
|
||||
bridge->br_width = atoi(argv[2]);
|
||||
if (bridge->br_width <= 0)
|
||||
{
|
||||
TechError("Bridge width must be greater than zero.\n");
|
||||
freeMagic(bridge);
|
||||
goto errorReturn;
|
||||
}
|
||||
newOp->co_client = (ClientData)bridge;
|
||||
break;
|
||||
|
||||
case CIFOP_BLOATALL:
|
||||
if (argc != 3) goto wrongNumArgs;
|
||||
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
|
||||
|
|
@ -1549,6 +1571,7 @@ cifComputeRadii(layer, des)
|
|||
shrink += curShrink;
|
||||
break;
|
||||
|
||||
case CIFOP_BRIDGE: break;
|
||||
case CIFOP_SQUARES: break;
|
||||
case CIFOP_SQUARES_G: break;
|
||||
}
|
||||
|
|
@ -1717,6 +1740,7 @@ CIFTechFinal()
|
|||
if (op->co_client)
|
||||
{
|
||||
BloatData *bloats;
|
||||
BridgeData *bridge;
|
||||
SquaresData *squares;
|
||||
SlotsData *slots;
|
||||
if (op->co_opcode == CIFOP_SLOTS)
|
||||
|
|
@ -1807,6 +1831,12 @@ CIFTechFinal()
|
|||
case CIFOP_MAXRECT:
|
||||
case CIFOP_NET:
|
||||
break;
|
||||
case CIFOP_BRIDGE:
|
||||
bridge = (BridgeData *)op->co_client;
|
||||
c = FindGCF(style->cs_scaleFactor,
|
||||
bridge->br_width);
|
||||
if (c < minReduce) minReduce = c;
|
||||
break;
|
||||
default:
|
||||
bloats = (BloatData *)op->co_client;
|
||||
for (j = 0; j < TT_MAXTYPES; j++)
|
||||
|
|
@ -1890,6 +1920,8 @@ CIFTechFinal()
|
|||
case CIFOP_AND:
|
||||
case CIFOP_ANDNOT:
|
||||
case CIFOP_SHRINK:
|
||||
case CIFOP_CLOSE:
|
||||
case CIFOP_BRIDGE:
|
||||
needThisLayer = TRUE;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2140,6 +2172,7 @@ CIFTechOutputScale(n, d)
|
|||
SquaresData *squares;
|
||||
SlotsData *slots;
|
||||
BloatData *bloats;
|
||||
BridgeData *bridge;
|
||||
bool has_odd_space = FALSE;
|
||||
|
||||
if (ostyle == NULL) return;
|
||||
|
|
@ -2294,6 +2327,13 @@ CIFTechOutputScale(n, d)
|
|||
case CIFOP_MAXRECT:
|
||||
case CIFOP_NET:
|
||||
break;
|
||||
case CIFOP_BRIDGE:
|
||||
bridge = (BridgeData *)op->co_client;
|
||||
bridge->br_width *= d;
|
||||
lgcf = FindGCF(abs(bridge->br_width),
|
||||
ostyle->cs_expander);
|
||||
lexpand = FindGCF(lexpand, lgcf);
|
||||
break;
|
||||
default:
|
||||
bloats = (BloatData *)op->co_client;
|
||||
for (j = 0; j < TT_MAXTYPES; j++)
|
||||
|
|
@ -2391,6 +2431,10 @@ CIFTechOutputScale(n, d)
|
|||
if (bloats->bl_distance[j] != 0)
|
||||
bloats->bl_distance[j] /= lexpand;
|
||||
break;
|
||||
case CIFOP_BRIDGE:
|
||||
bridge = (BridgeData *)op->co_client;
|
||||
bridge->br_width /= lexpand;
|
||||
break;
|
||||
default:
|
||||
/* op->co_opcode in CIFOP_OR is a pointer copy */
|
||||
/* and in CIFOP_BBOX and CIFOP_MAXRECT is a */
|
||||
|
|
|
|||
Loading…
Reference in New Issue