📄 pixeldrawing.java
字号:
for(Iterator<Export> it = ni.getExports(); it.hasNext();) { Export exp = it.next(); PortInst pi = exp.getOriginalPort(); Export e = (Export)pi.getPortProto(); if (!e.isAlwaysDrawn()) shownPorts[pi.getPortIndex()] = true; } int portDisplayLevel = User.getPortDisplayLevel(); for(int i = 0; i < numPorts; i++) { if (shownPorts[i]) continue; Export pp = (Export)ni.getProto().getPort(i); Poly portPoly = ni.getShapeOfPort(pp); if (portPoly == null) continue; portPoly.transform(trans); Color portColor = col; if (portColor == null) portColor = pp.getBasePort().getPortColor(); portGraphics.setColor(portColor); if (portDisplayLevel == 2) { // draw port as a cross drawCross(portPoly, portGraphics, false); } else { // draw port as text if (User.isTextVisibilityOnPort()) { // combine all features of port text with color of the port TextDescriptor descript = portPoly.getTextDescriptor(); TextDescriptor portDescript = pp.getTextDescriptor(Export.EXPORT_NAME).withColorIndex(descript.getColorIndex()); Poly.Type type = descript.getPos().getPolyType(); String portName = pp.getName(); if (portDisplayLevel == 1) { // use shorter port name portName = pp.getShortName(); } databaseToScreen(portPoly.getCenterX(), portPoly.getCenterY(), tempPt1); Rectangle rect = new Rectangle(tempPt1); drawText(rect, type, portDescript, portName, null, portGraphics, false); } } } } private void drawUnexpandedCell(NodeInst ni, Poly poly) { // draw the instance outline Point2D [] points = poly.getPoints(); for(int i=0; i<points.length; i++) { int lastI = i - 1; if (lastI < 0) lastI = points.length - 1; Point2D lastPt = points[lastI]; Point2D thisPt = points[i]; databaseToScreen(lastPt.getX(), lastPt.getY(), tempPt1); databaseToScreen(thisPt.getX(), thisPt.getY(), tempPt2); drawLine(tempPt1, tempPt2, null, instanceGraphics, 0, false); } // draw the instance name if (canDrawText && User.isTextVisibilityOnInstance()) { Rectangle2D bounds = poly.getBounds2D(); Rectangle rect = databaseToScreen(bounds); TextDescriptor descript = ni.getTextDescriptor(NodeInst.NODE_PROTO); NodeProto np = ni.getProto(); drawText(rect, Poly.Type.TEXTBOX, descript, np.describe(false), null, textGraphics, false); } } private void drawTinyLayers(Iterator<Layer> layerIterator, int x, int y) { for(Iterator<Layer> it = layerIterator; it.hasNext(); ) { Layer layer = it.next(); if (layer == null) continue; byte [][] layerBitMap = null; int col = 0; EGraphics graphics = layer.getGraphics(); if (graphics != null) { if (nowPrinting != 0 ? graphics.isPatternedOnPrinter() : graphics.isPatternedOnDisplay()) { int [] pattern = graphics.getPattern(); if (pattern != null) { int pat = pattern[y&15]; if (pat == 0 || (pat & (0x8000 >> (x&15))) == 0) continue; } } int layerNum = graphics.getTransparentLayer() - 1; if (layerNum < numLayerBitMaps) layerBitMap = getLayerBitMap(layerNum); col = graphics.getRGB(); } // set the bit if (layerBitMap == null) { int index = y * sz.width + x; int alpha = (opaqueData[index] >> 24) & 0xFF; if (alpha == 0xFF) opaqueData[index] = col; } else { layerBitMap[y][x>>3] |= (1 << (x&7)); } } } private void drawTinyArc(Iterator<Layer> layerIterator, Point head, Point tail) { for(Iterator<Layer> it = layerIterator; it.hasNext(); ) { Layer layer = it.next(); if (layer == null) continue; EGraphics graphics = layer.getGraphics(); byte [][] layerBitMap = null; if (graphics != null) { int layerNum = graphics.getTransparentLayer() - 1; if (layerNum < numLayerBitMaps) layerBitMap = getLayerBitMap(layerNum); } drawLine(head, tail, layerBitMap, graphics, 0, layer.isDimmed()); } } // ************************************* CELL CACHING ************************************* /** * @return true if the cell is properly handled and need no further processing. * False to render the contents recursively. */ private boolean expandedCellCached(Cell subCell, Orientation orient, AffineTransform origTrans, Cell topCell, Rectangle2D drawLimitBounds, boolean fullInstantiate) { // if there is no global for remembering cached cells, do not cache if (expandedCells == null) return false; // do not cache icons: they can be redrawn each time if (subCell.isIcon()) return false; ExpandedCellKey expansionKey = new ExpandedCellKey(subCell, orient); ExpandedCellInfo expandedCellCount = expandedCells.get(expansionKey); if (expandedCellCount != null) { // if this combination is not used multiple times, do not cache it if (expandedCellCount.singleton && expandedCellCount.instanceCount < 2 && expandedCellCount.offscreen == null) { if (numberToReconcile > 0) { numberToReconcile--; expandedCellCount.singleton = false; } else return false; } } if (expandedCellCount == null || expandedCellCount.offscreen == null) { // compute the cell's location on the screen Rectangle2D cellBounds = new Rectangle2D.Double(); cellBounds.setRect(subCell.getBounds()); Rectangle2D textBounds = subCell.getTextBounds(dummyWnd); if (textBounds != null) cellBounds.add(textBounds); AffineTransform rotTrans = orient.pureRotate(); DBMath.transformRect(cellBounds, rotTrans); int lX = (int)Math.floor(cellBounds.getMinX()*scale); int hX = (int)Math.ceil(cellBounds.getMaxX()*scale); int lY = (int)Math.floor(cellBounds.getMinY()*scale); int hY = (int)Math.ceil(cellBounds.getMaxY()*scale); Rectangle screenBounds = new Rectangle(lX, lY, hX - lX, hY - lY); if (screenBounds.width <= 0 || screenBounds.height <= 0) return true; // do not cache if the cell is too large (creates immense offscreen buffers) if (screenBounds.width >= topSz.width/2 && screenBounds.height >= topSz.height/2) return false; // if this is the first use, create the offscreen buffer if (expandedCellCount == null) { expandedCellCount = new ExpandedCellInfo(); expandedCells.put(expansionKey, expandedCellCount); } expandedCellCount.offscreen = new PixelDrawing(scale, screenBounds); expandedCellCount.offscreen.drawCell(subCell, null, fullInstantiate, orient, rotTrans, topCell); offscreensCreated++; offscreenPixelsCreated += expandedCellCount.offscreen.total; } // copy out of the offscreen buffer into the main buffer databaseToScreen(origTrans.getTranslateX(), origTrans.getTranslateY(), tempPt1); copyBits(expandedCellCount.offscreen, tempPt1.x, tempPt1.y); offscreensUsed++; offscreenPixelsUsed += expandedCellCount.offscreen.total; return true; } /** * Recursive method to count the number of times that a cell-transformation is used */ private void countCell(Cell cell, Rectangle2D drawLimitBounds, boolean fullInstantiate, Orientation orient, AffineTransform prevTrans) { // look for subcells for(Iterator<NodeInst> nodes = cell.getNodes(); nodes.hasNext(); ) { NodeInst ni = nodes.next(); if (!ni.isCellInstance()) continue; // if limiting drawing, reject when out of area if (drawLimitBounds != null) { Rectangle2D curBounds = ni.getBounds(); Rectangle2D bounds = new Rectangle2D.Double(curBounds.getX(), curBounds.getY(), curBounds.getWidth(), curBounds.getHeight()); DBMath.transformRect(bounds, prevTrans); if (!DBMath.rectsIntersect(bounds, drawLimitBounds)) return; } countNode(ni, drawLimitBounds, fullInstantiate, orient, prevTrans); } } /** * Recursive method to count the number of times that a cell-transformation is used */ private void countNode(NodeInst ni, Rectangle2D drawLimitBounds, boolean fullInstantiate, Orientation orient, AffineTransform trans) { // if the node is tiny, it will be approximated double objWidth = Math.max(ni.getXSize(), ni.getYSize()); if (objWidth < maxObjectSize) return; // transform into the subcell Orientation subOrient = orient.concatenate(ni.getOrient()); AffineTransform subTrans = ni.transformOut(trans); // compute where this cell lands on the screen NodeProto np = ni.getProto(); Cell subCell = (Cell)np; Rectangle2D cellBounds = subCell.getBounds(); Poly poly = new Poly(cellBounds); poly.transform(subTrans); cellBounds = poly.getBounds2D(); Rectangle screenBounds = databaseToScreen(cellBounds); if (screenBounds.width <= 0 || screenBounds.height <= 0) return; if (screenBounds.x > sz.width || screenBounds.x+screenBounds.width < 0) return; if (screenBounds.y > sz.height || screenBounds.y+screenBounds.height < 0) return; // only interested in expanded instances boolean expanded = ni.isExpanded(); if (fullInstantiate) expanded = true; // if not expanded, but viewing this cell in-place, expand it if (!expanded) { if (inPlaceNodePath != null) { for(int pathIndex=0; pathIndex<inPlaceNodePath.size(); pathIndex++) { NodeInst niOnPath = inPlaceNodePath.get(pathIndex); if (niOnPath.getProto() == subCell) { expanded = true; break; } } } } if (!expanded) return; if (screenBounds.width < sz.width/2 || screenBounds.height <= sz.height/2) { // construct the cell name that combines with the transformation ExpandedCellKey expansionKey = new ExpandedCellKey(subCell, subOrient); ExpandedCellInfo expansionCount = expandedCells.get(expansionKey); if (expansionCount == null) { expansionCount = new ExpandedCellInfo(); expansionCount.instanceCount = 1; expandedCells.put(expansionKey, expansionCount); } else { expansionCount.instanceCount++; if (expansionCount.instanceCount > 1) return; } } // now recurse countCell(subCell, null, fullInstantiate, subOrient, subTrans); } public static void forceRedraw(Cell cell) { synchronized (changedCells) { changedCells.add(cell.getId()); } } private static void forceRedraw(Set<CellId> changedCells) { // if there is no global for remembering cached cells, do not cache if (expandedCells == null) return; List<ExpandedCellKey> keys = new ArrayList<ExpandedCellKey>(); for(ExpandedCellKey eck : expandedCells.keySet() ) keys.add(eck); for(ExpandedCellKey expansionKey : keys) { if (changedCells.contains(expansionKey.cell.getId())) expandedCells.remove(expansionKey); } } /** * Method to copy the offscreen bits for a cell into the offscreen bits for the entire screen. */ private void copyBits(PixelDrawing srcOffscreen, int centerX, int centerY) { if (srcOffscreen == null) return; Dimension dim = srcOffscreen.sz; int cornerX = centerX - (int)srcOffscreen.originX; int cornerY = centerY - (int)srcOffscreen.originY; int minSrcX = Math.max(0, clipLX - cornerX); int maxSrcX = Math.min(dim.width - 1, clipHX - cornerX); int minSrcY = Math.max(0, clipLY - cornerY); int maxSrcY = Math.min(dim.height - 1, clipHY - cornerY); if (minSrcX > maxSrcX || minSrcY > maxSrcY) return; if (Job.getDebug() && numLayerBitMaps != srcOffscreen.numLayerBitMaps) System.out.println("Possible mixture of technologies in PixelDrawing.copyBits"); // copy the opaque and transparent layers for (int srcY = minSrcY; srcY <= maxSrcY; srcY++) { int destY = srcY + cornerY; assert destY >= clipLY && destY <= clipHY; if (destY < 0 || destY >= sz.height) continue; int srcBase = srcY * dim.width; int destBase = destY * sz.width; for (int srcX = minSrcX; srcX <= maxSrcX; srcX++) { int destX = srcX + cornerX; assert destX >= clipLX && destX <= clipHX; if (destX < 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -