📄 postscript.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: PostScript.java * Input/output tool: PostScript output * Written by Steven M. Rubin, Sun Microsystems. * * Copyright (c) 2004 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.DBMath;import com.sun.electric.database.geometry.EGraphics;import com.sun.electric.database.geometry.Poly;import com.sun.electric.database.geometry.PolyBase;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.text.TextUtils;import com.sun.electric.database.text.Version;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.database.variable.EditWindow_;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.UserInterface;import com.sun.electric.database.variable.Variable;import com.sun.electric.technology.Layer;import com.sun.electric.technology.PrimitiveNode;import com.sun.electric.technology.Technology;import com.sun.electric.technology.technologies.Generic;import com.sun.electric.tool.Job;import com.sun.electric.tool.io.IOTool;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.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.List;/** * This class writes files in PostScript format. */public class PostScript extends Output{ /** scale factor for PostScript */ private static final int PSSCALE = 4;// /** scale factor for PostScript text */ private static final double PSTEXTSCALE = 0.45; /** scale factor for PostScript text */ private static final double PSTEXTSCALE = 0.75; /** size of text in the corner */ private static final int CORNERDATESIZE = 14; /** default text plain font */ private static final String DEFAULTFONT = "Times-Roman"; /** default text bold font */ private static final String DEFAULTFONTBOLD = "Times-Bold"; /** default text italic font */ private static final String DEFAULTFONTITALIC = "Times-Italic"; /** default text bold-italic font */ private static final String DEFAULTFONTBI = "Times-BoldItalic"; /** write macros for dot drawing */ private static final int HEADERDOT = 1; /** write macros for line drawing */ private static final int HEADERLINE = 2; /** write macros for polygon drawing */ private static final int HEADERPOLYGON = 3; /** write macros for filled polygon drawing */ private static final int HEADERFPOLYGON = 4; /** write macros for text drawing */ private static final int HEADERSTRING = 5; /** true if the "dot" header code has been written. */ private boolean putHeaderDot; /** true if the "line" header code has been written. */ private boolean putHeaderLine; /** true if the "polygon" header code has been written. */ private boolean putHeaderPolygon; /** true if the "filled polygon" header code has been written. */ private boolean putHeaderFilledPolygon; /** true if the "string" header code has been written. */ private boolean putHeaderString; /** true to generate color PostScript. */ private boolean psUseColor; /** true to generate merged color PostScript. */ private boolean psUseColorMerge; /** the Cell being written. */ private Cell cell; private Rectangle2D printBounds; /** list of Polys to use instead of cell contents. */ private List<PolyBase> override; /** the EditWindow_ in which the cell resides. */ private EditWindow_ wnd; /** number of patterns emitted so far. */ private int psNumPatternsEmitted; /** list of patterns emitted so far. */ private HashMap<EGraphics,Integer> patternsEmitted; /** current layer number (-1: do all; 0: cleanup). */ private int currentLayer; /** the last color written out. */ private int lastColor; /** the normal width of lines. */ private int lineWidth; /** true to plot date information in the corner. */ private boolean plotDates; /** matrix from database units to PS units. */ private AffineTransform matrix; /** fake layer for drawing outlines and text. */ private static Layer blackLayer = Layer.newInstanceFree(null, "black", new EGraphics(false, false, null, 0, 100,100,100,1.0,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); /** * Main entry point for PostScript output. * @param cell the top-level cell to write. * @param filePath the disk file to create. * @param override a list of overriding polygons to write. */ public static void writePostScriptFile(Cell cell, String filePath, List<PolyBase> override) { // just do this file writeCellToFile(cell, filePath, override); } /** * Internal method for PostScript output. * @param cell the top-level cell to write. * @param filePath the disk file to create. * @param override a list of overriding polygons to write. */ private static boolean writeCellToFile(Cell cell, String filePath, List<PolyBase> override) { boolean error = false; PostScript out = new PostScript(cell, override); if (out.openTextOutputStream(filePath)) error = true; else { // write out the cell if (cell.getView().isTextView()) { // text cell out.printWriter.println("Library: " + cell.getLibrary().getName() + " Cell: " + cell.noLibDescribe()); if (User.isIncludeDateAndVersionInOutput()) { out.printWriter.println(" Created: " + TextUtils.formatDate(cell.getCreationDate()) + " Revised: " + TextUtils.formatDate(cell.getRevisionDate())); } out.printWriter.println("\n\n"); // print the text of the cell Variable var = cell.getVar(Cell.CELL_TEXT_KEY); if (var != null) { String [] strings = (String [])var.getObject(); for(int i=0; i<strings.length; i++) out.printWriter.println(strings[i]); } } else { // layout/schematics cell if (out.start()) { out.scanCircuit(); out.done(); } } if (out.closeTextOutputStream()) error = true; } if (!error) { System.out.println(filePath + " written"); } return error; } /** * PostScript constructor. */ private PostScript(Cell cell, List<PolyBase> override) { this.cell = cell; this.override = override; } /** * Method to initialize for writing a cell. * @return false to abort the process. */ private boolean start() { // find the edit window UserInterface ui = Job.getUserInterface(); wnd = ui.getCurrentEditWindow_(); if (wnd != null && wnd.getCell() != cell) wnd = null; // clear flags that tell whether headers have been included putHeaderDot = false; putHeaderLine = false; putHeaderPolygon = false; putHeaderFilledPolygon = false; putHeaderString = false; // get control options psUseColor = psUseColorMerge = false; switch (IOTool.getPrintColorMethod()) { case 1: // color psUseColor = true; break; case 2: // color stippled psUseColor = true; break; case 3: // color merged psUseColor = psUseColorMerge = true; break; } boolean usePlotter = IOTool.isPrintForPlotter(); plotDates = IOTool.isPlotDate(); boolean epsFormat = IOTool.isPrintEncapsulated(); double pageWid = IOTool.getPrintWidth() * 75; double pageHei = IOTool.getPrintHeight() * 75; double pageMarginPS = IOTool.getPrintMargin() * 75; double pageMargin = pageMarginPS; // not right!!! // determine the area of interest printBounds = null; if (override != null) { double lX=0, hX=0, lY=0, hY=0; boolean first = true; for(PolyBase poly : override) { Point2D [] points = poly.getPoints(); for(int i=0; i<points.length; i++) { double x = points[i].getX(); double y = points[i].getY(); if (first) { first = false; lX = hX = x; lY = hY = y; } else { if (x < lX) lX = x; if (x > hX) hX = x; if (y < lY) lY = y; if (y > hY) hY = y; } } } printBounds = new Rectangle2D.Double(lX, lY, hX-lX, hY-lY); } else { printBounds = getAreaToPrint(cell, false, wnd); } if (printBounds == null) return false; boolean rotatePlot = false; switch (IOTool.getPrintRotation()) { case 1: // rotate 90 degrees rotatePlot = true; break; case 2: // auto-rotate if (((pageHei > pageWid || usePlotter) && printBounds.getWidth() > printBounds.getHeight()) || (pageWid > pageHei && printBounds.getHeight() > printBounds.getWidth())) rotatePlot = true; break; } // if plotting, compute height from width if (usePlotter) { if (rotatePlot) { pageHei = pageWid * printBounds.getWidth() / printBounds.getHeight(); } else { pageHei = pageWid * printBounds.getHeight() / printBounds.getWidth(); } } // for pure color plotting, use special merging code if (psUseColorMerge && override == null) { PostScriptColor.psColorPlot(this, cell, epsFormat, usePlotter, pageWid, pageHei, pageMarginPS); return false; } // PostScript: compute the transformation matrix double cX = printBounds.getCenterX(); double cY = printBounds.getCenterY(); double unitsX = (pageWid-pageMargin*2) * PSSCALE; double unitsY = (pageHei-pageMargin*2) * PSSCALE; if (epsFormat) { double scale = IOTool.getPrintEPSScale(cell); if (scale != 0) { unitsX *= scale; unitsY *= scale; } } double i, j; if (usePlotter) { i = unitsX / printBounds.getWidth(); j = unitsX / printBounds.getHeight(); } else { i = Math.min(unitsX / printBounds.getWidth(), unitsY / printBounds.getHeight()); j = Math.min(unitsX / printBounds.getHeight(), unitsY / printBounds.getWidth()); } if (rotatePlot) i = j; double matrix00 = i; double matrix01 = 0; double matrix10 = 0; double matrix11 = i; double matrix20 = - i * cX + unitsX / 2 + pageMarginPS * PSSCALE; double matrix21; if (usePlotter) { matrix21 = - i * printBounds.getMinY() + pageMarginPS * PSSCALE; } else { matrix21 = - i * cY + unitsY / 2 + pageMarginPS * PSSCALE; } matrix = new AffineTransform(matrix00, matrix01, matrix10, matrix11, matrix20, matrix21); // write PostScript header if (epsFormat) printWriter.println("%!PS-Adobe-2.0 EPSF-2.0"); else printWriter.println("%!PS-Adobe-1.0"); printWriter.println("%%Title: " + cell.describe(false)); if (User.isIncludeDateAndVersionInOutput()) { printWriter.println("%%Creator: Electric VLSI Design System version " + Version.getVersion()); Date now = new Date(); printWriter.println("%%CreationDate: " + TextUtils.formatDate(now)); } else { printWriter.println("%%Creator: Electric VLSI Design System"); } if (epsFormat) printWriter.println("%%Pages: 0"); else printWriter.println("%%Pages: 1"); emitCopyright("% ", ""); // transform to PostScript units double bblx = printBounds.getMinX(); double bbhx = printBounds.getMaxX(); double bbly = printBounds.getMinY(); double bbhy = printBounds.getMaxY(); Point2D bbCorner1 = psXform(new Point2D.Double(bblx, bbly)); Point2D bbCorner2 = psXform(new Point2D.Double(bbhx, bbhy)); bblx = bbCorner1.getX(); bbly = bbCorner1.getY(); bbhx = bbCorner2.getX(); bbhy = bbCorner2.getY(); if (rotatePlot) { /* * fiddle with the bbox if image rotated on page * (at this point, bbox coordinates are absolute printer units) */ double t1 = bblx; double t2 = bbhx; bblx = -bbhy + pageHei * 300 / 75; bbhx = -bbly + pageHei * 300 / 75; bbly = t1 + pageMargin*2 * 300 / 75; // this may not work because "pageMargin" is badly defined bbhy = t2 + pageMargin*2 * 300 / 75; } if (bblx > bbhx) { double s = bblx; bblx = bbhx; bbhx = s; } if (bbly > bbhy) { double s = bbly; bbly = bbhy; bbhy = s; } bblx = bblx / (PSSCALE * 75.0) * 72.0 * (bblx>=0 ? 1 : -1); bbly = bbly / (PSSCALE * 75.0) * 72.0 * (bbly>=0 ? 1 : -1); bbhx = bbhx / (PSSCALE * 75.0) * 72.0 * (bbhx>=0 ? 1 : -1); bbhy = bbhy / (PSSCALE * 75.0) * 72.0 * (bbhy>=0 ? 1 : -1); /* * Increase the size of the bbox by one "pixel" to * prevent the edges from being obscured by some drawing tools */ printWriter.println("%%BoundingBox: " + (int)(bblx-1) + " " + (int)(bbly-1) + " " + (int)(bbhx+1) + " " + (int)(bbhy+1)); printWriter.println("%%DocumentFonts: " + DEFAULTFONT); printWriter.println("%%EndComments"); if (!epsFormat) printWriter.println("%%Page: 1 1"); // PostScript: add some debugging info if (cell != null) { Rectangle2D bounds = cell.getBounds(); printWriter.println("% cell dimensions: " + bounds.getWidth() + " wide x " + bounds.getHeight() + " high (database units)"); printWriter.println("% origin: " + bounds.getMinX() + " " + bounds.getMinY()); } // disclaimers if (epsFormat) { printWriter.println("% The EPS header should declare a private dictionary."); } else { printWriter.println("% The non-EPS header does not claim conformance to Adobe-2.0"); printWriter.println("% because the structure may not be exactly correct."); } printWriter.println("%"); // set the page size if this is a plotter if (usePlotter) { printWriter.println("<< /PageSize [" + (int)(pageWid * 72 / 75) + " " + (int)(pageHei * 72 / 75) + "] >> setpagedevice"); } // make the scale be exactly equal to one page pixel printWriter.println("72 " + PSSCALE*75 + " div 72 " + PSSCALE*75 + " div scale"); // set the proper typeface printWriter.println("/DefaultFont /" + DEFAULTFONT + " def"); printWriter.println("/scaleFont {"); printWriter.println(" DefaultFont findfont"); printWriter.println(" exch scalefont setfont} def"); // make the line width proper lineWidth = (int)(PSSCALE/2 * IOTool.getPrintPSLineWidth()); printWriter.println(lineWidth + " setlinewidth"); // make the line ends look right printWriter.println("1 setlinecap"); // rotate the image if requested if (rotatePlot) { if (usePlotter) { printWriter.println((pageWid/75) + " 300 mul " + ((pageHei-pageWid)/2/75) + " 300 mul translate 90 rotate"); } else { printWriter.println((pageHei+pageWid)/2/75 + " 300 mul " + (pageHei-pageWid)/2/75 + " 300 mul translate 90 rotate"); } } // initialize list of EGraphics modules that have been put out patternsEmitted = new HashMap<EGraphics,Integer>(); psNumPatternsEmitted = 0; return true; } /** * Method to clean-up writing a cell. */ private void done() { // draw the grid if requested if (psUseColor) printWriter.println("0 0 0 setrgbcolor"); if (wnd != null && wnd.isGrid()) { int gridx = (int)wnd.getGridXSpacing(); int gridy = (int)wnd.getGridYSpacing(); int lx = (int)cell.getBounds().getMinX(); int ly = (int)cell.getBounds().getMinY(); int hx = (int)cell.getBounds().getMaxX(); int hy = (int)cell.getBounds().getMaxY(); int gridlx = lx / gridx * gridx; int gridly = ly / gridy * gridy; // adjust to ensure that the first point is inside the range if (gridlx > lx) gridlx -= (gridlx - lx) / gridx * gridx; if (gridly > ly) gridly -= (gridly - ly) / gridy * gridy; while (gridlx < lx) gridlx += gridx; while (gridly < ly) gridly += gridy; // PostScript: write the grid loop double matrix00 = matrix.getScaleX(); double matrix01 = matrix.getShearX(); double matrix10 = matrix.getShearY();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -