📄 pixeldrawing.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: PixelDrawing.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.user.redisplay;import com.sun.electric.database.geometry.DBMath;import com.sun.electric.database.geometry.EGraphics;import com.sun.electric.database.geometry.GenMath;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.id.CellId;import com.sun.electric.database.prototype.NodeProto;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.database.variable.EditWindow0;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.VarContext;import com.sun.electric.technology.ArcProto;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.user.User;import com.sun.electric.tool.user.ui.EditWindow;import com.sun.electric.tool.user.ui.WindowFrame;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.Graphics2D;import java.awt.Image;import java.awt.Point;import java.awt.Rectangle;import java.awt.RenderingHints;import java.awt.font.FontRenderContext;import java.awt.font.GlyphVector;import java.awt.font.LineMetrics;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.awt.image.BufferedImage;import java.awt.image.DataBufferByte;import java.awt.image.DataBufferInt;import java.awt.image.Raster;import java.awt.image.WritableRaster;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import javax.swing.SwingUtilities;/** * This class manages an offscreen display for an associated EditWindow. * It renders an Image for copying to the display. * <P> * Every offscreen display consists of two parts: the transparent layers and the opaque image. * To tell how a layer is displayed, look at the "transparentLayer" field of its "EGraphics" object. * When this is nonzero, the layer is drawn transparent. * When this is zero, use the "red, green, blue" fields for the opaque color. * <P> * The opaque image is a full-color Image that is the size of the EditWindow. * Any layers that are marked "opaque" are drawn in full color in the image. * Colors are not combined in the opaque image: every color placed in it overwrites the previous color. * For this reason, opaque colors are often stipple patterns, so that they won't completely obscure other * opaque layers. * <P> * The transparent layers are able to combine with each other. * Typically, the more popular layers are made transparent (metal, poly, active, etc.) * For every transparent layer, there is a 1-bit deep bitmap that is the size of the EditWindow. * The bitmap is an array of "byte []" pointers, one for every Y coordinate in the EditWindow. * Each array contains the bits for that row, packed 8 per byte. * All of this information is in the "layerBitMaps" field, which is triply indexed. * <P> * Thus, to find bit (x,y) of transparent layer T, first lookup the appropriate transparent layer, * ("layerBitMaps[T]"). * Then, for that layer, find the array of bytes for the appropriate row * (by indexing the the Y coordinate into the rowstart array, "layerBitMaps[T][y]"). * Next, figure out which byte has the bit (by dividing the X coordinate by 8: "layerBitMaps[T][y][x>>3]"). * Finally, determine which bit to use (by using the low 3 bits of the X coordinate, * layerBitMaps[T][y][x>>3] & (1 << (x&7)) ). * <P> * Transparent layers are not allocated until needed. Thus, if there are 5 possible transparent layers, * but only 2 are used, then only two bitplanes will be created. * <P> * Each technology declares the number of possible transparent layers that it can generate. * In addition, it must provide a color map for describing every combination of transparent layer. * This map is, of course, 2-to-the-number-of-possible-transparent-layers long. * <P> * The expected number of transparent layers is taken from the current technology. If the user switches * the current technology, but draws something from a different technology, then the drawn circuitry * may make use of transparent layers that don't exist in the current technology. In such a case, * the transparent request is made opaque. * <P> * When all rendering is done, the full-color image is composited with the transparent layers to produce * the final image. * This is done by scanning the full-color image for any entries that were not filled-in. * These are then replaced by the transparent color at that point. * The transparent color is computed by looking at the bits in every transparent bitmap and * constructing an index. This is looked-up in the color table and the appropriate color is used. * If no transparent layers are set, the background color is used. * <P> * There are a number of efficiencies implemented here. * <UL> * <LI><B>Setting bits directly into the offscreen memory</B>. * Although Java's Swing package has a rendering model, it was found to be 3 times slower than * setting bits directly in the offscreen memory.</LI> * <LI><B>Tiny nodes and arcs are approximated</B>. * When a node or arc will be only 1 or 2 pixels in size on the screen, it is not necessary * to actually compute the edges of all of its parts. Instead, a single pixel of color is placed. * The color is taken from all of the layers that compose the node or arc. * For arcs that are long but only 1 pixel wide, a line is drawn in the same manner. * This optimization adds another factor of 2 to the speed of display.</LI> * <LI><B>Expanded cell contents are cached</B>. * When a cell is expanded, and its contents is drawn, the contents are preserved so that they * need be rendered only once. Subsequent instances of that expanded cell are able to be instantly drawn. * There are a number of extra considerations here: * <UL> * <LI>Cell instances can appear in any orientation. Therefore, the cache of drawn cells must * include the orientation.</LI> * <LI>Cached cells are retained as long as the current scale is maintained. But when zooming * in and out, the cache is cleared.</LI> * <LI>Cell instances may appear at different levels of the hierarchy, with different other circuitry over * them. For example, an instance may have been rendered at one level of hierarchy, and other items at that * same level then rendered over it. It is then no longer possible to copy those bits when the instance * appears again at another place in the hierarchy because it has been altered by neighboring circuitry. * The same problem happens when cell instances overlap. Therefore, it is necessary to render each expanded * cell instance into its own offscreen map, with its own separate opaque and transparent layers (which allows * it to be composited properly when re-instantiated). Thus, a new PixelDrawing" object is created for each * cached cell.</LI> * <LI>Subpixel alignment may not be the same for each cached instance. This turns out not to be * a problem, because at such zoomed-out scales, it is impossible to see individual objects anyway.</LI> * <LI>Large cell instances should not be cached. When zoomed-in, an expanded cell instance could * be many megabytes in size, and only a portion of it appears on the screen. Therefore, large cell * instances are not cached, but drawn directly. It is assumed that there will be few such instances. * The rule currently is that any cell whose width is greater than half of the display size AND whose * height is greater than half of the display size is too large to cache.</LI> * <LI>If an instance only appears once, it is not cached. This requires a preprocessing step to scan * the hierarchy and count the number of times that a particular cell-transformation is used. During * rendering, if the count is only 1, it is not cached. The exception to this rule is if the screen * is redisplayed without a change of magnification (during panning, for example). In such a case, * all cells will eventually be cached because, even those used once are being displayed with each redraw. </LI> * <LI>Texture patterns don't line-up. When drawing texture pattern to the final buffer, it is easy * to use the screen coordinates to index the pattern map, causing all of them to line-up. * Any two adjoining objects that use the same pattern will have their patterns line-up smoothly. * However, when caching cell instances, it is not possible to know where the contents will be placed * on the screen, and so the texture patterns rendered into the cache cannot be aligned globally. * To solve this, there are additional bitmaps created for every Patterned-Opaque-Layer (POL). * When rendering on a layer that is patterned and opaque, the bitmap is dynamically allocated * and filled (all bits are filled on the bitmap, not just those in the pattern). * When combining lower-level cell images with higher-level ones, these POLs are copied, too. * When compositing at the top level, however, the POLs are converted back to patterns, so that they line-up.</LI> * </UL> * </UL> * */public class PixelDrawing{ /** Text smaller than this will not be drawn. */ public static final int MINIMUMTEXTSIZE = 5; /** Text larger than this is granular. */ public static final int MAXIMUMTEXTSIZE = 100; /** Number of singleton cells to cache when redisplaying. */ public static final int SINGLETONSTOADD = 5; private static class PolySeg { private int fx,fy, tx,ty, direction, increment; private PolySeg nextedge; private PolySeg nextactive; } // statistics stuff private static final boolean TAKE_STATS = true; private static int tinyCells, tinyPrims, totalCells, renderedCells, totalPrims, tinyArcs, linedArcs, totalArcs; private static int offscreensCreated, offscreenPixelsCreated, offscreensUsed, offscreenPixelsUsed, cellsRendered; private static final boolean DEBUGRENDERTIMING = false; private static long renderTextTime; private static long renderPolyTime; private static class ExpandedCellKey { private Cell cell; private Orientation orient; private ExpandedCellKey(Cell cell, Orientation orient) { this.cell = cell; this.orient = orient; } @Override public boolean equals(Object obj) { if (obj instanceof ExpandedCellKey) { ExpandedCellKey that = (ExpandedCellKey)obj; return this.cell == that.cell && this.orient.equals(that.orient); } return false; } @Override public int hashCode() { return cell.hashCode()^orient.hashCode(); } } /** * This class holds information about expanded cell instances. * For efficiency, Electric remembers the bits in an expanded cell instance * and uses them when another expanded instance appears elsewhere. * Of course, the orientation of the instance matters, so each combination of * cell and orientation forms a "cell cache". The Cell Cache is stored in the * "wnd" field (which has its own PixelDrawing object). */ private static class ExpandedCellInfo { private boolean singleton; private int instanceCount; private PixelDrawing offscreen; ExpandedCellInfo() { singleton = true; offscreen = null; } } /** the size of the EditWindow */ private final Dimension sz; /** the scale of the EditWindow */ private double scale; /** the VarContext of the EditWindow */ private VarContext varContext = VarContext.globalContext; /** the X origin of the cell in display coordinates. */ private double originX; /** the Y origin of the cell in display coordinates. */ private double originY; /** 0: color display, 1: color printing, 2: B&W printing */ private int nowPrinting; /** the area of the cell to draw, in DB units */ private Rectangle2D drawBounds; /** whether any layers are highlighted/dimmed */ boolean highlightingLayers; /** true if the last display was a full-instantiate */ private boolean lastFullInstantiate = false; /** A List of NodeInsts to the cell being in-place edited. */private List<NodeInst> inPlaceNodePath; /** true if text can be drawn (not too zoomed-out) */ private boolean canDrawText; /** maximum size before an object is too small */ private static double maxObjectSize; /** half of maximum object size */ private static double halfMaxObjectSize; /** temporary objects (saves reallocation) */ private final Point tempPt1 = new Point(), tempPt2 = new Point(); /** temporary objects (saves reallocation) */ private final Point tempPt3 = new Point(), tempPt4 = new Point(); // the full-depth image /** the offscreen opaque image of the window */ private final BufferedImage img; /** opaque layer of the window */ private final int [] opaqueData; /** size of the opaque layer of the window */ private final int total; /** the background color of the offscreen image */ private int backgroundColor; /** the "unset" color of the offscreen image */ private int backgroundValue; // the transparent bitmaps /** the offscreen maps for transparent layers */ private byte [][][] layerBitMaps; /** row pointers for transparent layers */ private byte [][] compositeRows; /** the number of transparent layers */ int numLayerBitMaps; /** the number of bytes per row in offscreen maps */ private final int numBytesPerRow; /** the number of offscreen transparent maps made */ private int numLayerBitMapsCreated; /** the technology of the window */ private Technology curTech; // the patterned opaque bitmaps private static class PatternedOpaqueLayer { private byte[][] layerBitMap; PatternedOpaqueLayer(int height, int numBytesPerRow) { layerBitMap = new byte[height][numBytesPerRow]; } } /** the map from layers to Patterned Opaque bitmaps */ private Map<Layer,PatternedOpaqueLayer> patternedOpaqueLayers = new HashMap<Layer,PatternedOpaqueLayer>(); /** the top-level window being rendered */ private boolean renderedWindow; /** whether to occasionally update the display. */ private boolean periodicRefresh; /** keeps track of when to update the display. */ private int objectCount; /** keeps track of when to update the display. */ private long lastRefreshTime; /** the EditWindow being drawn */ private EditWindow wnd; /** the size of the top-level EditWindow */ private static Dimension topSz; /** the last Technology that had transparent layers */ private static Technology techWithLayers = null; /** list of cell expansions. */ private static Map<ExpandedCellKey,ExpandedCellInfo> expandedCells = null; /** Set of changed cells. */ private static final Set<CellId> changedCells = new HashSet<CellId>(); /** scale of cell expansions. */ private static double expandedScale = 0; /** number of extra cells to render this time */ private static int numberToReconcile; /** zero rectangle */ private static final Rectangle2D CENTERRECT = new Rectangle2D.Double(0, 0, 0, 0); private static Color textColor; private static EGraphics textGraphics = new EGraphics(false, false, null, 0, 0,0,0, 1.0,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}); private static EGraphics gridGraphics = new EGraphics(false, false, null, 0, 0,0,0, 1.0,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}); private static EGraphics instanceGraphics = new EGraphics(false, false, null, 0, 0,0,0, 1.0,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}); private static EGraphics portGraphics = new EGraphics(false, false, null, 0, 255,0,0, 1.0,true, new int[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}); private int clipLX, clipHX, clipLY, clipHY; private final EditWindow0 dummyWnd = new EditWindow0() { public VarContext getVarContext() { return varContext; } public double getScale() { return scale; } public double getGlobalTextScale() { return wnd.getGlobalTextScale(); } }; static class Drawing extends AbstractDrawing { private final VectorDrawing vd = new VectorDrawing(); private volatile PixelDrawing offscreen; Drawing(EditWindow wnd) { super(wnd); } @Override public boolean paintComponent(Graphics2D g, Dimension sz) { assert SwingUtilities.isEventDispatchThread(); assert sz.equals(wnd.getSize()); PixelDrawing offscreen = this.offscreen; if (offscreen == null || !offscreen.getSize().equals(sz)) return false; // show the image g.drawImage(offscreen.getBufferedImage(), 0, 0, wnd); return true; } @Override public void render(Dimension sz, WindowFrame.DisplayAttributes da, boolean fullInstantiate, Rectangle2D bounds) { PixelDrawing offscreen_ = this.offscreen; if (offscreen_ == null || !offscreen_.getSize().equals(sz))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -