1 18 package org.apache.batik.ext.awt.image.renderable; 19 20 import java.awt.Graphics2D ; 21 import java.awt.Rectangle ; 22 import java.awt.RenderingHints ; 23 import java.awt.Shape ; 24 import java.awt.geom.AffineTransform ; 25 import java.awt.geom.Point2D ; 26 import java.awt.geom.Rectangle2D ; 27 import java.awt.image.BufferedImage ; 28 import java.awt.image.RenderedImage ; 29 import java.awt.image.renderable.RenderContext ; 30 31 import org.apache.batik.ext.awt.RenderingHintsKeyExt; 32 import org.apache.batik.ext.awt.image.GraphicsUtil; 33 import org.apache.batik.ext.awt.image.rendered.AffineRed; 34 import org.apache.batik.ext.awt.image.rendered.BufferedImageCachableRed; 35 import org.apache.batik.ext.awt.image.rendered.CachableRed; 36 import org.apache.batik.ext.awt.image.rendered.TileRed; 37 38 44 public class TileRable8Bit 45 extends AbstractColorInterpolationRable 46 implements TileRable{ 47 50 private Rectangle2D tileRegion; 51 52 55 private Rectangle2D tiledRegion; 56 57 61 private boolean overflow; 62 63 66 public Rectangle2D getTileRegion(){ 67 return tileRegion; 68 } 69 70 73 public void setTileRegion(Rectangle2D tileRegion){ 74 if(tileRegion == null){ 75 throw new IllegalArgumentException (); 76 } 77 touch(); 78 this.tileRegion = tileRegion; 79 } 80 81 84 public Rectangle2D getTiledRegion(){ 85 return tiledRegion; 86 } 87 88 91 public void setTiledRegion(Rectangle2D tiledRegion){ 92 if(tiledRegion == null){ 93 throw new IllegalArgumentException (); 94 } 95 touch(); 96 this.tiledRegion = tiledRegion; 97 } 98 99 102 public boolean isOverflow(){ 103 return overflow; 104 } 105 106 109 public void setOverflow(boolean overflow){ 110 touch(); 111 this.overflow = overflow; 112 } 113 114 117 public TileRable8Bit(Filter source, 118 Rectangle2D tiledRegion, 119 Rectangle2D tileRegion, 120 boolean overflow){ 121 super(source); 122 123 setTileRegion(tileRegion); 124 setTiledRegion(tiledRegion); 125 setOverflow(overflow); 126 } 127 128 131 public void setSource(Filter src){ 132 init(src); 133 } 134 135 138 public Filter getSource(){ 139 return (Filter)srcs.get(0); 140 } 141 142 145 public Rectangle2D getBounds2D(){ 146 return (Rectangle2D )tiledRegion.clone(); 147 } 148 149 public RenderedImage createRendering(RenderContext rc){ 150 RenderingHints rh = rc.getRenderingHints(); 152 if (rh == null) rh = new RenderingHints (null); 153 154 AffineTransform at = rc.getTransform(); 156 157 double sx = at.getScaleX(); 158 double sy = at.getScaleY(); 159 160 double shx = at.getShearX(); 161 double shy = at.getShearY(); 162 163 double tx = at.getTranslateX(); 164 double ty = at.getTranslateY(); 165 166 double scaleX = Math.sqrt(sx*sx + shy*shy); 168 double scaleY = Math.sqrt(sy*sy + shx*shx); 169 170 173 179 Rectangle2D tiledRect = getBounds2D(); 181 Rectangle2D aoiRect; 182 Shape aoiShape = rc.getAreaOfInterest(); 183 if (aoiShape == null) 184 aoiRect = tiledRect; 185 else { 186 aoiRect = aoiShape.getBounds2D(); 187 188 if (tiledRect.intersects(aoiRect) == false) 189 return null; 190 Rectangle2D.intersect(tiledRect, aoiRect, tiledRect); 191 } 192 193 Rectangle2D tileRect = tileRegion; 195 196 int dw = (int)(Math.ceil(tileRect.getWidth() *scaleX)); 200 int dh = (int)(Math.ceil(tileRect.getHeight()*scaleY)); 201 202 double tileScaleX = dw/tileRect.getWidth(); 203 double tileScaleY = dh/tileRect.getHeight(); 204 205 208 int dx = (int)Math.floor(tileRect.getX()*tileScaleX); 211 int dy = (int)Math.floor(tileRect.getY()*tileScaleY); 212 213 double ttx = dx - (tileRect.getX()*tileScaleX); 214 double tty = dy - (tileRect.getY()*tileScaleY); 215 216 218 AffineTransform tileAt; 220 226 227 tileAt = AffineTransform.getTranslateInstance(ttx, tty); 228 tileAt.scale(tileScaleX, tileScaleY); 229 230 234 Filter source = getSource(); 239 240 Rectangle2D srcRect; 241 if (overflow) 242 srcRect = source.getBounds2D(); 243 else 244 srcRect = tileRect; 245 246 248 RenderContext tileRc = new RenderContext (tileAt, srcRect, rh); 249 RenderedImage tileRed = source.createRendering(tileRc); 251 252 255 if(tileRed == null) 259 return null; 260 261 262 264 Rectangle tiledArea = tileAt.createTransformedShape 265 (aoiRect).getBounds(); 266 267 if ((tiledArea.width == Integer.MAX_VALUE)|| 278 (tiledArea.height == Integer.MAX_VALUE)) { 279 tiledArea = new Rectangle (Integer.MIN_VALUE/4, 280 Integer.MIN_VALUE/4, 281 Integer.MAX_VALUE/2, 282 Integer.MAX_VALUE/2); 283 } 284 tileRed = convertSourceCS(tileRed); 286 TileRed tiledRed = new TileRed(tileRed, tiledArea, dw, dh); 287 288 291 AffineTransform shearAt = 293 new AffineTransform (sx/scaleX, shy/scaleX, 294 shx/scaleY, sy/scaleY, 295 tx, ty); 296 shearAt.scale(scaleX/tileScaleX, scaleY/tileScaleY); 297 298 shearAt.translate(-ttx, -tty); 299 300 CachableRed cr = tiledRed; 301 if(!shearAt.isIdentity()) 302 cr = new AffineRed(tiledRed, shearAt, rh); 303 304 306 return cr; 307 } 308 309 public Rectangle2D getActualTileBounds(Rectangle2D tiledRect){ 310 Rectangle2D tileRect = (Rectangle2D )tileRegion.clone(); 312 313 316 if ((tileRect.getWidth() <= 0) 317 || (tileRect.getHeight() <= 0) 318 || (tiledRect.getWidth() <= 0) 319 || (tiledRect.getHeight() <= 0)) 320 return null; 321 322 323 double tileWidth = tileRect.getWidth(); 324 double tileHeight = tileRect.getHeight(); 325 326 double tiledWidth = tiledRect.getWidth(); 327 double tiledHeight = tiledRect.getHeight(); 328 329 double w = Math.min(tileWidth, tiledWidth); 330 double h = Math.min(tileHeight, tiledHeight); 331 332 Rectangle2D realTileRect 333 = new Rectangle2D.Double (tileRect.getX(), 334 tileRect.getY(), 335 w, h); 336 337 return realTileRect; 338 } 339 340 355 public RenderedImage createTile(RenderContext rc){ 356 AffineTransform usr2dev = rc.getTransform(); 357 358 RenderingHints hints = rc.getRenderingHints(); 360 if(hints == null){ 361 hints = new RenderingHints (null); 362 } else { 363 hints = new RenderingHints (hints); 364 } 365 366 Rectangle2D tiledRect = getBounds2D(); 369 Shape aoiShape = rc.getAreaOfInterest(); 370 Rectangle2D aoiRect = aoiShape.getBounds2D(); 371 if (tiledRect.intersects(aoiRect) == false) 372 return null; 373 Rectangle2D.intersect(tiledRect, aoiRect, tiledRect); 374 375 Rectangle2D tileRect = (Rectangle2D )tileRegion.clone(); 377 378 381 if ((tileRect.getWidth() <= 0) 382 || (tileRect.getHeight() <= 0) 383 || (tiledRect.getWidth() <= 0) 384 || (tiledRect.getHeight() <= 0)) 385 return null; 386 387 416 426 double tileX = tileRect.getX(); 427 double tileY = tileRect.getY(); 428 double tileWidth = tileRect.getWidth(); 429 double tileHeight = tileRect.getHeight(); 430 431 double tiledX = tiledRect.getX(); 432 double tiledY = tiledRect.getY(); 433 double tiledWidth = tiledRect.getWidth(); 434 double tiledHeight = tiledRect.getHeight(); 435 436 double w = Math.min(tileWidth, tiledWidth); 437 double h = Math.min(tileHeight, tiledHeight); 438 double dx = (tiledX - tileX)%tileWidth; 439 double dy = (tiledY - tileY)%tileHeight; 440 441 if(dx > 0){ 442 dx = tileWidth - dx; 443 } 444 else{ 445 dx *= -1; 446 } 447 448 if(dy > 0){ 449 dy = tileHeight - dy; 450 } 451 else{ 452 dy *= -1; 453 } 454 455 double scaleX = usr2dev.getScaleX(); 459 double scaleY = usr2dev.getScaleY(); 460 double tdx = Math.floor(scaleX*dx); 461 double tdy = Math.floor(scaleY*dy); 462 463 dx = tdx/scaleX; 464 dy = tdy/scaleY; 465 466 468 Rectangle2D.Double A = new Rectangle2D.Double 469 (tileX + tileWidth - dx, tileY + tileHeight - dy, dx, dy); 470 Rectangle2D.Double B = new Rectangle2D.Double 471 (tileX, tileY + tileHeight - dy, w - dx, dy); 472 Rectangle2D.Double C = new Rectangle2D.Double 473 (tileX + tileWidth - dx, tileY, dx, h - dy); 474 Rectangle2D.Double D = new Rectangle2D.Double 475 (tileX, tileY, w - dx, h - dy); 476 477 Rectangle2D realTileRect 478 = new Rectangle2D.Double (tiledRect.getX(), 479 tiledRect.getY(), 480 w, h); 481 482 488 RenderedImage ARed = null, BRed = null, CRed = null, DRed = null; 493 Filter source = getSource(); 494 495 if (A.getWidth() > 0 && A.getHeight() > 0){ 496 Rectangle devA = usr2dev.createTransformedShape(A).getBounds(); 498 if(devA.width > 0 && devA.height > 0){ 499 AffineTransform ATxf = new AffineTransform (usr2dev); 500 ATxf.translate(-A.x + tiledX, 501 -A.y + tiledY); 502 503 Shape aoi = A; 504 if(overflow){ 505 aoi = new Rectangle2D.Double (A.x, 506 A.y, 507 tiledWidth, 508 tiledHeight); 509 } 510 511 hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST, 512 aoi); 513 514 RenderContext arc 515 = new RenderContext (ATxf, aoi, hints); 516 517 ARed = source.createRendering(arc); 518 519 } 524 } 525 526 if(B.getWidth() > 0 && B.getHeight() > 0){ 527 Rectangle devB = usr2dev.createTransformedShape(B).getBounds(); 529 if(devB.width > 0 && devB.height > 0){ 530 AffineTransform BTxf = new AffineTransform (usr2dev); 531 BTxf.translate(-B.x + (tiledX + dx), 532 -B.y + tiledY); 533 534 Shape aoi = B; 535 if(overflow){ 536 aoi = new Rectangle2D.Double (B.x - tiledWidth + w - dx, 537 B.y, 538 tiledWidth, 539 tiledHeight); 540 } 541 542 hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST, 543 aoi); 544 545 RenderContext brc 546 = new RenderContext (BTxf, aoi, hints); 547 548 BRed = source.createRendering(brc); 549 } 551 } 552 553 if(C.getWidth() > 0 && C.getHeight() > 0){ 554 Rectangle devC = usr2dev.createTransformedShape(C).getBounds(); 556 if(devC.width > 0 && devC.height > 0){ 557 AffineTransform CTxf = new AffineTransform (usr2dev); 558 CTxf.translate(-C.x + tiledX, 559 -C.y + (tiledY + dy)); 560 561 Shape aoi = C; 562 if(overflow){ 563 aoi = new Rectangle2D.Double (C.x, 564 C.y - tileHeight + h - dy, 565 tiledWidth, 566 tiledHeight); 567 } 568 569 hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST, 570 aoi); 571 572 RenderContext crc 573 = new RenderContext (CTxf, aoi, hints); 574 575 CRed = source.createRendering(crc); 576 } 578 } 579 580 if(D.getWidth() > 0 && D.getHeight() > 0){ 581 Rectangle devD = usr2dev.createTransformedShape(D).getBounds(); 583 if(devD.width > 0 && devD.height > 0){ 584 AffineTransform DTxf = new AffineTransform (usr2dev); 585 DTxf.translate(-D.x + (tiledX + dx), 586 -D.y + (tiledY + dy)); 587 588 Shape aoi = D; 589 if(overflow){ 590 aoi = new Rectangle2D.Double (D.x - tileWidth + w - dx, 591 D.y - tileHeight + h - dy, 592 tiledWidth, 593 tiledHeight); 594 } 595 596 hints.put(RenderingHintsKeyExt.KEY_AREA_OF_INTEREST, 597 aoi); 598 599 RenderContext drc 600 = new RenderContext (DTxf, aoi, hints); 601 602 DRed = source.createRendering(drc); 603 } 605 } 606 607 final Rectangle realTileRectDev 612 = usr2dev.createTransformedShape(realTileRect).getBounds(); 613 614 if(realTileRectDev.width == 0 || realTileRectDev.height == 0){ 615 return null; 616 } 617 618 BufferedImage realTileBI 619 = new BufferedImage (realTileRectDev.width, 620 realTileRectDev.height, 621 BufferedImage.TYPE_INT_ARGB); 622 623 Graphics2D g = GraphicsUtil.createGraphics(realTileBI, 624 rc.getRenderingHints()); 625 g.translate(-realTileRectDev.x, 628 -realTileRectDev.y); 629 630 632 AffineTransform redTxf = new AffineTransform (); 633 Point2D.Double redVec = new Point2D.Double (); 634 RenderedImage refRed = null; 635 if(ARed != null){ 636 g.drawRenderedImage(ARed, redTxf); 638 refRed = ARed; 639 } 640 if(BRed != null){ 641 643 if(refRed == null){ 644 refRed = BRed; 645 } 646 647 redVec.x = dx; 649 redVec.y = 0; 650 usr2dev.deltaTransform(redVec, redVec); 651 redVec.x = Math.floor(redVec.x) - (BRed.getMinX() - refRed.getMinX()); 652 redVec.y = Math.floor(redVec.y) - (BRed.getMinY() - refRed.getMinY()); 653 654 656 g.drawRenderedImage(BRed, redTxf); 658 } 659 if(CRed != null){ 660 662 if(refRed == null){ 663 refRed = CRed; 664 } 665 666 redVec.x = 0; 668 redVec.y = dy; 669 usr2dev.deltaTransform(redVec, redVec); 670 redVec.x = Math.floor(redVec.x) - (CRed.getMinX() - refRed.getMinX()); 671 redVec.y = Math.floor(redVec.y) - (CRed.getMinY() - refRed.getMinY()); 672 673 675 g.drawRenderedImage(CRed, redTxf); 677 } 678 if(DRed != null){ 679 681 if(refRed == null){ 682 refRed = DRed; 683 } 684 685 redVec.x = dx; 687 redVec.y = dy; 688 usr2dev.deltaTransform(redVec, redVec); 689 redVec.x = Math.floor(redVec.x) - (DRed.getMinX() - refRed.getMinX()); 690 redVec.y = Math.floor(redVec.y) - (DRed.getMinY() - refRed.getMinY()); 691 692 694 g.drawRenderedImage(DRed, redTxf); 696 } 697 698 CachableRed realTile; 699 realTile = new BufferedImageCachableRed(realTileBI, 700 realTileRectDev.x, 701 realTileRectDev.y); 702 703 return realTile; 704 } 705 } 706 | Popular Tags |