📄 layoutlib.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: LayoutLib.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool.generator.layout;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.net.URL;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.geometry.EPoint;import com.sun.electric.database.geometry.Orientation;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.hierarchy.Library;import com.sun.electric.database.prototype.NodeProto;import com.sun.electric.database.prototype.PortCharacteristic;import com.sun.electric.database.prototype.PortProto;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.Connection;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.topology.PortInst;import com.sun.electric.technology.ArcProto;import com.sun.electric.technology.Layer;import com.sun.electric.technology.SizeOffset;import com.sun.electric.technology.Technology;import com.sun.electric.tool.io.FileType;import com.sun.electric.tool.io.input.LibraryFiles;import com.sun.electric.tool.io.output.Output;import com.sun.electric.tool.user.ActivityLogger;import com.sun.electric.tool.user.dialogs.OpenFile;/* * The LayoutLib class provides an assortment of methods that I * found to be useful for programatic layout generation. */public class LayoutLib { // ---------------------------- public data ------------------------------ /** Use the default size. When a width or height argument has this * value the object should be created with its default * dimension. Note that -DEF_SIZE is also a legal * constant. Negative dimensions specify mirroring for certain * methods. */ public static final double DEF_SIZE = Double.POSITIVE_INFINITY; public static enum Corner { TL, TR, BL, BR; } // ---------------------------- public methods --------------------------- /** * Print a message, dump a stack trace, and throw a RuntimeException if * errorHasOccurred argument is true. * * @param errorHasOccurred indicates a runtime error has been detected * @param msg the message to print when an error occurs * @throws RuntimeException if errorHasOccurred is true */ public static void error(boolean errorHasOccurred, String msg) { if (!errorHasOccurred) return; RuntimeException e = new RuntimeException(msg); // The following prints a stack trace on the console ActivityLogger.logException(e); // The following prints a stack trace in the Electric messages window throw e; } /** * Open a library for reading. If a library is * already open then return it. Otherwise look for the library * file named libFileName and open that library. * * @param libFileName the fully qualified path name of the Library * file on disk * @return the open Library or null if it can't be found */ public static Library openLibForRead(String libFileName) { URL libFileURL = TextUtils.makeURLToFile(libFileName); String libName = TextUtils.getFileNameWithoutExtension(libFileURL); Library lib = Library.findLibrary(libName); FileType type = OpenFile.getOpenFileType(libFileName, FileType.DEFAULTLIB); if (lib==null) { lib = LibraryFiles.readLibrary(libFileURL, null, type, false); } error(lib==null, "can't open Library for reading: "+libFileName); return lib; } /** * Open a library for modification. If a library named libName is * already open then return it. Otherwise look for the file named: * libFileName and open that library. Finally, if all else fails * create a new Library and return it. * * @param libName the name of the Library * file on disk * @return the desired library */ // This doesn't work anymore.// public static Library openLibForModify(String libName, String libFileName) {// // return an open Library if it exists// Library lib = Library.findLibrary(libName);// if (lib!=null) return lib;//// // open a Library file if it exists// URL libFileURL = TextUtils.makeURLToFile(libFileName);// lib = Input.readLibrary(libFileURL, OpenFile.Type.ELIB);// if (lib!=null) return lib;// // // create a new Library// lib = Library.newInstance(libName, libFileURL);//// error(lib==null, "can't open Library for modify: "+libName);// return lib;// } public static Library openLibForWrite(String libName) { // return an open Library if it exists Library lib = Library.findLibrary(libName); if (lib!=null) return lib; // create a new Library lib = Library.newInstance(libName, null); URL libURL = TextUtils.makeURLToFile(libName); lib.setLibFile(libURL); error(lib==null, "can't open Library for modify: "+libName); return lib; } /** * Write a library in JELIB format. * @param lib the library to be written. */ public static void writeLibrary(Library lib) { Output.writeLibrary(lib, FileType.JELIB, false, false, false); } /** * Get the width of an ArcInst. The getArcInstWidth method differs * from ArcInst.getLambdaFullWidth() in that it subtracts off the "width * offset". Hence, getArcInstWidth returns a width that matches * that reported by the GUI. * * @param ai the ArcInst whose width is reported * @return the width of the ArcInst. */ public static double getArcInstWidth(ArcInst ai) { double w = ai.getLambdaBaseWidth(); return DBMath.round(w); } /** Get the default width of a NodeProto. The getNodeProtoWidth * method differs from NodeProto.getDefWidth in that it subtracts * off the "width offset". Hence getNodeProtoWidth returns a width * that matches that reported by the GUI. * * @param np the NodeProto we want the width of. * @return the width of the NodeProto. */ public static double getNodeProtoWidth(NodeProto np) { SizeOffset so = np.getProtoSizeOffset(); double w = np.getDefWidth() - so.getLowXOffset() - so.getHighXOffset(); return DBMath.round(w); } /** Get the default height of a NodeProto. The getNodeProtoHeight * method differs from NodeProto.getDefHeight in that it subtracts * off the "height offset". Hence getNodeProtoHeight returns a * height that matches that reported by the GUI. * * @param np the NodeProto we want the height of * @return the height of the NodeProto */ public static double getNodeProtoHeight(NodeProto np) { SizeOffset so = np.getProtoSizeOffset(); double h = np.getDefHeight() - so.getLowYOffset() - so.getHighYOffset(); return DBMath.round(h); } private static void prln(String msg) {System.out.println(msg);} /** * Find the width of the widest wire connected hierarchically to port. * * @param port the PortInst to check for attached wires. * @return the width of the widest wire. This width excludes the * "width offset" so it matches the width reported by the GUI. * If no wire is attached to port then return DEF_SIZE. */ public static double widestWireWidth(PortInst port) {// NodeInst ni = port.getNodeInst(); PortProto pp = port.getPortProto(); double maxWid = -1; for (Iterator<ArcInst> arcs=getArcInstsOnPortInst(port); arcs.hasNext();) { ArcInst ai = arcs.next(); //prln(" arc width: "+getArcInstWidth(ai)); maxWid = Math.max(maxWid, getArcInstWidth(ai)); } if (pp instanceof Export) { double lowerMax = widestWireWidth(((Export)pp).getOriginalPort()); if (lowerMax!=DEF_SIZE) maxWid = Math.max(maxWid, lowerMax); } if (maxWid < 0) return DEF_SIZE; return DBMath.round(maxWid); } /** Return a list of ArcInsts attached to PortInst, pi. * @param pi PortInst on which to find attached ArcInsts. */ public static Iterator<ArcInst> getArcInstsOnPortInst(PortInst pi) { ArrayList<ArcInst> arcs = new ArrayList<ArcInst>();// NodeInst ni = pi.getNodeInst(); for (Iterator<Connection> it=pi.getConnections(); it.hasNext();) { Connection c = it.next(); arcs.add(c.getArc()); }// for (Iterator it=ni.getConnections(); it.hasNext();) {// Connection c = it.next();// if (c.getPortInst()==pi) arcs.add(c.getArc());// } return arcs.iterator(); } /** The center returned by bounds might have a slight amount of rounding * error. Compensate for this by always rounding coordinates to a 103-4 * lambda grid when reading and writing the database. */ public static double roundCenterX(PortInst pi) { return pi.getCenter().getX();// return DBMath.round(pi.getBounds().getCenterX()); new way avoids rounding here } public static double roundCenterY(PortInst pi) { return pi.getCenter().getY();// return DBMath.round(pi.getBounds().getCenterY()); } public static Rectangle2D calculateNodeInst(NodeProto np, double x, double y, double width, double height) { if (np instanceof Cell) { width = (width<0 ? -1 : 1) * np.getDefWidth(); height = (height<0 ? -1 : 1) * np.getDefHeight(); } else { SizeOffset so = np.getProtoSizeOffset(); // Take the default width or height if that's what the user wants. // Otherwise adjust the user-specified width or height by the // SizeOffset. double signW = width<0 ? -1 : 1; if (width==DEF_SIZE || width==-DEF_SIZE) { width = signW * np.getDefWidth(); } else { double hi = so.getHighXOffset(); double lo = so.getLowXOffset(); error(lo!=hi, "asymmetric X offset"); width = signW * (Math.abs(width) + hi+lo); } double signH = height<0 ? -1 : 1; if (height==DEF_SIZE || height==-DEF_SIZE) { height = signH * np.getDefHeight(); } else { double hi = so.getHighYOffset(); double lo = so.getLowYOffset(); error(lo!=hi, "asymmetric Y offset"); height = signH * (Math.abs(height) + hi+lo); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -