diff --git a/VERSION b/VERSION index 7046f048..55013c22 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.96 +8.3.97 diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 5a3d18dc..7a45eb5e 100644 --- a/cif/CIFgen.c +++ b/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; } diff --git a/cif/CIFint.h b/cif/CIFint.h index fcde35e3..e44a17c5 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -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 diff --git a/cif/CIFtech.c b/cif/CIFtech.c index ce939289..af1ed9ad 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -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; } } diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index 8740bf09..5db00d00 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -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; } diff --git a/database/DBprop.c b/database/DBprop.c index 7a72d3e7..76b672cc 100644 --- a/database/DBprop.c +++ b/database/DBprop.c @@ -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) {