/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.scenegraph;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
import java.util.Map;
import org.jagatoo.util.arrays.ArrayUtils;
import org.openmali.types.twodee.Rect2i;
import org.openmali.vecmath2.Colorf;
import org.openmali.vecmath2.Tuple2i;
/**
* This is an adapter for pixel-perfect drawing onto a Texture2D.
*
* @author Marvin Froehlich (aka Qudus)
*/
public class Texture2DCanvas extends Graphics2D
{
public static abstract class DrawCallback2D
{
private boolean dirty = true;
/**
* Marks this draw callback dirty.
* This tells the render system to call the {@link #drawTexture(Texture2DCanvas, int, int)} method.
*
* @param dirty
*/
public void setDirty( boolean dirty )
{
this.dirty = dirty;
}
/**
* Checks, if this callback needs to be redrawn.
*
* @param nanoTime
*
* @return true, if the texture should be redrawn.
*/
public boolean needsRedraw( long nanoTime )
{
boolean result = dirty;
dirty = false;
return ( result );
}
/**
* This callback is invoked, when the Texture needs to be redrawn.
*
* @param texCanvas the {@link Texture2DCanvas} to draw on.
* @param texWidth the (original) width of the texture
* @param texHeight the (original) height of the texture
*/
public abstract void drawTexture( Texture2DCanvas texCanvas, int texWidth, int texHeight );
}
private final Texture2D texture;
private final TextureImage2D texImg;
private int imgWidth;
private int imgHeight;
private Graphics2D graphics;
private final AffineTransform baseAffineTransform;
private Rect2i currentUpdateRect = null;
private int currentlyAppliedUpdateRects = 0;
//private final ArrayList< DrawCallback2D > callbacks = new ArrayList< DrawCallback2D >( 1 );
private DrawCallback2D[] callbacks = new DrawCallback2D[ 0 ];
private int numCallbacks = 0;
public final Texture2D getTexture()
{
return ( texture );
}
public final TextureImage2D getImage()
{
return ( texImg );
}
public void addDrawCallback( DrawCallback2D callback )
{
callbacks = ArrayUtils.ensureCapacity( callbacks, DrawCallback2D.class, callbacks.length + 1 );
callbacks[numCallbacks++] = callback;
}
public void removeDrawCallback( DrawCallback2D callback )
{
int index = ArrayUtils.indexOf( callbacks, callback, false );
callbacks[index] = null;
System.arraycopy( callbacks, index + 1, callbacks, index, numCallbacks - index - 1 );
numCallbacks--;
}
final boolean notifyDrawCallbacks( long nanoTime )
{
if ( numCallbacks == 0 )
return ( false );
for ( int i = 0; i < numCallbacks; i++ )
{
final DrawCallback2D callback = callbacks[i];
if ( callback.needsRedraw( nanoTime ) )
callback.drawTexture( this, imgWidth, imgHeight );
}
return ( texture.hasUpdateList() );
}
private final void markDirty( int x, int y, int width, int height )
{
if ( currentUpdateRect != null )
{
if ( ( x >= currentUpdateRect.getLeft() ) &&
( y >= currentUpdateRect.getTop() ) &&
( x + width <= currentUpdateRect.getLeft() + currentUpdateRect.getWidth() ) &&
( y + height <= currentUpdateRect.getTop() + currentUpdateRect.getHeight() )
)
{
return;
}
}
Rect2i clip = getImage().getEffectiveClipRect();
int clipX = clip.getLeft();
int clipY = clip.getTop();
int clipW = clip.getWidth();
int clipH = clip.getHeight();
x = Math.max( clipX, x );
y = Math.max( clipY, y );
x = Math.min( x, clipX + clipW - 1 );
y = Math.min( y, clipY + clipH - 1 );
width = Math.min( width, clipX + clipW - x );
height = Math.min( height, clipY + clipH - y );
if ( ( width > 0 ) && ( height > 0 ) )
{
if ( texImg != null )
//texImg.update( x, y, width, height );
texImg.update( x, imgHeight - height - y, width, height );
if ( texture != null )
texture.setHasUpdateList( true );
}
}
private final void markDirty()
{
markDirty( 0, 0, imgWidth, imgHeight );
}
public final void beginUpdateRegion( int x, int y, int width, int height )
{
if ( currentUpdateRect != null )
{
currentUpdateRect.combine( x, y, width, height );
}
else
{
currentUpdateRect = Rect2i.fromPool( x, y, width, height );
}
currentlyAppliedUpdateRects++;
}
public final void beginUpdateRegionComplete()
{
beginUpdateRegion( 0, 0, imgWidth, imgHeight );
}
public final void finishUpdateRegion()
{
if ( currentUpdateRect == null )
return;
currentlyAppliedUpdateRects--;
if ( currentlyAppliedUpdateRects == 0 )
{
int l = currentUpdateRect.getLeft();
int t = currentUpdateRect.getTop();
int w = currentUpdateRect.getWidth();
int h = currentUpdateRect.getHeight();
Rect2i.toPool( currentUpdateRect );
currentUpdateRect = null;
markDirty( l, t, w, h );
}
}
public final java.awt.geom.AffineTransform getBaseAffineTransform()
{
return ( baseAffineTransform );
}
@Override
public GraphicsConfiguration getDeviceConfiguration()
{
return ( graphics.getDeviceConfiguration() );
}
@Override
public final void clearRect( int x, int y, int width, int height )
{
graphics.clearRect( x, y, width, height );
markDirty( x, y, width, height );
}
public final void clearRect( Rect2i rect )
{
clearRect( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight() );
}
@Override
public void clipRect( int x, int y, int width, int height )
{
graphics.clipRect( x, y, width, height );
}
public final void clip( Rect2i rect )
{
clipRect( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight() );
}
@Override
public final void clip( Shape shape )
{
graphics.clip( shape );
}
@Override
public final void copyArea( int x, int y, int width, int height, int dx, int dy )
{
graphics.copyArea( x, y, width, height, dx, dy );
markDirty( dx, dy, width, height );
}
public final void copyArea( Rect2i rect, int dx, int dy )
{
copyArea( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight(), dx, dy );
}
@Override
public final void draw( Shape shape )
{
graphics.draw( shape );
java.awt.Rectangle rect = shape.getBounds();
markDirty( rect.x, rect.y, rect.width, rect.height );
}
@Override
public final void drawArc( int x, int y, int width, int height, int startAngle, int arcAngle )
{
graphics.drawArc( x, y, width, height, startAngle, arcAngle );
markDirty( x, y, width, height );
}
public final void drawCircle( int x, int y, int radius )
{
drawArc( x - radius, y - radius, radius + radius, radius + radius, 0, 360 );
}
@Override
public final void drawBytes( byte[] data, int offset, int length, int x, int y )
{
graphics.drawBytes( data, offset, length, x, y );
markDirty( x, y, imgWidth - x, imgHeight - y );
}
@Override
public final void drawChars( char[] data, int offset, int length, int x, int y )
{
graphics.drawChars( data, offset, length, x, y );
markDirty( x, y, imgWidth - x, imgHeight - y );
}
@Override
public final void drawGlyphVector( GlyphVector g, float x, float y )
{
graphics.drawGlyphVector( g, x, y );
markDirty( (int)x, (int)y, imgWidth - (int)x, imgHeight - (int)y );
}
@Override
public final boolean drawImage( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver imgOb )
{
if ( ( dx2 < 0 ) || ( dy2 < 0 ) || ( dx1 >= imgWidth ) || ( dy1 >= imgHeight ) )
return ( true );
final boolean result = graphics.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, imgOb );
markDirty( dx1, dy1, dx2 - dx1 + 1, dy2 - dy1 + 1 );
return ( result );
}
public final void drawImage( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2 )
{
drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, (ImageObserver)null );
}
@Override
public final boolean drawImage( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgColor, ImageObserver imgOb )
{
final boolean result = graphics.drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgColor, imgOb );
markDirty( dx1, dy1, dx2 - dx1 + 1, dy2 - dy1 + 1 );
return ( result );
}
public final void drawImage( Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Colorf bgColor )
{
drawImage( img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgColor.getAWTColor(), (ImageObserver)null );
}
@Override
public final boolean drawImage( Image img, AffineTransform xform, ImageObserver imgOb )
{
final boolean result = graphics.drawImage( img, xform, imgOb );
markDirty();
return ( result );
}
@Override
public final void drawImage( BufferedImage img, BufferedImageOp op, int x, int y )
{
graphics.drawImage( img, op, x, y );
markDirty( x, y, img.getWidth() - x, img.getHeight() - y );
}
@Override
public final boolean drawImage( Image img, int x, int y, ImageObserver imgOb )
{
final boolean result = graphics.drawImage( img, x, y, imgOb );
markDirty( x, y, img.getWidth( null ) - x, img.getHeight( null ) - y );
return ( result );
}
public final void drawImage( Image img, int x, int y )
{
drawImage( img, x, y, (ImageObserver)null );
}
@Override
public final boolean drawImage( Image img, int x, int y, Color bgColor, ImageObserver imgOb )
{
final boolean result = graphics.drawImage( img, x, y, bgColor, imgOb );
markDirty( x, y, img.getWidth( null ) - x, img.getHeight( null ) - y );
return ( result );
}
public final void drawImage( Image img, int x, int y, Colorf bgColor )
{
drawImage( img, x, y, bgColor.getAWTColor(), (ImageObserver)null );
}
@Override
public final boolean drawImage( Image img, int x, int y, int width, int height, ImageObserver imgOb )
{
final boolean result = graphics.drawImage( img, x, y, width, height, null );
markDirty( x, y, width, height );
return ( result );
}
public final void drawImage( Image img, int x, int y, int width, int height )
{
drawImage( img, x, y, width, height, (ImageObserver)null );
}
@Override
public final boolean drawImage( Image img, int x, int y, int width, int height, Color bgColor, ImageObserver imgOb )
{
final boolean result = graphics.drawImage( img, x, y, width, height, bgColor, imgOb );
markDirty( x, y, width, height );
return ( result );
}
public final void drawImage( Image img, int x, int y, int width, int height, Colorf bgColor )
{
drawImage( img, x, y, width, height, bgColor.getAWTColor(), (ImageObserver)null );
}
@Override
public void drawRenderableImage( RenderableImage img, AffineTransform xform )
{
graphics.drawRenderableImage( img, xform );
markDirty();
}
@Override
public void drawRenderedImage( RenderedImage img, AffineTransform xform )
{
graphics.drawRenderedImage( img, xform );
markDirty();
}
@Override
public final void drawLine( int x1, int y1, int x2, int y2 )
{
//graphics.drawLine( x1, yy( y1 ), x2, yy( y2 ) );
graphics.drawLine( x1, y1, x2, y2 );
markDirty( x1, y1, x2 - x1, y2 - y1 );
}
public final void drawLineOffset( int x, int y, int dx, int dy )
{
drawLine( x, y, x + dx, y + dy );
}
@Override
public final void drawOval( int x, int y, int width, int height )
{
graphics.drawOval( x, y, width, height );
markDirty( x, y, width, height );
}
@Override
public final void drawPolygon( Polygon polygon )
{
graphics.drawPolygon( polygon );
java.awt.Rectangle rect = polygon.getBounds();
markDirty( rect.x, rect.y, rect.width, rect.height );
}
@Override
public final void drawPolygon( int[] xPoints, int[] yPoints, int nPoints )
{
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for ( int i = 0; i < nPoints; i++ )
{
if ( xPoints[i] < minX )
minX = xPoints[i];
if ( xPoints[i] > maxX )
maxX = xPoints[i];
}
for ( int i = 0; i < nPoints; i++ )
{
if ( yPoints[i] < minY )
minY = yPoints[i];
if ( yPoints[i] > maxY )
maxY = yPoints[i];
}
int width = maxX - minX + 1;
int height = maxY - minY + 1;
if ( ( width > 0 ) && ( height > 0 ) )
{
graphics.drawPolygon( xPoints, yPoints, nPoints );
markDirty( minX, minY, width, height );
}
}
@Override
public final void drawPolyline( int[] xPoints, int[] yPoints, int nPoints )
{
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for ( int i = 0; i < nPoints; i++ )
{
if ( xPoints[i] < minX )
minX = xPoints[i];
if ( xPoints[i] > maxX )
maxX = xPoints[i];
}
for ( int i = 0; i < nPoints; i++ )
{
if ( yPoints[i] < minY )
minY = yPoints[i];
if ( yPoints[i] > maxY )
maxY = yPoints[i];
}
int width = maxX - minX + 1;
int height = maxY - minY + 1;
if ( ( width > 0 ) && ( height > 0 ) )
{
graphics.drawPolyline( xPoints, yPoints, nPoints );
markDirty( minX, minY, width, height );
}
}
public final void drawPolygon( Tuple2i[] points )
{
final int nPoints = points.length;
if ( nPoints == 0 )
return;
final int[] xPoints = new int[ nPoints ];
final int[] yPoints = new int[ nPoints ];
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for ( int i = 0; i < nPoints; i++ )
{
xPoints[ i ] = points[ i ].getX();
yPoints[ i ] = points[ i ].getY();
if ( xPoints[ i ] < minX )
minX = xPoints[ i ];
if ( xPoints[ i ] > maxX )
maxX = xPoints[ i ];
if ( yPoints[ i ] < minY )
minY = yPoints[ i ];
if ( yPoints[ i ] > maxY )
maxY = yPoints[ i ];
}
int width = maxX - minX + 1;
int height = maxY - minY + 1;
if ( ( width > 0 ) && ( height > 0 ) )
{
graphics.drawPolygon( xPoints, yPoints, nPoints );
markDirty( minX, minY, width, height );
}
}
public final void drawPolyline( Tuple2i[] points )
{
final int nPoints = points.length;
if ( nPoints == 0 )
return;
final int[] xPoints = new int[ nPoints ];
final int[] yPoints = new int[ nPoints ];
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for ( int i = 0; i < nPoints; i++ )
{
xPoints[ i ] = points[ i ].getX();
yPoints[ i ] = points[ i ].getY();
if ( xPoints[ i ] < minX )
minX = xPoints[ i ];
if ( xPoints[ i ] > maxX )
maxX = xPoints[ i ];
if ( yPoints[ i ] < minY )
minY = yPoints[ i ];
if ( yPoints[ i ] > maxY )
maxY = yPoints[ i ];
}
int width = maxX - minX + 1;
int height = maxY - minY + 1;
if ( ( width > 0 ) && ( height > 0 ) )
{
graphics.drawPolyline( xPoints, yPoints, nPoints );
markDirty( minX, minY, width, height );
}
}
@Override
public final void drawRect( int x, int y, int width, int height )
{
graphics.drawRect( x, y, width, height );
markDirty( x, y, width, height );
}
public final void drawRect( Rect2i rect )
{
drawRect( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight() );
}
@Override
public final void drawRoundRect( int x, int y, int width, int height, int arcWidth, int arcHeight )
{
graphics.drawRoundRect( x, y, width, height, arcWidth, arcHeight );
markDirty( x, y, width, height );
}
public final void drawRoundRect( Rect2i rect, int arcWidth, int arcHeight )
{
drawRoundRect( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight(), arcWidth, arcHeight );
}
@Override
public final void drawString( AttributedCharacterIterator iterator, float x, float y )
{
graphics.drawString( iterator, x, y );
markDirty( (int)x, (int)y, imgWidth - (int)x, imgHeight - (int)y );
}
@Override
public final void drawString( AttributedCharacterIterator iterator, int x, int y )
{
graphics.drawString( iterator, x, y );
markDirty( x, y, imgWidth - x, imgHeight - y );
}
@Override
public final void drawString( String s, float x, float y )
{
graphics.drawString( s, x, y );
markDirty( (int)x, (int)y, imgWidth - (int)x, imgHeight - (int)y );
}
@Override
public final void drawString( String s, int x, int y )
{
graphics.drawString( s, x, y );
markDirty( x, y, imgWidth - x, imgHeight - y );
}
public final void drawString( String s, int x, int y, int boundsWidth, int boundsHeight )
{
graphics.drawString( s, x, y );
markDirty( x, y - boundsHeight, boundsWidth, boundsHeight );
}
@Override
public final void fill( Shape shape )
{
graphics.fill( shape );
java.awt.Rectangle rect = shape.getBounds();
markDirty( rect.x, rect.y, rect.width, rect.height );
}
@Override
public final void fillArc( int x, int y, int width, int height, int startAngle, int arcAngle )
{
graphics.fillArc( x, y, width, height, startAngle, arcAngle );
markDirty( x, y, width, height );
}
public final void fillCircle( int x, int y, int radius )
{
fillArc( x - radius, y - radius, radius + radius, radius + radius, 0, 360 );
}
@Override
public final void fillOval( int x, int y, int width, int height )
{
graphics.fillOval( x, y, width, height );
markDirty( x, y, width, height );
}
@Override
public final void fillPolygon( int[] xPoints, int[] yPoints, int nPoints )
{
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for ( int i = 0; i < nPoints; i++ )
{
if ( xPoints[i] < minX )
minX = xPoints[i];
if ( xPoints[i] > maxX )
maxX = xPoints[i];
}
for ( int i = 0; i < nPoints; i++ )
{
if ( yPoints[i] < minY )
minY = yPoints[i];
if ( yPoints[i] > maxY )
maxY = yPoints[i];
}
int width = maxX - minX + 1;
int height = maxY - minY + 1;
if ( ( width > 0 ) && ( height > 0 ) )
{
graphics.fillPolygon( xPoints, yPoints, nPoints );
markDirty( minX, minY, width, height );
}
}
public final void fillPolygon( Tuple2i[] points )
{
final int nPoints = points.length;
if ( nPoints == 0 )
return;
final int[] xPoints = new int[ nPoints ];
final int[] yPoints = new int[ nPoints ];
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int maxY = Integer.MIN_VALUE;
for ( int i = 0; i < nPoints; i++ )
{
xPoints[ i ] = points[ i ].getX();
yPoints[ i ] = points[ i ].getY();
if ( xPoints[ i ] < minX )
minX = xPoints[ i ];
if ( xPoints[ i ] > maxX )
maxX = xPoints[ i ];
if ( yPoints[ i ] < minY )
minY = yPoints[ i ];
if ( yPoints[ i ] > maxY )
maxY = yPoints[ i ];
}
int width = maxX - minX + 1;
int height = maxY - minY + 1;
if ( ( width > 0 ) && ( height > 0 ) )
{
graphics.fillPolygon( xPoints, yPoints, nPoints );
markDirty( minX, minY, width, height );
}
}
@Override
public final void fillRect( int x, int y, int width, int height )
{
graphics.fillRect( x, y, width, height );
markDirty( x + 1, y + 1, width - 2, height - 2 );
}
public final void fillRect( Rect2i rect )
{
fillRect( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight() );
}
@Override
public final void fillRoundRect( int x, int y, int width, int height, int arcWidth, int arcHeight )
{
graphics.fillRoundRect( x, y, width, height, arcWidth, arcHeight );
markDirty( x, y, width, height );
}
public final void fillRoundRect( Rect2i rect, int arcWidth, int arcHeight )
{
fillRoundRect( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight(), arcWidth, arcHeight );
}
@Override
public Color getBackground()
{
return ( graphics.getBackground() );
}
public final Colorf getBackgroundColor()
{
return ( new Colorf( graphics.getBackground() ) );
}
@Override
public final java.awt.Shape getClip()
{
return ( graphics.getClip() );
}
public final Rect2i getClipRect2i()
{
java.awt.Rectangle awtRect = graphics.getClipBounds();
return ( new Rect2i( awtRect.x, awtRect.y, awtRect.width, awtRect.height ) );
}
@Override
public final Rectangle getClipBounds()
{
return ( graphics.getClipBounds() );
}
public final Rect2i getClipBounds( Rect2i rect )
{
java.awt.Rectangle awtRect = new java.awt.Rectangle( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight() );
graphics.getClipBounds( awtRect );
return ( rect );
}
@Override
public final Color getColor()
{
return ( graphics.getColor() );
}
public final Colorf getColorf()
{
return ( new Colorf( graphics.getColor() ) );
}
@Override
public final java.awt.Font getFont()
{
return ( graphics.getFont() );
}
@Override
public final java.awt.FontMetrics getFontMetrics()
{
return ( graphics.getFontMetrics() );
}
@Override
public FontMetrics getFontMetrics( Font font )
{
return ( graphics.getFontMetrics( font ) );
}
@Override
public final java.awt.font.FontRenderContext getFontRenderContext()
{
return ( graphics.getFontRenderContext() );
}
@Override
public final java.awt.Paint getPaint()
{
return ( graphics.getPaint() );
}
@Override
public final Object getRenderingHint( java.awt.RenderingHints.Key hintKey )
{
return ( graphics.getRenderingHint( hintKey ) );
}
@Override
public final java.awt.RenderingHints getRenderingHints()
{
return ( graphics.getRenderingHints() );
}
@Override
public final java.awt.Stroke getStroke()
{
return ( graphics.getStroke() );
}
@Override
public final java.awt.geom.AffineTransform getTransform()
{
return ( graphics.getTransform() );
}
@Override
public final boolean hitClip( int x, int y, int width, int height )
{
return ( graphics.hitClip( x, y, width, height ) );
}
@Override
public boolean hit( Rectangle rect, Shape s, boolean onStroke )
{
return ( graphics.hit( rect, s, onStroke ) );
}
@Override
public final void rotate( double theta )
{
graphics.rotate( theta );
}
@Override
public final void rotate( double theta, double x, double y )
{
graphics.rotate( theta, x, y );
}
@Override
public final void scale( double sx, double sy )
{
graphics.scale( sx, sy );
}
public final void setBackgroundColor( Colorf color )
{
graphics.setBackground( color.getAWTColor() );
}
@Override
public final void setBackground( Color color )
{
graphics.setBackground( color );
}
@Override
public final void setClip( java.awt.Shape clip )
{
graphics.setClip( clip );
}
@Override
public final void setClip( int x, int y, int width, int height )
{
graphics.setClip( x, y, width, height );
getImage().setClipRect( x, y, width, height );
}
public final void setClip( Rect2i rect )
{
if ( rect == null )
setClip( 0, 0, getImage().getWidth(), getImage().getHeight() );
else
setClip( rect.getLeft(), rect.getTop(), rect.getWidth(), rect.getHeight() );
}
public final <Rect2i_ extends Rect2i> Rect2i_ getClip( Rect2i_ rect )
{
return ( getImage().getClipRect( rect ) );
}
@Override
public void setColor( Color color )
{
graphics.setColor( color );
}
public final void setColor( Colorf color )
{
graphics.setColor( color.getAWTColor() );
}
@Override
public final void setFont( java.awt.Font font )
{
graphics.setFont( font );
}
@Override
public final void setPaint( java.awt.Paint paint )
{
graphics.setPaint( paint );
}
@Override
public final void setPaintMode()
{
graphics.setPaintMode();
}
@Override
public final void setRenderingHint( java.awt.RenderingHints.Key hintKey, Object hintValue )
{
graphics.setRenderingHint( hintKey, hintValue );
}
public final void setRenderingHints( java.awt.RenderingHints hints )
{
graphics.setRenderingHints( hints );
}
@Override
public void setRenderingHints( Map< ?, ? > hints )
{
graphics.setRenderingHints( hints );
}
@Override
public void addRenderingHints( Map< ?, ? > hints )
{
graphics.addRenderingHints( hints );
}
public final void setAntialiazingEnabled( boolean enabled )
{
Object value = enabled ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF;
graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, value );
}
public final boolean isAntialiazingEnabled()
{
Object value = graphics.getRenderingHint( RenderingHints.KEY_ANTIALIASING );
return ( value == RenderingHints.VALUE_ANTIALIAS_ON );
}
@Override
public final void setStroke( java.awt.Stroke stroke )
{
graphics.setStroke( stroke );
}
@Override
public final void setTransform( java.awt.geom.AffineTransform Tx )
{
graphics.setTransform( Tx );
}
@Override
public final void setXORMode( Color color )
{
graphics.setXORMode( color );
}
@Override
public final void shear( double shx, double shy )
{
graphics.shear( shx, shy );
}
@Override
public final void transform( java.awt.geom.AffineTransform Tx )
{
graphics.transform( Tx );
}
@Override
public final void translate( double tx, double ty )
{
graphics.translate( tx, ty );
}
@Override
public final void translate( int tx, int ty )
{
graphics.translate( tx, ty );
}
protected void updateAffineTransform()
{
baseAffineTransform.setToIdentity();
if ( !texImg.getYUp() )
{
baseAffineTransform.concatenate( new AffineTransform( 1f, 0f, 0f, -1f, 0f, 0f ) );
baseAffineTransform.concatenate( new AffineTransform( 1f, 0f, 0f, 1f, 0f, -imgHeight ) );
}
this.graphics.setTransform( baseAffineTransform );
}
public final void notifyImagesizeChanged( int imgWidth, int imgHeight, Graphics2D graphics )
{
this.imgWidth = imgWidth;
this.imgHeight = imgHeight;
if ( ( graphics != null ) && ( graphics != this.graphics ) )
{
graphics.setBackground( this.graphics.getBackground() );
graphics.setClip( this.graphics.getClip() );
graphics.setColor( this.graphics.getColor() );
graphics.setComposite( this.graphics.getComposite() );
graphics.setFont( this.graphics.getFont() );
graphics.setPaint( this.graphics.getPaint() );
graphics.setRenderingHints( this.graphics.getRenderingHints() );
graphics.setStroke( this.graphics.getStroke() );
//graphics.setXORMode( this.graphics.getXORMode() );
this.graphics = graphics;
}
updateAffineTransform();
}
@Override
public void setComposite( Composite comp )
{
graphics.setComposite( comp );
}
@Override
public Composite getComposite()
{
return ( graphics.getComposite() );
}
@Override
public Graphics create()
{
throw new Error( "create() is not supported for this kind of Graphics2D." );
}
@Override
public void dispose()
{
graphics.dispose();
}
public Texture2DCanvas( Texture2D texture, TextureImage2D ti, int imgWidth, int imgHeight, Graphics2D graphics )
{
if ( graphics == null )
throw new IllegalArgumentException( "graphics must not be null." );
this.texture = texture;
this.texImg = ti;
this.imgWidth = imgWidth;
this.imgHeight = imgHeight;
this.graphics = graphics;
this.baseAffineTransform = new AffineTransform( 1f, 0f, 0f, 1f, 0f, 0f );
updateAffineTransform();
}
public Texture2DCanvas( Texture2D texture, TextureImage2D ti, int imgWidth, int imgHeight )
{
this( texture, ti, imgWidth, imgHeight, ti.createGraphics2D() );
}
public Texture2DCanvas( int imgWidth, int imgHeight, Graphics2D graphics )
{
this( null, null, imgWidth, imgHeight, graphics );
}
}