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 <stdlib.h> /* for abs() */
#include <math.h> /* for ceil() and sqrt() */ #include <math.h> /* for ceil() and sqrt() */
#include <ctype.h> #include <ctype.h>
#include <string.h> /* for strcmp() */
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
@ -5136,12 +5137,13 @@ CIFGenLayer(
CIFSquaresInfo csi; CIFSquaresInfo csi;
SearchContext scx; SearchContext scx;
TileType ttype; TileType ttype;
char *netname; char *netname, *text;
Label *label;
BloatStruct bls; BloatStruct bls;
BridgeStruct brs; BridgeStruct brs;
BridgeLimStruct brlims; BridgeLimStruct brlims;
BridgeData *bridge; BridgeData *bridge;
BloatData *bloats; BloatData *bloats, locbloat;
bool hstop = FALSE; bool hstop = FALSE;
PropertyRecord *proprec; PropertyRecord *proprec;
char *propvalue; char *propvalue;
@ -5601,6 +5603,105 @@ CIFGenLayer(
} }
break; 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: case CIFOP_BOUNDARY:
if (hier) 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_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_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_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 #define CIFOP_AND 1
@ -174,6 +175,7 @@ typedef struct cifop
#define CIFOP_BRIDGELIM 24 #define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25 #define CIFOP_MASKHINTS 25
#define CIFOP_NOTSQUARE 26 #define CIFOP_NOTSQUARE 26
#define CIFOP_LABELED 27
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */ /* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */ #define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */

View File

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

View File

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

View File

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