magic/plow/PlowRules3.c

401 lines
12 KiB
C

/*
* PlowRules3.c --
*
* Plowing rules: new sliver-avoidance rules.
* These are applied by plowProcessEdge() for each edge that is to be moved.
*
* *********************************************************************
* * 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/plow/PlowRules3.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 "tiles/tile.h"
#include "utils/hash.h"
#include "database/database.h"
#include "utils/undo.h"
#include "plow/plow.h"
#include "plow/plowInt.h"
#include "drc/drc.h"
/* Imports from other rules files */
extern int plowApplyRule();
/* Forward declarations */
int plowInSliverProc();
int scanDown(), scanUp();
int scanDownError(), scanUpError();
/* Argument passed to above filter functions */
struct inarg
{
Rect ina_area; /* Area to search for violations */
Edge *ina_moving; /* Edge causing this search */
TileType ina_t0; /* See comments in the procedures */
int (*ina_proc)(); /* Apply to look for rule violations */
/* Used while appling design rules */
PlowRule *ina_rule; /* Plowing design rule being applied */
int ina_incursion; /* Height of biggest DRC error */
bool ina_cantMove; /* TRUE if couldn't fix some error */
};
/*
* ----------------------------------------------------------------------------
*
* prInSliver --
*
* Avoid introducing slivers because the plow is too small.
* This rule only applies if the plow height is less than the
* maximum design-rule distance DRCTechHalo.
*
* Results:
* None.
*
* Side effects:
* May add edges to the queue of edges to be processed.
*
* ----------------------------------------------------------------------------
*/
void
prInSliver(edge)
Edge *edge; /* Edge being moved */
{
struct inarg inarg;
Rect edgeBorder;
Plane *plane;
if ((edge->e_flags & E_ISINITIAL) == 0
|| edge->e_ytop - edge->e_ybot >= DRCTechHalo)
return;
/* Look down from the top of the edge */
edgeBorder.r_xbot = edge->e_x - 1;
edgeBorder.r_xtop = edge->e_newx;
edgeBorder.r_ybot = edge->e_ytop;
edgeBorder.r_ytop = edge->e_ytop + 1;
plane = plowYankDef->cd_planes[edge->e_pNum];
inarg.ina_moving = edge;
inarg.ina_t0 = (TileType) -1;
inarg.ina_area.r_ytop = edge->e_ybot;
inarg.ina_proc = scanDown;
plowSrFinalArea(plane, &edgeBorder, &DBAllTypeBits, plowInSliverProc,
(ClientData) &inarg);
/* Look up from the bottom of the edge */
edgeBorder.r_ybot = edge->e_ybot - 1;
edgeBorder.r_ytop = edge->e_ybot;
inarg.ina_t0 = (TileType) -1;
inarg.ina_area.r_ybot = edge->e_ytop;
inarg.ina_proc = scanUp;
plowSrFinalArea(plane, &edgeBorder, &DBAllTypeBits, plowInSliverProc,
(ClientData) &inarg);
}
int
plowInSliverProc(tile, inarg)
Tile *tile;
struct inarg *inarg;
{
Edge *movingEdge = inarg->ina_moving;
#ifdef notdef
Edge newEdge;
#endif /* notdef */
TileType t1;
int xtop;
/* Is this the first tile we've seen? */
if (inarg->ina_t0 == (TileType) -1)
{
inarg->ina_t0 = TiGetType(tile);
inarg->ina_area.r_xbot = movingEdge->e_x;
inarg->ina_area.r_xtop = MIN(movingEdge->e_newx, LEADING(tile));
if (LEADING(tile) >= movingEdge->e_newx)
{
(*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE);
return (1);
}
return (0);
}
/* Is this still the same material? */
if (TiGetType(tile) == inarg->ina_t0)
{
/* Extend the edge to the right */
xtop = MIN(movingEdge->e_newx, LEADING(tile));
if (xtop > inarg->ina_area.r_xtop) inarg->ina_area.r_xtop = xtop;
/* Is this the last tile? */
if (LEADING(tile) >= movingEdge->e_newx)
{
(*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE);
return (1);
}
/* Keep looking */
return (0);
}
/* New type of material */
t1 = TiGetType(tile);
/* Can we not slide past the t0 | t1 edge? */
if ((movingEdge->e_ltype != TT_SPACE && movingEdge->e_rtype != TT_SPACE)
|| TTMaskHasType(&PlowCoveredTypes, inarg->ina_t0)
|| TTMaskHasType(&PlowCoveredTypes, t1)
|| inarg->ina_t0 != movingEdge->e_ltype
|| t1 != movingEdge->e_rtype)
{
#ifdef notdef
/* Move a 1-lambda high strip of the t0 | t1 edge */
newEdge.e_x = LEFT(tile);
newEdge.e_newx = movingEdge->e_newx;
newEdge.e_ybot = movingEdge->e_ytop;
newEdge.e_ytop = movingEdge->e_ytop + 1;
newEdge.e_pNum = movingEdge->e_pNum;
newEdge.e_ltype = inarg->ina_t0;
newEdge.e_rtype = t1;
newEdge.e_use = (CellUse *) NULL;
(*plowPropagateProcPtr)(&newEdge);
#endif /* notdef */
(*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE);
return (1);
}
/*
* Search the t0 edge up to the LHS of t1.
* We can only move violation edges to eliminate the errors we find.
*/
(*inarg->ina_proc)(inarg, inarg->ina_t0, FALSE);
/*
* Search the t1 edge as well.
* Move violation edges if possible, but we can move the
* t0 | t1 edge if we can't fix the violations.
*/
inarg->ina_area.r_xbot = inarg->ina_area.r_xtop;
inarg->ina_area.r_xtop = movingEdge->e_newx;
(*inarg->ina_proc)(inarg, t1, TRUE);
return (1);
}
int
scanDown(inarg, type, canMoveInargEdge)
struct inarg *inarg;
TileType type;
bool canMoveInargEdge;
{
TileType ltype = inarg->ina_moving->e_ltype;
Edge *movingEdge = inarg->ina_moving;
TileTypeBitMask badTypes;
PlowRule *pr;
int height;
inarg->ina_incursion = 0;
inarg->ina_cantMove = FALSE;
height = movingEdge->e_ytop - movingEdge->e_ybot;
for (pr = plowSpacingRulesTbl[type][ltype]; pr; pr = pr->pr_next)
{
if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height)
continue;
inarg->ina_area.r_ybot = movingEdge->e_ytop - pr->pr_dist;
inarg->ina_rule = pr;
TTMaskCom2(&badTypes, &pr->pr_oktypes);
plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area,
&badTypes, scanDownError, (ClientData) inarg);
}
for (pr = plowWidthRulesTbl[type][ltype]; pr; pr = pr->pr_next)
{
if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height)
continue;
inarg->ina_area.r_ybot = movingEdge->e_ytop - pr->pr_dist;
inarg->ina_rule = pr;
TTMaskCom2(&badTypes, &pr->pr_oktypes);
plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area,
&badTypes, scanDownError, (ClientData) inarg);
}
#ifdef notdef
/* Move the top edge if necessary */
if (canMoveInargEdge && inarg->ina_cantMove)
{
struct applyRule ar;
Rect shadowRect;
shadowRect.r_xbot = inarg->ina_area.r_xbot - 1;
shadowRect.r_ybot = movingEdge->e_ytop;
shadowRect.r_xtop = movingEdge->e_newx;
shadowRect.r_ytop = movingEdge->e_ytop + inarg->ina_incursion;
ar.ar_moving = movingEdge;
ar.ar_rule = (PlowRule *) NULL;
plowSrShadow(movingEdge->e_pNum, &shadowRect,
DBZeroTypeBits, plowApplyRule, (ClientData) &ar);
}
#endif /* notdef */
return 0;
}
int
scanDownError(tile, inarg)
Tile *tile;
struct inarg *inarg;
{
Rect atomRect;
int incursion;
incursion = MIN(TOP(tile), inarg->ina_area.r_ytop) - inarg->ina_area.r_ybot;
if (incursion > inarg->ina_incursion)
inarg->ina_incursion = incursion;
/*
* The following relies on maximal horizontal strips.
* If the violating tile extends to the left of the area
* we're checking, we can't eliminate the violation by
* moving its LHS.
*/
if (LEFT(tile) < inarg->ina_area.r_xbot)
{
inarg->ina_cantMove = TRUE;
return (0);
}
/*
* Eliminate the violation by moving the LHS of
* the violating tile.
*/
atomRect.r_xbot = LEFT(tile);
atomRect.r_xtop = inarg->ina_moving->e_newx;
atomRect.r_ybot = MAX(BOTTOM(tile), inarg->ina_area.r_ybot);
atomRect.r_ytop = MIN(TOP(tile), inarg->ina_area.r_ytop);
(void) plowAtomize(inarg->ina_rule->pr_pNum, &atomRect,
plowPropagateProcPtr, (ClientData) NULL);
return (0);
}
int
scanUp(inarg, type, canMoveInargEdge)
struct inarg *inarg;
TileType type;
bool canMoveInargEdge;
{
TileType ltype = inarg->ina_moving->e_ltype;
Edge *movingEdge = inarg->ina_moving;
TileTypeBitMask badTypes;
PlowRule *pr;
int height;
inarg->ina_incursion = 0;
inarg->ina_cantMove = FALSE;
height = movingEdge->e_ytop - movingEdge->e_ybot;
for (pr = plowSpacingRulesTbl[type][ltype]; pr; pr = pr->pr_next)
{
if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height)
continue;
inarg->ina_area.r_ytop = movingEdge->e_ybot + pr->pr_dist;
inarg->ina_rule = pr;
TTMaskCom2(&badTypes, &pr->pr_oktypes);
plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area,
&badTypes, scanUpError, (ClientData) inarg);
}
for (pr = plowWidthRulesTbl[type][ltype]; pr; pr = pr->pr_next)
{
if ((pr->pr_flags & PR_PENUMBRAONLY) || pr->pr_dist <= height)
continue;
inarg->ina_area.r_ytop = movingEdge->e_ybot + pr->pr_dist;
inarg->ina_rule = pr;
TTMaskCom2(&badTypes, &pr->pr_oktypes);
plowSrFinalArea(plowYankDef->cd_planes[pr->pr_pNum], &inarg->ina_area,
&badTypes, scanUpError, (ClientData) inarg);
}
#ifdef notdef
/* Move the bottom edge if necessary */
if (canMoveInargEdge && inarg->ina_cantMove)
{
struct applyRule ar;
Rect shadowRect;
shadowRect.r_xbot = inarg->ina_area.r_xbot - 1;
shadowRect.r_ybot = movingEdge->e_ybot - inarg->ina_incursion;
shadowRect.r_xtop = movingEdge->e_newx;
shadowRect.r_ytop = movingEdge->e_ybot;
ar.ar_moving = movingEdge;
ar.ar_rule = (PlowRule *) NULL;
plowSrShadow(movingEdge->e_pNum, &shadowRect,
DBZeroTypeBits, plowApplyRule, (ClientData) &ar);
}
#endif /* notdef */
return 0;
}
int
scanUpError(tile, inarg)
Tile *tile;
struct inarg *inarg;
{
Rect atomRect;
int incursion;
incursion = inarg->ina_area.r_ytop;
incursion -= MAX(BOTTOM(tile), inarg->ina_area.r_ybot);
if (incursion > inarg->ina_incursion)
inarg->ina_incursion = incursion;
/*
* The following relies on maximal horizontal strips.
* If the violating tile extends to the left of the area
* we're checking, we can't eliminate the violation by
* moving its LHS.
*/
if (LEFT(tile) < inarg->ina_area.r_xbot)
{
inarg->ina_cantMove = TRUE;
return (0);
}
/*
* Eliminate the violation by moving the LHS of
* the violating tile.
*/
atomRect.r_xbot = LEFT(tile);
atomRect.r_xtop = inarg->ina_moving->e_newx;
atomRect.r_ybot = MAX(BOTTOM(tile), inarg->ina_area.r_ybot);
atomRect.r_ytop = MIN(TOP(tile), inarg->ina_area.r_ytop);
(void) plowAtomize(inarg->ina_rule->pr_pNum, &atomRect,
plowPropagateProcPtr, (ClientData) NULL);
return (0);
}
int
plowSrFinalArea(plane, area, okTypes, proc, cdata)
Plane *plane;
Rect *area;
TileTypeBitMask *okTypes;
int (*proc)();
ClientData cdata;
{
return (DBSrPaintArea((Tile *) NULL, plane, area, okTypes, proc, cdata));
}