1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 package com.lightcrafts.jai;
4 
5 import com.lightcrafts.model.Region;
6 import com.lightcrafts.model.Contour;
7 import com.lightcrafts.jai.opimage.ShapedMask;
8 
9 import com.lightcrafts.mediax.jai.*;
10 import java.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.awt.*;
14 import java.awt.image.Raster;
15 import java.awt.geom.AffineTransform;
16 import java.awt.geom.Rectangle2D;
17 import java.awt.geom.NoninvertibleTransformException;
18 
19 /**
20  * Created by IntelliJ IDEA.
21  * User: fabio
22  * Date: Apr 5, 2005
23  * Time: 5:21:51 PM
24  * To change this template use File | Settings | File Templates.
25  */
26 public class LCROIShape extends ROIShape {
LCROIShape(Region r, AffineTransform transform)27     public LCROIShape(Region r, AffineTransform transform) {
28         super(r.getOuterShape());
29         this.transform = transform;
30         this.region = r;
31     }
32 
33     private Region region;
34     private AffineTransform transform;
35 
getTransform()36     public AffineTransform getTransform() {
37         return transform;
38     }
39 
getRegion()40     public Region getRegion() {
41         return region;
42     }
43 
intersects(Rectangle rect)44     public boolean intersects(Rectangle rect) {
45         return intersects(new Rectangle2D.Double(rect.x, rect.y, rect.width, rect.height));
46     }
47 
intersects(Rectangle2D rect)48     public boolean intersects(Rectangle2D rect) {
49         for (final Contour c : region.getContours()) {
50             AffineTransform combined = transform;
51             if (c.getTranslation() != null) {
52                 combined = AffineTransform.getTranslateInstance(c.getTranslation().getX(), c.getTranslation().getY());
53                 combined.preConcatenate(transform);
54             }
55             Rectangle2D translatedRect = rect;
56             if (!combined.isIdentity()) {
57                 try {
58                     AffineTransform inverse = combined.createInverse();
59                     translatedRect = inverse.createTransformedShape(rect).getBounds2D();
60                 } catch (NoninvertibleTransformException e) {
61                     e.printStackTrace();
62                 }
63             }
64 
65             // Take the blur tapering into account
66             Rectangle bounds = c.getOuterShape().getBounds();
67             bounds.grow((int) (c.getWidth()), (int) (c.getWidth()));
68 
69             if (bounds.intersects(translatedRect))
70                 return true;
71         }
72         return false;
73     }
74 
getOuterBounds()75     public Rectangle getOuterBounds() {
76         return ShapedMask.getOuterBounds(region, transform);
77     }
78 
79     private List<Object> contours = new LinkedList<Object>();
80 
somethingChanged()81     private synchronized boolean somethingChanged() {
82         int i = 0;
83         for (final Contour c : region.getContours()) {
84             if (c != contours.get(i))
85                 return true;
86 
87             if (c.getTranslation() != null) {
88                 if (contours.size() > (i+1) && c.getTranslation() != contours.get(i+1))
89                     return true;
90                 i+=2;
91             } else {
92                 i++;
93             }
94         }
95 
96         return contours.size() != i;
97     }
98 
99     private ShapedMask theMask = null;
100 
getData(Rectangle rect)101     public synchronized Raster getData(Rectangle rect) {
102         if (theMask == null || somethingChanged()) {
103             /*
104                 We keep the current configuration around
105                 to check if something changes in this region.
106             */
107             for (final Contour c : region.getContours()) {
108                 contours.add(c);
109 
110                 // if  a contour has a translation
111                 // put that in the next list slot
112                 if (c.getTranslation() != null)
113                     contours.add(c.getTranslation());
114             }
115 
116             theMask = new ShapedMask(region, this);
117         }
118 
119         return theMask.getData(rect);
120     }
121 }
122