📄 vectordrawing.java
字号:
result.y = (int)(scrY >= 0 ? scrY + 0.5 : scrY - 0.5); } } /** * Method to draw a tiny box on the screen in a given color. * Done when the object is too small to draw in full detail. * @param lX the low X coordinate of the box. * @param hX the high X coordinate of the box. * @param lY the low Y coordinate of the box. * @param hY the high Y coordinate of the box. * @param col the color to draw. */ private void drawTinyBox(int lX, int hX, int lY, int hY, int col, VectorCache.VectorCell greekedCell) { if (lX < screenLX) lX = screenLX; if (hX >= screenHX) hX = screenHX-1; if (lY < screenLY) lY = screenLY; if (hY >= screenHY) hY = screenHY-1; if (User.isUseCellGreekingImages()) { if (greekedCell != null && greekedCell.fadeImageColors != null) { int backgroundColor = User.getColor(User.ColorPrefType.BACKGROUND); int backgroundRed = (backgroundColor >> 16) & 0xFF; int backgroundGreen = (backgroundColor >> 8) & 0xFF; int backgroundBlue = backgroundColor & 0xFF; // render the icon properly with scale int greekWid = greekedCell.fadeImageWid; int greekHei = greekedCell.fadeImageHei; int wid = hX - lX; int hei = hY - lY; float xInc = greekWid / (float)wid; float yInc = greekHei / (float)hei; float yPos = 0; for(int y=0; y<hei; y++) { float yEndPos = yPos + yInc; int yS = (int)yPos; int yE = (int)yEndPos; float xPos = 0; for(int x=0; x<wid; x++) { float xEndPos = xPos + xInc; int xS = (int)xPos; int xE = (int)xEndPos; float r = 0, g = 0, b = 0; float totalArea = 0; for(int yGrab = yS; yGrab <= yE; yGrab++) { if (yGrab >= greekHei) continue; float yArea = 1; if (yGrab == yS) yArea = (1 - (yPos - yS)); if (yGrab == yE) yArea *= (yEndPos-yE); for(int xGrab = xS; xGrab <= xE; xGrab++) { if (xGrab >= greekWid) continue; int index = xGrab + yGrab*greekedCell.fadeImageWid; if (greekedCell.fadeImageColors==null || index >= greekedCell.fadeImageColors.length) continue; int value = greekedCell.fadeImageColors[index]; int red = (value >> 16) & 0xFF; int green = (value >> 8) & 0xFF; int blue = value & 0xFF; float area = yArea; if (xGrab == xS) area *= (1 - (xPos - xS)); if (xGrab == xE) area *= (xEndPos-xE); if (area <= 0) continue; r += red * area; g += green * area; b += blue * area; totalArea += area; } } if (totalArea > 0) { int red = (int)(r / totalArea); if (red > 255) red = 255; int green = (int)(g / totalArea); if (green > 255) green = 255; int blue = (int)(b / totalArea); if (blue > 255) blue = 255; if (Math.abs(backgroundRed-red) > 2 || Math.abs(backgroundGreen-green) > 2 || Math.abs(backgroundBlue-blue) > 2) { offscreen.drawPoint(lX+x, lY+y, null, (red << 16) | (green << 8) | blue); } } xPos = xEndPos; } yPos = yEndPos; } if (DEBUGIMAGES) { for(int y=0; y<greekedCell.fadeImageHei; y++) { for(int x=0; x<greekedCell.fadeImageWid; x++) { int valToSet = greekedCell.fadeImageColors[x+y*greekedCell.fadeImageWid]; topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+x+1, greekedCell.fadeOffsetY+y+1, null, valToSet); } topVD.offscreen.drawPoint(greekedCell.fadeOffsetX, greekedCell.fadeOffsetY+y+1, null, 0); topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+greekedCell.fadeImageWid+1, greekedCell.fadeOffsetY+y+1, null, 0); } for(int x=0; x<greekedCell.fadeImageWid; x++) { topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+x, greekedCell.fadeOffsetY, null, 0); topVD.offscreen.drawPoint(greekedCell.fadeOffsetX+x, greekedCell.fadeOffsetY+greekedCell.fadeImageHei+1, null, 0); } } return; } } // no greeked image: just use the greeked color for(int y=lY; y<=hY; y++) { for(int x=lX; x<=hX; x++) offscreen.drawPoint(x, y, null, col); } } /** * Method to determine whether a cell has tiny contents. * Recursively examines the cache of this and all subcells to see if the * maximum feature sizes are all below the global threshold "maxObjectSize". * @param cell the Cell in question. * @param vc the cached representation of the cell. * @param trans the Orientation of the cell. * @return true if the cell has all tiny contents. */ private boolean isContentsTiny(Cell cell, VectorCache.VectorCell vc, Orientation trans, VarContext context) throws AbortRenderingException { if (vc.maxFeatureSize > maxObjectSize) return false; for(VectorCache.VectorSubCell vsc : vc.subCells) { NodeInst ni = cell.getNodeById(vsc.n.nodeId); VectorCache.VectorCell subVC = VectorCache.theCache.findVectorCell(vsc.subCellId, vc.orient.concatenate(vsc.n.orient)); if (ni.isExpanded() || fullInstantiate) { Orientation thisOrient = ni.getOrient(); Orientation recurseTrans = trans.concatenate(thisOrient); VarContext subContext = context.push(ni); Cell subCell = (Cell)ni.getProto(); VectorCache.VectorCell subVC_ = drawCell(subCell, recurseTrans, subContext); assert subVC_ == subVC; boolean subCellTiny = isContentsTiny(subCell, subVC, recurseTrans, subContext); if (!subCellTiny) return false; continue; } if (subVC.vcg.cellMinSize > maxObjectSize) return false; } return true; } private void makeGreekedImage(VectorCache.VectorCell subVC) throws AbortRenderingException { if (subVC.fadeImage) return; if (!User.isUseCellGreekingImages()) return; // determine size and scale of greeked cell image Rectangle2D cellBounds = subVC.vcg.bounds; Rectangle2D ownBounds = new Rectangle2D.Double(cellBounds.getMinX(), cellBounds.getMinY(), cellBounds.getWidth(), cellBounds.getHeight()); AffineTransform trans = subVC.orient.rotateAbout(0, 0); DBMath.transformRect(ownBounds, trans); double greekScale = MAXGREEKSIZE / ownBounds.getHeight(); if (ownBounds.getWidth() > ownBounds.getHeight()) greekScale = MAXGREEKSIZE / ownBounds.getWidth(); int lX = (int)Math.floor(cellBounds.getMinX()*greekScale); int hX = (int)Math.ceil(cellBounds.getMaxX()*greekScale); int lY = (int)Math.floor(cellBounds.getMinY()*greekScale); int hY = (int)Math.ceil(cellBounds.getMaxY()*greekScale); if (hX <= lX) hX = lX + 1; int greekWid = hX - lX; if (hY <= lY) hY = lY + 1; int greekHei = hY - lY; Rectangle screenBounds = new Rectangle(lX, lY, greekWid, greekHei); // construct the offscreen buffers for the greeked cell image PixelDrawing offscreen = new PixelDrawing(greekScale, screenBounds); Point2D cellCtr = new Point2D.Double(ownBounds.getCenterX(), ownBounds.getCenterY()); VectorDrawing subVD = new VectorDrawing(); subVC.fadeOffsetX = debugXP; subVC.fadeOffsetY = debugYP; debugXP += MAXGREEKSIZE + 5; if (topVD != null) { if (debugXP + MAXGREEKSIZE+2 >= topVD.offscreen.getSize().width) { debugXP = 0; debugYP += MAXGREEKSIZE + 5; } } // set rendering information for the greeked cell image subVD.offscreen = offscreen; subVD.screenLX = 0; subVD.screenHX = greekWid; subVD.screenLY = 0; subVD.screenHY = greekHei; subVD.szHalfWidth = greekWid / 2; subVD.szHalfHeight = greekHei / 2; subVD.maxObjectSize = 0; subVD.maxTextSize = 0; subVD.scale = (float)greekScale; subVD.scale_ = (float)(greekScale/DBMath.GRID); subVD.factorX = (float)(cellCtr.getX()*DBMath.GRID - subVD.szHalfWidth/subVD.scale_); subVD.factorY = (float)(cellCtr.getY()*DBMath.GRID + subVD.szHalfHeight/subVD.scale_); subVD.factorX_ = (int)subVD.factorX; subVD.factorY_ = (int)subVD.factorY; subVD.scale_int = (int)(subVD.scale_ * (1 << SCALE_SH)); subVD.fullInstantiate = true; subVD.takingLongTime = true; // render the greeked cell subVD.offscreen.clearImage(null); subVD.render(subVC, 0, 0, VarContext.globalContext, -1); subVD.offscreen.composite(null); // remember the greeked cell image int[] img = offscreen.getOpaqueData(); subVC.fadeImageWid = greekWid; subVC.fadeImageHei = greekHei; subVC.fadeImageColors = new int[subVC.fadeImageWid * subVC.fadeImageHei]; int i = 0; for(int y=0; y<subVC.fadeImageHei; y++) { for(int x=0; x<subVC.fadeImageWid; x++) { int value = img[i]; subVC.fadeImageColors[i++] = value & 0xFFFFFF; } } subVC.fadeImage = true; } /** * Method to determine the "fade" color for a cached cell. * Fading is done when the cell is too tiny to draw (or all of its contents are too tiny). * Instead of drawing the cell contents, the entire cell is painted with the "fade" color. * @param vc the cached cell. * @return the fade color (an integer with red/green/blue). */ private int getFadeColor(VectorCache.VectorCell vc, VarContext context) throws AbortRenderingException { if (vc.hasFadeColor) return vc.fadeColor; // examine all shapes Map<Layer,MutableDouble> layerAreas = new HashMap<Layer,MutableDouble>(); gatherContents(vc, layerAreas, context); // now compute the color Set<Layer> keys = layerAreas.keySet(); double totalArea = 0; for(Layer layer : keys) { MutableDouble md = layerAreas.get(layer); totalArea += md.doubleValue(); } double r = 0, g = 0, b = 0; if (totalArea != 0) { for(Layer layer : keys) { MutableDouble md = layerAreas.get(layer); double portion = md.doubleValue() / totalArea; EGraphics desc = layer.getGraphics(); Color col = desc.getColor(); r += col.getRed() * portion; g += col.getGreen() * portion; b += col.getBlue() * portion; } } if (r < 0) r = 0; if (r > 255) r = 255; if (g < 0) g = 0; if (g > 255) g = 255; if (b < 0) b = 0; if (b > 255) b = 255; vc.fadeColor = (((int)r) << 16) | (((int)g) << 8) | (int)b; vc.hasFadeColor = true; return vc.fadeColor; } /** * Helper method to recursively examine a cached cell and its subcells and compute * the coverage of each layer. * @param vc the cached cell to examine. * @param layerAreas a HashMap of all layers and the areas they cover. */ private void gatherContents(VectorCache.VectorCell vc, Map<Layer,MutableDouble> layerAreas, VarContext context) throws AbortRenderingException { for(VectorCache.VectorBase vb : vc.filledShapes) { Layer layer = vb.layer; if (layer == null) continue; Layer.Function fun = layer.getFunction(); if (fun.isImplant() || fun.isSubstrate()) continue; // handle each shape double area = 0; if (vb instanceof VectorCache.VectorManhattan) { VectorCache.VectorManhattan vm = (VectorCache.VectorManhattan)vb; for (int i = 0; i < vm.coords.length; i += 4) { double c1X = vm.coords[i]; double c1Y = vm.coords[i + 1]; double c2X = vm.coords[i + 2]; double c2Y = vm.coords[i + 3]; area += (c1X-c2X) * (c1Y-c2Y); } } else if (vb instanceof VectorCache.VectorPolygon) { VectorCache.VectorPolygon vp = (VectorCache.VectorPolygon)vb; area = GenMath.getAreaOfPoints(vp.points); } else if (vb instanceof VectorCache.VectorCircle) { VectorCache.VectorCircle vci = (VectorCache.VectorCircle)vb; double radius = new Point2D.Double(vci.cX, vci.cY).distance(new Point2D.Double(vci.eX, vci.eY)); area = radius * radius * Math.PI; } if (area == 0) continue; MutableDouble md = layerAreas.get(layer); if (md == null) { md = new MutableDouble(0); layerAreas.put(layer, md); } md.setValue(md.doubleValue() + area); } Cell cell = VectorCache.theCache.database.getCell(vc.vcg.cellId); for(VectorCache.VectorSubCell vsc : vc.subCells) { VectorCache.VectorCellGroup vcg = VectorCache.theCache.findCellGroup(vsc.subCellId); VectorCache.VectorCell subVC = vcg.getAnyCell(); NodeInst ni = cell.getNodeById(vsc.n.nodeId); VarContext subContext = context.push(ni); if (subVC == null) subVC = drawCell((Cell)ni.getProto(), Orientation.IDENT, subContext); gatherContents(subVC, layerAreas, subContext); } } // ************************************* CACHE CREATION ************************************* /** * Method to cache the contents of a cell. * @param cell the Cell to cache * @param prevTrans the orientation of the cell (just a rotation, no offsets here). * @return a cached cell object for the given Cell. */ private VectorCache.VectorCell drawCell(Cell cell, Orientation prevTrans, VarContext context) throws AbortRenderingException { // caching the cell: check for abort and delay reporting if (stopRendering) throw new AbortRenderingException(); if (!takingLongTime) { long currentTime = System.currentTimeMillis(); if (currentTime - startTime > 1000) { System.out.print("Display caching, please wait..."); TopLevel.setBusyCursor(true); takingLongTime = true; } } return VectorCache.theCache.drawCell(cell.getId(), prevTrans, context, scale); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -