Implemented new cifinput/cifoutput operator "labeled" which operates

like "bloat-all" except starting with a label and expanding into a
type rather than starting with a layer.  This is equivalent to what
many tools refer to as "stamping".
This commit is contained in:
R. Timothy Edwards 2026-03-11 15:06:24 -04:00
parent 7bdd9e1d4f
commit 15943d0cb1
6 changed files with 128 additions and 12 deletions

View File

@ -1 +1 @@
8.3.618
8.3.619

View File

@ -25,6 +25,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include <stdlib.h> /* for abs() */
#include <math.h> /* for ceil() and sqrt() */
#include <ctype.h>
#include <string.h> /* for strcmp() */
#include "utils/magic.h"
#include "utils/geometry.h"
@ -5136,12 +5137,13 @@ CIFGenLayer(
CIFSquaresInfo csi;
SearchContext scx;
TileType ttype;
char *netname;
char *netname, *text;
Label *label;
BloatStruct bls;
BridgeStruct brs;
BridgeLimStruct brlims;
BridgeData *bridge;
BloatData *bloats;
BloatData *bloats, locbloat;
bool hstop = FALSE;
PropertyRecord *proprec;
char *propvalue;
@ -5601,6 +5603,105 @@ CIFGenLayer(
}
break;
case CIFOP_LABELED:
if (hier)
{
hstop = TRUE; /* Stop hierarchical processing */
break;
}
/*
* Find all relevant labels by text matching and then continue
* like CIFOP_BLOATALL. CIFOP_BLOATALL uses a BloatData record
* which is not part of CIFOP_LABELED. Create a BloatData record
* on the fly for each labeled area based on type, and swap it for
* the text, so that cifBloatAllFunc believes this is actually a
* CIFOP_BLOATALL operation. Note that we don't actually care
* what layer the label is attached to (lab_type). We are looking
* for labels whose lab_rect values overlap the types that are given
* in the rule.
*/
cifPlane = curPlane;
bls.op = op;
bls.def = cellDef;
bls.temps = temps;
text = (char *)op->co_client;
bloats = &locbloat;
if (!TTMaskIsZero(&op->co_cifMask))
{
bloats->bl_plane = -1;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
{
if (TTMaskHasType(&op->co_cifMask, ttype))
bloats->bl_distance[ttype] = 1;
else
bloats->bl_distance[ttype] = 0;
}
}
else if (!TTMaskIsZero(&op->co_paintMask))
{
int plane, pmask;
pmask = DBTechTypesToPlanes(&op->co_paintMask);
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
if (PlaneMaskHasPlane(pmask, plane))
break;
bloats->bl_plane = plane;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
{
if (TTMaskHasType(&op->co_paintMask, ttype))
bloats->bl_distance[ttype] = 1;
else
bloats->bl_distance[ttype] = 0;
}
}
/* Replace the client data with the bloat record */
op->co_client = (ClientData)bloats;
if (bloats->bl_plane < 0)
{
/* bl_plane == -1 indicates bloating into a CIF templayer, */
/* so the only connecting type should be CIF_SOLIDTYPE. */
TTMaskSetOnlyType(&bls.connect, CIF_SOLIDTYPE);
}
else
{
int i;
TTMaskZero(&bls.connect);
for (i = 0; i < TT_MAXTYPES; i++)
if (bloats->bl_distance[i] != 0)
TTMaskSetType(&bls.connect, i);
}
for (label = cellDef->cd_labels; label; label = label->lab_next)
if (!strcmp(label->lab_text, text))
cifSrTiles(op, &label->lab_rect, cellDef, temps,
cifBloatAllFunc, (ClientData)&bls);
/* Reset marked tiles */
if (bloats->bl_plane < 0) /* Bloat types are CIF types */
{
bls.temps = temps;
for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++)
if (bloats->bl_distance[ttype] > 0)
(void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect,
&CIFSolidBits, cifProcessResetFunc,
(ClientData)NULL);
}
else
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
(ClientData)NULL);
/* Replace the client data */
op->co_client = (ClientData)text;
break;
case CIFOP_BOUNDARY:
if (hier)
{

View File

@ -146,6 +146,7 @@ typedef struct cifop
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
* CIFOP_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
* CIFOP_LABELED - Added 3/11/26---Find geometry attached to the given text label
*/
#define CIFOP_AND 1
@ -174,6 +175,7 @@ typedef struct cifop
#define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25
#define CIFOP_NOTSQUARE 26
#define CIFOP_LABELED 27
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */

View File

@ -613,7 +613,7 @@ CIFPaintCurrent(
CIFOp *op;
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
&TiPlaneRect, cifReadCellDef, cifReadCellDef,
cifCurReadPlanes, FALSE, (ClientData)NULL);
/* Generate a paint/erase table, then paint from the CIF

View File

@ -332,7 +332,8 @@ cifNewReadStyle(void)
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->crl_ops; op != NULL; op = op->co_next)
{
if (op->co_opcode == CIFOP_MASKHINTS)
if (op->co_opcode == CIFOP_MASKHINTS ||
op->co_opcode == CIFOP_LABELED)
freeMagic((char *)op->co_client);
freeMagic1(&mm1, (char *)op);
}
@ -998,6 +999,8 @@ CIFReadTechLine(
newOp->co_opcode = CIFOP_NOTSQUARE;
else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS;
else if (strcmp(argv[0], "labeled") == 0)
newOp->co_opcode = CIFOP_LABELED;
else
{
TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1028,6 +1031,11 @@ CIFReadTechLine(
if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
break;
case CIFOP_LABELED:
if (argc != 3) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
break;
}
/* Link the new CIFOp onto the list. */

View File

@ -1107,6 +1107,8 @@ CIFTechLine(
newOp->co_opcode = CIFOP_BBOX;
else if (strcmp(argv[0], "net") == 0)
newOp->co_opcode = CIFOP_NET;
else if (strcmp(argv[0], "labeled") == 0)
newOp->co_opcode = CIFOP_LABELED;
else if (strcmp(argv[0], "maxrect") == 0)
newOp->co_opcode = CIFOP_MAXRECT;
else if (strcmp(argv[0], "boundary") == 0)
@ -1357,6 +1359,7 @@ bloatCheck:
bloatDone: break;
case CIFOP_NET:
case CIFOP_LABELED:
if (argc != 3) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
@ -1671,12 +1674,12 @@ cifComputeRadii(
for (op = layer->cl_ops; op != NULL; op = op->co_next)
{
/* BBOX, NET, and MASKHINTS operators should never be used */
/* hierarchically so ignore any grow/shrink operators that */
/* BBOX, NET, LABELED, and MASKHINTS operators should never be */
/* used hierarchically so ignore any grow/shrink operators that */
/* come after them. */
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
op->co_opcode == CIFOP_MASKHINTS)
op->co_opcode == CIFOP_LABELED || op->co_opcode == CIFOP_MASKHINTS)
break;
/* If CIF layers are used, switch to the max of current
@ -1988,8 +1991,8 @@ CIFTechFinal(void)
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
/* of the SquaresData pointer from a following operator. */
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
/* uses it for a string. */
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */
/* CIFOP_LABELED use it for a string. */
else
{
switch (op->co_opcode)
@ -2001,6 +2004,7 @@ CIFTechFinal(void)
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
case CIFOP_LABELED:
break;
case CIFOP_BRIDGELIM:
case CIFOP_BRIDGE:
@ -2536,6 +2540,7 @@ CIFTechOutputScale(
case CIFOP_MAXRECT:
case CIFOP_MANHATTAN:
case CIFOP_NET:
case CIFOP_LABELED:
case CIFOP_INTERACT:
break;
case CIFOP_BRIDGELIM:
@ -2651,8 +2656,8 @@ CIFTechOutputScale(
default:
/* op->co_opcode in CIFOP_OR is a pointer copy, */
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
/* string. */
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */
/* CIFOP_LABELED is a string. */
break;
}
}