Widening/vararging

git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@757 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Dave Hoover
2009-01-17 23:48:10 +00:00
parent e7132a127f
commit f381f4fe01
4 changed files with 64 additions and 90 deletions
@@ -32,9 +32,8 @@ import com.threerings.resource.ResourceManager;
import com.threerings.media.MediaPrefs; import com.threerings.media.MediaPrefs;
/** /**
* Provides a single point of access for image retrieval and caching - just like the * Provides a single point of access for image retrieval and caching - just like the ImageManager
* ImageManager but adds a tie in to the RuntimeAdjust system to control caching and * but adds a tie in to the RuntimeAdjust system to control caching and mirage creation.
* mirage creation.
*/ */
public class ClientImageManager extends ImageManager public class ClientImageManager extends ImageManager
{ {
@@ -108,8 +107,8 @@ public class ClientImageManager extends ImageManager
"narya.media.image.cache_size", MediaPrefs.config, DEFAULT_CACHE_SIZE); "narya.media.image.cache_size", MediaPrefs.config, DEFAULT_CACHE_SIZE);
/** /**
* Cache size to be used in this run. Adjusted by setCacheSize without affecting * Cache size to be used in this run. Adjusted by setCacheSize without affecting the stored
* the stored value. * value.
*/ */
protected static int _runCacheSize = _cacheSize.getValue(); protected static int _runCacheSize = _cacheSize.getValue();
@@ -66,8 +66,7 @@ public class ImageManager
} }
ImageKey okey = (ImageKey)other; ImageKey okey = (ImageKey)other;
return ((okey.daprov.getIdent().equals(daprov.getIdent())) && return ((okey.daprov.getIdent().equals(daprov.getIdent())) && (okey.path.equals(path)));
(okey.path.equals(path)));
} }
@Override @Override
@@ -101,7 +100,7 @@ public class ImageManager
// create our image cache // create our image cache
int icsize = getCacheSize(); int icsize = getCacheSize();
log.debug("Creating image cache [size=" + icsize + "k]."); log.debug("Creating image cache", "size", (icsize + "k"));
_ccache = new LRUHashMap<ImageKey, CacheRecord>( _ccache = new LRUHashMap<ImageKey, CacheRecord>(
icsize * 1024, new LRUHashMap.ItemSizer<CacheRecord>() { icsize * 1024, new LRUHashMap.ItemSizer<CacheRecord>() {
public int computeSize (CacheRecord value) { public int computeSize (CacheRecord value) {
@@ -266,10 +265,10 @@ public class ImageManager
crec = _ccache.get(key); crec = _ccache.get(key);
} }
if (crec != null) { if (crec != null) {
// Log.info("Cache hit [key=" + key + ", crec=" + crec + "]."); // log.info("Cache hit", "key", key, "crec", crec);
return crec.getImage(zations, _ccache); return crec.getImage(zations, _ccache);
} }
// Log.info("Cache miss [key=" + key + ", crec=" + crec + "]."); // log.info("Cache miss", "key", key, "crec", crec);
// load up the raw image // load up the raw image
BufferedImage image = loadImage(key); BufferedImage image = loadImage(key);
@@ -279,8 +278,8 @@ public class ImageManager
image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_INDEXED); image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_INDEXED);
} }
// Log.info("Loaded " + key.path + ", image=" + image + // log.info("Loaded Image", "path", key.path, "image", image,
// ", size=" + ImageUtil.getEstimatedMemoryUsage(image)); // "size", ImageUtil.getEstimatedMemoryUsage(image));
// create a cache record // create a cache record
crec = new CacheRecord(key, image); crec = new CacheRecord(key, image);
@@ -439,8 +438,8 @@ public class ImageManager
} }
eff = _ccache.getTrackedEffectiveness(); eff = _ccache.getTrackedEffectiveness();
} }
log.info("ImageManager LRU [mem=" + (size / 1024) + "k, size=" + _ccache.size() + log.info("ImageManager LRU", "mem", ((size / 1024) + "k"), "size", _ccache.size(),
", hits=" + eff[0] + ", misses=" + eff[1] + ", totalKeys=" + _keySet.size() + "]."); "hits", eff[0], "misses", eff[1], "totalKeys", _keySet.size());
} }
/** Maintains a source image and a set of colorized versions in the image cache. */ /** Maintains a source image and a set of colorized versions in the image cache. */
@@ -482,8 +481,8 @@ public class ImageManager
return cimage; return cimage;
} catch (Exception re) { } catch (Exception re) {
log.warning("Failure recoloring image [source" + _key + log.warning("Failure recoloring image",
", zations=" + StringUtil.toString(zations) + ", error=" + re + "]."); "source", _key, "zations", StringUtil.toString(zations), "error", re);
// return the uncolorized version // return the uncolorized version
return _source; return _source;
} }
@@ -46,13 +46,12 @@ import java.awt.image.WritableRaster;
*/ */
public class FastImageIO public class FastImageIO
{ {
/** A suffix for use when storing raw images in bundles or on the file /** A suffix for use when storing raw images in bundles or on the file system. */
* system. */
public static final String FILE_SUFFIX = ".raw"; public static final String FILE_SUFFIX = ".raw";
/** /**
* Returns true if the supplied image is of a format that is supported * Returns true if the supplied image is of a format that is supported by the fast image I/O
* by the fast image I/O services, false if not. * services, false if not.
*/ */
public static boolean canWrite (BufferedImage image) public static boolean canWrite (BufferedImage image)
{ {
@@ -63,8 +62,7 @@ public class FastImageIO
/** /**
* Writes the supplied image to the supplied output stream. * Writes the supplied image to the supplied output stream.
* *
* @exception IOException thrown if an error occurs writing to the * @exception IOException thrown if an error occurs writing to the output stream.
* output stream.
*/ */
public static void write (BufferedImage image, OutputStream out) public static void write (BufferedImage image, OutputStream out)
throws IOException throws IOException
@@ -84,8 +82,8 @@ public class FastImageIO
int[] map = new int[msize]; int[] map = new int[msize];
cmodel.getRGBs(map); cmodel.getRGBs(map);
dout.writeInt(msize); dout.writeInt(msize);
for (int ii = 0; ii < map.length; ii++) { for (int element : map) {
dout.writeInt(map[ii]); dout.writeInt(element);
} }
// write the raster data // write the raster data
@@ -101,11 +99,10 @@ public class FastImageIO
} }
/** /**
* Reads an image from the supplied file (which must contain an image * Reads an image from the supplied file (which must contain an image previously written via a
* previously written via a call to {@link #write}). * call to {@link #write}).
* *
* @exception IOException thrown if an error occurs reading from the * @exception IOException thrown if an error occurs reading from the file.
* file.
*/ */
public static BufferedImage read (File file) public static BufferedImage read (File file)
throws IOException throws IOException
@@ -114,8 +111,7 @@ public class FastImageIO
FileChannel fchan = raf.getChannel(); FileChannel fchan = raf.getChannel();
try { try {
MappedByteBuffer mbuf = fchan.map( MappedByteBuffer mbuf = fchan.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
FileChannel.MapMode.READ_ONLY, 0, file.length());
// read in our integer fields // read in our integer fields
IntBuffer ibuf = mbuf.asIntBuffer(); IntBuffer ibuf = mbuf.asIntBuffer();
@@ -124,10 +120,8 @@ public class FastImageIO
/* int tpixel = */ ibuf.get(); /* int tpixel = */ ibuf.get();
int msize = ibuf.get(); int msize = ibuf.get();
if (width > Short.MAX_VALUE || width < 0 || if (width > Short.MAX_VALUE || width < 0 || height > Short.MAX_VALUE || height < 0) {
height > Short.MAX_VALUE || height < 0) { throw new IOException("Bogus image size " + width + "x" + height);
throw new IOException("Bogus image size " +
width + "x" + height);
} }
IndexColorModel cmodel; IndexColorModel cmodel;
@@ -138,8 +132,7 @@ public class FastImageIO
} }
// read in the data and create our colormap // read in the data and create our colormap
ibuf.get(_cmap, 0, msize); ibuf.get(_cmap, 0, msize);
cmodel = new IndexColorModel( cmodel = new IndexColorModel(8, msize, _cmap, 0, DataBuffer.TYPE_BYTE, null);
8, msize, _cmap, 0, DataBuffer.TYPE_BYTE, null);
} }
// advance the byte buffer accordingly // advance the byte buffer accordingly
@@ -155,8 +148,7 @@ public class FastImageIO
PixelInterleavedSampleModel smodel = PixelInterleavedSampleModel smodel =
new PixelInterleavedSampleModel( new PixelInterleavedSampleModel(
DataBuffer.TYPE_BYTE, width, height, 1, width, offsets); DataBuffer.TYPE_BYTE, width, height, 1, width, offsets);
WritableRaster raster = WritableRaster.createWritableRaster( WritableRaster raster = WritableRaster.createWritableRaster(smodel, dbuf, _origin);
smodel, dbuf, _origin);
return new BufferedImage(cmodel, raster, false, null); return new BufferedImage(cmodel, raster, false, null);
} finally { } finally {
@@ -59,10 +59,9 @@ public class FileResourceBundle extends ResourceBundle
* Constructs a resource bundle with the supplied jar file. * Constructs a resource bundle with the supplied jar file.
* *
* @param source a file object that references our source jar file. * @param source a file object that references our source jar file.
* @param delay if true, the bundle will wait until someone calls * @param delay if true, the bundle will wait until someone calls {@link #sourceIsReady}
* {@link #sourceIsReady} before allowing access to its resources. * before allowing access to its resources.
* @param unpack if true the bundle will unpack itself into a * @param unpack if true the bundle will unpack itself into a temporary directory
* temporary directory
*/ */
public FileResourceBundle (File source, boolean delay, boolean unpack) public FileResourceBundle (File source, boolean delay, boolean unpack)
{ {
@@ -102,8 +101,7 @@ public class FileResourceBundle extends ResourceBundle
} }
/** /**
* Returns the {@link File} from which resources are fetched for this * Returns the {@link File} from which resources are fetched for this bundle.
* bundle.
*/ */
public File getSource () public File getSource ()
{ {
@@ -111,8 +109,7 @@ public class FileResourceBundle extends ResourceBundle
} }
/** /**
* @return true if the bundle is fully downloaded and successfully * @return true if the bundle is fully downloaded and successfully unpacked.
* unpacked.
*/ */
public boolean isUnpacked () public boolean isUnpacked ()
{ {
@@ -121,11 +118,11 @@ public class FileResourceBundle extends ResourceBundle
} }
/** /**
* Called by the resource manager once it has ensured that our * Called by the resource manager once it has ensured that our resource jar file is up to date
* resource jar file is up to date and ready for reading. * and ready for reading.
* *
* @return true if we successfully unpacked our resources, false if we * @return true if we successfully unpacked our resources, false if we encountered errors in
* encountered errors in doing so. * doing so.
*/ */
public boolean sourceIsReady () public boolean sourceIsReady ()
{ {
@@ -137,8 +134,7 @@ public class FileResourceBundle extends ResourceBundle
try { try {
resolveJarFile(); resolveJarFile();
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Failure resolving jar file '" + _source + log.warning("Failure resolving jar file", "source", _source, ioe);
"': " + ioe + ".");
wipeBundle(true); wipeBundle(true);
return false; return false;
} }
@@ -146,8 +142,7 @@ public class FileResourceBundle extends ResourceBundle
log.info("Unpacking into " + _cache + "..."); log.info("Unpacking into " + _cache + "...");
if (!_cache.exists()) { if (!_cache.exists()) {
if (!_cache.mkdir()) { if (!_cache.mkdir()) {
log.warning("Failed to create bundle cache directory '" + log.warning("Failed to create bundle cache directory", "dir", _cache);
_cache + "'.");
closeJar(); closeJar();
// we are hopelessly fucked // we are hopelessly fucked
return false; return false;
@@ -168,12 +163,10 @@ public class FileResourceBundle extends ResourceBundle
try { try {
_unpacked.createNewFile(); _unpacked.createNewFile();
if (!_unpacked.setLastModified(_sourceLastMod)) { if (!_unpacked.setLastModified(_sourceLastMod)) {
log.warning("Failed to set last mod on stamp file '" + log.warning("Failed to set last mod on stamp file", "file", _unpacked);
_unpacked + "'.");
} }
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Failure creating stamp file '" + _unpacked + log.warning("Failure creating stamp file", "file", _unpacked, ioe);
"': " + ioe + ".");
// no need to stick a fork in things at this point // no need to stick a fork in things at this point
} }
} }
@@ -182,9 +175,8 @@ public class FileResourceBundle extends ResourceBundle
} }
/** /**
* Clears out everything associated with this resource bundle in the * Clears out everything associated with this resource bundle in the hopes that we can
* hopes that we can download it afresh and everything will work the * download it afresh and everything will work the next time around.
* next time around.
*/ */
public void wipeBundle (boolean deleteJar) public void wipeBundle (boolean deleteJar)
{ {
@@ -202,28 +194,26 @@ public class FileResourceBundle extends ResourceBundle
// that we ensure that it is revalidated // that we ensure that it is revalidated
File vfile = new File(FileUtil.resuffix(_source, ".jar", ".jarv")); File vfile = new File(FileUtil.resuffix(_source, ".jar", ".jarv"));
if (vfile.exists() && !vfile.delete()) { if (vfile.exists() && !vfile.delete()) {
log.warning("Failed to delete " + vfile + "."); log.warning("Failed to delete vfile", "file", vfile);
} }
// close and delete our source jar file // close and delete our source jar file
if (deleteJar && _source != null) { if (deleteJar && _source != null) {
closeJar(); closeJar();
if (!_source.delete()) { if (!_source.delete()) {
log.warning("Failed to delete " + _source + log.warning("Failed to delete source",
" [exists=" + _source.exists() + "]."); "source", _source, "exists", _source.exists());
} }
} }
} }
/** /**
* Returns a file from which the specified resource can be loaded. * Returns a file from which the specified resource can be loaded. This method will unpack the
* This method will unpack the resource into a temporary directory and * resource into a temporary directory and return a reference to that file.
* return a reference to that file.
* *
* @param path the path to the resource in this jar file. * @param path the path to the resource in this jar file.
* *
* @return a file from which the resource can be loaded or null if no * @return a file from which the resource can be loaded or null if no such resource exists.
* such resource exists.
*/ */
public File getResourceFile (String path) public File getResourceFile (String path)
throws IOException throws IOException
@@ -251,7 +241,7 @@ public class FileResourceBundle extends ResourceBundle
JarEntry entry = _jarSource.getJarEntry(path); JarEntry entry = _jarSource.getJarEntry(path);
if (entry == null) { if (entry == null) {
// Log.info("Couldn't locate " + path + " in " + _jarSource + "."); // log.info("Couldn't locate path in jar", "path", path, "jar", _jarSource);
return null; return null;
} }
@@ -266,9 +256,9 @@ public class FileResourceBundle extends ResourceBundle
} }
/** /**
* Returns true if this resource bundle contains the resource with the * Returns true if this resource bundle contains the resource with the specified path. This
* specified path. This avoids actually loading the resource, in the * avoids actually loading the resource, in the event that the caller only cares to know that
* event that the caller only cares to know that the resource exists. * the resource exists.
*/ */
public boolean containsResource (String path) public boolean containsResource (String path)
{ {
@@ -296,15 +286,13 @@ public class FileResourceBundle extends ResourceBundle
} }
/** /**
* Creates the internal jar file reference if we've not already got * Creates the internal jar file reference if we've not already got it; we do this lazily so
* it; we do this lazily so as to avoid any jar- or zip-file-related * as to avoid any jar- or zip-file-related antics until and unless doing so is required, and
* antics until and unless doing so is required, and because the * because the resource manager would like to be able to create bundles before the associated
* resource manager would like to be able to create bundles before the * files have been fully downloaded.
* associated files have been fully downloaded.
* *
* @return true if the jar file could not yet be resolved because we * @return true if the jar file could not yet be resolved because we haven't yet heard from
* haven't yet heard from the resource manager that it is ready for us * the resource manager that it is ready for us to access, false if all is cool.
* to access, false if all is cool.
*/ */
protected boolean resolveJarFile () protected boolean resolveJarFile ()
throws IOException throws IOException
@@ -316,8 +304,7 @@ public class FileResourceBundle extends ResourceBundle
} }
if (!_source.exists()) { if (!_source.exists()) {
throw new IOException("Missing jar file for resource bundle: " + throw new IOException("Missing jar file for resource bundle: " + _source + ".");
_source + ".");
} }
try { try {
@@ -327,8 +314,7 @@ public class FileResourceBundle extends ResourceBundle
return false; return false;
} catch (IOException ioe) { } catch (IOException ioe) {
String msg = "Failed to resolve resource bundle jar file '" + String msg = "Failed to resolve resource bundle jar file '" + _source + "'";
_source + "'";
log.warning(msg + ".", ioe); log.warning(msg + ".", ioe);
throw (IOException) new IOException(msg).initCause(ioe); throw (IOException) new IOException(msg).initCause(ioe);
} }
@@ -344,8 +330,7 @@ public class FileResourceBundle extends ResourceBundle
_jarSource.close(); _jarSource.close();
} }
} catch (Exception ioe) { } catch (Exception ioe) {
log.warning("Failed to close jar file [path=" + _source + log.warning("Failed to close jar file", "path", _source, "error", ioe);
", error=" + ioe + "].");
} }
} }
@@ -407,8 +392,7 @@ public class FileResourceBundle extends ResourceBundle
/** The last modified time of our source jar file. */ /** The last modified time of our source jar file. */
protected long _sourceLastMod = -1; protected long _sourceLastMod = -1;
/** A file whose timestamp indicates whether or not our existing jar /** A file whose timestamp indicates whether or not our existing jar file has been unpacked. */
* file has been unpacked. */
protected File _unpacked; protected File _unpacked;
/** A directory into which we unpack files from our bundle. */ /** A directory into which we unpack files from our bundle. */