// Near Infinity - An Infinity Engine Browser and Editor
// Copyright (C) 2001 - 2005 Jon Olav Hauglid
// See LICENSE.txt for license information
package org.infinity.resource.video;
import java.awt.Image;
import java.util.Arrays;
import java.util.Collection;
import org.infinity.resource.graphics.ColorConvert;
/**
* Basic implementation of the BufferedRenderer interface.
*/
public class BasicVideoBuffer implements VideoBuffer
{
private Image[] buffer;
private Object[] extraData;
private int numBuffers;
private int currentBuffer;
/**
* Creates an empty buffer chain.
*/
public BasicVideoBuffer()
{
buffer = null;
extraData = null;
}
/**
* Creates a new BufferedRenderer with the specified parameters.
* @param numBuffers The number of buffers in the buffer chain (usually 1 to 3).
* @param width The image width in pixels.
* @param height The image height in pixels.
* @param hasTransparency Enable/Disable transparency/alpha support.
*/
public BasicVideoBuffer(int numBuffers, int width, int height, boolean hasTransparency)
{
buffer = null;
extraData = null;
if (!create(numBuffers, width, height, hasTransparency))
throw new NullPointerException();
}
/**
* Creates a BufferedRenderer using the specified BufferedImage objects for the buffer chain.
* @param buffers The array of BufferedImage objects to use.
*/
public BasicVideoBuffer(Image[] buffers)
{
buffer = null;
extraData = null;
if (buffers == null)
throw new NullPointerException();
if (!create(Arrays.asList(buffers)))
throw new NullPointerException();
}
/**
* Creates a BufferedRenderer using the specified BufferedImage objects for the buffer chain.
* @param buffers The collection of BufferedImage objects to use.
*/
public BasicVideoBuffer(Collection<Image> buffers)
{
buffer = null;
extraData = null;
if (!create(buffers))
throw new NullPointerException();
}
@Override
public Image frontBuffer()
{
return (buffer != null) ? buffer[currentBuffer] : null;
}
@Override
public Image backBuffer()
{
return (buffer != null) ? buffer[(currentBuffer + numBuffers - 1) % numBuffers] : null;
}
@Override
public void flipBuffers()
{
if (buffer != null) {
currentBuffer = (currentBuffer + 1) % numBuffers;
extraData[(currentBuffer + numBuffers - 1) % numBuffers] = null;
}
}
@Override
public int bufferCount()
{
return numBuffers;
}
@Override
public void attachData(Object data)
{
if (extraData != null) {
int bufferIndex = (currentBuffer + numBuffers - 1) % numBuffers;
extraData[bufferIndex] = data;
}
}
@Override
public Object fetchData()
{
if (extraData != null) {
return extraData[currentBuffer];
} else {
return null;
}
}
/**
* Initializes the buffer chain using the specified parameters. Old buffers will be discarded.
* @param numBuffers The number of buffers in the buffer chain (usually 1 to 3).
* @param width The image width in pixels
* @param height The image height in pixels
* @param hasTransparency Enable/Disable transparency/alpha support.
* @return {@code true} if the new buffer chain has been created successfully,
* {@code false} otherwise.
*/
public boolean create(int numBuffers, int width, int height, boolean hasTransparency)
{
release();
if (width <= 0 || height <= 0)
return false;
if (numBuffers < 1)
numBuffers = 1;
this.numBuffers = numBuffers;
buffer = new Image[this.numBuffers];
extraData = new Object[this.numBuffers];
currentBuffer = 0;
for (int i = 0; i < this.numBuffers; i++) {
if (width > 0 && height > 0) {
buffer[i] = ColorConvert.createCompatibleImage(width, height, hasTransparency);
} else {
buffer[i] = null;
}
extraData[i] = null;
}
return (width > 0 && height > 0);
}
/**
* Initializes the buffer chain using the BufferedImage objects from the specified list.
* Old buffers will be discarded.
* @param bufferList The collection of BufferedImage objects.
* @return {@code true} if the new buffer chain has been created successfully,
* {@code false} otherwise.
*/
public boolean create(Collection<Image> bufferList)
{
release();
if (bufferList == null)
throw new NullPointerException();
// check for valid content
int num = 0;
for (final Image image: bufferList) {
if (image != null)
num++;
}
// add buffers to chain
if (num > 0) {
this.numBuffers = num;
buffer = new Image[this.numBuffers];
currentBuffer = 0;
num = 0;
for (final Image image: bufferList) {
if (image != null) {
buffer[num++] = image;
}
}
extraData = new Object[this.numBuffers];
for (num = 0; num < this.numBuffers; num++) {
extraData[num] = null;
}
return true;
} else {
return false;
}
}
/**
* Releases old BufferedImage objects.
*/
public void release()
{
if (buffer != null && extraData != null) {
for (int i = 0; i < numBuffers; i++) {
if (buffer[i] != null) {
buffer[i].flush();
}
buffer[i] = null;
extraData[i] = null;
}
buffer = null;
extraData = null;
}
}
}