📄 layerdrawing.java
字号:
clipHY = Math.min(renderBounds.y + renderBounds.height, sz.height) - 1; } else { clipLX = 0; clipHX = sz.width - 1; clipLY = 0; clipHY = sz.height - 1; } clearImage(renderBounds); periodicRefresh = true; this.wnd = wnd; objectCount = 0; lastRefreshTime = System.currentTimeMillis(); Set<CellId> changedCellsCopy; synchronized (changedCells) { changedCellsCopy = new HashSet<CellId>(changedCells); changedCells.clear(); } forceRedraw(changedCellsCopy); VectorCache.theCache.forceRedraw(); // reset cached cell counts numberToReconcile = SINGLETONSTOADD; for(ExpandedCellInfo count : expandedCells.values()) count.instanceCount = 0; if (TAKE_STATS) clearTime = System.currentTimeMillis(); // determine which cells should be cached (must have at least 2 instances) countCell(cell, drawLimitBounds, fullInstantiate, Orientation.IDENT, DBMath.MATID); if (TAKE_STATS) countTime = System.currentTimeMillis(); // now render it all renderTextList.clear(); greekTextList.clear(); crossTextList.clear(); drawCell(cell, drawLimitBounds, fullInstantiate, Orientation.IDENT, 0, 0, true, wnd.getVarContext()); // if a grid is requested, overlay it if (cell != null && wnd.isGrid()) drawGrid(wnd, drawing.da); if (TAKE_STATS) { long endTime = System.currentTimeMillis(); long curUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long memConsumed = curUsed - initialUsed; System.out.println("Took "+TextUtils.getElapsedTime(endTime-startTime) + "(" + (clearTime-startTime) + "+" + (countTime - clearTime) + "+" + (endTime-countTime) + ")"+ ", rendered "+cellsRendered+" cells, used "+offscreensUsed+" ("+offscreenPixelsUsed+" pixels) " + offscreensUsedSet.size() + "cached cells, created "+ offscreensCreated+" ("+offscreenPixelsCreated+" pixels) new cell caches (my size is "+total+" pixels), memory used="+memConsumed); System.out.println(" Cells ("+totalCells+") "+tinyCells+" are tiny;"+ " Primitives ("+totalPrims+") "+tinyPrims+" are tiny;"+ " Arcs ("+totalArcs+") "+tinyArcs+" are tiny, "+linedArcs+" are lines" + " Texts " + renderTextList.size() + " Greeks " + greekTextList.size()); if (true) { System.out.print(" " + (boxCount+polygonCount+discCount+lineCount+crossCount+circleCount+arcCount)+" rendered: "); if (boxArrayCount != 0) System.out.print(boxCount+"("+boxArrayCount+","+boxDisplayCount+") boxes "); if (polygonCount != 0) System.out.print(polygonCount+" polygons "); if (discCount != 0) System.out.print(discCount+" discs "); if (lineCount != 0) System.out.print(lineCount+" lines "); if (crossCount != 0) System.out.print(crossCount+" crosses "); if (circleCount != 0) System.out.print(circleCount+" circles "); if (arcCount != 0) System.out.print(arcCount+" circleArcs "); System.out.println(); } } } // ************************************* INTERMEDIATE CONTROL LEVEL ************************************* /** * Method to erase the offscreen data in this PixelDrawing. * This is called before any rendering is done. * @param bounds the area of the image to actually draw (null to draw all). */ public void clearImage(Rectangle bounds) { // erase the patterned opaque layer bitmaps if (bounds == null) { for(TransparentRaster raster: layerRasters.values()) raster.eraseAll(); } else { for(TransparentRaster raster: layerRasters.values()) raster.eraseBox(clipLX, clipHX, clipLY, clipHY); } } /** * Method to draw the grid into the offscreen buffer */ private void drawGrid(EditWindow wnd, WindowFrame.DisplayAttributes da) { double spacingX = wnd.getGridXSpacing(); double spacingY = wnd.getGridYSpacing(); if (spacingX == 0 || spacingY == 0) return; double boldSpacingX = spacingX * User.getDefGridXBoldFrequency(); double boldSpacingY = spacingY * User.getDefGridYBoldFrequency(); double boldSpacingThreshX = spacingX / 4; double boldSpacingThreshY = spacingY / 4; // screen extent Rectangle2D displayable = displayableBounds(da.getIntoCellTransform()); double lX = displayable.getMinX(); double lY = displayable.getMaxY(); double hX = displayable.getMaxX(); double hY = displayable.getMinY(); double scaleX = sz.width / (hX - lX); double scaleY = sz.height / (lY - hY); // initial grid location double x1 = DBMath.toNearest(lX, spacingX); double y1 = DBMath.toNearest(lY, spacingY); // adjust grid placement according to scale boolean allBoldDots = false; if (spacingX * scaleX < 5 || spacingY * scaleY < 5) { // normal grid is too fine: only show the "bold dots" x1 = DBMath.toNearest(x1, boldSpacingX); spacingX = boldSpacingX; y1 = DBMath.toNearest(y1, boldSpacingY); spacingY = boldSpacingY; // if even the bold dots are too close, don't draw a grid if (spacingX * scaleX < 10 || spacingY * scaleY < 10) return; } else if (spacingX * scaleX > 75 && spacingY * scaleY > 75) { // if zoomed-out far enough, show all bold dots allBoldDots = true; } // draw the grid Point2D.Double tmpPt = new Point2D.Double(); AffineTransform outofCellTransform = da.getOutofCellTransform(); ERaster raster = getRaster(gridLayer, gridGraphics, false); for(double i = y1; i > hY; i -= spacingY) { double boldValueY = i; if (i < 0) boldValueY -= boldSpacingThreshY/2; else boldValueY += boldSpacingThreshY/2; boolean everyTenY = Math.abs(boldValueY) % boldSpacingY < boldSpacingThreshY; for(double j = x1; j < hX; j += spacingX) { tmpPt.setLocation(j, i); outofCellTransform.transform(tmpPt, tmpPt); databaseToScreen(tmpPt.getX(), tmpPt.getY(), tempPt1); int x = tempPt1.x; int y = tempPt1.y; if (x < 0 || x >= sz.width) continue; if (y < 0 || y >= sz.height) continue; double boldValueX = j; if (j < 0) boldValueX -= boldSpacingThreshX/2; else boldValueX += boldSpacingThreshX/2; boolean everyTenX = Math.abs(boldValueX) % boldSpacingX < boldSpacingThreshX; if (allBoldDots && everyTenX && everyTenY) { int boxLX = x-2; if (boxLX < 0) boxLX = 0; int boxHX = x+2; if (boxHX >= sz.width) boxHX = sz.width-1; int boxLY = y-2; if (boxLY < 0) boxLY = 0; int boxHY = y+2; if (boxHY >= sz.height) boxHY = sz.height-1; // draw box in opaque area raster.fillBox(boxLX, boxHX, boxLY, boxHY);// for(int yg=boxLY; yg<=boxHY; yg++) {// int baseIndex = yg * sz.width;// for(int xg=boxLX; xg<=boxHX; xg++)// opaqueData[baseIndex + xg] = col;// baseIndex += sz.width;// } if (x > 1) raster.fillPoint(x - 2, y); if (x < sz.width-2) raster.fillPoint(x + 2, y); if (y > 1) raster.fillPoint(x, y - 2); if (y < sz.height-2) raster.fillPoint(x, y + 2);// if (x > 1) opaqueData[y * sz.width + (x-2)] = col;// if (x < sz.width-2) opaqueData[y * sz.width + (x+2)] = col;// if (y > 1) opaqueData[(y-2) * sz.width + x] = col;// if (y < sz.height-2) opaqueData[(y+2) * sz.width + x] = col; continue; } // special case every 10 grid points in each direction if (allBoldDots || (everyTenX && everyTenY)) { raster.fillPoint(x, y); if (x > 0) raster.fillPoint(x - 1, y); if (x < sz.width-1) raster.fillPoint(x + 1, y); if (y > 0) raster.fillPoint(x, y - 1); if (y < sz.height-1) raster.fillPoint(x, y + 1);// opaqueData[y * sz.width + x] = col;// if (x > 0) opaqueData[y * sz.width + (x-1)] = col;// if (x < sz.width-1) opaqueData[y * sz.width + (x+1)] = col;// if (y > 0) opaqueData[(y-1) * sz.width + x] = col;// if (y < sz.height-1) opaqueData[(y+1) * sz.width + x] = col; continue; } // just a single dot raster.fillPoint(x, y);// opaqueData[y * sz.width + x] = col; } } if (User.isGridAxesShown()) { tmpPt.setLocation(0, 0); outofCellTransform.transform(tmpPt, tmpPt); databaseToScreen(tmpPt.getX(), tmpPt.getY(), tempPt1); int x = tempPt1.x; int y = tempPt1.y; if (x >= 0 && x < sz.width) { raster.fillVerLine(x, 0, sz.height - 1);// int baseIndex = xy.x;// for (int y = 0; y < sz.height; y++) {// opaqueData[baseIndex] = col;// baseIndex += sz.width;// } } if (y >= 0 && y < sz.height) { raster.fillHorLine(y, 0, sz.width - 1);// int baseIndex = xy.y * sz.width;// for (int x = 0; x < sz.width; x++)// opaqueData[baseIndex + x] = col; } } } /** * Method to return a rectangle in database coordinates that covers the viewable extent of this window. * @return a rectangle that describes the viewable extent of this window (database coordinates). */ private Rectangle2D displayableBounds(AffineTransform intoCellTransform) { Point2D low = new Point2D.Double(); screenToDatabase(0, 0, low); intoCellTransform.transform(low, low); Point2D high = new Point2D.Double(); screenToDatabase(sz.width-1, sz.height-1, high); intoCellTransform.transform(high, high); double lowX = Math.min(low.getX(), high.getX()); double lowY = Math.min(low.getY(), high.getY()); double sizeX = Math.abs(high.getX()-low.getX()); double sizeY = Math.abs(high.getY()-low.getY()); Rectangle2D bounds = new Rectangle2D.Double(lowX, lowY, sizeX, sizeY); return bounds; } private void periodicRefresh() { // handle refreshing if (periodicRefresh) { objectCount++; if (objectCount > 100) { objectCount = 0; long currentTime = System.currentTimeMillis(); if (currentTime - lastRefreshTime > 1000) { wnd.repaint(); } } } } // ************************************* HIERARCHY TRAVERSAL ************************************* /** * Method to draw the contents of a cell, transformed through "prevTrans". */ private void drawCell(Cell cell, Rectangle2D drawLimitBounds, boolean fullInstantiate, Orientation orient, int oX, int oY, boolean topLevel, VarContext context) { renderedCells++; VectorCache.VectorCell vc = VectorCache.theCache.drawCell(cell.getId(), orient, context, scale); // draw all subcells for(VectorCache.VectorSubCell vsc : vc.subCells) { totalCells++; // 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, t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -