diff --git a/VERSION b/VERSION index 37e1482b..b2898ae9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.617 +8.3.618 diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 4c0b25fa..8f8cc362 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -5044,6 +5044,47 @@ cifInteractingRegions( } } +/* + * ---------------------------------------------------------------------------- + * + * cifCopyPropPlaneFunc -- + * + * Copy the contents of a plane saved as a plane-type property into the + * current CIF plane. The property plane is in magic internal + * coordinates, so each tile needs to be scaled and redrawn into the + * current CIF plane. + * + * Results: + * Zero to keep the search going + * + * Side effects: + * Copies translated geometry into the target plane. + * + * ---------------------------------------------------------------------------- + */ + +int +cifCopyPropPlaneFunc(Tile *tile, + TileType dinfo, + Plane *curPlane) +{ + Rect bbox; + + TiToRect(tile, &bbox); + + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + bbox.r_xbot *= cifScale; + bbox.r_ybot *= cifScale; + bbox.r_xtop *= cifScale; + bbox.r_ytop *= cifScale; + + cifScale = 1; + DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox, + CIFPaintTable, (PaintUndoInfo *)NULL); + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -5646,6 +5687,7 @@ CIFGenLayer( int n; char propname[512]; char *layername = (char *)op->co_client; + Tile *t; snprintf(propname, 512, "MASKHINTS_%s", layername); @@ -5653,30 +5695,11 @@ CIFGenLayer( proprec = DBPropGet(cellDef, propname, &found); if (!found) break; /* No mask hints available */ - if (proprec->prop_type == PROPERTY_TYPE_DIMENSION) - { - for (n = 0; n < proprec->prop_len; n += 4) - { - if ((n + 3) >= proprec->prop_len) break; - - cifPlane = curPlane; - cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; - - bbox.r_xbot = proprec->prop_value.prop_integer[n]; - bbox.r_ybot = proprec->prop_value.prop_integer[n + 1]; - bbox.r_xtop = proprec->prop_value.prop_integer[n + 2]; - bbox.r_ytop = proprec->prop_value.prop_integer[n + 3]; - - bbox.r_xbot *= cifScale; - bbox.r_ybot *= cifScale; - bbox.r_xtop *= cifScale; - bbox.r_ytop *= cifScale; - - cifScale = 1; - DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox, - CIFPaintTable, (PaintUndoInfo *)NULL); - } - } + ASSERT (proprec->prop_type == PROPERTY_TYPE_PLANE, "CIFGenLayer"); + t = PlaneGetHint(proprec->prop_value.prop_plane); + DBSrPaintArea(t, proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, + cifCopyPropPlaneFunc, (ClientData)curPlane); } break; diff --git a/cif/CIFhier.c b/cif/CIFhier.c index fe74ab7c..fed584f6 100644 --- a/cif/CIFhier.c +++ b/cif/CIFhier.c @@ -209,16 +209,52 @@ typedef struct _maskHintsData { Transform *mh_trans; CellDef *mh_def; + Plane *mh_plane; } MaskHintsData; +/* + * ---------------------------------------------------------------------------- + * + * cifCopyMaskHintFunc -- + * + * Callback function used by cifFlatMaskHints. Transforms a tile + * from the original plane and paints it into the target plane, + * both of which are properties. + * + * Results: + * Zero to keep the search going. + * + * Side effects: + * Paints geometry into the target plane. + * + * ---------------------------------------------------------------------------- + */ + +int +cifCopyMaskHintFunc(Tile *tile, + TileType dinfo, + ClientData cdata) +{ + MaskHintsData *mhd = (MaskHintsData *)cdata; + Rect r, newr; + + TiToRect(tile, &r); + + /* Transform tile area to coordinates of mhd->mh_plane and paint */ + GeoTransRect(mhd->mh_trans, &r, &newr); + DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL); + + return 0; +} + /* * ---------------------------------------------------------------------------- * * cifFlatMaskHints -- * * Copy a mask hint into a flattened cell by transforming it into the - * coordinate system of the flattened cell, and adding it to the - * property list of the flattened cell. + * coordinate system of the flattened cell, and painting it into the + * property plane of the flattened cell. * * Returns: * 0 to keep the search going. @@ -240,6 +276,7 @@ cifFlatMaskHints( bool propfound; int i, lastlen, numvals; PropertyRecord *newproprec, *oldproprec; + Plane *plane; if (!strncmp(name, "MASKHINTS_", 10)) { @@ -247,53 +284,24 @@ cifFlatMaskHints( oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound); if (propfound) { - newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + - (oldproprec->prop_len + proprec->prop_len - 2) * sizeof(int)); - newproprec->prop_len = oldproprec->prop_len + proprec->prop_len; - newproprec->prop_type = PROPERTY_TYPE_DIMENSION; + ASSERT(oldproprec->prop_value.prop_type == PROPERTY_TYPE_PLANE, + "cifFlatMaskHints"); + plane = oldproprec->prop_value.prop_plane; } else { - newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + - (proprec->prop_len - 2) * sizeof(int)); - newproprec->prop_len = proprec->prop_len; - newproprec->prop_type = PROPERTY_TYPE_DIMENSION; + newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + newproprec->prop_len = 0; /* (unused) */ + newproprec->prop_type = PROPERTY_TYPE_PLANE; + plane = DBNewPlane((ClientData)TT_SPACE); + newproprec->prop_value.prop_plane = plane; + DBPropPut(mhd->mh_def, name, newproprec); } - for (i = 0; i < proprec->prop_len; i += 4) - { - /* There should be a multiple of 4 values but avoid an array overrun - * if not. - */ - if ((i + 3) >= proprec->prop_len) - { - TxError("MASKHINTS_%s: Expected 4 values, found only %d\n", - name + 10, numvals); - break; - } - - r.r_xbot = proprec->prop_value.prop_integer[i]; - r.r_ybot = proprec->prop_value.prop_integer[i + 1]; - r.r_xtop = proprec->prop_value.prop_integer[i + 2]; - r.r_ytop = proprec->prop_value.prop_integer[i + 3]; - - /* Transform rectangle to top level coordinates */ - GeoTransRect(mhd->mh_trans, &r, &newr); - - newproprec->prop_value.prop_integer[i] = newr.r_xbot; - newproprec->prop_value.prop_integer[i + 1] = newr.r_ybot; - newproprec->prop_value.prop_integer[i + 2] = newr.r_xtop; - newproprec->prop_value.prop_integer[i + 3] = newr.r_ytop; - } - - /* If there were existing entries, copy them into the new property */ - if (propfound) - { - for (i = 0; i < oldproprec->prop_len; i++) - newproprec->prop_value.prop_integer[i + proprec->prop_len] = - oldproprec->prop_value.prop_integer[i]; - } - DBPropPut(mhd->mh_def, name, newproprec); + mhd->mh_plane = plane; + DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, + cifCopyMaskHintFunc, (ClientData)mhd); } return 0; } @@ -304,9 +312,10 @@ cifFlatMaskHints( * CIFCopyMaskHints -- * * Callback function to copy mask hints from one cell into another. + * (Occasionally called as a standalone function, not as a callback.) * * Results: - * None. + * Return 0 to keep the search going. * * Side effects: * May modify properties in the target cell. @@ -314,7 +323,7 @@ cifFlatMaskHints( * ---------------------------------------------------------------------------- */ -void +int CIFCopyMaskHints( SearchContext *scx, CellDef *targetDef) @@ -324,38 +333,9 @@ CIFCopyMaskHints( CellDef *sourceDef = scx->scx_use->cu_def; mhd.mh_trans = &scx->scx_trans; mhd.mh_def = targetDef; + mhd.mh_plane = (Plane *)NULL; DBPropEnum(sourceDef, cifFlatMaskHints, &mhd); -} - -/* - * ---------------------------------------------------------------------------- - * - * cifHierCopyMaskHints -- - * - * Callback function to copy mask hints from a subcell into a flattened - * cell, which is passed in the clientData record. - * - * Results: - * Always returns 0 to keep the search alive. - * - * Side effects: - * May modify properties in the flattened cell. - * - * ---------------------------------------------------------------------------- - */ - -int -cifHierCopyMaskHints( - SearchContext *scx, - ClientData clientData) -{ - MaskHintsData mhd; - - mhd.mh_trans = &scx->scx_trans; - mhd.mh_def = (CellDef *)clientData; - - DBPropEnum(scx->scx_use->cu_def, cifFlatMaskHints, &mhd); return 0; } @@ -480,7 +460,7 @@ cifHierCellFunc( /* Flatten mask hints in the area of interest */ CIFCopyMaskHints(scx, CIFComponentDef); - DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&newscx, 0, CIFCopyMaskHints, (ClientData)CIFComponentDef); /* Set CIFErrorDef to NULL to ignore errors here... these will @@ -808,7 +788,7 @@ CIFGenSubcells( cifHierCopyFunc, (ClientData) CIFTotalDef); /* Flatten mask hints in the area of interest */ CIFCopyMaskHints(&scx, CIFTotalDef); - DBTreeSrCells(&scx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&scx, 0, CIFCopyMaskHints, (ClientData)CIFTotalDef); CIFErrorDef = def; @@ -986,14 +966,14 @@ cifHierElementFunc( (void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0, cifHierCopyFunc, (ClientData) CIFTotalDef); CIFCopyMaskHints(&scx, CIFTotalDef); - DBTreeSrCells(&scx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&scx, 0, CIFCopyMaskHints, (ClientData)CIFTotalDef); DBCellClearDef(CIFComponentDef); (void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0, cifHierCopyFunc, (ClientData) CIFComponentDef); CIFCopyMaskHints(&scx, CIFComponentDef); - DBTreeSrCells(&scx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&scx, 0, CIFCopyMaskHints, (ClientData)CIFComponentDef); CIFErrorDef = (CellDef *) NULL; diff --git a/cif/CIFint.h b/cif/CIFint.h index a19aa3d6..1b91a72d 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -338,9 +338,8 @@ extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef bool hier, ClientData clientdata); extern void CIFInitCells(void); extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp); -extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData); extern void CIFLoadStyle(char *stylename); -extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef); +extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef); /* C99 compat */ extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist); diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c index 538c46c6..cf10a7b3 100644 --- a/cif/CIFrdcl.c +++ b/cif/CIFrdcl.c @@ -718,6 +718,9 @@ CIFPaintCurrent( &DBAllButSpaceBits, cifCheckPaintFunc, (ClientData)NULL) == 1)) { + /* (To do: remove the linked Rects and paint directly + * into the plane in cifMaskHintFunc()) + */ DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, &CIFSolidBits, cifMaskHintFunc, (ClientData)&lrec); @@ -728,30 +731,29 @@ CIFPaintCurrent( char *propname, *layername; int proplen, i, savescale; bool origfound = FALSE; + Plane *plane; layername = (char *)op->co_client; propname = (char *)mallocMagic(11 + strlen(layername)); sprintf(propname, "MASKHINTS_%s", layername); - /* Turn all linked Rects into a mask-hints property in the - * target cell. + /* If there is already a mask hint plane for this layer, + * then add to it; otherwise, create a new plane. */ - proplen = 0; - for (lsrch = lrec; lsrch; lsrch = lsrch->r_next) - proplen += 4; + proprec = DBPropGet(cifReadCellDef, layername, &origfound); + if (origfound) + plane = proprec->prop_value.prop_plane; + else + { + proprec = (PropertyRecord *)mallocMagic( + sizeof(PropertyRecord)); + proprec->prop_type = PROPERTY_TYPE_PLANE; + proprec->prop_len = 0; /* (unused) */ + plane = DBNewPlane((ClientData)TT_SPACE); + proprec->prop_value.prop_plane = plane; + DBPropPut(cifReadCellDef, propname, proprec); + } - /* If there is already a mask hint for this layer, then - * prepend to its data. - */ - proporig = DBPropGet(cifReadCellDef, layername, &origfound); - if (origfound) proplen += proporig->prop_len; - - proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) * - (proplen - 2) * sizeof(int)); - proprec->prop_type = PROPERTY_TYPE_DIMENSION; - proprec->prop_len = proplen; - - proplen = 0; while (lrec != NULL) { lrec->r_r.r_xtop = @@ -787,29 +789,14 @@ CIFPaintCurrent( (savescale / cifCurReadStyle->crs_scaleFactor); } - proprec->prop_value.prop_integer[proplen] = - lrec->r_r.r_xbot; - proprec->prop_value.prop_integer[proplen + 1] = - lrec->r_r.r_ybot; - proprec->prop_value.prop_integer[proplen + 2] = - lrec->r_r.r_xtop; - proprec->prop_value.prop_integer[proplen + 3] = - lrec->r_r.r_ytop; + DBPaintPlane(plane, &lrec->r_r, CIFPaintTable, + (PaintUndoInfo *)NULL); free_magic1_t mm1 = freeMagic1_init(); freeMagic1(&mm1, lrec); lrec = lrec->r_next; freeMagic1_end(&mm1); - - proplen += 4; } - - if (origfound) - for (i = 0; i < proporig->prop_len; i++) - proprec->prop_value.prop_integer[proplen++] = - proporig->prop_value.prop_integer[i]; - - DBPropPut(cifReadCellDef, propname, proprec); freeMagic(propname); } } @@ -926,7 +913,9 @@ CIFPaintCurrent( (CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL); /* Scan the resulting plane and generate linked Rect structures for - * each shape found. + * each shape found. (To do: Remove the linked Rects and paint + * directly into the plane in cifMaskHintFunc(), which is more + * efficient but not hugely so.) */ DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits, cifMaskHintFunc, (ClientData)&lrec); @@ -934,44 +923,45 @@ CIFPaintCurrent( if (lrec != NULL) { PropertyRecord *proprec; + bool propfound; char *propname; - int proplen; + Plane *plane; propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i])); sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]); - /* Turn all linked Rects into a mask-hints property in the - * target cell. + /* Paint all linked Rects into a mask-hints property plane + * in the target cell. */ - proplen = 0; - for (lsrch = lrec; lsrch; lsrch = lsrch->r_next) - proplen += 4; - proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) * - (proplen - 2) * sizeof(int)); - proprec->prop_type = PROPERTY_TYPE_DIMENSION; - proprec->prop_len = proplen; + proprec = DBPropGet(cifReadCellDef, propname, &propfound); + if (!propfound) + { + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + proprec->prop_type = PROPERTY_TYPE_PLANE; + proprec->prop_len = 0; /* (unused) */ + plane = DBNewPlane((ClientData)TT_SPACE); + proprec->prop_value.prop_plane = plane; + DBPropPut(cifReadCellDef, propname, proprec); + } + else + plane = proprec->prop_value.prop_plane; - proplen = 0; while (lrec != NULL) { - proprec->prop_value.prop_integer[proplen] = - lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor; - proprec->prop_value.prop_integer[proplen + 1] = - lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor; - proprec->prop_value.prop_integer[proplen + 2] = - lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor; - proprec->prop_value.prop_integer[proplen + 3] = - lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor; + lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor; + lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor; + lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor; + lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor; + + DBPaintPlane(plane, &lrec->r_r, CIFPaintTable, + (PaintUndoInfo *)NULL); free_magic1_t mm1 = freeMagic1_init(); freeMagic1(&mm1, lrec); lrec = lrec->r_next; freeMagic1_end(&mm1); - - proplen += 4; } - DBPropPut(cifReadCellDef, propname, proprec); freeMagic(propname); } diff --git a/cif/CIFsee.c b/cif/CIFsee.c index 3c02c7ff..531851b6 100644 --- a/cif/CIFsee.c +++ b/cif/CIFsee.c @@ -166,9 +166,9 @@ CIFPaintLayer( scx.scx_use = CIFDummyUse; scx.scx_trans = GeoIdentityTransform; (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, - cifHierCopyFunc, (ClientData) CIFComponentDef); + cifHierCopyFunc, (ClientData) CIFComponentDef); CIFCopyMaskHints(&scx, CIFComponentDef); - DBTreeSrCells(&scx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&scx, 0, CIFCopyMaskHints, (ClientData)CIFComponentDef); oldCount = DBWFeedbackCount; @@ -287,9 +287,9 @@ CIFSeeLayer( scx.scx_use = CIFDummyUse; scx.scx_trans = GeoIdentityTransform; (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, - cifHierCopyFunc, (ClientData) CIFComponentDef); + cifHierCopyFunc, (ClientData) CIFComponentDef); CIFCopyMaskHints(&scx, CIFComponentDef); - DBTreeSrCells(&scx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&scx, 0, CIFCopyMaskHints, (ClientData)CIFComponentDef); oldCount = DBWFeedbackCount; @@ -459,9 +459,9 @@ CIFCoverageLayer( scx.scx_use = CIFDummyUse; scx.scx_trans = GeoIdentityTransform; (void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0, - cifHierCopyFunc, (ClientData) CIFComponentDef); + cifHierCopyFunc, (ClientData) CIFComponentDef); CIFCopyMaskHints(&scx, CIFComponentDef); - DBTreeSrCells(&scx, 0, cifHierCopyMaskHints, + DBTreeSrCells(&scx, 0, CIFCopyMaskHints, (ClientData)CIFComponentDef); CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE, diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index d33df697..54dcab53 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -45,9 +45,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi #include "utils/undo.h" #include "select/select.h" #include "netmenu/netmenu.h" - -/* C99 compat */ #include "cif/cif.h" +#include "cif/CIFint.h" /* Forward declarations */ @@ -2335,13 +2334,15 @@ CmdDoProperty( Tcl_Obj *tobj; #endif - int printPropertiesFunc(); /* Forward declaration */ + /* Forward declarations */ + int printPropertiesFunc(); + int printPlanePropFunc(); /* These should match the property codes in database.h.in, except * for "compat" which must come at the end. */ static const char * const cmdPropertyType[] = { - "string", "integer", "dimension", "double", "compat", NULL + "string", "integer", "dimension", "double", "plane", "compat", NULL }; /* If a property type is given, parse it and then strip it from @@ -2393,7 +2394,7 @@ CmdDoProperty( return; } - /* print the value of the indicated property */ + /* Print the value of the indicated property */ proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound); if (propfound) { @@ -2434,6 +2435,14 @@ CmdDoProperty( Tcl_SetObjResult(magicinterp, tobj); } break; + case PROPERTY_TYPE_PLANE: + tobj = Tcl_NewListObj(0, NULL); + DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, printPlanePropFunc, + (ClientData)tobj); + Tcl_SetObjResult(magicinterp, tobj); + break; case PROPERTY_TYPE_DOUBLE: if (proprec->prop_len == 1) Tcl_SetObjResult(magicinterp, @@ -2469,6 +2478,13 @@ CmdDoProperty( TxPrintf("\n"); break; + case PROPERTY_TYPE_PLANE: + DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, printPlanePropFunc, + (ClientData)NULL); + TxPrintf("\n"); + break; case PROPERTY_TYPE_DOUBLE: for (i = 0; i < proprec->prop_len; i++) TxPrintf( "%"DLONG_PREFIX"d", @@ -2514,7 +2530,7 @@ CmdDoProperty( * keyword functions work correctly. * * GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE - * MASKHINTS_*: PROPERTY_TYPE_DIMENSION + * MASKHINTS_*: PROPERTY_TYPE_PLANE * FIXED_BBOX: PROPERTY_TYPE_DIMENSION */ if (!strcmp(cmd->tx_argv[argstart], "GDS_START")) @@ -2528,7 +2544,7 @@ CmdDoProperty( else if (!strcmp(cmd->tx_argv[argstart], "OBS_BBOX")) proptype = PROPERTY_TYPE_DIMENSION; else if (!strncmp(cmd->tx_argv[argstart], "MASKHINTS_", 10)) - proptype = PROPERTY_TYPE_DIMENSION; + proptype = PROPERTY_TYPE_PLANE; if (strlen(cmd->tx_argv[argstart + 1]) == 0) DBPropPut(def, cmd->tx_argv[argstart], NULL); @@ -2543,8 +2559,11 @@ CmdDoProperty( proprec->prop_len = proplen; strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]); } - else /* PROPERTY_TYPE_INTEGER or PROPERTY_TYPE_DIMENSION */ + else /* All non-string properties */ { + Plane *plane; + Rect r; + /* Two choices: If locargc == 3 then all values are in one * argument. If locargc > 3, then parse each argument as a * separate value. @@ -2555,6 +2574,12 @@ CmdDoProperty( if (proptype == PROPERTY_TYPE_DOUBLE) proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + (proplen - 1)*sizeof(dlong)); + else if (proptype == PROPERTY_TYPE_PLANE) + { + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + plane = DBNewPlane((ClientData)TT_SPACE); + proprec->prop_value.prop_plane = plane; + } else proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + (proplen - 2)*sizeof(int)); @@ -2587,6 +2612,28 @@ CmdDoProperty( proprec->prop_value.prop_double[i - 1] = 0; } } + else if (proptype == PROPERTY_TYPE_PLANE) + { + propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i], + FALSE, ((i % 2) == 0) ? FALSE : TRUE); + switch ((i - 1) % 4) + { + case 0: + r.r_xbot = propvalue; + break; + case 1: + r.r_ybot = propvalue; + break; + case 2: + r.r_xtop = propvalue; + break; + case 3: + r.r_ytop = propvalue; + DBPaintPlane(plane, &r, CIFPaintTable, + (PaintUndoInfo *)NULL); + break; + } + } else /* PROPERTY_TYPE_DIMENSION */ { propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i], @@ -2601,22 +2648,32 @@ CmdDoProperty( * the valid number of arguments, then again to parse the * values, once the property record has been allocated */ - value = cmd->tx_argv[argstart + 1]; - for (proplen = 0; *value != '\0'; ) + if (proptype == PROPERTY_TYPE_PLANE) { - if (isspace(*value) && (*value != '\0')) value++; - if (!isspace(*value)) - { - proplen++; - while (!isspace(*value) && (*value != '\0')) value++; - } + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + plane = DBNewPlane((ClientData)TT_SPACE); + proprec->prop_value.prop_plane = plane; } - if (proplen > 0) + else { - proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + - (proplen - 2)*sizeof(int)); - proprec->prop_type = proptype; - proprec->prop_len = proplen; + value = cmd->tx_argv[argstart + 1]; + for (proplen = 0; *value != '\0'; ) + { + if (isspace(*value) && (*value != '\0')) value++; + if (!isspace(*value)) + { + proplen++; + while (!isspace(*value) && (*value != '\0')) value++; + } + } + if (proplen > 0) + { + proprec = (PropertyRecord *)mallocMagic( + sizeof(PropertyRecord) + + (proplen - 2) * sizeof(int)); + proprec->prop_type = proptype; + proprec->prop_len = proplen; + } } /* Second pass */ value = cmd->tx_argv[argstart + 1]; @@ -2657,6 +2714,28 @@ CmdDoProperty( } proprec->prop_value.prop_double[proplen] = dvalue; } + else if (proptype == PROPERTY_TYPE_PLANE) + { + propvalue = cmdParseCoord(w, value, FALSE, + ((proplen % 2) == 0) ? TRUE : FALSE); + switch (proplen % 4) + { + case 0: + r.r_xbot = propvalue; + break; + case 1: + r.r_ybot = propvalue; + break; + case 2: + r.r_xtop = propvalue; + break; + case 3: + r.r_ytop = propvalue; + DBPaintPlane(plane, &r, CIFPaintTable, + (PaintUndoInfo *)NULL); + break; + } + } else /* PROPERTY_TYPE_DIMENSION */ { propvalue = cmdParseCoord(w, value, FALSE, @@ -2727,6 +2806,59 @@ CmdProperty( CmdDoProperty(def, w, cmd, 1); } +/* + * ---------------------------------------------------------------------------- + * Callback function for printing values from a Plane property + * ---------------------------------------------------------------------------- + */ + +#ifdef MAGIC_WRAPPER +int +printPlanePropFunc( + Tile *tile, + TileType dinfo, + Tcl_Obj *lobj) +{ + Rect r; + MagWindow *w; + + TiToRect(tile, &r); + windCheckOnlyWindow(&w, DBWclientID); + + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(DBWPrintValue(r.r_xbot, w, TRUE), -1)); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(DBWPrintValue(r.r_ybot, w, FALSE), -1)); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(DBWPrintValue(r.r_xtop, w, TRUE), -1)); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(DBWPrintValue(r.r_ytop, w, FALSE), -1)); + return 0; +} + +#else + +int +printPlanePropFunc( + Tile *tile, + TileType dinfo, + ClientData cdata /* (unused) */ +{ + Rect r; + MagWindow *w; + + TiToRect(tile, &r) + windCheckOnlyWindow(&w, DBWclientID); + + TxPrintf("%s ", DBWPrintValue(r.r_xbot, w, TRUE); + TxPrintf("%s ", DBWPrintValue(r.r_ybot, w, FALSE); + TxPrintf("%s ", DBWPrintValue(r.r_xtop, w, TRUE); + TxPrintf("%s ", DBWPrintValue(r.r_ytop, w, FALSE); + return 0; +} + +#endif + /* * ---------------------------------------------------------------------------- * Callback function for printing a single property key:value pair @@ -2766,6 +2898,12 @@ printPropertiesFunc( DBWPrintValue(proprec->prop_value.prop_integer[i], w, ((i % 2) == 0) ? TRUE : FALSE), -1)); break; + case PROPERTY_TYPE_PLANE: + DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, printPlanePropFunc, + (ClientData)lobj); + break; case PROPERTY_TYPE_DOUBLE: for (i = 0; i < proprec->prop_len; i++) Tcl_ListObjAppendElement(magicinterp, lobj, @@ -2794,6 +2932,13 @@ printPropertiesFunc( w, ((i % 2) == 0) ? TRUE : FALSE); TxPrintf("\n"); break; + case PROPERTY_TYPE_PLANE: + TxPrintf("%s = ", name); + DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, printPlanePropFunc, + (ClientData)NULL); + TxPrintf("\n"); + break; case PROPERTY_TYPE_DOUBLE: TxPrintf("%s = ", name); for (i = 0; i < proprec->prop_len; i++) diff --git a/database/DBcellcopy.c b/database/DBcellcopy.c index e0d647e8..3e0ae334 100644 --- a/database/DBcellcopy.c +++ b/database/DBcellcopy.c @@ -37,9 +37,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "windows/windows.h" #include "dbwind/dbwind.h" #include "commands/commands.h" - -/* C99 compat */ #include "graphics/graphics.h" +#include "cif/CIFint.h" /* * The following variable points to the tables currently used for @@ -357,10 +356,43 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func) struct propUseDefStruct { CellDef *puds_source; CellDef *puds_dest; + Plane *puds_plane; /* Mask hint plane in dest */ Transform *puds_trans; /* Transform from source use to dest */ Rect *puds_area; /* Clip area in source coordinates */ }; +/* + *----------------------------------------------------------------------------- + * + * dbCopyMaskHintPlaneFunc -- + * + * Translate tiles from a child mask-hint property plane into the + * coordinate system of the parent, and paint the mask-hint area + * into the mask-hint property plane of the parent. + * + *----------------------------------------------------------------------------- + */ + +int +dbCopyMaskHintPlaneFunc(Tile *tile, + TileType dinfo, + struct propUseDefStruct *puds) +{ + Transform *trans = puds->puds_trans; + Rect *clip = puds->puds_area; + Rect r, rnew; + Plane *plane = puds->puds_plane; + + TiToRect(tile, &r); + GeoClip(&r, clip); + if (!GEO_RECTNULL(&r)) + { + GeoTransRect(trans, &r, &rnew); + DBPaintPlane(plane, &rnew, CIFPaintTable, (PaintUndoInfo *)NULL); + } + return 0; +} + /* *----------------------------------------------------------------------------- * @@ -399,56 +431,34 @@ dbCopyMaskHintsFunc(key, proprec, puds) { char *vptr, *lastval; int lastlen; + Plane *plane; - /* Append to existing mask hint (if any) */ + ASSERT(proprec->prop_type == PROPERTY_TYPE_PLANE, "dbCopyMaskHintsFunc"); + + /* Get the existing mask hint plane in the parent cell, and + * create it if it does not already exist. + */ parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound); if (propfound) - { - newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + - (proprec->prop_len + parentproprec->prop_len - 2) * - sizeof(int)); - newproprec->prop_type = PROPERTY_TYPE_DIMENSION; - newproprec->prop_len = parentproprec->prop_len; - } + plane = parentproprec->prop_value.prop_plane; else { - newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + - (proprec->prop_len - 2) * sizeof(int)); - newproprec->prop_type = PROPERTY_TYPE_DIMENSION; + newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + newproprec->prop_type = PROPERTY_TYPE_PLANE; newproprec->prop_len = 0; + plane = DBNewPlane((ClientData)TT_SPACE); + newproprec->prop_value.prop_plane = plane; + DBPropPut(dest, key, newproprec); } + puds->puds_plane = plane; - for (i = 0, j = 0; i < proprec->prop_len; i += 4) - { - r.r_xbot = proprec->prop_value.prop_integer[i]; - r.r_ybot = proprec->prop_value.prop_integer[i + 1]; - r.r_xtop = proprec->prop_value.prop_integer[i + 2]; - r.r_ytop = proprec->prop_value.prop_integer[i + 3]; - GeoClip(&r, clip); - if (!GEO_RECTNULL(&r)) - { - GeoTransRect(trans, &r, &rnew); - newproprec->prop_value.prop_integer[j] = rnew.r_xbot; - newproprec->prop_value.prop_integer[j + 1] = rnew.r_ybot; - newproprec->prop_value.prop_integer[j + 2] = rnew.r_xtop; - newproprec->prop_value.prop_integer[j + 3] = rnew.r_ytop; - newproprec->prop_len += 4; - j += 4; - } - } - - if (propfound) - { - /* Append the original values to the end of the list */ - for (i = 0; i < parentproprec->prop_len; i++) - newproprec->prop_value.prop_integer[i + j] = - parentproprec->prop_value.prop_integer[i]; - } - - DBPropPut(dest, key, newproprec); + /* Copy the properties from child to parent */ + DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + clip, &CIFSolidBits, dbCopyMaskHintPlaneFunc, + (ClientData)puds); } - return 0; } diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index 8fac59b6..d7770209 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -1713,7 +1713,7 @@ dbTileMoveFunc(tile, dinfo, mvvals) if (IsSplit(tile)) type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile); DBNMPaintPlane(mvvals->ptarget, exact, &targetRect, - DBStdPaintTbl(type, mvvals->pnum), + (mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum), (PaintUndoInfo *)NULL); return 0; } @@ -1814,7 +1814,22 @@ int dbScaleProp(name, proprec, cps) int i, scalen, scaled; Point p; - /* Only "dimension" type properties get scaled */ + /* Only "dimension" and "plane" type properties get scaled */ + + if (proprec->prop_type == PROPERTY_TYPE_PLANE) + { + Plane *newplane; + newplane = DBNewPlane((ClientData)TT_SPACE); + DBClearPaintPlane(newplane); + /* Plane index is unused; arbitrarily substitute -1 */ + dbScalePlane(proprec->prop_value.prop_plane, newplane, -1, + scalen, scaled, TRUE); + DBFreePaintPlane(proprec->prop_value.prop_plane); + TiFreePlane(proprec->prop_value.prop_plane); + proprec->prop_value.prop_plane = newplane; + return 0; + } + if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0; /* Scale numerator held in point X value, */ @@ -1857,7 +1872,22 @@ int dbMoveProp(name, proprec, cps) char *newvalue; Point p; - /* Only "dimension" type properties get scaled */ + /* Only "dimension" and "plane" type properties get scaled */ + + if (proprec->prop_type == PROPERTY_TYPE_PLANE) + { + Plane *newplane; + + newplane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(newplane); + /* Use plane index -1 to indicate use of CIFPaintTable */ + dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy); + DBFreePaintPlane(proprec->prop_value.prop_plane); + TiFreePlane(proprec->prop_value.prop_plane); + proprec->prop_value.prop_plane = newplane; + return 0; + } + if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0; origx = cps->cps_point.p_x; diff --git a/database/DBio.c b/database/DBio.c index cc4ec1ad..70fc0f63 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -73,10 +73,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/undo.h" #include "utils/malloc.h" #include "utils/signals.h" - -/* C99 compat */ #include "dbwind/dbwtech.h" #include "cif/cif.h" +#include "cif/CIFint.h" #include "lef/lef.h" #include "commands/commands.h" #include "graphics/graphics.h" @@ -2492,10 +2491,24 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled) * (2) "integer" (a fixed integer or list of integers) * (3) "dimension" (an integer that scales with internal units) * (4) "double" (a fixed double-wide integer or list thereof) + * (5) "plane" (a tile plane structure) */ switch (option) { + case PROPERTY_TYPE_PLANE: + /* Treat this like "string" but make sure property is a + * mask hint. There is currently no method to specify + * a plane property other than to write out the bounding + * box coordinates of all the tiles in a list. + */ + if (strncmp(propertyname, "MASKHINTS_", 10)) + { + TxError("Plane type specified for property \"%s\" but " + "property is not a mask hint!\n", propertyname); + break; + } + /* Else drop through */ case PROPERTY_TYPE_STRING: /* Go ahead and process the vendor GDS property */ if (!strcmp(propertyname, "GDS_FILE")) @@ -2565,68 +2578,54 @@ dbReadProperties(cellDef, line, len, f, scalen, scaled) else if (!strncmp(propertyname, "MASKHINTS_", 10)) { pptr = pvalueptr; + proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord)); + proprec->prop_type = PROPERTY_TYPE_PLANE; + proprec->prop_len = 0; - /* Do one pass through the string to count the number of - * values and make sure they all parse as integers. - */ - numvals = 0; - while (*pptr != '\0') - { - while (isspace(*pptr) && (*pptr != '\0')) pptr++; - if (!isspace(*pptr)) - { - char *endptr; - long result; - - /* Check that the value is an integer */ - result = strtol(pptr, &endptr, 0); - if (endptr == pptr) - { - /* Unable to parse correctly. Save as a string value */ - proplen = strlen(pvalueptr); - proprec = (PropertyRecord *)mallocMagic( - sizeof(PropertyRecord) - 7 + proplen); - proprec->prop_type = PROPERTY_TYPE_STRING; - proprec->prop_len = proplen; - strcpy(proprec->prop_value.prop_string, pvalueptr); - (void) DBPropPut(cellDef, propertyname, proprec); - break; - } - while (!isspace(*pptr) && (*pptr != '\0')) pptr++; - numvals++; - } - } - if (numvals % 4 != 0) - { - TxError("Cannot read bounding box values in %s property", - propertyname); - /* This does not need to be a fatal error. Extra - * values will be unused. - */ - } - - pptr = pvalueptr; - proprec = (PropertyRecord *)mallocMagic( - sizeof(PropertyRecord) + ((numvals - 2) * sizeof(int))); - proprec->prop_type = PROPERTY_TYPE_DIMENSION; - proprec->prop_len = numvals; - - /* Do a second pass through the string to convert the values - * to dimensions and save as an integer array. + proprec->prop_value.prop_plane = DBNewPlane((ClientData)TT_SPACE); + + /* Parse the string and convert sets of four values + * to coordinates and paint into the plane. */ numvals = 0; while (*pptr != '\0') { + Rect r; while (isspace(*pptr) && (*pptr != '\0')) pptr++; if (!isspace(*pptr)) { sscanf(pptr, "%d", &ival); if (scalen > 1) ival *= scalen; if (scaled > 1) ival /= scaled; - proprec->prop_value.prop_integer[numvals] = ival; - + switch (numvals) + { + case 0: + r.r_xbot = ival; + numvals++; + break; + case 1: + r.r_ybot = ival; + numvals++; + break; + case 2: + r.r_xtop = ival; + numvals++; + break; + case 3: + r.r_ytop = ival; + numvals = 0; + /* Paint this into the plane */ + DBPaintPlane(proprec->prop_value.prop_plane, + &r, CIFPaintTable, + (PaintUndoInfo *)NULL); + break; + } while (!isspace(*pptr) && (*pptr != '\0')) pptr++; - numvals++; + } + if (numvals == 0) + { + TxError("Mask-hint property number of values is not" + " divisible by four. Truncated.\n"); } } (void) DBPropPut(cellDef, propertyname, proprec); @@ -3481,6 +3480,23 @@ DBCellFindScale(cellDef) return ggcf; } +/* + * ---------------------------------------------------------------------------- + * + * dbFindGCFFunc --- + * + * Find the greatest common factor between the current GCF and each point + * in a tile. + * + * Results: + * 0 to keep the search going. + * + * Side effects: + * May modify the GCF passed as client data to the function. + * + * ---------------------------------------------------------------------------- + */ + int dbFindGCFFunc(tile, dinfo, ggcf) Tile *tile; @@ -3503,6 +3519,24 @@ dbFindGCFFunc(tile, dinfo, ggcf) return (*ggcf == 1) ? 1 : 0; } +/* + * ---------------------------------------------------------------------------- + * + * dbFindCellGCFFunc --- + * + * Find the greatest common factor between the current GCF and each point + * of a uses bounding box, each component of the use's transform , and + * for arrays, the array pitch. + * + * Results: + * 0 to keep the search going. + * + * Side effects: + * May modify the GCF passed as client data to the function. + * + * ---------------------------------------------------------------------------- + */ + int dbFindCellGCFFunc(cellUse, ggcf) CellUse *cellUse; /* Cell use whose "call" is to be written to a file */ @@ -3543,6 +3577,23 @@ dbFindCellGCFFunc(cellUse, ggcf) return (*ggcf == 1) ? 1 : 0; } +/* + * ---------------------------------------------------------------------------- + * + * dbFindPropGCFFunc --- + * + * Find the greatest common factor between the current GCF and each point + * of a dimension property, or each point of each tile in a plane property. + * + * Results: + * 0 to keep the search going. + * + * Side effects: + * May modify the GCF passed as client data to the function. + * + * ---------------------------------------------------------------------------- + */ + int dbFindPropGCFFunc(key, proprec, ggcf) char *key; @@ -3551,20 +3602,28 @@ dbFindPropGCFFunc(key, proprec, ggcf) { int value, n; - /* Only PROPERTY_TYPE_DIMENSION properties get handled */ - if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0; - - for (n = 0; n < proprec->prop_len; n++) + if (proprec->prop_type == PROPERTY_TYPE_PLANE) { - value = proprec->prop_value.prop_integer[n]; - if (value % (*ggcf) != 0) - *ggcf = FindGCF(value, *ggcf); + if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, dbFindGCFFunc, (ClientData)ggcf)) + return (*ggcf == 1) ? 1 : 0; } - - return (*ggcf == 1) ? 1 : 0; + else if (proprec->prop_type == PROPERTY_TYPE_DIMENSION) + { + for (n = 0; n < proprec->prop_len; n++) + { + value = proprec->prop_value.prop_integer[n]; + if (value % (*ggcf) != 0) + *ggcf = FindGCF(value, *ggcf); + } + return (*ggcf == 1) ? 1 : 0; + } + else + /* Only PROPERTY_TYPE_PLANE and PROPERTY_TYPE_DIMENSION get handled */ + return 0; } - /* * ---------------------------------------------------------------------------- * @@ -3573,6 +3632,12 @@ dbFindPropGCFFunc(key, proprec, ggcf) * String comparison of two instance names, for the purpose of sorting * the instances in a .mag file output in a repeatable way. * + * Results: + * The string comparison, equivalent to the return value of strcmp(). + * + * Side effects: + * None. + * * ---------------------------------------------------------------------------- */ @@ -3610,6 +3675,9 @@ struct cellUseList { * Return value: * Return 0 to keep the search going. * + * Side effects: + * Adds to the list of cell uses passed as client data. + * * ---------------------------------------------------------------------------- */ @@ -3635,6 +3703,9 @@ dbGetUseFunc(cellUse, useRec) * Return value: * Return 0 to keep the search going. * + * Side effects: + * Increments the count passed as client data. + * * ---------------------------------------------------------------------------- */ @@ -3663,6 +3734,12 @@ struct keyValuePair { * String comparison of two property keys, for the purpose of sorting * the properties in a .mag file output in a repeatable way. * + * Results: + * The string comparison, equivalent to the result of strcmp(). + * + * Side effects: + * None. + * * ---------------------------------------------------------------------------- */ @@ -3698,6 +3775,9 @@ struct cellPropList { * Return value: * Return 0 to keep the search going. * + * Side Effects: + * Adds to the list of property records passed as client data. + * * ---------------------------------------------------------------------------- */ @@ -3727,6 +3807,9 @@ dbGetPropFunc(key, proprec, propRec) * Return value: * Return 0 to keep the search going. * + * Side Effects: + * Increments the count passed as client data. + * * ---------------------------------------------------------------------------- */ @@ -4064,6 +4147,52 @@ ioerror: return (TRUE); } +/* + * ---------------------------------------------------------------------------- + * + * dbWritePropPaintFunc -- + * + * Transform tiles in a plane into a set of four coordinate values and output + * them to the file. This turns plane data into a PROP_TYPE_DIMENSION array, + * which is not a very efficient form and may be revisited. For relatively + * simple plane data, it suffices. The property planes are single-bit types. + * Note that there is no support for non-Manhattan geometry in the property + * plane at this time. + * + * Results: + * 0 to keep the search going. + * + * Side effects: + * Writes output to a file. + * + * ---------------------------------------------------------------------------- + */ + +int +dbWritePropPaintFunc(Tile *tile, + TileType dinfo, + ClientData cdata) +{ + pwfrec *pwf = (pwfrec *)cdata; + FILE *f = pwf->pwf_file; + int reducer = pwf->pwf_reducer; + Rect r; + char newvalue[20]; + + TiToRect(tile, &r); + + snprintf(newvalue, 20, " %d", r.r_xbot / reducer); + FPUTSR(f, newvalue); + snprintf(newvalue, 20, " %d", r.r_ybot / reducer); + FPUTSR(f, newvalue); + snprintf(newvalue, 20, " %d", r.r_xtop / reducer); + FPUTSR(f, newvalue); + snprintf(newvalue, 20, " %d", r.r_ytop / reducer); + FPUTSR(f, newvalue); + + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -4111,6 +4240,12 @@ dbWritePropFunc(key, proprec, cdata) case PROPERTY_TYPE_INTEGER: FPUTSR(f, "integer "); break; + case PROPERTY_TYPE_PLANE: + /* A mask hint is a plane type property; declare it + * as a dimension, but it's arbitrary anyway since + * the prefix "MASKHINTS_" is detected on read-in and + * the property is parsed as plane data. + */ case PROPERTY_TYPE_DIMENSION: FPUTSR(f, "dimension "); break; @@ -4143,6 +4278,13 @@ dbWritePropFunc(key, proprec, cdata) FPUTSR(f, newvalue); } break; + case PROPERTY_TYPE_PLANE: + /* Scan the plane and output each non-space tile as four values */ + DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, dbWritePropPaintFunc, + (ClientData)cdata); + break; case PROPERTY_TYPE_DOUBLE: for (i = 0; i < proprec->prop_len; i++) { @@ -4395,6 +4537,12 @@ ioerror: * Callback function used by DBCellWriteCommandFile() to output * commands corresponding to cell layout geometry. * + * Results: + * 0 to keep the search going. + * + * Side effects: + * Writes output to a file. + * * ---------------------------------------------------------------------------- */ @@ -4460,6 +4608,12 @@ dbWritePaintCommandsFunc(tile, dinfo, cdarg) * Callback function used by DBCellWriteCommandFile() to output * commands corresponding to cell uses in the layout. * + * Results: + * 0 to keep the search going. + * + * Side effects: + * Writes output to a file. + * * ---------------------------------------------------------------------------- */ @@ -4479,6 +4633,45 @@ dbWriteUseCommandsFunc(cellUse, cdarg) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * dbWritePropCommandPaintFunc -- + * + * Transform tiles in a plane into a set of four coordinate values and output + * them to the file. This turns plane data into a PROP_TYPE_DIMENSION array, + * which is not a very efficient form and may be revisited. For relatively + * simple plane data, it suffices. The property planes are single-bit types. + * Note that there is no support for non-Manhattan geometry in the property + * plane at this time. + * + * Results: + * 0 to keep the search going. + * + * Side effects: + * Writes output to a file. + * + * ---------------------------------------------------------------------------- + */ + +int +dbWritePropCommandPaintFunc(Tile *tile, + TileType dinfo, + FILE *f) +{ + Rect r; + MagWindow *w; + + TiToRect(tile, &r); + windCheckOnlyWindow(&w, DBWclientID); + fprintf(f, "%s ", DBWPrintValue(r.r_xbot, w, TRUE)); + fprintf(f, "%s ", DBWPrintValue(r.r_ybot, w, FALSE)); + fprintf(f, "%s ", DBWPrintValue(r.r_xtop, w, TRUE)); + fprintf(f, "%s ", DBWPrintValue(r.r_ytop, w, FALSE)); + + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -4487,6 +4680,12 @@ dbWriteUseCommandsFunc(cellUse, cdarg) * Callback function used by DBCellWriteCommandFile() to output * commands corresponding to properties in the layout. * + * Results: + * 0 to keep the search going. + * + * Side effects: + * Writes output to a file. + * * ---------------------------------------------------------------------------- */ @@ -4540,6 +4739,19 @@ dbWritePropCommandsFunc(key, proprec, cdarg) fprintf(f, "\n"); break; + case PROPERTY_TYPE_PLANE: + /* Plane properties are automatically handled as plane data, + * so the property type does not need to be declared. + * Only mask hints can be plane properties. + */ + fprintf(f, "property %s ", key); + DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &TiPlaneRect, &CIFSolidBits, dbWritePropCommandPaintFunc, + (ClientData)f); + fprintf(f, "\n"); + break; + case PROPERTY_TYPE_DOUBLE: fprintf(f, "property double %s ", key); for (i = 0; i < proprec->prop_len; i++) @@ -4573,7 +4785,6 @@ dbWritePropCommandsFunc(key, proprec, cdarg) * the file. If successful, rewind the now-expanded file and * overwrite the beginning of the file, then truncate it. * - * * Results: * TRUE if the cell could be written successfully, FALSE otherwise. * diff --git a/database/DBprop.c b/database/DBprop.c index f44ffecc..b3ff0aed 100644 --- a/database/DBprop.c +++ b/database/DBprop.c @@ -106,7 +106,18 @@ DBPropPut(cellDef, name, value) entry = HashFind(htab, name); oldvalue = (PropertyRecord *)HashGetValue(entry); - if (oldvalue != NULL) freeMagic((char *)oldvalue); + /* All properties are allocated as a single block and can just be freed, + * except for plane properties, which require freeing the plane. + */ + if (oldvalue != NULL) + { + if (oldvalue->prop_type == PROPERTY_TYPE_PLANE) + { + DBFreePaintPlane(oldvalue->prop_value.prop_plane); + TiFreePlane(oldvalue->prop_value.prop_plane); + } + freeMagic((char *)oldvalue); + } if (value == (PropertyRecord *)NULL) HashRemove(htab, name); else diff --git a/database/database.h.in b/database/database.h.in index 45939459..20440897 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -719,6 +719,7 @@ typedef struct char prop_string[8]; /* For PROPERTY_TYPE_STRING */ int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */ dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */ + Plane *prop_plane; /* For PROPERTY_TYPE_PLANE */ } prop_value; } PropertyRecord; @@ -760,6 +761,7 @@ typedef struct #define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */ #define PROPERTY_TYPE_DIMENSION 2 /* Integer property that scales with units */ #define PROPERTY_TYPE_DOUBLE 3 /* Double-long integer (for file positions) */ +#define PROPERTY_TYPE_PLANE 4 /* A tile plane structure */ /* -------------------- Exported procedure headers -------------------- */ diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index 7d59ae6b..78acd5f9 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -27,6 +27,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include #include // for memcpy() #include // for sqrt() for diagonal check + +#include "tcltk/tclmagic.h" #include "utils/magic.h" #include "utils/geometry.h" #include "tiles/tile.h" @@ -36,7 +38,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/signals.h" #include "utils/maxrect.h" #include "utils/malloc.h" +#include "utils/undo.h" #include "textio/textio.h" +#include "cif/CIFint.h" int dbDRCDebug = 0; @@ -62,7 +66,33 @@ extern MaxRectsData *drcCanonicalMaxwidth(); /* *----------------------------------------------------------------------- * - * drcCifPointToSegment + * drcFoundOneFunc -- + * + * Simple callback for a plane search on a mask-hint plane inside + * a DRC check area. + * + * Results: + * Return 1 always, indicating that a tile has been found in the + * DRC search area, and the search can end. + * + * Side effects: + * None. + * + *----------------------------------------------------------------------- + */ + +int +drcFoundOneFunc(Tile *tile, + TileType dinfo, + ClientData cdata) +{ + return 1; +} + +/* + *----------------------------------------------------------------------- + * + * drcCifPointToSegment -- * * Euclidean-distance point-to-segment distance (squared) * calculation (borrowed from XCircuit) @@ -468,6 +498,13 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata) DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED); (void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum], checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg); + +#ifdef MAGIC_WRAPPER + /* Execute pending Tcl events, so the DRC process doesn't block. */ + UndoEnable(); + while (Tcl_DoOneEvent(TCL_DONT_WAIT)); + UndoDisable(); +#endif } drcCifCheck(&arg); if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist); @@ -743,27 +780,17 @@ drcTile (tile, dinfo, arg) /* If an exception area exists, is the error edge inside? */ if (propfound) { - int i; - Rect r, redge; + Rect redge; redge.r_xbot = redge.r_xtop = edgeX; redge.r_ybot = edgeBot; redge.r_ytop = edgeTop; - isinside = FALSE; - for (i = 0; i < proprec->prop_len; i += 4) - { - if ((i + 4) > proprec->prop_len) break; - r.r_xbot = proprec->prop_value.prop_integer[i]; - r.r_ybot = proprec->prop_value.prop_integer[i + 1]; - r.r_xtop = proprec->prop_value.prop_integer[i + 2]; - r.r_ytop = proprec->prop_value.prop_integer[i + 3]; - if (GEO_OVERLAP(&redge, &r)) - { - isinside = TRUE; - break; - } - } + if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &redge, &CIFSolidBits, drcFoundOneFunc, + (ClientData)NULL) == 1) + isinside = TRUE; } /* Exemption rules are ignored if the edge is inside @@ -1205,26 +1232,17 @@ drcTile (tile, dinfo, arg) /* If an exception area exists, is the error edge inside? */ if (propfound) { - int i; - Rect r, redge; + Rect redge; redge.r_ybot = redge.r_ytop = edgeY; redge.r_xbot = edgeLeft; redge.r_xtop = edgeRight; - for (i = 0; i < proprec->prop_len; i += 4) - { - if ((i + 4) > proprec->prop_len) break; - r.r_xbot = proprec->prop_value.prop_integer[i]; - r.r_ybot = proprec->prop_value.prop_integer[i + 1]; - r.r_xtop = proprec->prop_value.prop_integer[i + 2]; - r.r_ytop = proprec->prop_value.prop_integer[i + 3]; - if (GEO_OVERLAP(&redge, &r)) - { - isinside = TRUE; - break; - } - } + if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane), + proprec->prop_value.prop_plane, + &redge, &CIFSolidBits, drcFoundOneFunc, + (ClientData)NULL) == 1) + isinside = TRUE; } /* Exemption rules are ignored if the edge is inside