1 /* Copyright (C) 2005-2011 Fabio Riccardi */
2 
3 /*
4  * $RCSfile: SunCachedTile.java,v $
5  *
6  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
7  *
8  * Use is subject to license terms.
9  *
10  * $Revision: 1.1 $
11  * $Date: 2005/02/11 04:57:02 $
12  * $State: Exp $
13  */
14 package com.lightcrafts.jai.utils;
15 
16 import java.awt.image.DataBuffer;
17 import java.awt.image.Raster;
18 import java.awt.image.RenderedImage;
19 import java.lang.ref.WeakReference;
20 import java.math.BigInteger;
21 import com.lightcrafts.mediax.jai.CachedTile;
22 import com.lightcrafts.mediax.jai.PlanarImage;
23 import com.lightcrafts.mediax.jai.remote.SerializableRenderedImage;
24 
25 /**
26  * Information associated with a cached tile.
27  *
28  * <p> This class is used by SunTileCache to create an object that
29  * includes all the information associated with a tile, and is put
30  * into the tile cache.
31  *
32  * <p> It also serves as a double linked list.
33  *
34  * @see LCTileCache
35  *
36  */
37 final class LCCachedTile implements CachedTile {
38 
39     // Soft or Weak references need to be used, or the objects
40     // never get garbage collected.   The OpImage finalize
41     // method calls removeTiles().  It was suggested, that
42     // the owner be a weak reference.
43     Raster tile;                // the tile to be cached
44     WeakReference owner;        // the RenderedImage this tile belongs to
45 
46     int tileX;			// tile X index
47     int tileY;			// tile Y index
48 
49     Object tileCacheMetric;     // Metric for weighting tile computation cost
50     long timeStamp;		// the last time this tile is accessed
51 
52     Object key;			// the key used to hash this tile
53     long memorySize;		// the memory used by this tile in bytes
54 
55     LCCachedTile previous;	// the SunCachedTile before this tile
56     LCCachedTile next;		// the SunCachedTile after this tile
57 
58     int action = 0;             // add, remove, update from tile cache
59 
60 
61     /**
62      * Constructor that takes a tile cache metric
63      * @since 1.1
64      */
LCCachedTile(RenderedImage owner, int tileX, int tileY, Raster tile, Object tileCacheMetric)65     LCCachedTile(RenderedImage owner,
66                   int tileX,
67                   int tileY,
68                   Raster tile,
69                   Object tileCacheMetric) {
70 
71         this.owner = new WeakReference(owner);
72         this.tile  = tile;
73         this.tileX = tileX;
74         this.tileY = tileY;
75 
76         this.tileCacheMetric = tileCacheMetric;  // may be null
77 
78         key = hashKey(owner, tileX, tileY);
79 
80         // tileMemorySize(Raster tile) inlined for performance
81         DataBuffer db = tile.getDataBuffer();
82         memorySize = db.getDataTypeSize(db.getDataType()) / 8L *
83                      db.getSize() * db.getNumBanks();
84 
85     }
86 
fastHashKey(RenderedImage owner, int tileX, int tileY)87     static Object fastHashKey(RenderedImage owner,
88                               int tileX,
89                               int tileY) {
90         return new Integer(((Object) owner).hashCode() + tileY * owner.getNumXTiles() + tileX);
91     }
92 
93     /**
94      * Returns the hash table "key" as a <code>Object</code> for this
95      * tile.  For <code>PlanarImage</code> and
96      * <code>SerializableRenderedImage</code>, the key is generated by
97      * the method <code>ImageUtilgenerateID(Object) </code>.  For the
98      * other cases, a <code>Long</code> object is returned.
99      * The upper 32 bits for this <code>Long</code> is the tile owner's
100      * hash code, and the lower 32 bits is the tile's index.
101      */
hashKey(RenderedImage owner, int tileX, int tileY)102     static Object hashKey(RenderedImage owner,
103                               int tileX,
104                               int tileY) {
105         long idx = tileY * (long)owner.getNumXTiles() + tileX;
106 
107         BigInteger imageID = null;
108         if (owner instanceof PlanarImage)
109             imageID = (BigInteger)((PlanarImage)owner).getImageID();
110         else if (owner instanceof SerializableRenderedImage)
111             imageID = (BigInteger)((SerializableRenderedImage)owner).getImageID();
112 
113         if (imageID != null) {
114             byte[] buf = imageID.toByteArray();
115             int length = buf.length;
116             byte[] buf1 = new byte[length + 8];
117             System.arraycopy(buf, 0, buf1, 0, length);
118             for (int i = 7, j = 0; i >= 0; i--, j += 8)
119                 buf1[length++] = (byte)(idx >> j);
120             return new BigInteger(buf1);
121         }
122 
123         idx = idx & 0x00000000ffffffffL;
124         return new Long(((long)owner.hashCode() << 32) | idx);
125     }
126 
127     /**
128      *  Special version of hashKey for use in SunTileCache.removeTiles().
129      *  Minimizes the overhead of repeated calls to
130      *  hashCode and getNumTiles(). Note that this causes a
131      *  linkage between the CachedTile and SunTileCache classes
132      *  in that SunTileCache now has to understand how the
133      *  tileIndex is calculated.
134      */
135 /*
136     static Long hashKey(int ownerHashCode,
137                         int tileIndex) {
138         long idx = (long)tileIndex;
139         idx = idx & 0x00000000ffffffffL;
140         return new Long(((long)ownerHashCode << 32) | idx);
141     }
142 */
143     /** Returns the owner's hash code. */
144 /*    static long getOwnerHashCode(Long key) {
145         return key.longValue() >>> 32;
146     }
147 */
148     /** Returns a string representation of the class object. */
toString()149     public String toString() {
150         RenderedImage o = (RenderedImage) getOwner();
151         String ostring = o == null ? "null" : o.toString();
152 
153         Raster t = getTile();
154         String tstring = t == null ? "null" : t.toString();
155 
156         return getClass().getName() + "@" + Integer.toHexString(hashCode()) +
157                ": owner = " + ostring +
158                " tileX = " + Integer.toString(tileX) +
159                " tileY = " + Integer.toString(tileY) +
160                " tile = " + tstring +
161                " key = " + ((key instanceof Long)? Long.toHexString(((Long)key).longValue()) : key.toString()) +
162                " memorySize = " + Long.toString(memorySize) +
163                " timeStamp = " + Long.toString(timeStamp);
164     }
165 
166     /** Returns the cached tile. */
getTile()167     public Raster getTile() {
168         return tile;
169     }
170 
171     /** Returns the owner of the cached tile. */
getOwner()172     public RenderedImage getOwner() {
173         return (RenderedImage)owner.get();
174     }
175 
176     /** Returns the current time stamp */
getTileTimeStamp()177     public long getTileTimeStamp() {
178         return timeStamp;
179     }
180 
181     /** Returns the tileCacheMetric object */
getTileCacheMetric()182     public Object getTileCacheMetric() {
183         return tileCacheMetric;
184     }
185 
186     /** Returns the tile memory size */
getTileSize()187     public long getTileSize() {
188         return memorySize;
189     }
190 
191     /** Returns information about the method that
192      *  triggered the notification event.
193      */
getAction()194     public int getAction() {
195         return action;
196     }
197 }
198