Files
magic/plow/PlowRules3.c
T
R. Timothy Edwards 516c9d7635 First cut of pulling the TT_SIDE bit out of the tile database
and forcing it to be passed as an argument to all the callback
functions for the search routines that require it.  Magic now
compiles and runs with the new code, but there are a number of
known issues that need to be fixed up.  Committing now so that
I can rebase on the last update to the master branch.
2026-01-09 12:05:03 -05:00

402 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, dinfo, inarg)
Tile *tile;
TileType dinfo; /* (unused) */
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));
}