If we're creating a CompositedMultiFrameImage with only a single source image and it's a TileSetFrameImage, just use the Mirages in that TileSet rather than creating a whole new set of BufferedImages to composite them into. This halves the image memory used by anything that's just colorizing and transforming its images and doesn't really need composition.

git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@295 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Charlie Groves
2007-09-26 21:49:11 +00:00
parent 8d5fc6c6ea
commit c45878681f
4 changed files with 131 additions and 29 deletions
@@ -90,7 +90,7 @@ public class CompositedMaskedImage extends CompositedMultiFrameImage
/** /**
* Combines the image in the first source with the masks in the rest. */ * Combines the image in the first source with the masks in the rest. */
protected class MaskedMirage extends CompositedMirage protected class MaskedMirage extends CompositedVolatileMirage
{ {
public MaskedMirage (int index) public MaskedMirage (int index)
{ {
@@ -0,0 +1,21 @@
package com.threerings.cast;
import java.util.Comparator;
import com.threerings.cast.CompositedActionFrames.ComponentFrames;
import com.threerings.media.image.Mirage;
public interface CompositedMirage
extends Mirage, Comparator<ComponentFrames>
{
/**
* Returns the x offset into our image.
*/
public int getX ();
/**
* Returns the y offset into our image.
*/
public int getY ();
}
@@ -25,17 +25,15 @@ import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Transparency; import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import com.threerings.cast.CompositedActionFrames.ComponentFrames;
import com.threerings.cast.bundle.BundledComponentRepository.TileSetFrameImage;
import com.threerings.media.image.ImageManager; import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage; import com.threerings.media.image.Mirage;
import com.threerings.media.image.VolatileMirage; import com.threerings.media.image.VolatileMirage;
import com.threerings.cast.CompositedActionFrames.ComponentFrames;
import com.threerings.cast.TrimmedMultiFrameImage;
/** /**
* Used to composite the action frames for a particular orientation of a * Used to composite the action frames for a particular orientation of a
* {@link CompositedActionFrames}. * {@link CompositedActionFrames}.
@@ -75,12 +73,14 @@ public class CompositedMultiFrameImage
return _images[index].getHeight(); return _images[index].getHeight();
} }
public int getXOrigin (int index) { public int getXOrigin (int index)
return _images[index].getXOrigin(); {
return _images[index].getX();
} }
public int getYOrigin (int index) { public int getYOrigin (int index)
return _images[index].getYOrigin(); {
return _images[index].getY();
} }
// documentation inherited from interface // documentation inherited from interface
@@ -115,7 +115,78 @@ public class CompositedMultiFrameImage
*/ */
protected CompositedMirage createCompositedMirage (int index) protected CompositedMirage createCompositedMirage (int index)
{ {
return new CompositedMirage(index); if (_sources.length == 1 && _sources[0].frames instanceof TileSetFrameImage) {
TileSetFrameImage frames = (TileSetFrameImage)_sources[0].frames;
Rectangle tbounds = new Rectangle();
frames.getTrimmedBounds(_orient, index, tbounds);
int x = frames.getXOrigin(_orient, index) - tbounds.x;
int y = frames.getYOrigin(_orient, index) - tbounds.y;
return new SubmirageForwarder(frames.getTileMirage(_orient, index), x, y);
}
return new CompositedVolatileMirage(index);
}
/**
* A CompositedMirage that forwards all of its Mirage calls to a delegate Mirage.
*/
protected class SubmirageForwarder implements CompositedMirage {
public SubmirageForwarder(Mirage m, int x, int y) {
delegate = m;
this.x = x;
this.y = y;
}
public int getX ()
{
return x;
}
public int getY ()
{
return y;
}
// documentation inherited from interface
public int compare (ComponentFrames cf1, ComponentFrames cf2)
{
return (cf1.ccomp.componentClass.getRenderPriority(_action, _orient) -
cf2.ccomp.componentClass.getRenderPriority(_action, _orient));
}
public long getEstimatedMemoryUsage ()
{
return delegate.getEstimatedMemoryUsage();
}
public int getHeight ()
{
return delegate.getHeight();
}
public BufferedImage getSnapshot ()
{
return delegate.getSnapshot();
}
public int getWidth ()
{
return delegate.getWidth();
}
public boolean hitTest (int x, int y)
{
return delegate.hitTest(x, y);
}
public void paint (Graphics2D gfx, int x, int y)
{
delegate.paint(gfx, x, y);
}
protected int x, y;
protected Mirage delegate;
} }
// documentation inherited // documentation inherited
@@ -142,10 +213,10 @@ public class CompositedMultiFrameImage
/** /**
* Used to create our mirage using the source action frame images. * Used to create our mirage using the source action frame images.
*/ */
protected class CompositedMirage extends VolatileMirage protected class CompositedVolatileMirage extends VolatileMirage
implements Comparator implements CompositedMirage
{ {
public CompositedMirage (int index) public CompositedVolatileMirage (int index)
{ {
super(CompositedMultiFrameImage.this._imgr, super(CompositedMultiFrameImage.this._imgr,
new Rectangle(0, 0, 0, 0)); new Rectangle(0, 0, 0, 0));
@@ -192,14 +263,10 @@ public class CompositedMultiFrameImage
} }
// documentation inherited from interface // documentation inherited from interface
public int compare (Object o1, Object o2) public int compare (ComponentFrames cf1, ComponentFrames cf2)
{ {
ComponentFrames cf1 = (ComponentFrames)o1, return (cf1.ccomp.componentClass.getRenderPriority(_action, _orient) -
cf2 = (ComponentFrames)o2; cf2.ccomp.componentClass.getRenderPriority(_action, _orient));
return (cf1.ccomp.componentClass.getRenderPriority(
_action, _orient) -
cf2.ccomp.componentClass.getRenderPriority(
_action, _orient));
} }
/** /**
@@ -374,7 +374,7 @@ public class BundledComponentRepository
/** /**
* Used to provide multiframe images using data obtained from a tileset. * Used to provide multiframe images using data obtained from a tileset.
*/ */
protected static class TileSetFrameImage implements ActionFrames public static class TileSetFrameImage implements ActionFrames
{ {
/** /**
* Constructs a tileset frame image with the specified tileset and for the specified * Constructs a tileset frame image with the specified tileset and for the specified
@@ -437,17 +437,21 @@ public class BundledComponentRepository
} }
public void getTrimmedBounds (int index, Rectangle bounds) { public void getTrimmedBounds (int index, Rectangle bounds) {
Tile tile = _set.getTile(getTileIndex(orient, index)); TileSetFrameImage.this.getTrimmedBounds(orient, index, bounds);
if (tile instanceof TrimmedTile) {
((TrimmedTile)tile).getTrimmedBounds(bounds);
} else {
bounds.setBounds(0, 0, tile.getWidth(), tile.getHeight());
}
bounds.translate(_dx, _dy);
} }
}; };
} }
public void getTrimmedBounds (int orient, int index, Rectangle bounds) {
Tile tile = getTile(orient, index);
if (tile instanceof TrimmedTile) {
((TrimmedTile)tile).getTrimmedBounds(bounds);
} else {
bounds.setBounds(0, 0, tile.getWidth(), tile.getHeight());
}
bounds.translate(_dx, _dy);
}
// documentation inherited from interface // documentation inherited from interface
public int getXOrigin (int orient, int index) public int getXOrigin (int orient, int index)
{ {
@@ -477,6 +481,15 @@ public class BundledComponentRepository
return _orients.get(orient) * _fcount + index; return _orients.get(orient) * _fcount + index;
} }
public Tile getTile (int orient, int index)
{
return _set.getTile(getTileIndex(orient, index));
}
public Mirage getTileMirage(int orient, int index) {
return _set.getTileMirage(getTileIndex(orient, index));
}
/** The tileset from which we obtain our frame images. */ /** The tileset from which we obtain our frame images. */
protected TileSet _set; protected TileSet _set;
@@ -491,6 +504,7 @@ public class BundledComponentRepository
/** A mapping from orientation code to animation sequence index. */ /** A mapping from orientation code to animation sequence index. */
protected IntIntMap _orients = new IntIntMap(); protected IntIntMap _orients = new IntIntMap();
} }
/** We use the image manager to decode and cache images. */ /** We use the image manager to decode and cache images. */