Added new cif operator bridge-lim

The new CIF operator BRIDGE-LIM is similar to the BRIDGE operator with the difference that the material created to meet the minimum spacing/width rules do not overlap the limiting layers. Syntax of the new operator is:

bridge-lim spacing width layers

where "layers" are the limiting layers.
This commit is contained in:
fabian-l-c 2020-07-27 17:40:31 -03:00 committed by Tim Edwards
parent 6b633be797
commit c872db78b3
3 changed files with 882 additions and 0 deletions

View File

@ -3775,6 +3775,831 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg)
&CIFSolidBits, func, (ClientData) cdArg);
}
/* Data structure to pass plane and minimum width to the callback function */
typedef struct _bridgeLimStruct {
Plane *plane;
BridgeData *bridge;
CellDef *def;
Plane **temps;
TileTypeBitMask co_paintMask;/* Zero or more paint layers to consider. */
TileTypeBitMask co_cifMask; /* Zero or more other CIF layers. */
} BridgeLimStruct;
static int xOverlap, yOverlap;
/* Bridge-lim Check data structure */
typedef struct _bridgeLimCheckStruct {
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 */
long sqdistance; /* Square of the minimum distance */
} BridgeLimCheckStruct;
/*
*-----------------------------------------------------------------------
* Callback function for bridgeLimSrTiles used when a limiting layer tile
* was found in the specified area. If calcOverlap is TRUE then the xOverlap
* and yOverlap are updated and return 0 to continue searching. Otherwise
* return 1 to stop the search.
*-----------------------------------------------------------------------
*/
int
bridgeLimFound(tile, calcOverlap)
Tile *tile;
bool calcOverlap;
{
if (calcOverlap)
{
if (RIGHT(tile) > xOverlap)
xOverlap = RIGHT(tile);
if (TOP(tile) > yOverlap)
yOverlap = TOP(tile);
return 0; // continue searching
} else
return 1; // tile found, stop the search
}
/*
*------------------------------------------------------------------------
* Callback function used in bridge-lim operations to find if the specified
* area contains tiles of the limiting layers.
*------------------------------------------------------------------------
*/
int
bridgeLimSrTiles(brlims, area, calcOverlap)
BridgeLimStruct *brlims; /* Bridge-Lim structure. */
Rect *area; /* Area of Magic paint to consider. */
bool calcOverlap; /* TRUE to calculate the overlap of the limiting tiles in the specified area. */
{
TileTypeBitMask maskBits;
TileType t;
int i;
Plane **temps = brlims->temps;
xOverlap = area->r_xbot;
yOverlap = area->r_ybot;
for (i = PL_DRC_CHECK; i < DBNumPlanes; i++)
{
maskBits = DBPlaneTypes[i];
TTMaskAndMask(&maskBits, &brlims->co_paintMask);
if (!TTMaskEqual(&maskBits, &DBZeroTypeBits))
if (DBSrPaintArea((Tile *) NULL, brlims->def->cd_planes[i], area, &brlims->co_paintMask, bridgeLimFound, calcOverlap))
return 0;
}
for (t = 0; t < TT_MAXTYPES; t++, temps++)
if (TTMaskHasType(&brlims->co_cifMask, t))
if (DBSrPaintArea((Tile *) NULL, *temps, area, &CIFSolidBits, bridgeLimFound, calcOverlap))
return 0;
if (( xOverlap != area->r_xbot) || (yOverlap != area->r_ybot))
return 0; //Constraint tile found
else
return 1; //Nothing found
}
/*
* ----------------------------------------------------------------------------
*
* cifBridgeLimFunc0 --
*
* Called for each relevant tile during bridge-lim operations. The
* bridge-lim operation is similar to the bridge operation with the
* difference that the material created to meet the minimum spacing/width
* rules do not overlap the limiting layers.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* May paint into cifNewPlane
*
* Algorithm (based on maximum horizontal stripes rule):
* This function grows dimentions of tiles to meet a minimimum width rule (only
* applies to vertical or horizontal directions). This is done in two steps:
* 1. Adjust tile width to accomplish the minimimum width rule, limited by
* the constraint layers.
* 2. Search top and bottom tiles of same type, for each segment verify if
* height meets the minimimum value, if not, adjust the segment height
* but do not paint over limiting layer tiles.
* ----------------------------------------------------------------------------
*/
int
cifBridgeLimFunc0(tile, brlims)
Tile *tile;
BridgeLimStruct *brlims;
{
Plane *plane = brlims->plane;
Rect area, parea;
int minDistance = brlims->bridge->br_width;
int width, height, ybot0, tp2lim;
Tile *tp, *tp2;
TiToRect(tile, &area);
/* Check whole tile for minimum width */
width = area.r_xtop - area.r_xbot;
if (width < minDistance)
{
area.r_xbot = area.r_xtop - minDistance;
if (!bridgeLimSrTiles(brlims, &area, TRUE))
{
area.r_xbot = MIN(LEFT(tile), xOverlap);
area.r_xtop = area.r_xbot + minDistance;
}
}
/* If there is another tile on top or bottom, and the height is */
/* less than minimum, then extend height in the direction of */
/* the bordering tile. Otherwise, if the height is less than */
/* minimum, then grow considering the limiting layers. */
height = area.r_ytop - area.r_ybot;
if (height < minDistance)
{
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
{
tp2lim = MAX(LEFT(tp), area.r_xbot);
for (tp2 = RT(tile); RIGHT(tp2) > tp2lim; tp2 = BL(tp2))
if (LEFT(tp2) < RIGHT(tp))
{
parea.r_xbot = MAX(LEFT(tp2), tp2lim);
parea.r_xtop = MIN(MIN(RIGHT(tp2), RIGHT(tp)), area.r_xtop);
if (TiGetBottomType(tp2) == TiGetTopType(tile))
parea.r_ytop = TOP(tp2);
else
parea.r_ytop = area.r_ytop;
if (TiGetTopType(tp) == TiGetBottomType(tile))
ybot0 = BOTTOM(tp);
else
ybot0 = area.r_ybot;
height = parea.r_ytop - ybot0;
if (height < minDistance)
{
parea.r_ybot = parea.r_ytop - minDistance;
if (!bridgeLimSrTiles(brlims, &parea, TRUE))
{
parea.r_ybot = MIN(ybot0 , yOverlap);
parea.r_ytop = parea.r_ybot + minDistance;
}
DBPaintPlane(cifPlane, &parea, CIFPaintTable, (PaintUndoInfo *) NULL);
}
}
}
}
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
return 0;
}
/*
*-----------------------------------------------------------------------
* Callback function for cifBridgeLimFunc1 and cifBridgeLimFunc2 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
bridgeLimCheckFunc(tile, brlimcs)
Tile *tile;
BridgeLimCheckStruct *brlimcs;
{
int dir = brlimcs->direction;
Tile *self = brlimcs->tile;
Tile *tp1, *tp2;
TileType checktype = brlimcs->checktype;
long sqdistance = brlimcs->sqdistance;
int dx, dy;
long sqcheck;
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))
{
dx = LEFT(tile) - RIGHT(self);
dy = BOTTOM(self) - TOP(tile);
if ((dx > 0) && (dy > 0))
{
sqcheck = (long)dx*dx + (long)dy*dy;
if (sqcheck >= sqdistance)
return 0;
}
brlimcs->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))
{
dx = LEFT(self) - RIGHT(tile);
dy = BOTTOM(self) - TOP(tile);
if ((dx > 0) && (dy > 0))
{
sqcheck = (long)dx*dx + (long)dy*dy;
if (sqcheck >= sqdistance)
return 0;
}
brlimcs->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))
{
dx = LEFT(tile) - RIGHT(self);
dy = BOTTOM(tile) - TOP(self);
if ((dx > 0) && (dy > 0))
{
sqcheck = (long)dx*dx + (long)dy*dy;
if (sqcheck >= sqdistance)
return 0;
}
brlimcs->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))
{
dx = LEFT(self) - RIGHT(tile);
dy = BOTTOM(tile) - TOP(self);
if ((dx > 0) && (dy > 0))
{
sqcheck = (long)dx*dx + (long)dy*dy;
if (sqcheck >= sqdistance)
return 0;
}
brlimcs->violator = tile;
return 1; /* Violator found */
}
break;
}
return 0; /* Nothing found here, so keep going */
}
/*
*-----------------------------------------------------------------------
* Callback function used in bridge-lim operations to do not paint areas
* where new bridge overlaps the limiting layer tiles.
*-----------------------------------------------------------------------
*/
int
bridgeErase(brlims, area)
BridgeLimStruct *brlims; /* Bridge-lim structure. */
Rect *area; /* Area of Magic paint to consider. */
{
TileTypeBitMask maskBits;
TileType t;
int i;
Plane **temps = brlims->temps;
for (i = PL_DRC_CHECK; i < DBNumPlanes; i++)
{
maskBits = DBPlaneTypes[i];
TTMaskAndMask(&maskBits, &brlims->co_paintMask);
if (!TTMaskEqual(&maskBits, &DBZeroTypeBits))
if (DBSrPaintArea((Tile *) NULL, brlims->def->cd_planes[i], area, &brlims->co_paintMask, cifPaintFunc, CIFEraseTable))
return 0;
}
for (t = 0; t < TT_MAXTYPES; t++, temps++)
if (TTMaskHasType(&brlims->co_cifMask, t))
if (DBSrPaintArea((Tile *) NULL, *temps, area, &CIFSolidBits, cifPaintFunc, CIFEraseTable))
return 0;
return 1; //Nothing found
}
/*
* ----------------------------------------------------------------------------
*
* cifBridgeLimFunc1 --
*
* Called for each relevant tile during bridge-lim operations. The
* bridge-lim operation is similar to the bridge operation with the
* difference that the material created to meet the minimum spacing/width
* rules do not overlap the limiting layers.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* May paint into cifNewPlane
* ----------------------------------------------------------------------------
*/
int
cifBridgeLimFunc1(tile, brlims)
Tile *tile;
BridgeLimStruct *brlims;
{
Plane *plane = brlims->plane;
Rect area;
Tile *tp1, *tp2, *tpx;
int width = brlims->bridge->br_width;
int spacing = growDistance;
BridgeLimCheckStruct brlimcs;
brlimcs.sqdistance = (long) spacing * spacing;
/* 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);
area.r_xtop = RIGHT(tile) + spacing;
area.r_ybot = TOP(tile);
area.r_ytop = TOP(tile) + spacing;
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_SW;
brlimcs.checktype = TT_SPACE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&CIFSolidBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx) + width);
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx));
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile));
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile) - width);
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* First option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_ytop = TOP(tile);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xbot = LEFT(tpx);
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx));
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx));
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx) + width);
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile) - width);
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile));
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* Second option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_ybot = BOTTOM(tpx);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xtop = RIGHT(tile);
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile));
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
/* Last option (Limiting tiles are present on both sides, those areas must be excluded from the bridge)*/
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx) + width);
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx) + width);
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile) - width);
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile) - width);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
bridgeErase(brlims, &area);
}
}
}
}
/* 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);
area.r_ybot = BOTTOM(tile) - spacing;
area.r_ytop = BOTTOM(tile);
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_NE;
brlimcs.checktype = TT_SPACE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&CIFSolidBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile) + width);
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile));
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx));
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx) - width);
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* First option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_ytop = TOP(tpx);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xbot = LEFT(tile);
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile));
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile));
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile) + width);
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx) - width);
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx));
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* Second option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_ybot = BOTTOM(tile);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xtop = RIGHT(tpx);
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx));
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
/* Last option (Limiting tiles are present on both sides, those areas must be excluded from the bridge)*/
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile) + width);
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile) + width);
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx) - width);
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx) - width);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
bridgeErase(brlims, &area);
}
}
}
}
/* 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);
area.r_xtop = RIGHT(tile) + spacing;
area.r_ybot = BOTTOM(tile) - spacing;
area.r_ytop = BOTTOM(tile);
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_NW;
brlimcs.checktype = TT_SPACE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&CIFSolidBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx));
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx) - width);
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile) - width);
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile));
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* First option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_xtop = RIGHT(tile);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx));
area.r_ytop = TOP(tpx);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx) + width);
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx));
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile));
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile) + width);
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* Second option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_xbot = LEFT(tpx);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile));
area.r_ybot = BOTTOM(tile);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
/* Last option (Limiting tiles are present on both sides, those areas must be excluded from the bridge)*/
area.r_xtop = MAX(RIGHT(tile), LEFT(tpx) + width);
area.r_ybot = MIN(BOTTOM(tile), TOP(tpx) - width);
area.r_xbot = MIN(LEFT(tpx), RIGHT(tile) - width);
area.r_ytop = MAX(TOP(tpx), BOTTOM(tile) + width);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
bridgeErase(brlims, &area);
}
}
}
}
/* 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);
area.r_ybot = TOP(tile);
area.r_ytop = TOP(tile) + spacing;
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_SE;
brlimcs.checktype = TT_SPACE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&CIFSolidBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile));
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile) - width);
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx) - width);
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx));
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* First option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_xtop = RIGHT(tpx);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile));
area.r_ytop = TOP(tile);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile) + width);
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile));
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx));
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx) + width);
if (bridgeLimSrTiles(brlims, &area, FALSE))
{
/* Second option of bridge can be implemented (there are not limiting tiles in the area)*/
area.r_xbot = LEFT(tile);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx));
area.r_ybot = BOTTOM(tpx);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
}
else
{
/* Last option (Limiting tiles are present on both sides, those areas must be excluded from the bridge)*/
area.r_xtop = MAX(RIGHT(tpx), LEFT(tile) + width);
area.r_ybot = MIN(BOTTOM(tpx), TOP(tile) - width);
area.r_xbot = MIN(LEFT(tile), RIGHT(tpx) - width);
area.r_ytop = MAX(TOP(tile), BOTTOM(tpx) + width);
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
bridgeErase(brlims, &area);
}
}
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
* cifBridgeLimFunc2 --
*
* Called for each relevant tile during bridge-lim operations. The
* bridge-lim operation is similar to the bridge operation with the
* difference that the material created to meet the minimum spacing/width
* rules do not overlap the limiting layers.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* May paint into cifNewPlane
* ----------------------------------------------------------------------------
*/
int
cifBridgeLimFunc2(tile, brlims)
Tile *tile;
BridgeLimStruct *brlims;
{
Plane *plane = brlims->plane;
Rect area;
Tile *tp1, *tp2, *tpx;
int width = brlims->bridge->br_width;
int thirdOption;
int spacing = growDistance;
BridgeLimCheckStruct brlimcs;
brlimcs.sqdistance = (long) width * width;
/* 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);
area.r_xtop = RIGHT(tile) + width;
area.r_ybot = TOP(tile);
area.r_ytop = TOP(tile) + width;
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_SW;
brlimcs.checktype = CIF_SOLIDTYPE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&DBSpaceBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = RIGHT(tile);
area.r_ytop = TOP(tile);
area.r_xbot = LEFT(tpx) - width;
area.r_ybot = BOTTOM(tpx) - width;
thirdOption = 0;
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xtop = RIGHT(tile) + width;
area.r_ytop = TOP(tile) + width;
area.r_xbot = LEFT(tpx);
area.r_ybot = BOTTOM(tpx);
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xbot = LEFT(tpx) - width;
area.r_ybot = BOTTOM(tpx) - width;
thirdOption = 1;
}
}
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
if (thirdOption)
bridgeErase(brlims, &area);
}
}
/* 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);
area.r_ybot = BOTTOM(tile) - width;
area.r_ytop = BOTTOM(tile);
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_NE;
brlimcs.checktype = CIF_SOLIDTYPE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&DBSpaceBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = RIGHT(tpx);
area.r_ytop = TOP(tpx);
area.r_xbot = LEFT(tile) - width;
area.r_ybot = BOTTOM(tile) - width;
thirdOption = 0;
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xtop = RIGHT(tpx) + width;
area.r_ytop = TOP(tpx) + width;
area.r_xbot = LEFT(tile);
area.r_ybot = BOTTOM(tile);
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xbot = LEFT(tile) - width;
area.r_ybot = BOTTOM(tile) - width;
thirdOption = 1;
}
}
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
if (thirdOption)
bridgeErase(brlims, &area);
}
}
/* 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);
area.r_xtop = RIGHT(tile) + width;
area.r_ybot = BOTTOM(tile) - width;
area.r_ytop = BOTTOM(tile);
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_NW;
brlimcs.checktype = CIF_SOLIDTYPE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&DBSpaceBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = RIGHT(tile) + width;
area.r_ytop = TOP(tpx);
area.r_xbot = LEFT(tpx);
area.r_ybot = BOTTOM(tile) - width;
thirdOption = 0;
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xtop = RIGHT(tile);
area.r_ytop = TOP(tpx) + width;
area.r_xbot = LEFT(tpx) - width;
area.r_ybot = BOTTOM(tile);
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xtop = RIGHT(tile) + width;
area.r_ybot = BOTTOM(tile) - width;
thirdOption = 1;
}
}
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
if (thirdOption)
bridgeErase(brlims, &area);
}
}
/* 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);
area.r_ybot = TOP(tile);
area.r_ytop = TOP(tile) + width;
/* Find violator tiles */
brlimcs.tile = tile;
brlimcs.direction = BRIDGE_SE;
brlimcs.checktype = CIF_SOLIDTYPE;
if (DBSrPaintArea((Tile *) NULL, plane, &area,
&DBSpaceBits, bridgeLimCheckFunc, (ClientData)&brlimcs) == 1)
{
tpx = brlimcs.violator;
area.r_xtop = RIGHT(tpx) + width;
area.r_ytop = TOP(tile);
area.r_xbot = LEFT(tile);
area.r_ybot = BOTTOM(tpx) - width;
thirdOption = 0;
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xtop = RIGHT(tpx);
area.r_ytop = TOP(tile) + width;
area.r_xbot = LEFT(tile) - width;
area.r_ybot = BOTTOM(tpx);
if (!bridgeLimSrTiles(brlims, &area, FALSE))
{
area.r_xtop = RIGHT(tpx) + width;
area.r_ybot = BOTTOM(tpx) - width;
thirdOption = 1;
}
}
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
if (thirdOption)
bridgeErase(brlims, &area);
}
}
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -3828,6 +4653,7 @@ CIFGenLayer(op, area, cellDef, origDef, temps, clientdata)
char *netname;
BloatStruct bls;
BridgeStruct brs;
BridgeLimStruct brlims;
BridgeData *bridge;
int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ?
cifGrowEuclideanFunc : cifGrowFunc;
@ -4052,6 +4878,32 @@ CIFGenLayer(op, area, cellDef, origDef, temps, clientdata)
nextPlane = temp;
break;
case CIFOP_BRIDGELIM:
growDistance = op->co_distance;
DBClearPaintPlane(nextPlane);
cifPlane = nextPlane;
cifScale = 1;
brlims.bridge = (BridgeData *)op->co_client;
brlims.def = cellDef;
brlims.temps = temps;
brlims.co_paintMask = op->co_paintMask;
brlims.co_cifMask = op->co_cifMask;
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifBridgeLimFunc0, (ClientData)&brlims);
temp = curPlane;
curPlane = nextPlane;
brlims.plane = curPlane;
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifBridgeLimFunc1, (ClientData)&brlims);
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&DBSpaceBits, cifBridgeLimFunc2, (ClientData)&brlims);
curPlane = nextPlane;
nextPlane = temp;
break;
case CIFOP_BLOAT:
cifPlane = curPlane;
cifSrTiles(op, area, cellDef, temps,

View File

@ -141,6 +141,7 @@ typedef struct cifop
* 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
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
*/
#define CIFOP_AND 1
@ -164,6 +165,8 @@ typedef struct cifop
#define CIFOP_COPYUP 19
#define CIFOP_CLOSE 20
#define CIFOP_BRIDGE 21
#define CIFOP_BRIDGELIM 22
/* Added by Tim 10/21/2004 */
/* The following structure is used to pass information on how to draw

View File

@ -1058,6 +1058,8 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_CLOSE;
else if (strcmp(argv[0], "bridge") == 0)
newOp->co_opcode = CIFOP_BRIDGE;
else if (strcmp(argv[0], "bridge-lim") == 0)
newOp->co_opcode = CIFOP_BRIDGELIM;
else
{
TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1107,6 +1109,26 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_client = (ClientData)bridge;
break;
case CIFOP_BRIDGELIM:
if (argc != 4) 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;
}
cifParseLayers(argv[3], CIFCurStyle, &newOp->co_paintMask, &newOp->co_cifMask,FALSE);
newOp->co_client = (ClientData)bridge;
break;
case CIFOP_BLOATALL:
if (argc != 3) goto wrongNumArgs;
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
@ -1572,6 +1594,7 @@ cifComputeRadii(layer, des)
break;
case CIFOP_BRIDGE: break;
case CIFOP_BRIDGELIM: break;
case CIFOP_SQUARES: break;
case CIFOP_SQUARES_G: break;
}
@ -1831,6 +1854,7 @@ CIFTechFinal()
case CIFOP_MAXRECT:
case CIFOP_NET:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
bridge = (BridgeData *)op->co_client;
c = FindGCF(style->cs_scaleFactor,
@ -1928,6 +1952,7 @@ CIFTechFinal()
case CIFOP_ANDNOT:
case CIFOP_SHRINK:
case CIFOP_CLOSE:
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
needThisLayer = TRUE;
break;
@ -2359,6 +2384,7 @@ CIFTechOutputScale(n, d)
case CIFOP_MAXRECT:
case CIFOP_NET:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
bridge = (BridgeData *)op->co_client;
bridge->br_width *= d;
@ -2463,6 +2489,7 @@ CIFTechOutputScale(n, d)
if (bloats->bl_distance[j] != 0)
bloats->bl_distance[j] /= lexpand;
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
bridge = (BridgeData *)op->co_client;
bridge->br_width /= lexpand;