📄 postscriptcolor.java
字号:
/* -*- tab-width: 4 -*- * Electric(tm) VLSI Design System * * File: PostScriptColor.java * Input/output tool: PostScript color merged output * Written by: David Harris, 4/20/01 (David_Harris@hmc.edu) * Translated to Java by Steven Rubin: 12/05 * * Copyright (c) 2005 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.io.output;import com.sun.electric.database.geometry.EGraphics;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.prototype.NodeProto;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.text.Version;import com.sun.electric.database.topology.ArcInst;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.variable.EditWindow_;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.technology.Layer;import com.sun.electric.technology.Technology;import com.sun.electric.tool.Job;import com.sun.electric.tool.user.User;import java.awt.Color;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.Date;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;/** * This class writes files in PostScript format. * It handles color better than existing freely available * postscript generators. It does not handle arbitrary rotations. * * Limitations: * the code to handle quad trees is rather messy now * * Ideas: * center port labels * give options about aspect ratio / page size * put date on caption * print layers on caption * draw outlines around edges * handle black & white mode * * Things still to do: * circles and arcs * rotation of the plot * eps */public class PostScriptColor{ // Constants private static final int MAXLAYERS = 1000; private static final int TREETHRESHOLD = 500; private static final double SMALL_NUM = 0.000001; private static final String FONTNAME = "Helvetica"; private static class PsPoly { double [] coords; int layer; }; private static class PsBox { double [] pos = new double[4]; // 0: dx, 1: dy, 2: left, 3: bot int layer; boolean visible; }; private static class PsLabel { String label; double [] pos = new double[4]; Poly.Type style; TextDescriptor descript; }; private static class PsCell { int cellNum; List<PsBox> boxes; List<PsPoly> polys; List<PsLabel> labels; List<PsCellInst> inst; }; private static class PsCellInst { double [] transform = new double[9]; PsCell inst; }; private static class PsBoxElement { double [] pos = new double[4]; // 0: dx, 1: dy, 2: left, 3: bot int layer; boolean visible; }; private static class PxBoxQuadTree { int numBoxes; PsBoxElement [] boxes; double [] bounds = new double[4]; // 0: dx, 1: dy, 2: left, 3: bot PxBoxQuadTree tl; PxBoxQuadTree tr; PxBoxQuadTree bl; PxBoxQuadTree br; PxBoxQuadTree parent; int level; }; private static class LayerMap { Layer layer; int mix1, mix2; // layer made from mix of previous layers, or -1 if not double r, g, b; double opacity; boolean foreground; }; // Globals private double [] psBoundaries = new double[4]; private List<PsCell> allCells; private LayerMap [] allLayers = new LayerMap[MAXLAYERS]; private List<ArrayList<PsBox>>flattenedBoxes = new ArrayList<ArrayList<PsBox>>(); private PxBoxQuadTree [] quadTrees = new PxBoxQuadTree[MAXLAYERS]; private List<ArrayList<PsPoly>>flattenedPolys = new ArrayList<ArrayList<PsPoly>>(); private int numLayers; private int totalBoxes = 0; private int totalCells = 0; private int totalPolys = 0; private int totalInstances = 0; private int cellNumber; private boolean curveWarning; private Set<Technology> techsSetup; private Map<Cell,PsCell> cellStructs; private PostScript psObject; private PostScriptColor(PostScript psObject) { this.psObject = psObject; } /** * Main entry point for color PostScript output. * @param psObject the PostScript writer object. * @param cell the Cell being written. * @param epsFormat true to write encapsulated PostScript. * @param usePlotter true for an infinitely-tall plotter, where page height is not a consideration. * @param pageWid the paper width (in 1/75 of an inch). * @param pageHei the paper height (in 1/75 of an inch). * @param pageMargin the inset margins (in 1/75 of an inch). */ public static void psColorPlot(PostScript psObject, Cell cell, boolean epsFormat, boolean usePlotter, double pageWid, double pageHei, double pageMargin) { PostScriptColor psc = new PostScriptColor(psObject); psc.doPrinting(cell, epsFormat, usePlotter, pageWid, pageHei, pageMargin); } private void doPrinting(Cell cell, boolean epsFormat, boolean usePlotter, double pageWid, double pageHei, double pageMargin) { totalBoxes = totalCells = totalPolys = totalInstances = 0; psBoundaries[0] = 1<<30; psBoundaries[1] = 1<<30; psBoundaries[2] = -1<<30; psBoundaries[3] = -1<<30; for (int i=0; i<MAXLAYERS; i++) quadTrees[i] = null; cellNumber = 1; // initialize layer maps for the current technology numLayers = 0; techsSetup = new HashSet<Technology>(); // mark all cells as "not written" cellStructs = new HashMap<Cell,PsCell>(); getLayerMap(Technology.getCurrent()); curveWarning = false; allCells = new ArrayList<PsCell>(); extractDatabase(cell); mergeBoxes(); flatten(); genOverlapShapesAfterFlattening(); writePS(cell, usePlotter, pageWid, pageHei, pageMargin);// printStatistics(); } /** * Method to get the print colors and load them into the layer map. */ private void getLayerMap(Technology tech) { // see if this technology has already been done if (techsSetup.contains(tech)) return; techsSetup.add(tech); // read layer map int startLayer = numLayers; List<Layer> layerSorts = new ArrayList<Layer>(); for(int i=0; i<tech.getNumLayers(); i++) { Layer layer = tech.getLayer(i); if (layer.isPseudoLayer()) continue; layerSorts.add(layer); } // sort by layer height Collections.sort(layerSorts, new LayersByDepth()); // load the layer information for(int i=0; i<layerSorts.size(); i++) { if (numLayers >= MAXLAYERS) { System.out.println("More than " + MAXLAYERS + " layers"); break; } Layer layer = layerSorts.get(i); allLayers[numLayers] = new LayerMap(); allLayers[numLayers].layer = layer; EGraphics graph = layer.getGraphics(); allLayers[numLayers].opacity = graph.getOpacity(); allLayers[numLayers].foreground = graph.getForeground(); Color col = graph.getColor(); allLayers[numLayers].r = col.getRed() / 255.0; allLayers[numLayers].g = col.getGreen() / 255.0; allLayers[numLayers].b = col.getBlue() / 255.0; allLayers[numLayers].mix1 = -1; allLayers[numLayers].mix2 = -1; if (allLayers[numLayers].opacity < 1) { // create new layers to provide transparency int curLayer = numLayers; for (int k=startLayer; k < curLayer; k++) { if (allLayers[k].foreground) { allLayers[++numLayers] = new LayerMap(); allLayers[numLayers].opacity = 1; allLayers[numLayers].layer = null; allLayers[numLayers].foreground = true; allLayers[numLayers].r = allLayers[curLayer].r*allLayers[curLayer].opacity + allLayers[k].r*(1-allLayers[curLayer].opacity); allLayers[numLayers].g = allLayers[curLayer].g*allLayers[curLayer].opacity + allLayers[k].g*(1-allLayers[curLayer].opacity); allLayers[numLayers].b = allLayers[curLayer].b*allLayers[curLayer].opacity + allLayers[k].b*(1-allLayers[curLayer].opacity); allLayers[numLayers].mix1 = k; allLayers[numLayers].mix2 = curLayer; } } } numLayers++; } } /** * Comparator class for sorting Layers by their height. */ private static class LayersByDepth implements Comparator<Layer> { /** * Method to sort LayerSort by their height. */ public int compare(Layer l1, Layer l2) { double diff = l1.getDepth() - l2.getDepth(); if (diff == 0.0) return 0; if (diff < 0.0) return -1; return 1; } } private void extractDatabase(Cell cell) { // check for subcells that haven't been written yet for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); if (!ni.isCellInstance()) continue; if (!ni.isExpanded()) continue; Cell subCell = (Cell)ni.getProto(); if (cellStructs.get(subCell) != null) continue; extractDatabase(subCell); } // create a cell PsCell curCell = new PsCell(); curCell.cellNum = cellNumber++; curCell.boxes = new ArrayList<PsBox>(); curCell.polys = new ArrayList<PsPoly>(); curCell.labels = new ArrayList<PsLabel>(); curCell.inst = new ArrayList<PsCellInst>(); totalCells++; // add to the lists allCells.add(curCell); cellStructs.put(cell, curCell); // examine all nodes in the cell for(Iterator<NodeInst> it = cell.getNodes(); it.hasNext(); ) { NodeInst ni = it.next(); NodeProto np = ni.getProto(); if (ni.isCellInstance()) { // instance if (!ni.isExpanded()) { // look for a black layer int i = 0; for( ; i<numLayers; i++) if (allLayers[i].r == 0 && allLayers[i].g == 0 && allLayers[i].b == 0 && allLayers[i].opacity == 1) break; if (i < numLayers) { // draw a box by plotting 4 lines Rectangle2D niBounds = ni.getBounds(); PsBox curBox = new PsBox(); curBox.layer = i; curBox.visible = true; curBox.pos[0] = 1; curBox.pos[1] = niBounds.getHeight(); curBox.pos[2] = niBounds.getMinX(); curBox.pos[3] = niBounds.getMinY(); curCell.boxes.add(curBox); curBox = new PsBox(); curBox.layer = i; curBox.visible = true; curBox.pos[0] = niBounds.getWidth(); curBox.pos[1] = 1; curBox.pos[2] = niBounds.getMinX(); curBox.pos[3] = niBounds.getMinY(); curCell.boxes.add(curBox); curBox = new PsBox(); curBox.layer = i; curBox.visible = true; curBox.pos[0] = 1; curBox.pos[1] = niBounds.getHeight(); curBox.pos[2] = niBounds.getMaxX(); curBox.pos[3] = niBounds.getMinY(); curCell.boxes.add(curBox); curBox = new PsBox(); curBox.layer = i; curBox.visible = true; curBox.pos[0] = niBounds.getWidth(); curBox.pos[1] = 1; curBox.pos[2] = niBounds.getMinX(); curBox.pos[3] = niBounds.getMaxY(); curCell.boxes.add(curBox); // add the cell name PsLabel curLabel = new PsLabel(); curLabel.label = ni.getProto().describe(false); curLabel.pos[0] = niBounds.getMinX(); curLabel.pos[1] = niBounds.getMaxX(); curLabel.pos[2] = niBounds.getMinY(); curLabel.pos[3] = niBounds.getMaxY(); curLabel.style = Poly.Type.TEXTBOX; curLabel.descript = ni.getTextDescriptor(NodeInst.NODE_NAME); curCell.labels.add(curLabel); } } else { // expanded instance: make the invocation Cell npCell = (Cell)np; PsCell subCell = cellStructs.get(npCell); PsCellInst curInst = new PsCellInst(); curInst.inst = subCell; newIdentityMatrix(curInst.transform); // account for instance position double [] transT = new double[9]; newIdentityMatrix(transT); Rectangle2D cellBounds = npCell.getBounds(); transT[2*3+0] -= cellBounds.getCenterX(); transT[2*3+1] -= cellBounds.getCenterY(); matrixMul(curInst.transform, curInst.transform, transT); // account for instance rotation double [] transR = new double[9]; newIdentityMatrix(transR); Orientation o = ni.getOrient(); double rotation = o.getCAngle() / 1800.0 * Math.PI; transR[0*3+0] = Math.cos(rotation); if (Math.abs(transR[0]) < SMALL_NUM) transR[0] = 0; transR[0*3+1] = Math.sin(rotation); if (Math.abs(transR[1]) < SMALL_NUM) transR[1] = 0; transR[1*3+0] = -Math.sin(rotation); if (Math.abs(transR[3]) < SMALL_NUM) transR[3] = 0; transR[1*3+1] = Math.cos(rotation); if (Math.abs(transR[4]) < SMALL_NUM) transR[4] = 0; matrixMul(curInst.transform, curInst.transform, transR); // account for instance transposition if (o.isCTranspose()) { newIdentityMatrix(transR); transR[0*3+0] = 0; transR[1*3+1] = 0; transR[0*3+1] = -1; transR[1*3+0] = -1; matrixMul(curInst.transform, curInst.transform, transR); } // account for instance location newIdentityMatrix(transT); transT[2*3+0] = ni.getAnchorCenterX(); transT[2*3+1] = ni.getAnchorCenterY(); matrixMul(curInst.transform, curInst.transform, transT); curCell.inst.add(curInst); } } else { // primitive: generate its layers AffineTransform trans = ni.rotateOut();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -