Implemented first part of "mask hints", a method to allow mask
layers that are normally automatically generated to be supplemented with additional geometry in the form of properties. The first commit implements a CIF operator "mask-hints" that tells CIFGenLayer that additional geometry may be specified with a property named "MASKHINTS_" plus the name passed to the operator as its only argument. A more extensive commit to be done will allow this operator to be used on cifinput to use mask hints to retain the exact geometry of mask layers used in the input file.
This commit is contained in:
parent
2b513eb3bb
commit
ea9d8cc3e5
58
cif/CIFgen.c
58
cif/CIFgen.c
|
|
@ -4673,6 +4673,9 @@ CIFGenLayer(op, area, cellDef, origDef, temps, hier, clientdata)
|
|||
BridgeData *bridge;
|
||||
BloatData *bloats;
|
||||
bool hstop = FALSE;
|
||||
char *propvalue;
|
||||
bool found;
|
||||
|
||||
int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ?
|
||||
cifGrowEuclideanFunc : cifGrowFunc;
|
||||
|
||||
|
|
@ -5079,9 +5082,6 @@ CIFGenLayer(op, area, cellDef, origDef, temps, hier, clientdata)
|
|||
|
||||
if (origDef && (origDef->cd_flags & CDFIXEDBBOX))
|
||||
{
|
||||
char *propvalue;
|
||||
bool found;
|
||||
|
||||
propvalue = (char *)DBPropGet(origDef, "FIXED_BBOX", &found);
|
||||
if (!found) break;
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
|
|
@ -5138,6 +5138,58 @@ CIFGenLayer(op, area, cellDef, origDef, temps, hier, clientdata)
|
|||
CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||
break;
|
||||
|
||||
/* The CIFOP_MASKHINTS operator checks the current cell for */
|
||||
/* a property with "MASKHINTS_" followed by the name saved */
|
||||
/* in the co_client record. If there is such a property, */
|
||||
/* then the property value is parsed for geometry in */
|
||||
/* internal units, grouped in sets of four values llx lly */
|
||||
/* urx ury. */
|
||||
|
||||
case CIFOP_MASKHINTS:
|
||||
{
|
||||
int j, numfound;
|
||||
char propname[512];
|
||||
char *propptr;
|
||||
char *layername = (char *)op->co_client;
|
||||
|
||||
sprintf(propname, "MASKHINTS_%s", layername);
|
||||
|
||||
propvalue = (char *)DBPropGet(origDef, propname, &found);
|
||||
if (!found) break; /* No mask hints available */
|
||||
propptr = propvalue;
|
||||
while (TRUE)
|
||||
{
|
||||
numfound = sscanf(propptr, "%d %d %d %d",
|
||||
&bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop);
|
||||
|
||||
if (numfound != 4)
|
||||
{
|
||||
/* To do: Allow keyword "rect", "tri", or "poly"
|
||||
* at the start of the list and parse accordingly.
|
||||
* For now, this only flags an error.
|
||||
*/
|
||||
TxError("MASKHINTS_%s: Cannot read rectangle values.\n",
|
||||
propname);
|
||||
break;
|
||||
}
|
||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||
bbox.r_xbot *= cifScale;
|
||||
bbox.r_xtop *= cifScale;
|
||||
bbox.r_ybot *= cifScale;
|
||||
bbox.r_ytop *= cifScale;
|
||||
cifScale = 1;
|
||||
DBNMPaintPlane(cifPlane, CIF_SOLIDTYPE, &bbox,
|
||||
CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
while (*propptr && isspace(*propptr)) propptr++;
|
||||
while (*propptr && !isspace(*propptr)) propptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ typedef struct cifop
|
|||
* 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
|
||||
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
|
||||
*/
|
||||
|
||||
#define CIFOP_AND 1
|
||||
|
|
@ -166,6 +167,7 @@ typedef struct cifop
|
|||
#define CIFOP_CLOSE 20
|
||||
#define CIFOP_BRIDGE 21
|
||||
#define CIFOP_BRIDGELIM 22
|
||||
#define CIFOP_MASKHINTS 23
|
||||
|
||||
|
||||
/* Added by Tim 10/21/2004 */
|
||||
|
|
@ -224,12 +226,9 @@ typedef struct
|
|||
*
|
||||
* CIF_TEMP: Means that this is a temporary layer used to build
|
||||
* up CIF information. It isn't output in the CIF file.
|
||||
* CIF_BBOX_TOP: Indicates that the bounding box rectangle should
|
||||
* only be generated if the cell is a top-level cell.
|
||||
*/
|
||||
|
||||
#define CIF_TEMP 1
|
||||
#define CIF_BBOX_TOP 2
|
||||
|
||||
/* The following data structure describes a complete set of CIF
|
||||
* layers. The number of CIF layers (MAXCIFLAYERS) must not be
|
||||
|
|
|
|||
|
|
@ -1054,6 +1054,8 @@ CIFTechLine(sectionName, argc, argv)
|
|||
newOp->co_opcode = CIFOP_MAXRECT;
|
||||
else if (strcmp(argv[0], "boundary") == 0)
|
||||
newOp->co_opcode = CIFOP_BOUNDARY;
|
||||
else if (strcmp(argv[0], "mask-hints") == 0)
|
||||
newOp->co_opcode = CIFOP_MASKHINTS;
|
||||
else if (strcmp(argv[0], "close") == 0)
|
||||
newOp->co_opcode = CIFOP_CLOSE;
|
||||
else if (strcmp(argv[0], "bridge") == 0)
|
||||
|
|
@ -1247,6 +1249,11 @@ bloatCheck:
|
|||
&newOp->co_cifMask, FALSE);
|
||||
break;
|
||||
|
||||
case CIFOP_MASKHINTS:
|
||||
if (argc != 2) goto wrongNumArgs;
|
||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||
break;
|
||||
|
||||
case CIFOP_MAXRECT:
|
||||
if (argc == 2)
|
||||
{
|
||||
|
|
@ -1537,10 +1544,12 @@ cifComputeRadii(layer, des)
|
|||
|
||||
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
||||
{
|
||||
/* BBOX and NET operators should never be used hierarchically */
|
||||
/* so ignore any grow/shrink operators that come after them. */
|
||||
/* BBOX, NET, 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)
|
||||
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
||||
op->co_opcode == CIFOP_MASKHINTS)
|
||||
break;
|
||||
|
||||
/* If CIF layers are used, switch to the max of current
|
||||
|
|
@ -1565,11 +1574,11 @@ cifComputeRadii(layer, des)
|
|||
|
||||
switch (op->co_opcode)
|
||||
{
|
||||
case CIFOP_AND: break;
|
||||
|
||||
case CIFOP_ANDNOT: break;
|
||||
|
||||
case CIFOP_OR: break;
|
||||
case CIFOP_AND:
|
||||
case CIFOP_ANDNOT:
|
||||
case CIFOP_OR:
|
||||
case CIFOP_MASKHINTS:
|
||||
break;
|
||||
|
||||
case CIFOP_GROW:
|
||||
case CIFOP_GROWMIN:
|
||||
|
|
@ -1850,13 +1859,15 @@ CIFTechFinal()
|
|||
/* 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 uses it for a string. */
|
||||
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
|
||||
/* uses it for a string. */
|
||||
else
|
||||
{
|
||||
switch (op->co_opcode)
|
||||
{
|
||||
case CIFOP_OR:
|
||||
case CIFOP_BBOX:
|
||||
case CIFOP_MASKHINTS:
|
||||
case CIFOP_BOUNDARY:
|
||||
case CIFOP_MAXRECT:
|
||||
case CIFOP_NET:
|
||||
|
|
@ -2388,6 +2399,7 @@ CIFTechOutputScale(n, d)
|
|||
case CIFOP_OR:
|
||||
case CIFOP_BBOX:
|
||||
case CIFOP_BOUNDARY:
|
||||
case CIFOP_MASKHINTS:
|
||||
case CIFOP_MAXRECT:
|
||||
case CIFOP_NET:
|
||||
break;
|
||||
|
|
@ -2502,9 +2514,10 @@ CIFTechOutputScale(n, d)
|
|||
bridge->br_width /= lexpand;
|
||||
break;
|
||||
default:
|
||||
/* op->co_opcode in CIFOP_OR is a pointer copy */
|
||||
/* and in CIFOP_BBOX and CIFOP_MAXRECT is a */
|
||||
/* flag, and in CIFOP_NET is a string. */
|
||||
/* 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. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1775,6 +1775,100 @@ DBSrCellUses(cellDef, func, arg)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/* Structure used by dbScaleProp() and dbMoveProp() */
|
||||
typedef struct _cellpropstruct {
|
||||
Point cps_point;
|
||||
CellDef *cps_def;
|
||||
} CellPropStruct;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* dbScaleProp --
|
||||
*
|
||||
* Callback function for dbScaleCell. Finds properties that represent
|
||||
* internal geometry (FIXED_BBOX and MASKHINTS_*) and scale the values
|
||||
* by the numerator / denominator values passed as a pointer to a Point
|
||||
* structure, where p_x is the numerator value and p_y is the denominator
|
||||
* value.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int dbScaleProp(name, value, cps)
|
||||
char *name;
|
||||
char *value;
|
||||
CellPropStruct *cps;
|
||||
{
|
||||
int scalen, scaled;
|
||||
char *newvalue;
|
||||
Rect r;
|
||||
|
||||
if (!strcmp(name, "FIXED_BBOX") || !strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
/* Scale numerator held in point X value, */
|
||||
/* scale denominator held in point Y value */
|
||||
|
||||
scalen = cps->cps_point.p_x;
|
||||
scaled = cps->cps_point.p_y;
|
||||
|
||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
||||
|
||||
newvalue = (char *)mallocMagic(40);
|
||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||
r.r_xtop, r.r_ytop);
|
||||
DBPropPut(cps->cps_def, name, newvalue);
|
||||
}
|
||||
}
|
||||
return 0; /* Keep enumerating through properties */
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* dbMoveProp --
|
||||
*
|
||||
* Callback function for ??. Finds properties that represent
|
||||
* internal geometry (FIXED_BBOX and MASKHINTS_*) and modifies the values
|
||||
* by the X, Y values passed as a pointer to a Point structure in ClientData.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int dbMoveProp(name, value, cps)
|
||||
char *name;
|
||||
char *value;
|
||||
CellPropStruct *cps;
|
||||
{
|
||||
int origx, origy;
|
||||
char *newvalue;
|
||||
Rect r;
|
||||
|
||||
if (!strcmp(name, "FIXED_BBOX") || !strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
origx = cps->cps_point.p_x;
|
||||
origy = cps->cps_point.p_y;
|
||||
|
||||
DBMovePoint(&r.r_ll, origx, origy);
|
||||
DBMovePoint(&r.r_ur, origx, origy);
|
||||
|
||||
newvalue = (char *)mallocMagic(40);
|
||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||
r.r_xtop, r.r_ytop);
|
||||
DBPropPut(cps->cps_def, name, newvalue);
|
||||
}
|
||||
}
|
||||
return 0; /* Keep enumerating through properties */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -1799,6 +1893,7 @@ dbScaleCell(cellDef, scalen, scaled)
|
|||
LinkedCellUse *luhead, *lu;
|
||||
Plane *newplane;
|
||||
BPlane *cellPlane, *cellPlaneOrig;
|
||||
CellPropStruct cps;
|
||||
|
||||
/* DBCellEnum() attempts to read unavailable celldefs. We don't */
|
||||
/* want to do that here, so check CDAVAILABLE flag first. */
|
||||
|
|
@ -1936,6 +2031,18 @@ donecell:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check all properties for ones with keys beginning with "MASKHINTS_"
|
||||
* or the key "FIXED_BBOX", and scale them by the same amount as all
|
||||
* the geometry.
|
||||
*/
|
||||
|
||||
|
||||
cps.cps_point.p_x = scalen;
|
||||
cps.cps_point.p_y = scaled;
|
||||
cps.cps_def = cellDef;
|
||||
DBPropEnum(cellDef, dbScaleProp, &cps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2023,6 +2130,7 @@ DBMoveCell(cellDef, origx, origy)
|
|||
LinkedCellUse *luhead, *lu;
|
||||
Plane *newplane;
|
||||
BPlane *cellPlane, *cellPlaneOrig;
|
||||
CellPropStruct cps;
|
||||
|
||||
/* Unlike dbScaleCell(), this routine is only run on valid edit defs */
|
||||
|
||||
|
|
@ -2120,31 +2228,15 @@ donecell:
|
|||
DBMovePoint(&cellDef->cd_extended.r_ll, origx, origy);
|
||||
DBMovePoint(&cellDef->cd_extended.r_ur, origx, origy);
|
||||
|
||||
/* If the cell is an abstract view with a fixed bounding box, then */
|
||||
/* adjust the bounding box property to match the new scale. */
|
||||
/* Check all properties for ones with keys beginning with "MASKHINTS_"
|
||||
* or the key "FIXED_BBOX", and move them by the same amount as all
|
||||
* the geometry.
|
||||
*/
|
||||
|
||||
if ((cellDef->cd_flags & CDFIXEDBBOX) != 0)
|
||||
{
|
||||
Rect r;
|
||||
bool found;
|
||||
char *propval;
|
||||
|
||||
propval = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if (sscanf(propval, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
DBMovePoint(&r.r_ll, origx, origy);
|
||||
DBMovePoint(&r.r_ur, origx, origy);
|
||||
|
||||
propval = (char *)mallocMagic(40);
|
||||
sprintf(propval, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||
r.r_xtop, r.r_ytop);
|
||||
DBPropPut(cellDef, "FIXED_BBOX", propval);
|
||||
}
|
||||
}
|
||||
}
|
||||
cps.cps_point.p_x = origx;
|
||||
cps.cps_point.p_y = origy;
|
||||
cps.cps_def = cellDef;
|
||||
DBPropEnum(cellDef, dbMoveProp, &cps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,8 +57,15 @@ DBPropPut(cellDef, name, value)
|
|||
HashEntry *entry;
|
||||
char *oldvalue;
|
||||
|
||||
/* Honor the NOEDIT flag */
|
||||
if (cellDef->cd_flags & CDNOEDIT) return;
|
||||
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
||||
/* the value would be saved in the hash table, so if it is not */
|
||||
/* being used, then it must be freed here. */
|
||||
|
||||
if (cellDef->cd_flags & CDNOEDIT)
|
||||
{
|
||||
freeMagic((char *)value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cellDef->cd_props == (ClientData) NULL)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue