KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > image > rendered > CompositeRed


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.image.rendered;
19
20 import java.awt.CompositeContext JavaDoc;
21 import java.awt.Graphics2D JavaDoc;
22 import java.awt.Point JavaDoc;
23 import java.awt.Rectangle JavaDoc;
24 import java.awt.color.ColorSpace JavaDoc;
25 import java.awt.image.BufferedImage JavaDoc;
26 import java.awt.image.ColorModel JavaDoc;
27 import java.awt.image.DataBuffer JavaDoc;
28 import java.awt.image.DirectColorModel JavaDoc;
29 import java.awt.image.Raster JavaDoc;
30 import java.awt.image.SampleModel JavaDoc;
31 import java.awt.image.WritableRaster JavaDoc;
32 import java.util.Iterator JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.Vector JavaDoc;
35
36 import org.apache.batik.ext.awt.image.CompositeRule;
37 import org.apache.batik.ext.awt.image.GraphicsUtil;
38 import org.apache.batik.ext.awt.image.PadMode;
39 import org.apache.batik.ext.awt.image.SVGComposite;
40
41 /**
42  * This is an implementation of an affine operation as a RenderedImage.
43  * Right now the implementation makes use of the AffineBufferedImageOp
44  * to do the work. Eventually this may move to be more tiled in nature.
45  *
46  * @author <a HREF="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
47  * @version $Id: CompositeRed.java,v 1.9 2004/08/18 07:14:08 vhardy Exp $ */

48 public class CompositeRed extends AbstractRed {
49
50     CompositeRule rule;
51     CompositeContext JavaDoc [] contexts;
52
53     public CompositeRed(List JavaDoc srcs, CompositeRule rule) {
54         super(); // We _must_ call init...
55

56         CachableRed src = (CachableRed)srcs.get(0);
57
58         ColorModel JavaDoc cm = fixColorModel (src);
59
60         this.rule = rule;
61
62         SVGComposite comp = new SVGComposite(rule);
63         contexts = new CompositeContext JavaDoc[srcs.size()];
64
65         int idx = 0;
66         Iterator JavaDoc i = srcs.iterator();
67         Rectangle JavaDoc myBounds = null;
68         while (i.hasNext()) {
69             CachableRed cr = (CachableRed)i.next();
70
71             contexts[idx++] = comp.createContext(cr.getColorModel(), cm, null);
72
73             Rectangle JavaDoc newBound = cr.getBounds();
74             if (myBounds == null) {
75                 myBounds = newBound;
76                 continue;
77             }
78
79             switch (rule.getRule()) {
80             case CompositeRule.RULE_IN:
81                 if (myBounds.intersects(newBound))
82                     myBounds = myBounds.intersection(newBound);
83                 else {
84                     myBounds.width = 0;
85                     myBounds.height = 0;
86                 }
87                 break;
88             case CompositeRule.RULE_OUT:
89                 // Last node determines bounds...
90
myBounds = newBound;
91                 break;
92             default:
93                 myBounds= myBounds.union(newBound);
94             }
95         }
96
97         if (myBounds == null)
98             throw new IllegalArgumentException JavaDoc
99                 ("Composite Operation Must have some source!");
100
101         if (rule.getRule() == CompositeRule.RULE_ARITHMETIC) {
102             Vector JavaDoc vec = new Vector JavaDoc();
103             i = srcs.iterator();
104             while (i.hasNext()) {
105                 CachableRed cr = (CachableRed)i.next();
106                 Rectangle JavaDoc r = cr.getBounds();
107                 // For arithmatic make sure they are all the same size...
108
if ((r.x != myBounds.x) ||
109                     (r.y != myBounds.y) ||
110                     (r.width != myBounds.width) ||
111                     (r.height != myBounds.height))
112                     cr = new PadRed(cr, myBounds, PadMode.ZERO_PAD, null);
113                 vec.add(cr);
114             }
115             srcs = vec;
116         }
117
118         // fix my sample model so it makes sense given my size.
119
SampleModel JavaDoc sm = fixSampleModel(src, cm, myBounds);
120
121         // System.out.println("Comp: " + myBounds);
122
// System.out.println(" SM: " + sm.getWidth()+"x"+sm.getHeight());
123

124         int defSz = AbstractTiledRed.getDefaultTileSize();
125
126         // Make tile(0,0) fall on the closest intersection of defaultSz.
127
int tgX = defSz*(int)Math.floor(myBounds.x/defSz);
128         int tgY = defSz*(int)Math.floor(myBounds.y/defSz);
129
130         // Finish initializing our base class...
131
init(srcs, myBounds, cm, sm, tgX, tgY, null);
132     }
133
134     public WritableRaster JavaDoc copyData(WritableRaster JavaDoc wr) {
135         // copyToRaster(wr);
136
genRect(wr);
137         return wr;
138     }
139
140     public Raster JavaDoc getTile(int x, int y) {
141         int tx = tileGridXOff+x*tileWidth;
142         int ty = tileGridYOff+y*tileHeight;
143         Point JavaDoc pt = new Point JavaDoc(tx, ty);
144         WritableRaster JavaDoc wr = Raster.createWritableRaster(sm, pt);
145         genRect(wr);
146         
147         return wr;
148     }
149
150     public void emptyRect(WritableRaster JavaDoc wr) {
151         PadRed.ZeroRecter zr = PadRed.ZeroRecter.getZeroRecter(wr);
152         zr.zeroRect(new Rectangle JavaDoc(wr.getMinX(), wr.getMinY(),
153                                   wr.getWidth(), wr.getHeight()));
154     }
155
156     public void genRect(WritableRaster JavaDoc wr) {
157         // long startTime = System.currentTimeMillis();
158
// System.out.println("Comp GenR: " + wr);
159
Rectangle JavaDoc r = wr.getBounds();
160         
161         int idx = 0;
162         Iterator JavaDoc i = srcs.iterator();
163         boolean first = true;
164         while (i.hasNext()) {
165             CachableRed cr = (CachableRed)i.next();
166             if (first) {
167                 Rectangle JavaDoc crR = cr.getBounds();
168                 if ((r.x < crR.x) ||
169                     (r.y < crR.y) ||
170                     (r.x+r.width > crR.x+crR.width) ||
171                     (r.y+r.height > crR.y+crR.height))
172                     // Portions outside my bounds, zero them...
173
emptyRect(wr);
174
175                 // Fill in initial image...
176
cr.copyData(wr);
177
178                 if (cr.getColorModel().isAlphaPremultiplied() == false)
179                     GraphicsUtil.coerceData(wr, cr.getColorModel(), true);
180                 first = false;
181             } else {
182                 Rectangle JavaDoc crR = cr.getBounds();
183                 if (crR.intersects(r)) {
184                     Rectangle JavaDoc smR = crR.intersection(r);
185                     Raster JavaDoc ras = cr.getData(smR);
186                     WritableRaster JavaDoc smWR = wr.createWritableChild
187                         (smR.x, smR.y, smR.width, smR.height,
188                          smR.x, smR.y, null);
189                     
190                     contexts[idx].compose(ras, smWR, smWR);
191                 }
192             }
193
194             idx++;
195         }
196         // long endTime = System.currentTimeMillis();
197
// System.out.println("Other: " + (endTime-startTime));
198
}
199
200     // This is an alternate Implementation that uses drawImage.
201
// In testing this was not significantly faster and it had some
202
// problems with alpha premultiplied.
203
public void genRect_OVER(WritableRaster JavaDoc wr) {
204         // long startTime = System.currentTimeMillis();
205
// System.out.println("Comp GenR: " + wr);
206
Rectangle JavaDoc r = wr.getBounds();
207
208         ColorModel JavaDoc cm = getColorModel();
209
210         BufferedImage JavaDoc bi = new BufferedImage JavaDoc
211             (cm, wr.createWritableTranslatedChild(0,0),
212              cm.isAlphaPremultiplied(), null);
213
214         Graphics2D JavaDoc g2d = GraphicsUtil.createGraphics(bi);
215         g2d.translate(-r.x, -r.y);
216
217         Iterator JavaDoc i = srcs.iterator();
218         boolean first = true;
219         while (i.hasNext()) {
220             CachableRed cr = (CachableRed)i.next();
221             if (first) {
222                 Rectangle JavaDoc crR = cr.getBounds();
223                 if ((r.x < crR.x) ||
224                     (r.y < crR.y) ||
225                     (r.x+r.width > crR.x+crR.width) ||
226                     (r.y+r.height > crR.y+crR.height))
227                     // Portions outside my bounds, zero them...
228
emptyRect(wr);
229
230                 // Fill in initial image...
231
cr.copyData(wr);
232
233                 GraphicsUtil.coerceData(wr, cr.getColorModel(),
234                                         cm.isAlphaPremultiplied());
235                 first = false;
236             } else {
237                 GraphicsUtil.drawImage(g2d, cr);
238             }
239         }
240         // long endTime = System.currentTimeMillis();
241
// System.out.println("OVER: " + (endTime-startTime));
242
}
243
244         /**
245          * This function 'fixes' the source's sample model.
246          * right now it just ensures that the sample model isn't
247          * much larger than my width.
248          */

249     protected static SampleModel JavaDoc fixSampleModel(CachableRed src,
250                                                 ColorModel JavaDoc cm,
251                                                 Rectangle JavaDoc bounds) {
252         int defSz = AbstractTiledRed.getDefaultTileSize();
253
254         // Make tile(0,0) fall on the closest intersection of defaultSz.
255
int tgX = defSz*(int)Math.floor(bounds.x/defSz);
256         int tgY = defSz*(int)Math.floor(bounds.y/defSz);
257
258         int tw = (bounds.x+bounds.width)-tgX;
259         int th = (bounds.y+bounds.height)-tgY;
260
261         SampleModel JavaDoc sm = src.getSampleModel();
262
263         int w = sm.getWidth();
264         if (w < defSz) w = defSz;
265         if (w > tw) w = tw;
266
267         int h = sm.getHeight();
268         if (h < defSz) h = defSz;
269         if (h > th) h = th;
270
271         if ((w <= 0) || (h <= 0)) {
272             w = 1;
273             h = 1;
274         }
275
276         // System.out.println("tg: " + tgX + "x" + tgY);
277
// System.out.println("t: " + tw + "x" + th);
278
// System.out.println("sz: " + w + "x" + h);
279

280         return cm.createCompatibleSampleModel(w, h);
281     }
282
283     protected static ColorModel JavaDoc fixColorModel(CachableRed src) {
284         ColorModel JavaDoc cm = src.getColorModel();
285
286         if (cm.hasAlpha()) {
287             if (!cm.isAlphaPremultiplied())
288                 cm = GraphicsUtil.coerceColorModel(cm, true);
289             return cm;
290         }
291
292         int b = src.getSampleModel().getNumBands()+1;
293         if (b > 4)
294             throw new IllegalArgumentException JavaDoc
295                 ("CompositeRed can only handle up to three band images");
296         
297         int [] masks = new int[4];
298         for (int i=0; i < b-1; i++)
299             masks[i] = 0xFF0000 >> (8*i);
300         masks[3] = 0xFF << (8*(b-1));
301         ColorSpace JavaDoc cs = cm.getColorSpace();
302
303         return new DirectColorModel JavaDoc(cs, 8*b, masks[0], masks[1],
304                                     masks[2], masks[3],
305                                     true, DataBuffer.TYPE_INT);
306     }
307 }
308
Popular Tags