Altered the behavior of handling labels when a layer under a label

is erased.  In cases where magic would previously unattach the
label from the material and attach it to "space", now magic will
instead adjust the size of the label to stay entirely on the
material.  That avoids a common error of losing label or port
connections when the material is trimmed back.  Thanks to Philipp
Guhring for suggesting this implementation (github issue #305).
This commit is contained in:
Tim Edwards 2024-05-04 21:12:55 -04:00
parent efccdbf341
commit ca99d0b76a
1 changed files with 88 additions and 9 deletions

View File

@ -561,6 +561,41 @@ DBReOrientLabel(cellDef, area, newPos)
}
}
/*
* ----------------------------------------------------------------------------
*
* dbGetLabelArea ---
*
* Callback function used by DBAdjustLabels. Find all material under a label
* that is *not* the label type, and return the
*
* Note: This clips in a regular order, and does not consider what is the
* largest rectangular area outside the area that has been clipped out.
*
* ----------------------------------------------------------------------------
*/
int
dbGetLabelArea(tile, area)
Tile *tile; /* Tile found. */
Rect *area; /* Area to be modified. */
{
Rect r;
TiToRect(tile, &r);
if (r.r_xbot > area->r_xbot)
area->r_xtop = r.r_xbot;
else if (r.r_xtop < area->r_xtop)
area->r_xbot = r.r_xtop;
else if (r.r_ybot > area->r_ybot)
area->r_ytop = r.r_ybot;
else if (r.r_ytop < area->r_ytop)
area->r_ybot = r.r_ytop;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -590,7 +625,7 @@ DBAdjustLabels(def, area)
{
Label *lab;
TileType newType;
bool modified = FALSE;
bool modified = FALSE, adjusted = FALSE;
/* First, find each label that crosses the area we're
* interested in.
@ -602,16 +637,60 @@ DBAdjustLabels(def, area)
newType = DBPickLabelLayer(def, lab, FALSE);
if (newType == lab->lab_type) continue;
if (lab->lab_flags & LABEL_STICKY) continue;
if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
/* New behavior (5/2024) (idea from Philipp Guhring)---If the new
* type is space, then instead of immediately casting the label off
* of its material, find the amount of the label that is still
* covered by the material. If the material covers more than half
* the label area, then adjust the label area to match the material.
*/
adjusted = FALSE;
if (newType == TT_SPACE)
{
TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
DBTypeLongName(newType), def->cd_name);
Rect r;
TileTypeBitMask lmask;
TTMaskSetOnlyType(&lmask, lab->lab_type);
/* To do: Add compatible types (contact, residue) */
TTMaskCom(&lmask);
r = lab->lab_rect;
DBSrPaintArea((Tile *) NULL, def->cd_planes[DBPlane(lab->lab_type)],
&lab->lab_rect, &lmask, dbGetLabelArea, (ClientData) &r);
if (!GEO_RECTNULL(&r))
{
if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
{
TxPrintf("Adjusting size of label \"%s\" in cell %s.\n",
lab->lab_text, def->cd_name);
}
DBUndoEraseLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
lab->lab_rect = r;
DBFontLabelSetBBox(lab);
DBUndoPutLabel(def, lab);
DBWLabelChanged(def, lab, DBW_ALLWINDOWS);
modified = TRUE;
adjusted = TRUE;
}
}
if (!adjusted)
{
if ((DBVerbose >= DB_VERBOSE_ALL) && ((def->cd_flags & CDINTERNAL) == 0))
{
TxPrintf("Moving label \"%s\" from %s to %s in cell %s.\n",
lab->lab_text, DBTypeLongName(lab->lab_type),
DBTypeLongName(newType), def->cd_name);
}
DBUndoEraseLabel(def, lab);
lab->lab_type = newType;
DBUndoPutLabel(def, lab);
modified = TRUE;
}
DBUndoEraseLabel(def, lab);
lab->lab_type = newType;
DBUndoPutLabel(def, lab);
modified = TRUE;
}
if (modified) DBCellSetModified(def, TRUE);