public static Library makeLibFromTech(Technology tech, EditingPreferences ep, GraphicsPreferences gp)
I think that getExamples(...) returns null along with error messages (which breaks conversion to library) in some cases when errors are not critical by their nature.
Example are: "No highlight layer found", "Too many highlight layers found"
and may be some other cases as well.
The error status set by tcr.markError(...) is also verified somewhere around makeLibFromTech(...) and breks process even if getExamples() returns NOT a null.
It seems that it's no reason from preventing user from editing graphical representations of libraries which have extra/missing of highlights or other primitives.
com.sun.electric.tool.user.tecEdit.Exmple
/**
* Method to parse the node examples in cell "np" and return a list of
* EXAMPLEs (one per example). "isNode" is true if this is a node
* being examined. Returns NOEXAMPLE on error.
*/
public static List<Example> getExamples(Cell np, boolean isNode, TechConversionResult tcr, List<Example> variations)
{
Map<NodeInst,Object> nodeExamples = new HashMap<NodeInst,Object>();
for(Iterator<NodeInst> it = np.getNodes(); it.hasNext(); )
{
NodeInst ni = it.next();
// ignore special nodes with function information
int funct = Manipulate.getOptionOnNode(ni);
if (funct != Info.LAYERPATCH && funct != Info.PORTOBJ && funct != Info.HIGHLIGHTOBJ)
{
nodeExamples.put(ni, new Integer(0));
}
}
List<Example> neList = new ArrayList<Example>();
for(Iterator<NodeInst> it = np.getNodes(); it.hasNext(); )
{
NodeInst ni = it.next();
if (nodeExamples.get(ni) != null) continue;
// get a new cluster of nodes
Example ne = new Example();
neList.add(ne);
Poly poly = new Poly(ni.getAnchorCenterX(), ni.getAnchorCenterY(),
ni.getLambdaBaseXSize(), ni.getLambdaBaseYSize());
poly.transform(ni.rotateOut());
Rectangle2D soFar = poly.getBounds2D();
// now find all others that touch this area
boolean gotBBox = false;
boolean foundOne = true;
int hCount = 0;
while (foundOne)
{
foundOne = false;
// begin to search the area so far
List<NodeInst> sortedNodes = new ArrayList<NodeInst>();
for(Iterator<Geometric> oIt = np.searchIterator(soFar); oIt.hasNext(); )
{
Geometric geom = oIt.next();
if (geom == null) break;
if (geom instanceof NodeInst)
sortedNodes.add((NodeInst)geom);
}
for(NodeInst otherNi: sortedNodes)
{
Poly oPoly = new Poly(otherNi.getAnchorCenterX(), otherNi.getAnchorCenterY(),
otherNi.getLambdaBaseXSize(), otherNi.getLambdaBaseYSize());
oPoly.transform(otherNi.rotateOut());
Rectangle2D otherRect = oPoly.getBounds2D();
if (!DBMath.rectsIntersect(otherRect, soFar)) continue;
// make sure the node is valid
Object otherAssn = nodeExamples.get(otherNi);
if (otherAssn != null)
{
if (otherAssn instanceof Integer) continue;
if ((Example)otherAssn == ne) continue;
String error = "Examples are too close. Found " + neList.size() + " examples at:";
for(Example nee : neList)
{
error += " [" + TextUtils.formatDistance(nee.lx) + "<=X<=" + TextUtils.formatDistance(nee.hx) +
" and " + TextUtils.formatDistance(
nee.ly) + "<=Y<=" + TextUtils.formatDistance(nee.hy) + "]";
}
tcr.markError(otherNi, np, error);
return null;
}
nodeExamples.put(otherNi, ne);
// add it to the cluster
Sample ns = new Sample();
ns.node = otherNi;
ns.values = null;
ns.msg = null;
ns.parent = ne;
ne.samples.add(ns);
ns.assoc = null;
ns.xPos = otherRect.getCenterX();
ns.yPos = otherRect.getCenterY();
int funct = Manipulate.getOptionOnNode(otherNi);
switch (funct)
{
case Info.PORTOBJ:
if (!isNode)
{
tcr.markError(otherNi, np, "Ports can only exist in nodes");
return null;
}
ns.layer = Generic.tech().portNode;
break;
case Info.CENTEROBJ:
if (!isNode)
{
tcr.markError(otherNi, np, "Grab points can only exist in nodes");
return null;
}
ns.layer = Generic.tech().cellCenterNode;
break;
case Info.HIGHLIGHTOBJ:
hCount++;
break;
default:
ns.layer = Manipulate.getLayerCell(otherNi);
if (ns.layer == null)
{
Manipulate.getLayerCell(otherNi);
tcr.markError(otherNi, np, "Node has no layer information");
return null;
}
break;
}
// accumulate state if this is not a "grab point" mark
if (!Generic.isCellCenter(otherNi))
{
if (!gotBBox)
{
ne.lx = otherRect.getMinX(); ne.hx = otherRect.getMaxX();
ne.ly = otherRect.getMinY(); ne.hy = otherRect.getMaxY();
gotBBox = true;
} else
{
if (otherRect.getMinX() < ne.lx) ne.lx = otherRect.getMinX();
if (otherRect.getMaxX() > ne.hx) ne.hx = otherRect.getMaxX();
if (otherRect.getMinY() <
ne.ly)
ne.ly = otherRect.getMinY();
if (otherRect.getMaxY() > ne.hy) ne.hy = otherRect.getMaxY();
}
soFar.setRect(ne.lx,
ne.ly, ne.hx-ne.lx,
ne.hy-ne.ly);
}
foundOne = true;
}
}
if (hCount == 0)
{
tcr.markError(null, np, "No highlight layer found");
return null;
}
if (hCount != 1)
{
tcr.markError(null, np, "Too many highlight layers found: " + hCount);
return null;
}
}
if (neList == null)
{
tcr.markError(null, np, "No examples found");
return neList;
}
// put variations in a separate list
if (variations != null)
{
for(int i=0; i<neList.size(); i++)
{
Example e = neList.get(i);
for(Sample s : e.samples)
{
if (!s.node.getNameKey().isTempname())
{
// named a layer: this is a variation
variations.add(e);
neList.remove(i);
i--;
break;
}
}
}
if (neList.size() == 0 && variations.size() > 0)
{
tcr.markError(null, np, "All examples have text on them...text should be used only in variations");
return neList;
}
}
// now search the list for the smallest, most upper-left example (the "main" example)
double sizeX = 0;
double sizeY = 0;
double locX = 0;
double locY = 0;
Example bestNe = null;
for(Example ne : neList)
{
double newSize = ne.hx-ne.lx;
newSize *=
ne.hy-ne.ly;
if (bestNe != null)
{
if (newSize > sizeX*sizeY) continue;
if (newSize == sizeX*sizeY && (ne.lx+ne.hx)/2 >= locX && (
ne.ly+ne.hy)/2 <= locY)
continue;
}
sizeX = ne.hx - ne.lx;
sizeY = ne.hy -
ne.ly;
locX = (ne.lx + ne.hx) / 2;
locY = (
ne.ly + ne.hy) / 2;
bestNe = ne;
}
// place the main example at the top of the list
if (bestNe != null && bestNe != neList)
{
neList.remove(bestNe);
neList.add(0, bestNe);
}
// done
return neList;
}
}