📄 vectordrawing.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: VectorDrawing.java * * 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.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.geometry.GenMath.MutableDouble;import com.sun.electric.database.hierarchy.Cell;import com.sun.electric.database.hierarchy.Export;import com.sun.electric.database.text.TextUtils;import com.sun.electric.database.topology.NodeInst;import com.sun.electric.database.variable.TextDescriptor;import com.sun.electric.database.variable.VarContext;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 com.sun.electric.tool.user.ui.TopLevel;import java.awt.Color;import java.awt.Dimension;import java.awt.Point;import java.awt.Rectangle;import java.awt.geom.AffineTransform;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;/** * Class to do rapid redraw by caching the vector coordinates of all objects. */class VectorDrawing{ private static final boolean TAKE_STATS = false; private static final boolean DEBUGIMAGES = false; private static final int MAXGREEKSIZE = 25; private static final int SCALE_SH = 20; /** the rendering object */ private PixelDrawing offscreen; /** the window scale */ private float scale; /** the window scale */ private float scale_; /** the window scale and pan factor */ private float factorX, factorY; private int factorX_, factorY_; private int scale_int; /** true if "peeking" and expanding to the bottom */ private boolean fullInstantiate; /** A List of NodeInsts to the cell being in-place edited. */private List<NodeInst> inPlaceNodePath; /** The current cell being in-place edited. */ private Cell inPlaceCurrent; /** time that rendering started */ private long startTime; /** true if the user has been told of delays */ private boolean takingLongTime; /** true to stop rendering */ private boolean stopRendering; /** the half-sizes of the window (in pixels) */ private int szHalfWidth, szHalfHeight; /** the screen clipping */ private int screenLX, screenHX, screenLY, screenHY; /** statistics */ private int boxCount, tinyBoxCount, lineBoxCount, lineCount, polygonCount; /** statistics */ private int crossCount, textCount, circleCount, arcCount; /** statistics */ private int subCellCount, tinySubCellCount; /** the threshold of object sizes */ private float maxObjectSize; /** the threshold of text sizes */ private float maxTextSize; /** the maximum cell size above which no greeking */ private float maxCellSize; /** temporary objects (saves allocation) */ private Point tempPt1 = new Point(), tempPt2 = new Point(); /** temporary objects (saves allocation) */ private Point tempPt3 = new Point(); /** temporary object (saves allocation) */ private Rectangle tempRect = new Rectangle(); /** the color of text */ private Color textColor; /** the object that draws the rendered screen */ private static VectorDrawing topVD; /** location for debugging icon displays */ private static int debugXP, debugYP; 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 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}); // ************************************* TOP LEVEL ************************************* /** * Constructor creates a VectorDrawing object for a given EditWindow. * @param wnd the EditWindow associated with this VectorDrawing. */ public VectorDrawing() { } /** * Main entry point for drawing a cell. * @param offscreen offscreen buffer * @param scale edit window scale * @param offset the offset factor for this window * @param cell the cell to draw * @param fullInstantiate true to draw all the way to the bottom of the hierarchy. * @param inPlaceNodePath a List of NodeInsts to the cell being in-place edited * @param screenLimit the area in the cell to display (null to show all). */ public void render(PixelDrawing offscreen, double scale, Point2D offset, Cell cell, boolean fullInstantiate, List<NodeInst> inPlaceNodePath, Cell inPlaceCurrent, Rectangle screenLimit, VarContext context) { // set colors to use textGraphics.setColor(new Color(User.getColor(User.ColorPrefType.TEXT))); instanceGraphics.setColor(new Color(User.getColor(User.ColorPrefType.INSTANCE))); textColor = new Color(User.getColor(User.ColorPrefType.TEXT) & 0xFFFFFF); // see if any layers are being highlighted/dimmed this.offscreen = offscreen; offscreen.highlightingLayers = false; for(Iterator<Layer> it = Technology.getCurrent().getLayers(); it.hasNext(); ) { Layer layer = it.next(); if (layer.isDimmed()) { offscreen.highlightingLayers = true; break; } } // set size limit Dimension sz = offscreen.getSize(); this.scale = (float)scale; scale_ = (float)(scale/DBMath.GRID); maxObjectSize = (float)User.getGreekSizeLimit() / this.scale; maxTextSize = maxObjectSize / (float)User.getGlobalTextScale(); double screenArea = sz.getWidth()/scale * sz.getHeight()/scale; maxCellSize = (float)(User.getGreekCellSizeLimit() * screenArea); // statistics startTime = System.currentTimeMillis(); long initialUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); takingLongTime = false; boxCount = tinyBoxCount = lineBoxCount = lineCount = polygonCount = 0; crossCount = textCount = circleCount = arcCount = 0; subCellCount = tinySubCellCount = 0; // draw recursively this.fullInstantiate = fullInstantiate; this.inPlaceNodePath = inPlaceNodePath; this.inPlaceCurrent = inPlaceCurrent; szHalfWidth = sz.width / 2; szHalfHeight = sz.height / 2; screenLX = 0; screenHX = sz.width; screenLY = 0; screenHY = sz.height; factorX = (float)(offset.getX()*DBMath.GRID - szHalfWidth/scale_); factorY = (float)(offset.getY()*DBMath.GRID + szHalfHeight/scale_); factorX_ = (int)factorX; factorY_ = (int)factorY; scale_int = (int)(scale_ * (1 << SCALE_SH)); if (screenLimit != null) { screenLX = screenLimit.x; if (screenLX < 0) screenLX = 0; screenHX = screenLimit.x + screenLimit.width; if (screenHX >= sz.width) screenHX = sz.width-1; screenLY = screenLimit.y; if (screenLY < 0) screenLY = 0; screenHY = screenLimit.y + screenLimit.height; if (screenHY >= sz.height) screenHY = sz.height-1; } // draw the screen, starting with the top cell stopRendering = false; try { VectorCache.VectorCell topVC = drawCell(cell, Orientation.IDENT, context); topVD = this; render(topVC, 0, 0, context, 0); drawList(0, 0, topVC.getTopOnlyShapes(), 0, false); } catch (AbortRenderingException e) { } topVD = null; if (takingLongTime) { TopLevel.setBusyCursor(false); System.out.println("Done"); } if (TAKE_STATS && Job.getDebug()) { long curUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long memUsed = curUsed - initialUsed; long renderTime = System.currentTimeMillis() - startTime; System.out.println("Time to render: "+TextUtils.getElapsedTime(renderTime) + " Memory Used: "+ memUsed); System.out.println(" Rendered "+boxCount+" boxes ("+tinyBoxCount+" tiny, "+lineBoxCount+" lines), "+ lineCount+" lines, "+polygonCount+" polys, "+crossCount+" crosses, "+ textCount+" texts, "+circleCount+" circles, "+arcCount+" arcs, "+ subCellCount+" subcells ("+tinySubCellCount+" tiny)"); } } /** * Main entry point for drawing a tech menu entry. * @param offscreen offscreen buffer * @param scale edit window scale * @param offset the offset factor for this window * @param shapes shapes of tech menu * @param forceVisible true to force all layers to be drawn (regardless of user settings) */ public void render(PixelDrawing offscreen, double scale, Point2D offset, VectorCache.VectorBase[] shapes, boolean forceVisible) { // set colors to use textGraphics.setColor(new Color(User.getColor(User.ColorPrefType.TEXT))); textColor = new Color(User.getColor(User.ColorPrefType.TEXT) & 0xFFFFFF); // see if any layers are being highlighted/dimmed this.offscreen = offscreen; // set size limit Dimension sz = offscreen.getSize(); this.scale = (float)scale; scale_ = (float)(scale/DBMath.GRID); // draw recursively szHalfWidth = sz.width / 2; szHalfHeight = sz.height / 2; screenLX = 0; screenHX = sz.width; screenLY = 0; screenHY = sz.height; factorX = (float)(offset.getX()*DBMath.GRID - szHalfWidth/scale_); factorY = (float)(offset.getY()*DBMath.GRID + szHalfHeight/scale_); factorX_ = (int)factorX; factorY_ = (int)factorY; scale_int = (int)(scale_ * (1 << SCALE_SH)); // draw the screen, starting with the top cell try { List<VectorCache.VectorBase> shapeList = Arrays.asList(shapes); drawList(0, 0, shapeList, 0, forceVisible); } catch (AbortRenderingException e) { } } /** * Class to define a signal to abort rendering. */ class AbortRenderingException extends Exception {} /** * Method to request that the current rendering be aborted because it must be restarted. * */ public void abortRendering() { stopRendering = true; } /** * Method to recursively render a cached cell. * @param vc the cached cell to render * @param oX the X offset for rendering the cell (in database grid coordinates). * @param oY the Y offset for rendering the cell (in database grid coordinates). * @param context the VarContext for this point in the rendering. * @param level: 0=top-level cell in window; 1=low level cell; -1=greeked cell. */ private void render(VectorCache.VectorCell vc, int oX, int oY, VarContext context, int level) throws AbortRenderingException { // render main list of shapes drawList(oX, oY, vc.filledShapes, level, false); drawList(oX, oY, vc.shapes, level, false); // now render subcells Cell cell = VectorCache.theCache.database.getCell(vc.vcg.cellId); for(VectorCache.VectorSubCell vsc : vc.subCells) { if (stopRendering) throw new AbortRenderingException(); NodeInst ni = cell.getNodeById(vsc.n.nodeId); Cell subCell = (Cell)ni.getProto(); subCellCount++; // get instance location int soX = vsc.offsetX + oX; int soY = vsc.offsetY + oY; VectorCache.VectorCell subVC = VectorCache.theCache.findVectorCell(vsc.subCellId, vc.orient.concatenate(vsc.n.orient)); gridToScreen(subVC.lX + soX, subVC.hY + soY, tempPt1); gridToScreen(subVC.hX + soX, subVC.lY + soY, tempPt2); int lX = tempPt1.x; int lY = tempPt1.y; int hX = tempPt2.x; int hY = tempPt2.y; // see if the subcell is clipped if (hX < screenLX || lX >= screenHX) continue; if (hY < screenLY || lY >= screenHY) continue; // see if the cell is too tiny to draw if (subVC.vcg.cellMinSize < maxObjectSize) { Orientation thisOrient = vsc.n.orient; Orientation recurseTrans = vc.orient.concatenate(thisOrient); VarContext subContext = context.push(ni); VectorCache.VectorCell subVC_ = drawCell(subCell, recurseTrans, subContext); assert subVC_ == subVC; makeGreekedImage(subVC); int fadeColor = getFadeColor(subVC, subContext); drawTinyBox(lX, hX, lY, hY, fadeColor, subVC); tinySubCellCount++; continue; } // see if drawing "down in place" boolean onPathDown = false; if (inPlaceNodePath != null) { for(NodeInst niOnPath : inPlaceNodePath) { if (niOnPath.getProto().getId() == vsc.subCellId) { onPathDown = true; break; } } } // see if cell contents should be drawn boolean expanded = ni.isExpanded() || fullInstantiate; // if not expanded, but viewing this cell in-place, expand it if (!expanded && onPathDown) expanded = true; if (expanded) { Orientation thisOrient = vsc.n.orient; Orientation recurseTrans = vc.orient.concatenate(thisOrient); VarContext subContext = context.push(ni); VectorCache.VectorCell subVC_ = drawCell(subCell, recurseTrans, subContext); assert subVC_ == subVC; // expanded cells may be replaced with greeked versions (not icons) if (!subCell.isIcon()) { // may also be "tiny" if all features in the cell are tiny boolean allFeaturesTiny = subVC.maxFeatureSize > 0 && subVC.maxFeatureSize < maxObjectSize && subVC.vcg.cellArea < maxCellSize && isContentsTiny(subCell, subVC, recurseTrans, context); // may also be "tiny" if the cell is smaller than the greeked image boolean smallerThanGreek = User.isUseCellGreekingImages() && hX-lX <= MAXGREEKSIZE && hY-lY <= MAXGREEKSIZE; if (allFeaturesTiny || smallerThanGreek) { makeGreekedImage(subVC); int fadeColor = getFadeColor(subVC, context); drawTinyBox(lX, hX, lY, hY, fadeColor, subVC); tinySubCellCount++; continue; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -