1 18 package org.apache.batik.gvt.renderer; 19 20 import java.awt.AlphaComposite ; 21 import java.awt.Graphics2D ; 22 import java.awt.Point ; 23 import java.awt.Rectangle ; 24 import java.awt.RenderingHints ; 25 import java.awt.Shape ; 26 import java.awt.geom.AffineTransform ; 27 import java.awt.image.BufferedImage ; 28 import java.awt.image.ColorModel ; 29 import java.awt.image.Raster ; 30 import java.awt.image.RenderedImage ; 31 import java.awt.image.SampleModel ; 32 import java.awt.image.WritableRaster ; 33 import java.awt.image.renderable.RenderContext ; 34 import java.lang.ref.SoftReference ; 35 import java.util.ArrayList ; 36 import java.util.Iterator ; 37 import java.util.Collection ; 38 39 import org.apache.batik.ext.awt.image.GraphicsUtil; 40 import org.apache.batik.ext.awt.image.PadMode; 41 import org.apache.batik.ext.awt.image.renderable.Filter; 42 import org.apache.batik.ext.awt.image.rendered.CachableRed; 43 import org.apache.batik.ext.awt.image.rendered.PadRed; 44 import org.apache.batik.ext.awt.image.rendered.TileCacheRed; 45 import org.apache.batik.ext.awt.image.rendered.TranslateRed; 46 import org.apache.batik.ext.awt.geom.RectListManager; 47 import org.apache.batik.gvt.GraphicsNode; 48 import org.apache.batik.util.HaltingThread; 49 50 57 public class StaticRenderer implements ImageRenderer { 58 61 private static final String ILLEGAL_ARGUMENT_NULL_OFFSCREEN = 62 "offScreen should not be null"; 63 private static final String ILLEGAL_ARGUMENT_ZERO_WIDTH_OR_HEIGHT = 64 "offScreen should have positive width/height"; 65 66 69 protected GraphicsNode rootGN; 70 protected Filter rootFilter; 71 protected CachableRed rootCR; 72 protected SoftReference lastCR; 73 protected SoftReference lastCache; 74 75 78 protected boolean isDoubleBuffered = false; 79 80 83 protected WritableRaster currentBaseRaster; 84 protected WritableRaster currentRaster; 85 protected BufferedImage currentOffScreen; 86 87 protected WritableRaster workingBaseRaster; 88 protected WritableRaster workingRaster; 89 protected BufferedImage workingOffScreen; 90 91 protected int offScreenWidth; 92 protected int offScreenHeight; 93 94 97 protected RenderingHints renderingHints; 98 protected AffineTransform usr2dev; 99 100 protected static RenderingHints defaultRenderingHints; 101 static { 102 defaultRenderingHints = new RenderingHints (null); 103 defaultRenderingHints.put(RenderingHints.KEY_ANTIALIASING, 104 RenderingHints.VALUE_ANTIALIAS_ON); 105 106 defaultRenderingHints.put(RenderingHints.KEY_INTERPOLATION, 107 RenderingHints.VALUE_INTERPOLATION_BILINEAR); 108 } 109 110 114 public StaticRenderer(RenderingHints rh, 115 AffineTransform at){ 116 renderingHints = new RenderingHints (rh); 117 usr2dev = new AffineTransform (at); 118 } 119 120 123 public StaticRenderer(){ 124 renderingHints = new RenderingHints (defaultRenderingHints); 125 usr2dev = new AffineTransform (); 126 } 127 128 129 132 public void dispose() { 133 rootGN = null; 134 rootFilter = null; 135 rootCR = null; 136 137 workingOffScreen = null; 138 workingBaseRaster = null; 139 workingRaster = null; 140 141 currentOffScreen = null; 142 currentBaseRaster = null; 143 currentRaster = null; 144 145 renderingHints = null; 146 } 147 148 153 public void setTree(GraphicsNode rootGN){ 154 this.rootGN = rootGN; 155 rootFilter = null; 156 rootCR = null; 157 158 workingOffScreen = null; 159 workingRaster = null; 160 161 currentOffScreen = null; 162 currentRaster = null; 163 164 } 166 167 170 public GraphicsNode getTree(){ 171 return rootGN; 172 } 173 174 177 public void setRenderingHints(RenderingHints rh) { 178 renderingHints = new RenderingHints (rh); 179 180 rootFilter = null; 181 rootCR = null; 182 183 workingOffScreen = null; 184 workingRaster = null; 185 186 currentOffScreen = null; 187 currentRaster = null; 188 } 189 190 194 public RenderingHints getRenderingHints() { 195 return renderingHints; 196 } 197 198 205 public void setTransform(AffineTransform usr2dev){ 206 if (this.usr2dev.equals(usr2dev)) 207 return; 208 209 if(usr2dev == null) 210 this.usr2dev = new AffineTransform (); 211 else 212 this.usr2dev = new AffineTransform (usr2dev); 213 214 rootCR = null; 215 } 216 217 222 public AffineTransform getTransform(){ 223 return usr2dev; 224 } 225 226 231 public boolean isDoubleBuffered(){ 232 return isDoubleBuffered; 233 } 234 235 242 public void setDoubleBuffered(boolean isDoubleBuffered){ 243 if (this.isDoubleBuffered == isDoubleBuffered) 244 return; 245 246 this.isDoubleBuffered = isDoubleBuffered; 247 if (isDoubleBuffered) { 248 currentOffScreen = null; 250 currentBaseRaster = null; 251 currentRaster = null; 252 } else { 253 currentOffScreen = workingOffScreen; 255 currentBaseRaster = workingBaseRaster; 256 currentRaster = workingRaster; 257 } 258 } 259 260 261 269 public void updateOffScreen(int width, int height) { 270 offScreenWidth = width; 271 offScreenHeight = height; 272 } 273 274 285 public BufferedImage getOffScreen() { 286 if (rootGN == null) 287 return null; 288 289 return currentOffScreen; 290 } 291 292 303 public void clearOffScreen() { 304 305 if (isDoubleBuffered) 308 return; 309 310 updateWorkingBuffers(); 311 if ((rootCR == null) || 312 (workingBaseRaster == null)) 313 return; 314 315 ColorModel cm = rootCR.getColorModel(); 316 WritableRaster syncRaster = workingBaseRaster; 317 318 synchronized (syncRaster) { 320 BufferedImage bi = new BufferedImage 321 (cm, workingBaseRaster, cm.isAlphaPremultiplied(), null); 322 Graphics2D g2d = bi.createGraphics(); 323 g2d.setComposite(AlphaComposite.Clear); 324 g2d.fillRect(0, 0, bi.getWidth(), bi.getHeight()); 325 g2d.dispose(); 326 } 327 } 328 329 330 343 public void repaint(Shape area) { 344 if (area == null) return; 345 RectListManager rlm = new RectListManager(); 346 rlm.add(usr2dev.createTransformedShape(area).getBounds()); 347 repaint(rlm); 348 } 349 350 363 public void repaint(RectListManager areas) { 364 365 if (areas == null) 366 return; 367 368 370 372 CachableRed cr; 373 WritableRaster syncRaster; 374 WritableRaster copyRaster; 375 376 updateWorkingBuffers(); 379 if ((rootCR == null) || 380 (workingBaseRaster == null)) 381 return; 382 383 cr = rootCR; 384 syncRaster = workingBaseRaster; 385 copyRaster = workingRaster; 386 387 Rectangle srcR = rootCR.getBounds(); 388 Rectangle dstR = workingRaster.getBounds(); 389 if ((dstR.x < srcR.x) || 390 (dstR.y < srcR.y) || 391 (dstR.x+dstR.width > srcR.x+srcR.width) || 392 (dstR.y+dstR.height > srcR.y+srcR.height)) 393 cr = new PadRed(cr, dstR, PadMode.ZERO_PAD, null); 394 395 synchronized (syncRaster) { 397 cr.copyData(copyRaster); 398 } 399 400 if (!HaltingThread.hasBeenHalted()) { 401 BufferedImage tmpBI = workingOffScreen; 403 404 workingBaseRaster = currentBaseRaster; 405 workingRaster = currentRaster; 406 workingOffScreen = currentOffScreen; 407 408 currentRaster = copyRaster; 409 currentBaseRaster = syncRaster; 410 currentOffScreen = tmpBI; 411 412 } 414 } 415 416 419 public void flush() { 420 if (lastCache == null) return; 421 Object o = lastCache.get(); 422 if (o == null) return; 423 424 TileCacheRed tcr = (TileCacheRed)o; 425 tcr.flushCache(tcr.getBounds()); 426 } 427 428 431 public void flush(Collection areas) { 432 AffineTransform at = getTransform(); 433 Iterator i = areas.iterator(); 434 while (i.hasNext()) { 435 Shape s = (Shape )i.next(); 436 Rectangle r = at.createTransformedShape(s).getBounds(); 437 flush(r); 438 } 439 } 440 441 444 public void flush(Rectangle r) { 445 if (lastCache == null) return; 446 Object o = lastCache.get(); 447 if (o == null) return; 448 449 TileCacheRed tcr = (TileCacheRed)o; 450 r = (Rectangle )r.clone(); 451 r.x -= Math.round((float)usr2dev.getTranslateX()); 452 r.y -= Math.round((float)usr2dev.getTranslateY()); 453 tcr.flushCache(r); 455 } 456 457 protected CachableRed setupCache(CachableRed img) { 458 if ((lastCR == null) || 459 (img != lastCR.get())) { 460 lastCR = new SoftReference (img); 461 lastCache = null; 462 } 463 464 Object o = null; 465 if (lastCache != null) 466 o = lastCache.get(); 467 if (o != null) 468 return (CachableRed)o; 469 470 img = new TileCacheRed(img); 471 lastCache = new SoftReference (img); 472 return img; 473 } 474 475 protected CachableRed renderGNR() { 476 AffineTransform at, rcAT; 477 at = usr2dev; 478 rcAT = new AffineTransform (at.getScaleX(), at.getShearY(), 479 at.getShearX(), at.getScaleY(), 480 0, 0); 481 482 RenderContext rc = new RenderContext (rcAT, null, renderingHints); 483 484 RenderedImage ri = rootFilter.createRendering(rc); 485 if (ri == null) 486 return null; 487 488 CachableRed ret; 489 ret = GraphicsUtil.wrap(ri); 490 ret = setupCache(ret); 491 492 int dx = Math.round((float)at.getTranslateX()); 493 int dy = Math.round((float)at.getTranslateY()); 494 ret = new TranslateRed(ret, ret.getMinX()+dx, ret.getMinY()+dy); 495 ret = GraphicsUtil.convertTosRGB(ret); 496 497 return ret; 498 } 499 500 501 505 protected void updateWorkingBuffers() { 506 if (rootFilter == null) { 507 rootFilter = rootGN.getGraphicsNodeRable(true); 508 rootCR = null; 509 } 510 511 rootCR = renderGNR(); 512 if (rootCR == null) { 513 workingRaster = null; 515 workingOffScreen = null; 516 workingBaseRaster = null; 517 518 currentOffScreen = null; 519 currentBaseRaster = null; 520 currentRaster = null; 521 return; 522 } 523 524 SampleModel sm = rootCR.getSampleModel(); 525 int w = offScreenWidth; 526 int h = offScreenHeight; 527 528 int tw = sm.getWidth(); 529 int th = sm.getHeight(); 530 w = (((w+tw-1)/tw)+1)*tw; 531 h = (((h+th-1)/th)+1)*th; 532 533 if ((workingBaseRaster == null) || 534 (workingBaseRaster.getWidth() < w) || 535 (workingBaseRaster.getHeight() < h)) { 536 537 sm = sm.createCompatibleSampleModel(w, h); 538 539 workingBaseRaster 540 = Raster.createWritableRaster(sm, new Point (0,0)); 541 } 542 543 int tgx = -rootCR.getTileGridXOffset(); 544 int tgy = -rootCR.getTileGridYOffset(); 545 int xt, yt; 546 if (tgx>=0) xt = tgx/tw; 547 else xt = (tgx-tw+1)/tw; 548 if (tgy>=0) yt = tgy/th; 549 else yt = (tgy-th+1)/th; 550 551 int xloc = xt*tw - tgx; 552 int yloc = yt*th - tgy; 553 554 workingRaster = workingBaseRaster.createWritableChild 561 (0, 0, w, h, xloc, yloc, null); 562 563 workingOffScreen = new BufferedImage 564 (rootCR.getColorModel(), 565 workingRaster.createWritableChild (0, 0, offScreenWidth, 566 offScreenHeight, 0, 0, null), 567 rootCR.getColorModel().isAlphaPremultiplied(), null); 568 569 570 if (!isDoubleBuffered) { 571 currentOffScreen = workingOffScreen; 572 currentBaseRaster = workingBaseRaster; 573 currentRaster = workingRaster; 574 } 575 } 576 } 577 | Popular Tags |