package graphics.common;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import utils.Receivable;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import utils.GlobalData;
import utils.GraphicsTypes;
import utils.ThreadManager;
public class GraphicsDB {
private static final Object mCacheLock = new Object();
private static Map<String, Object> mCache;
private static List< Receivable > mReceivables;
private static List< String > mReceivableNames;
// these might not be needed anymore
//private static final String[] mOpaqueTypes = { ".bmp", ".jpg", ".jpeg" };
//private static final String[] mBitmaskTypes = { ".gif" };
//private static final String[] mTransTypes = { ".png" };
public GraphicsDB() {
mCache = new HashMap<String, Object>();
mReceivables = new ArrayList< Receivable >();
mReceivableNames = new ArrayList< String >();
}
/**
* This is an ambiguous call to the database to cache a graphic that
* what type of graphic will be loaded is based on a constant set during
* the setup of the program. (GlobalFlags.GRAPHICS_TYPE)
* @param dir the directory of the graphic to be loaded.
* @param name The key to stored the loaded image under.
*/
public static void cacheGraphic( String dir, String name ) {
if ( GlobalData.GRAPHICS_TYPE == GraphicsTypes.GRAPHICS_SOFTWARE ) {
cacheJavaImage( dir, name );
} else {
cacheGlTexture( dir, name );
}
}
/**
* Loads and caches a BufferedImage from the passed dir.
* The BufferedImage is put into a Map using the passed name as the key, which
* can later be used to retrieve the BufferedImage.
* @param dir The directory of the image to be loaded.
* @param name The key to store the loaded image under.
*/
public static void cacheJavaImage( String dir, String name ) {
class SoftwareImageLoader implements Runnable {
private String mDir, mName;
private Image mIm;
public SoftwareImageLoader( String dir, String name ) {
mDir = dir;
mName = name;
}
@Override
public void run() {
if ( (mIm = loadJavaImage( mDir )) != null ) {
synchronized ( mCacheLock ) {
mCache.put( mName, mIm );
}
checkReceivables( mName, mIm );
}
}
}
ThreadManager.addThread( new SoftwareImageLoader( dir, name ) );
}
/**
* Loads and caches an OpenGL texture
* @param dir The directory of the texture to be loaded.
* @param name The key to store the loaded image under.
*/
public static void cacheGlTexture( String dir, String name ) {
}
/**
* Removes a graphic asset from the Map of stored graphics.
* @param name The name of the graphical asset to be removed.
*/
public static void removeGraphic( String name ) {
Object obj = null;
synchronized ( mCacheLock ) {
obj = mCache.remove( name );
}
if ( obj == null ) {
return;
}
if ( obj instanceof Image ) {
Image im = (Image) obj;
im.flush();
im = null;
} else if ( obj instanceof Image[] ) {
Image[] ims = (Image[]) obj;
for ( Image im : ims ) {
im.flush();
im = null;
}
ims = null;
}
// will need to add 3D model support later when that is added to the engine
}
/**
* Returns an Object representation of some graphical resource stored in the
* cache that is assigned to the passed name.
* @param name The name assigned to the graphical resource that is desired.
* @return The Object value that is paired with the passed name.
*/
public static Object retrieveGraphicObj( String name ) {
synchronized ( mCacheLock ) {
return mCache.get( name );
}
}
/**
* Uses reflection to cast an Object that is stored in the cache to the
* proper type that is trying to be obtained, or null if the Object that is
* being stored in the cache under the passed name is not of the type desired.
* @param <T> The desired class type.
* @param name The name assigned to the desired resource.
* @param classType The Class reflective definition of the desired class type.
* @return The object stored in the cache that is of the proper type, or null
* if it is not the proper type.
*/
@SuppressWarnings( "unchecked" )
public static <T> T retrieveGraphic( String name, Class<?> classType ) {
Object obj = null;
Object ret = null;
synchronized ( mCacheLock ) {
obj = mCache.get( name );
}
try {
ret = classType.cast( obj );
} catch ( ClassCastException e ) {
return null;
}
if ( ret == null ) {
return null;
} else {
return (T) ret;
}
}
public static void registerReceivable( Receivable r, String name ) {
mReceivables.add( r );
mReceivableNames.add( name );
}
private static void checkReceivables( String name, Object obj ) {
Receivable r;
int index;
while( ( index = mReceivableNames.indexOf( name ) ) != -1 ) {
mReceivables.get( index ).give( obj );
mReceivables.remove( index );
mReceivableNames.remove( index );
}
}
/**
* Loads a BufferedImage and returns it, or null if something failed.
* @param dir The directory of the image.
* @return The BufferedImage, or null if it failed to load.
*/
private static Image loadJavaImage( String dir ) {
BufferedImage ret = null;
try {
if ( dir.charAt( 0 ) != '/' ) {
dir = "/".concat( dir );
}
URL url = GraphicsDB.class.getResource( dir );
ret = ImageIO.read( url );
ret = checkCompatibility( ret );
} catch ( IOException e ) {
e.printStackTrace();
}
return ret;
}
private static BufferedImage checkCompatibility( BufferedImage im ) {
// obtain the current system graphical settings
GraphicsConfiguration gfx_config = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
/*
* if image is already compatible and optimized for current system
* settings, simply return it
*/
if ( im.getColorModel().equals( gfx_config.getColorModel() ) ) {
return im;
}
// image is not optimized, so create a new image that is
BufferedImage new_image = gfx_config.createCompatibleImage(
im.getWidth(), im.getHeight(), im.getTransparency() );
// get the graphics context of the new image to draw the old image on
Graphics2D g2d = (Graphics2D) new_image.getGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage( im, 0, 0, null );
g2d.dispose();
// return the new optimized image
return new_image;
}
/**
* Unimplemented.
* @param dir
*/
private void loadModelSoftware( String dir ) {
}
/**
* Unimplemented.
* @param dir
*/
private void loadModelHardware( String dir ) {
}
}