I've got a problem. I use image, which takes big space e.g. 40000x40000 px. and so there is a problem with the amount of memory. I've found a compromise. The bigger cache we use the faster the performance will be. I use my own ImageRenderer (DRenderer.java) and RenderedImage (ExtRenderedImage.java) instead BufferedImage. I suggest to use a RenderedImage in follow classes for flexibility.
org.apache.batik.bridge.RepaintManager; org.apache.batik.bridge.UpdateManagerEvent; org.apache.batik.swing.gvt.GVTTreeRenderer; org.apache.batik.swing.gvt.GVTTreeRendererEvent; org.apache.batik.swing.gvt.JGVTComponent; org.apache.batik.swing.svg.JSVGComponent; ----------------------DRenderer--------------------------------- package org.apache.batik.gvt.renderer; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.awt.image.renderable.*; import java.util.*; import java.util.List; import borlas.utils.*; import borlas.utils.TileCache; import org.apache.batik.ext.awt.geom.*; import org.apache.batik.ext.awt.image.*; import org.apache.batik.ext.awt.image.renderable.*; import org.apache.batik.ext.awt.image.rendered.*; import org.apache.batik.gvt.*; import org.apache.batik.gvt.filter.*; public class DRenderer implements ImageRenderer{ final static int COPY_OVERHEAD = 1000; final static int COPY_LINE_OVERHEAD = 10; protected RenderingHints renderingHints; protected AffineTransform usr2dev; protected GraphicsNode rootGN; protected Filter rootFilter; protected RenderedImage image = null; protected int offScreenWidth; protected int offScreenHeight; protected boolean isDoubleBuffered; protected RectListManager dirtyAreas = new RectListManager(); protected TileCache cache; protected static RenderingHints defaultRenderingHints; static { defaultRenderingHints = new RenderingHints(null); defaultRenderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); defaultRenderingHints.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); } public void setDoubleBuffered(boolean flag){ isDoubleBuffered = flag; } public boolean isDoubleBuffered(){ return isDoubleBuffered; } public AffineTransform getTransform(){ return usr2dev; } public void setTransform(AffineTransform usr2dev){ if (this.usr2dev.equals(usr2dev)) return; if(usr2dev == null) this.usr2dev = new AffineTransform(); else this.usr2dev = new AffineTransform(usr2dev); } public void updateOffScreen(int width, int height) { offScreenWidth = width; offScreenHeight = height; } public void dispose() { rootGN = null; rootFilter = null; renderingHints = null; } public void repaint(Shape area){ if (area == null) return; List l = new ArrayList(1); l.add(area); repaint(l); } public GraphicsNode getTree(){ return rootGN; } public void setTree(GraphicsNode rootGN){ this.rootGN = rootGN; rootFilter = null; image = null; renderingHints = new RenderingHints(defaultRenderingHints); } public DRenderer(TileCache tci){ cache = tci; renderingHints = new RenderingHints(defaultRenderingHints); usr2dev = new AffineTransform(); } public DRenderer(RenderingHints rh, AffineTransform at,TileCache tci){ cache = tci; renderingHints = new RenderingHints(rh); usr2dev = new AffineTransform(at); } public void flush(){ cache.flush(); } public void clearOffScreen() { renderGNR(); } public void repaint(RectListManager rLM){ Iterator iter = rLM.iterator(); while (iter.hasNext()) { Rectangle r = (Rectangle)iter.next(); dirtyAreas.add(r); } dirtyAreas.mergeRects(COPY_OVERHEAD, COPY_LINE_OVERHEAD); iter = dirtyAreas.iterator(); while(iter.hasNext()){ Rectangle rect = (Rectangle)iter.next(); flush(rect); } dirtyAreas.clear(); return; } public void flush(Rectangle r) { if(image == null) return; r = usr2dev.createTransformedShape(r).getBounds(); int lb = xToTile(r.x); int rb = xToTile(r.x + r.width); int tb = yToTile(r.y); int bb = yToTile(r.y + r.height); for(int i = lb; i <= rb; i++){ for(int j = tb; j <= bb; j++){ cache.removeTile(image,i,j); } } return; } public void flush(Collection areas) { Iterator iter = areas.iterator(); while(iter.hasNext()){ Rectangle rect = ((Shape)iter.next()).getBounds(); dirtyAreas.add(rect); } dirtyAreas.mergeRects(COPY_OVERHEAD, COPY_LINE_OVERHEAD); iter = dirtyAreas.iterator(); while(iter.hasNext()){ Rectangle rect = (Rectangle)iter.next(); flush(rect); } dirtyAreas.clear(); return; } public RenderedImage getOffScreen() { if (rootGN == null) return null; return image; } public void repaint(List areas) { if (areas == null) return; if(image == null || image.getWidth() < offScreenWidth || image.getHeight() < offScreenHeight ){ renderGNR(); } flush(areas); } protected int xToTile(int x){ int off = image.getTileGridXOffset(); int tw = image.getTileWidth(); return (x - off)/tw; } protected int yToTile(int y){ int off = image.getTileGridYOffset(); int th = image.getTileHeight(); return (y - off)/th; } protected int xTileToX(int xt){ int off = image.getTileGridXOffset(); int tw = image.getTileWidth(); return xt*tw + off; } protected int yTileToY(int yt){ int off = image.getTileGridYOffset(); int th = image.getTileHeight(); return yt*th + off; } protected void renderGNR() { if(rootGN == null) return; if (rootFilter == null) { rootFilter = rootGN.getGraphicsNodeRable(true); } cache.flush(); AffineTransform at, rcAT; at = usr2dev; rcAT = new AffineTransform(at.getScaleX(), at.getShearY(), at.getShearX(), at.getScaleY(), 0, 0); RenderContext rc = new RenderContext(rcAT, null, renderingHints); Rectangle bounds = new Rectangle(offScreenWidth,offScreenHeight); RenderedImage ri = new ExtRenderedImage((GraphicsNodeRable8Bit)rootFilter,rc.getTransform(),rc.getRenderingHints(),bounds); if (ri == null){ image = null; return; } CachableRed ret; ret = GraphicsUtil.wrap(ri); int dx = Math.round((float)at.getTranslateX()); int dy = Math.round((float)at.getTranslateY()); ret = new TranslateRed(ret, ret.getMinX()+dx, ret.getMinY()+dy); image = GraphicsUtil.convertTosRGB(ret); } } --------------------------------------------------------ExtRnderedImge--------------------------- package borlas.utils; import org.apache.batik.ext.awt.image.GraphicsUtil; import org.apache.batik.ext.awt.image.rendered.AbstractTiledRed; import org.apache.batik.ext.awt.image.rendered.AbstractRed; import org.apache.batik.ext.awt.image.rendered.CachableRed; import java.awt.AlphaComposite; import java.awt.Rectangle; import java.awt.Point; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.Raster; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import org.apache.batik.gvt.GraphicsNode; import org.apache.batik.gvt.filter.GraphicsNodeRable8Bit; public class ExtRenderedImage extends AbstractRed { private AffineTransform node2dev = null; private GraphicsNodeRable8Bit filter = null; private RenderingHints renderingHints = null; public ExtRenderedImage(GraphicsNodeRable8Bit rable, AffineTransform node2dev,RenderingHints rh, Rectangle bounds){ super(); // We _must_ call init... filter = rable; renderingHints = rh; this.node2dev = node2dev; ColorModel cm = GraphicsUtil.sRGB_Unpre; int defSz = AbstractTiledRed.getDefaultTileSize(); // Make tile(0,0) fall on the closest intersection of defaultSz. int tgX = defSz*(int)Math.floor(bounds.x/defSz); int tgY = defSz*(int)Math.floor(bounds.y/defSz); int tw = (bounds.x+bounds.width)-tgX; if (tw > defSz) tw = defSz; int th = (bounds.y+bounds.height)-tgY; if (th > defSz) th = defSz; if ((tw <= 0) || (th <= 0)) { tw = 1; th = 1; } // fix my sample model so it makes sense given my size. SampleModel sm = cm.createCompatibleSampleModel(tw, th); // Finish initializing our base class... init((CachableRed)null, bounds, cm, sm, tgX, tgY, null); } public WritableRaster copyData(WritableRaster wr) { genRect(wr); return wr; } public void genRect(WritableRaster wr) { // System.out.println(" Rect: " + wr.getBounds()); BufferedImage offScreen = new BufferedImage(cm, wr.createWritableTranslatedChild(0,0), cm.isAlphaPremultiplied(), null); Graphics2D g = GraphicsUtil.createGraphics(offScreen,renderingHints); g.setComposite(AlphaComposite.Clear); g.fillRect(0, 0, wr.getWidth(), wr.getHeight()); g.setComposite(AlphaComposite.SrcOver); g.translate(-wr.getMinX(), -wr.getMinY()); // Set transform g.transform(node2dev); filter.paintRable(g); g.dispose(); } } --------------------------------------------------------------------------------------------------- And piece of MyCanvas that extends JSVGComponent protected ImageRenderer createImageRenderer() { if(isDynamicDocument){ return new DRenderer(cache); }else{ return rendererFactory.createStaticImageRenderer(); } } public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D)g; Rectangle d = g.getClipBounds(); Dimension dim = this.getSize(); if(d == null){ d = new Rectangle(0,0,dim.width,dim.height); } g2d.setComposite(AlphaComposite.SrcOver); g2d.setPaint(getBackground()); g2d.fillRect(0, 0, dim.width, dim.height); paintPrev(g2d); this.PaintBackground(g); if (image != null) { if (paintingTransform != null) { g2d.transform(paintingTransform); } g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); int lb, rb, tb, bb; int numTX = image.getNumXTiles(); int numTY = image.getNumYTiles(); int mtx = image.getMinTileX(); int mty = image.getMinTileY(); lb = xToTile(d.x); lb = Math.max(lb, image.getMinTileX()); lb = Math.min(lb, mtx + numTX - 1); rb = xToTile(d.x + d.width - 1); rb = Math.max(rb, image.getMinTileX()); rb = Math.min(rb, mtx + numTX - 1); tb = yToTile(d.y); tb = Math.max(tb, image.getMinTileY()); tb = Math.min(tb, mty + numTY - 1); bb = yToTile(d.y + d.height - 1); bb = Math.max(bb, image.getMinTileY()); bb = Math.min(bb, mty + numTY - 1); for(int i = lb; i <= rb; i++){ for(int j = tb; j <= bb; j++){ int tx = xTileToX(i); int ty = yTileToY(j); Raster raster = cache.getTile(image,i,j); if(raster == null){ raster = image.getTile(i,j); if(raster == null) return; cache.addTile(image,i,j,raster); } DataBuffer dataBuffer = raster.getDataBuffer(); SampleModel sampleModel = image.getSampleModel(); WritableRaster wr = Raster.createWritableRaster(sampleModel,dataBuffer,new Point(0,0)); BufferedImage bi = new BufferedImage(image.getColorModel(),wr, image.getColorModel().isAlphaPremultiplied(),null); g2d.drawRenderedImage(bi, AffineTransform.getTranslateInstance(tx,ty)); } } Iterator it = overlays.iterator(); while (it.hasNext()) { ((Overlay)it.next()).paint(g); } } } protected int xToTile(int x){ int off = image.getTileGridXOffset(); int tw = image.getTileWidth(); return (x - off)/tw; } protected int yToTile(int y){ int off = image.getTileGridYOffset(); int th = image.getTileHeight(); return (y - off)/th; } protected int xTileToX(int xt){ int off = image.getTileGridXOffset(); int tw = image.getTileWidth(); return xt*tw + off; } protected int yTileToY(int yt){ int off = image.getTileGridYOffset(); int th = image.getTileHeight(); return yt*th + off; } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]