KickJava   Java API By Example, From Geeks To Geeks.

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


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.Point JavaDoc;
21 import java.awt.Rectangle JavaDoc;
22 import java.awt.image.ColorModel JavaDoc;
23 import java.awt.image.DataBufferInt JavaDoc;
24 import java.awt.image.Raster JavaDoc;
25 import java.awt.image.SampleModel JavaDoc;
26 import java.awt.image.WritableRaster JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29
30 import org.apache.batik.ext.awt.image.GraphicsUtil;
31 import org.apache.batik.util.HaltingThread;
32
33 /**
34  * This is an abstract base class that takes care of most of the
35  * normal issues surrounding the implementation of the CachableRed
36  * (RenderedImage) interface. It tries to make no assumptions about
37  * the subclass implementation.
38  *
39  * @author <a HREF="mailto:Thomas.DeWeeese@Kodak.com">Thomas DeWeese</a>
40  * @version $Id: AbstractTiledRed.java,v 1.20 2005/03/27 08:58:33 cam Exp $
41  */

42 public abstract class AbstractTiledRed
43     extends AbstractRed
44     implements TileGenerator {
45
46     private TileStore tiles;
47
48     private static int defaultTileSize = 128;
49     public static int getDefaultTileSize() { return defaultTileSize; }
50
51     /**
52      * void constructor. The subclass must call one of the
53      * flavors of init before the object becomes usable.
54      * This is useful when the proper parameters to the init
55      * method need to be computed in the subclasses constructor.
56      */

57     protected AbstractTiledRed() { }
58
59
60     /**
61      * Construct an Abstract RenderedImage from a bounds rect and props
62      * (may be null). The srcs Vector will be empty.
63      * @param bounds this defines the extent of the rable in the
64      * user coordinate system.
65      * @param props this initializes the props Map (may be null)
66      */

67     protected AbstractTiledRed(Rectangle JavaDoc bounds, Map JavaDoc props) {
68         super(bounds, props);
69     }
70
71     /**
72      * Construct an Abstract RenderedImage from a source image and
73      * props (may be null).
74      * @param src will be the first (and only) member of the srcs
75      * Vector. Src is also used to set the bounds, ColorModel,
76      * SampleModel, and tile grid offsets.
77      * @param props this initializes the props Map. */

78     protected AbstractTiledRed(CachableRed src, Map JavaDoc props) {
79         super(src, props);
80     }
81
82     /**
83      * Construct an Abstract RenderedImage from a source image, bounds
84      * rect and props (may be null).
85      * @param src will be the first (and only) member of the srcs
86      * Vector. Src is also used to set the ColorModel, SampleModel,
87      * and tile grid offsets.
88      * @param bounds The bounds of this image.
89      * @param props this initializes the props Map. */

90     protected AbstractTiledRed(CachableRed src, Rectangle JavaDoc bounds, Map JavaDoc props) {
91         super(src, bounds, props);
92     }
93
94     /**
95      * Construct an Abstract RenderedImage from a source image, bounds
96      * rect and props (may be null).
97      * @param src will be the first (and only) member of the srcs
98      * Vector. Src is also used to set the ColorModel, SampleModel,
99      * and tile grid offsets.
100      * @param bounds The bounds of this image.
101      * @param cm The ColorModel to use. If null it will default to
102      * ComponentColorModel.
103      * @param sm The sample model to use. If null it will construct
104      * a sample model the matches the given/generated ColorModel and is
105      * the size of bounds.
106      * @param props this initializes the props Map. */

107     protected AbstractTiledRed(CachableRed src, Rectangle JavaDoc bounds,
108                           ColorModel JavaDoc cm, SampleModel JavaDoc sm,
109                           Map JavaDoc props) {
110         super(src, bounds, cm, sm, props);
111     }
112
113     /**
114      * Construct an Abstract Rable from a bounds rect and props
115      * (may be null). The srcs Vector will be empty.
116      * @param src will be the first (and only) member of the srcs
117      * Vector. Src is also used to set the ColorModel, SampleModel,
118      * and tile grid offsets.
119      * @param bounds this defines the extent of the rable in the
120      * user coordinate system.
121      * @param cm The ColorModel to use. If null it will default to
122      * ComponentColorModel.
123      * @param sm The sample model to use. If null it will construct
124      * a sample model the matches the given/generated ColorModel and is
125      * the size of bounds.
126      * @param tileGridXOff The x location of tile 0,0.
127      * @param tileGridYOff The y location of tile 0,0.
128      * @param props this initializes the props Map.
129      */

130     protected AbstractTiledRed(CachableRed src, Rectangle JavaDoc bounds,
131                           ColorModel JavaDoc cm, SampleModel JavaDoc sm,
132                           int tileGridXOff, int tileGridYOff,
133                           Map JavaDoc props) {
134         super(src, bounds, cm, sm, tileGridXOff, tileGridYOff, props);
135     }
136
137     /**
138      * This is one of two basic init function (this is for single
139      * source rendereds).
140      * It is provided so subclasses can compute various values
141      * before initializing all the state in the base class.
142      * You really should call this method before returning from
143      * your subclass constructor.
144      *
145      * @param src The source for the filter
146      * @param bounds The bounds of the image
147      * @param cm The ColorModel to use. If null it defaults to
148      * ComponentColorModel/ src's ColorModel.
149      * @param sm The Sample modle to use. If this is null it will
150      * use the src's sample model if that is null it will
151      * construct a sample model that matches the ColorModel
152      * and is the size of the whole image.
153      * @param tileGridXOff The x location of tile 0,0.
154      * @param tileGridYOff The y location of tile 0,0.
155      * @param props Any properties you want to associate with the image.
156      */

157     protected void init(CachableRed src, Rectangle JavaDoc bounds,
158                         ColorModel JavaDoc cm, SampleModel JavaDoc sm,
159                         int tileGridXOff, int tileGridYOff,
160                         Map JavaDoc props) {
161         init(src, bounds, cm, sm, tileGridXOff, tileGridYOff, null, props);
162     }
163
164
165     /**
166      * This is one of two basic init function (this is for single
167      * source rendereds).
168      * It is provided so subclasses can compute various values
169      * before initializing all the state in the base class.
170      * You really should call this method before returning from
171      * your subclass constructor.
172      *
173      * @param src The source for the filter
174      * @param bounds The bounds of the image
175      * @param cm The ColorModel to use. If null it defaults to
176      * ComponentColorModel/ src's ColorModel.
177      * @param sm The Sample modle to use. If this is null it will
178      * use the src's sample model if that is null it will
179      * construct a sample model that matches the ColorModel
180      * and is the size of the whole image.
181      * @param tileGridXOff The x location of tile 0,0.
182      * @param tileGridYOff The y location of tile 0,0.
183      * @param tiles The tileStore to use (or null).
184      * @param props Any properties you want to associate with the image.
185      */

186     protected void init(CachableRed src, Rectangle JavaDoc bounds,
187                         ColorModel JavaDoc cm, SampleModel JavaDoc sm,
188                         int tileGridXOff, int tileGridYOff,
189                         TileStore tiles,
190                         Map JavaDoc props) {
191         super.init(src, bounds, cm, sm, tileGridXOff, tileGridYOff, props);
192         this.tiles = tiles;
193         if (this.tiles == null)
194             this.tiles = createTileStore();
195     }
196
197     /**
198      * Construct an Abstract Rable from a List of sources a bounds rect
199      * and props (may be null).
200      * @param srcs This is used to initialize the srcs Vector. All
201      * the members of srcs must be CachableRed otherwise an error
202      * will be thrown.
203      * @param bounds this defines the extent of the rendered in pixels
204      * @param props this initializes the props Map.
205      */

206     protected AbstractTiledRed(List JavaDoc srcs, Rectangle JavaDoc bounds, Map JavaDoc props) {
207         super(srcs, bounds, props);
208     }
209
210     /**
211      * Construct an Abstract RenderedImage from a bounds rect,
212      * ColorModel (may be null), SampleModel (may be null) and props
213      * (may be null). The srcs Vector will be empty.
214      * @param srcs This is used to initialize the srcs Vector. All
215      * the members of srcs must be CachableRed otherwise an error
216      * will be thrown.
217      * @param bounds this defines the extent of the rendered in pixels
218      * @param cm The ColorModel to use. If null it will default to
219      * ComponentColorModel.
220      * @param sm The sample model to use. If null it will construct
221      * a sample model the matches the given/generated ColorModel and is
222      * the size of bounds.
223      * @param props this initializes the props Map.
224      */

225     protected AbstractTiledRed(List JavaDoc srcs, Rectangle JavaDoc bounds,
226                           ColorModel JavaDoc cm, SampleModel JavaDoc sm,
227                           Map JavaDoc props) {
228         super(srcs, bounds, cm, sm, props);
229     }
230
231     /**
232      * Construct an Abstract RenderedImage from a bounds rect,
233      * ColorModel (may be null), SampleModel (may be null), tile grid
234      * offsets and props (may be null). The srcs Vector will be
235      * empty.
236      * @param srcs This is used to initialize the srcs Vector. All
237      * the members of srcs must be CachableRed otherwise an error
238      * will be thrown.
239      * @param bounds this defines the extent of the rable in the
240      * user coordinate system.
241      * @param cm The ColorModel to use. If null it will default to
242      * ComponentColorModel.
243      * @param sm The sample model to use. If null it will construct
244      * a sample model the matches the given/generated ColorModel and is
245      * the size of bounds.
246      * @param tileGridXOff The x location of tile 0,0.
247      * @param tileGridYOff The y location of tile 0,0.
248      * @param props this initializes the props Map.
249      */

250     protected AbstractTiledRed(List JavaDoc srcs, Rectangle JavaDoc bounds,
251                           ColorModel JavaDoc cm, SampleModel JavaDoc sm,
252                           int tileGridXOff, int tileGridYOff,
253                           Map JavaDoc props) {
254         super(srcs, bounds, cm, sm, tileGridXOff, tileGridYOff, props);
255     }
256
257     /**
258      * This is the basic init function.
259      * It is provided so subclasses can compute various values
260      * before initializing all the state in the base class.
261      * You really should call this method before returning from
262      * your subclass constructor.
263      *
264      * @param srcs The list of sources
265      * @param bounds The bounds of the image
266      * @param cm The ColorModel to use. If null it defaults to
267      * ComponentColorModel.
268      * @param sm The Sample modle to use. If this is null it will
269      * construct a sample model that matches the ColorModel
270      * and is the size of the whole image.
271      * @param tileGridXOff The x location of tile 0,0.
272      * @param tileGridYOff The y location of tile 0,0.
273      * @param props Any properties you want to associate with the image.
274      */

275     protected void init(List JavaDoc srcs, Rectangle JavaDoc bounds,
276                         ColorModel JavaDoc cm, SampleModel JavaDoc sm,
277                         int tileGridXOff, int tileGridYOff,
278                         Map JavaDoc props) {
279         super.init(srcs, bounds, cm, sm, tileGridXOff, tileGridYOff, props);
280         tiles = createTileStore();
281     }
282
283     public TileStore getTileStore() {
284         return tiles;
285     }
286
287     protected void setTileStore(TileStore tiles) {
288         this.tiles = tiles;
289     }
290
291     protected TileStore createTileStore() {
292         return TileCache.getTileMap(this);
293     }
294
295     public WritableRaster JavaDoc copyData(WritableRaster JavaDoc wr) {
296         copyToRasterByBlocks(wr);
297         return wr;
298     }
299
300         
301     public Raster JavaDoc getData(Rectangle JavaDoc rect) {
302         int xt0 = getXTile(rect.x);
303         int xt1 = getXTile(rect.x+rect.width-1);
304         int yt0 = getYTile(rect.y);
305         int yt1 = getYTile(rect.y+rect.height-1);
306
307         if ((xt0 == xt1) && (yt0 == yt1)) {
308             Raster JavaDoc r = getTile(xt0, yt0);
309             return r.createChild(rect.x, rect.y, rect.width, rect.height,
310                                  rect.x, rect.y, null);
311         }
312         // rect crosses tile boundries...
313
return super.getData(rect);
314     }
315
316
317     public Raster JavaDoc getTile(int x, int y) {
318         return tiles.getTile(x, y);
319     }
320
321     public Raster JavaDoc genTile(int x, int y) {
322         WritableRaster JavaDoc wr = makeTile(x, y);
323         genRect(wr);
324         return wr;
325     }
326
327     public abstract void genRect(WritableRaster JavaDoc wr);
328     // { copyToRaster(wr); }
329

330
331     public void setTile(int x, int y, Raster JavaDoc ras) {
332         tiles.setTile(x, y, ras);
333     }
334
335     public void copyToRasterByBlocks(WritableRaster JavaDoc wr) {
336         final boolean is_INT_PACK =
337             GraphicsUtil.is_INT_PACK_Data(getSampleModel(), false);
338
339         Rectangle JavaDoc bounds = getBounds();
340         Rectangle JavaDoc wrR = wr.getBounds();
341
342         int tx0 = getXTile(wrR.x);
343         int ty0 = getYTile(wrR.y);
344         int tx1 = getXTile(wrR.x+wrR.width -1);
345         int ty1 = getYTile(wrR.y+wrR.height-1);
346
347         if (tx0 < minTileX) tx0 = minTileX;
348         if (ty0 < minTileY) ty0 = minTileY;
349
350         if (tx1 >= minTileX+numXTiles) tx1 = minTileX+numXTiles-1;
351         if (ty1 >= minTileY+numYTiles) ty1 = minTileY+numYTiles-1;
352
353         if ((tx1 < tx0) || (ty1 < ty0))
354             return;
355
356         // System.out.println("WR: " + wrR);
357
// System.out.println("ME: " + bounds);
358

359         int insideTx0 = tx0;
360         int insideTx1 = tx1;
361
362         int insideTy0 = ty0;
363         int insideTy1 = ty1;
364
365         // Now figure out what tiles lie completely inside wr...
366
int tx, ty;
367         tx = tx0*tileWidth+tileGridXOff;
368         if ((tx < wrR.x) && (bounds.x != wrR.x))
369             // Partial tile off the left.
370
insideTx0++;
371
372         ty= ty0*tileHeight+tileGridYOff;
373         if ((ty < wrR.y) && (bounds.y != wrR.y))
374             // Partial tile off the top.
375
insideTy0++;
376
377         tx= (tx1+1)*tileWidth+tileGridXOff-1;
378         if ((tx >= (wrR.x+wrR.width)) &&
379             ((bounds.x+bounds.width) != (wrR.x+wrR.width)))
380             // Partial tile off right
381
insideTx1--;
382
383         ty= (ty1+1)*tileHeight+tileGridYOff-1;
384         if ((ty >= (wrR.y+wrR.height)) &&
385             ((bounds.y+bounds.height) != (wrR.y+wrR.height)))
386             // Partial tile off bottom
387
insideTy1--;
388
389         int xtiles = insideTx1-insideTx0+1;
390         int ytiles = insideTy1-insideTy0+1;
391         boolean [] occupied = null;
392         if ((xtiles > 0) && (ytiles > 0))
393             occupied = new boolean[xtiles*ytiles];
394
395         boolean [] got = new boolean[2*(tx1-tx0+1) + 2*(ty1-ty0+1)];
396         int idx = 0;
397         int numFound = 0;
398         // Collect all the tiles that we currently have in cache...
399
for (int y=ty0; y<=ty1; y++) {
400             for (int x=tx0; x<=tx1; x++) {
401                 Raster JavaDoc ras = tiles.getTileNoCompute(x, y);
402                 boolean found = (ras != null);
403                 if ((y>=insideTy0) && (y<=insideTy1) &&
404                     (x>=insideTx0) && (x<=insideTx1))
405                     occupied[(x-insideTx0)+(y-insideTy0)*xtiles] = found;
406                 else
407                     got[idx++] = found;
408
409                 if (!found) continue;
410
411                 numFound++;
412
413                 if (is_INT_PACK)
414                     GraphicsUtil.copyData_INT_PACK(ras, wr);
415                 else
416                     GraphicsUtil.copyData_FALLBACK(ras, wr);
417             }
418         }
419
420         // System.out.println("Found: " + numFound + " out of " +
421
// ((tx1-tx0+1)*(ty1-ty0+1)));
422

423         // Compute the stuff from the middle in the largest possible Chunks.
424
if ((xtiles > 0) && (ytiles > 0)) {
425             TileBlock block = new TileBlock
426                 (insideTx0, insideTy0, xtiles, ytiles, occupied,
427                  0, 0, xtiles, ytiles);
428             // System.out.println("Starting Splits");
429
drawBlock(block, wr);
430             // Exception e= new Exception("Foo");
431
// e.printStackTrace();
432
}
433
434         // Check If we should halt early.
435
if (HaltingThread.hasBeenHalted())
436             return;
437
438         idx = 0;
439         // Fill in the ones that weren't in the cache.
440
for (ty=ty0; ty<=ty1; ty++) {
441
442             for (tx=tx0; tx<=tx1; tx++) {
443                 // At least touch the tile...
444
Raster JavaDoc ras = tiles.getTileNoCompute(tx, ty);
445
446                 if ((ty>=insideTy0) && (ty<=insideTy1) &&
447                     (tx>=insideTx0) && (tx<=insideTx1)) {
448
449                     if (ras != null) continue;
450
451                     // Fill the tile from wr (since wr is full now
452
// at least in the middle).
453
WritableRaster JavaDoc tile = makeTile(tx, ty);
454                     if (is_INT_PACK)
455                         GraphicsUtil.copyData_INT_PACK(wr, tile);
456                     else
457                         GraphicsUtil.copyData_FALLBACK(wr, tile);
458
459                     tiles.setTile(tx, ty, tile);
460                 }
461                 else {
462                     if (got[idx++]) continue;
463
464                     // System.out.println("Computing : " + x + "," + y);
465

466                     ras = getTile(tx, ty);// Compute the tile..
467
// Check If we should halt early.
468
if (HaltingThread.hasBeenHalted())
469                         return;
470
471                     if (is_INT_PACK)
472                         GraphicsUtil.copyData_INT_PACK(ras, wr);
473                     else
474                         GraphicsUtil.copyData_FALLBACK(ras, wr);
475                 }
476             }
477         }
478
479         // System.out.println("Ending Computation: " + this);
480
}
481
482     /**
483      * Copies data from this images tile grid into wr. wr may
484      * extend outside the bounds of this image in which case the
485      * data in wr outside the bounds will not be touched.
486      * @param wr Raster to fill with image data.
487      */

488     public void copyToRaster(WritableRaster JavaDoc wr) {
489         Rectangle JavaDoc wrR = wr.getBounds();
490             
491         int tx0 = getXTile(wrR.x);
492         int ty0 = getYTile(wrR.y);
493         int tx1 = getXTile(wrR.x+wrR.width -1);
494         int ty1 = getYTile(wrR.y+wrR.height-1);
495
496         if (tx0 < minTileX) tx0 = minTileX;
497         if (ty0 < minTileY) ty0 = minTileY;
498
499         if (tx1 >= minTileX+numXTiles) tx1 = minTileX+numXTiles-1;
500         if (ty1 >= minTileY+numYTiles) ty1 = minTileY+numYTiles-1;
501
502         final boolean is_INT_PACK =
503             GraphicsUtil.is_INT_PACK_Data(getSampleModel(), false);
504
505         int xtiles = (tx1-tx0+1);
506         boolean [] got = new boolean[xtiles*(ty1-ty0+1)];
507
508         // Run through and get the tiles that are just sitting in the
509
// cache...
510
for (int y=ty0; y<=ty1; y++)
511             for (int x=tx0; x<=tx1; x++) {
512                 Raster JavaDoc r = tiles.getTileNoCompute(x, y);
513                 if (r == null) continue; // Not there.
514

515                 got[x-tx0 + (y-ty0)*xtiles] = true;
516
517                 if (is_INT_PACK)
518                     GraphicsUtil.copyData_INT_PACK(r, wr);
519                 else
520                     GraphicsUtil.copyData_FALLBACK(r, wr);
521             }
522
523         // Run through and pick up the ones we need to compute...
524
for (int y=ty0; y<=ty1; y++)
525             for (int x=tx0; x<=tx1; x++) {
526                 if (got[x-tx0 + (y-ty0)*xtiles]) continue; // already have.
527

528                 Raster JavaDoc r = getTile(x, y);
529                 if (is_INT_PACK)
530                     GraphicsUtil.copyData_INT_PACK(r, wr);
531                 else
532                     GraphicsUtil.copyData_FALLBACK(r, wr);
533             }
534     }
535
536     protected void drawBlock(TileBlock block, WritableRaster JavaDoc wr) {
537     TileBlock [] blocks = block.getBestSplit();
538     if (blocks == null)
539         return;
540
541         drawBlockInPlace(blocks, wr);
542     }
543
544     protected void drawBlockAndCopy(TileBlock []blocks, WritableRaster JavaDoc wr) {
545     if (blocks.length == 1) {
546         TileBlock curr = blocks[0];
547         int xloc = curr.getXLoc()*tileWidth +tileGridXOff;
548         int yloc = curr.getYLoc()*tileHeight+tileGridYOff;
549         if ((xloc == wr.getMinX()) &&
550         (yloc == wr.getMinY())) {
551         // Safe to draw in place...
552
drawBlockInPlace(blocks, wr);
553         return;
554         }
555     }
556
557     int maxSz=0;
558     for (int i=0; i<blocks.length; i++) {
559         int sz = ((blocks[i].getWidth() *tileWidth)*
560               (blocks[i].getHeight()*tileHeight));
561         if (sz > maxSz) maxSz=sz;
562     }
563     DataBufferInt JavaDoc dbi = new DataBufferInt JavaDoc(maxSz);
564     int [] masks = { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 };
565     boolean use_INT_PACK = GraphicsUtil.is_INT_PACK_Data
566         (wr.getSampleModel(), false);
567
568     for (int i=0; i<blocks.length; i++) {
569         TileBlock curr = blocks[i];
570         int xloc = curr.getXLoc()*tileWidth +tileGridXOff;
571         int yloc = curr.getYLoc()*tileHeight+tileGridYOff;
572         Rectangle JavaDoc tb = new Rectangle JavaDoc(xloc, yloc,
573                      curr.getWidth()*tileWidth,
574                      curr.getHeight()*tileHeight);
575         tb = tb.intersection(bounds);
576         Point JavaDoc loc = new Point JavaDoc(tb.x, tb.y);
577         WritableRaster JavaDoc child = Raster.createPackedRaster
578         (dbi, tb.width, tb.height, tb.width, masks, loc);
579         genRect(child);
580         if (use_INT_PACK) GraphicsUtil.copyData_INT_PACK(child, wr);
581         else GraphicsUtil.copyData_FALLBACK(child, wr);
582
583             // Check If we should halt early.
584
if (HaltingThread.hasBeenHalted())
585         return;
586     }
587     }
588
589
590     protected void drawBlockInPlace(TileBlock [] blocks, WritableRaster JavaDoc wr) {
591     // System.out.println("Ending Splits: " + blocks.length);
592

593     for (int i=0; i<blocks.length; i++) {
594         TileBlock curr = blocks[i];
595                     
596         // System.out.println("Block " + i + ":\n" + curr);
597

598         int xloc = curr.getXLoc()*tileWidth +tileGridXOff;
599         int yloc = curr.getYLoc()*tileHeight+tileGridYOff;
600         Rectangle JavaDoc tb = new Rectangle JavaDoc(xloc, yloc,
601                      curr.getWidth()*tileWidth,
602                      curr.getHeight()*tileHeight);
603         tb = tb.intersection(bounds);
604
605         WritableRaster JavaDoc child =
606         wr.createWritableChild(tb.x, tb.y, tb.width, tb.height,
607                        tb.x, tb.y, null);
608         // System.out.println("Computing : " + child);
609
genRect(child);
610
611             // Check If we should halt early.
612
if (HaltingThread.hasBeenHalted())
613         return;
614     }
615     }
616 }
617
618
Popular Tags