package net.xoetrope.optional.laf.synth;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.plaf.synth.SynthContext;
import javax.swing.plaf.synth.SynthPainter;
import net.xoetrope.debug.DebugLogger;
import net.xoetrope.optional.svg.svgsalamander.XSvgPainter;
//import net.xoetrope.optional.svg.batik.XSvgPainter;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.XProjectManager;
import net.xoetrope.optional.laf.ImageConverter;
import net.xoetrope.optional.laf.synth.svgsalamander.SvgImageTranscoder;
/**
* <p>Paints an image in sections, distinguishing the corners and edges and
* center so that the eges can be stretched.</p>
* <p>
* A variation on the Synth ImagePainter class but as the Syth class is not public
* we cannot derive from it so this class duplicates some of its methods.
* </p>
* <p>Copyright: Copyright (c) Xoetrope Ltd., 2004-2005<br>
* License: see license.txt
* $Revision: 1.4 $
* @see javax.swing.plaf.synth.ImagePainter
*/
public class ImagePainter extends SynthPainter
{
private int x;
private int y;
private int w;
private int h;
private int imageWidth;
private int imageHeight;
private Image image;
private XSvgPainter painter;
private Insets sourceInsets;
private Insets destinationInsets;
private boolean tiles;
private boolean paintCenter;
private boolean convertSvg;
private Object renderingHint, lastHint;
private XProject currentProject;
private SynthContext context;
private static ImageConverter imageConverter;
public ImagePainter()
{
currentProject = XProjectManager.getCurrentProject();
}
public ImagePainter( SynthContext c, Graphics g, int ax, int ay, int aw, int ah,
String imagePath, Insets srcInsets, Insets dstInsets,
boolean bTiles, boolean bCenter, boolean convert )
{
currentProject = XProjectManager.getCurrentProject();
convertSvg = convert;
context = c;
x = ax;
y = ay;
setW(aw);
setH(ah);
tiles = bTiles;
paintCenter = bCenter;
image = getImage( imagePath );
if ( image != null ) {
imageWidth = image.getWidth( null );
imageHeight = image.getHeight( null );
}
sourceInsets = srcInsets;
destinationInsets = dstInsets;
}
public ImagePainter( SynthContext c, Graphics g, int ax, int ay, int aw, int ah,
String imagePath, Insets srcInsets, Insets dstInsets,
boolean bTiles, boolean bCenter )
{
this( c, g, ax, ay, aw, ah, imagePath, srcInsets, dstInsets, bTiles, bCenter, false );
}
public Image getImage( String imagePath )
{
return getImage( imagePath, convertSvg );
}
public Image getImage( String imagePath, boolean convert )
{
try {
if ( painter == null )
painter = new XSvgPainter( context.getComponent() );
if ( image != null )
return image;
if ( convert ) {
if ( imageConverter == null )
imageConverter = new SvgImageTranscoder();
URL url = currentProject.findResource( imagePath.substring( 0, imagePath.lastIndexOf( '.' )) + ".svg" );
if ( url != null ) {
String urlStr = url.getPath();
String resName = urlStr;
File f = new File( urlStr.substring( 0, urlStr.lastIndexOf( '.' )) + ".png" );
FileOutputStream fos = new FileOutputStream( f );
imageConverter.convert( resName, url.openStream(), fos, w, h );
fos.close();
imagePath = resName.substring( 0, resName.indexOf( '.' )) + ".png";
}
else
DebugLogger.logError( "Image not found: " + imagePath );
}
else {
int pos = imagePath.lastIndexOf( '/' );
String path = imagePath.substring( 0, pos + 1 );
String fileName = imagePath.substring( pos + 1 );
fileName = fileName.substring( 0, fileName.indexOf( '.' ));
URL url1 = currentProject.getUrl( fileName + ".svg" );
// painter = new XSvgPainter( context.getComponent() );
painter.setImage( url1 );//, w, h );
return null;
}
}
catch ( Exception e )
{
}
URL url = currentProject.getUrl( imagePath );
if ( url != null )
image = ( new ImageIcon( url ) ).getImage();
if ( image == null )
return new ImageIcon( imagePath, null ).getImage();
return image;
}
public void paint( Graphics g )
{
Graphics2D g2d = (Graphics2D)g;
if ( renderingHint != null ) {
lastHint = g2d.getRenderingHint( RenderingHints.KEY_INTERPOLATION );
if ( lastHint == null )
lastHint = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
g2d.setRenderingHint( RenderingHints.KEY_INTERPOLATION, renderingHint );
}
else {
lastHint = g2d.getRenderingHint( RenderingHints.KEY_RENDERING );
g2d.setRenderingHint( RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY );
}
if ( painter != null ) {
painter.setInsets( sourceInsets );
painter.paint( g2d, context.getComponent(), w, h );
g2d.setRenderingHint( RenderingHints.KEY_RENDERING, lastHint );
return;
}
drawTopLeft( g );
drawTopCenter( g );
drawTopRight( g );
drawLeft( g );
drawRight( g );
drawBottomLeft( g );
drawBottomCenter( g );
drawBottomRight( g );
drawCenter( g );
}
public void drawTopLeft( Graphics g )
{
g.drawImage( image, x, y, x + destinationInsets.left, y + destinationInsets.top, 0, 0, sourceInsets.left, sourceInsets.top, null );
}
public void drawTopCenter( Graphics g )
{
drawChunk( image, g, tiles, x + destinationInsets.left, y, ( x + w ) - destinationInsets.right, y + destinationInsets.top, sourceInsets.left, 0,
imageWidth - sourceInsets.right, sourceInsets.top, true );
}
public void drawTopRight( Graphics g )
{
g.drawImage( image, ( x + w ) - destinationInsets.right, y, x + w, y + destinationInsets.top, imageWidth - sourceInsets.right, 0, imageWidth,
sourceInsets.top, null );
}
public void drawRight( Graphics g )
{
drawChunk( image, g, tiles, ( x + w ) - destinationInsets.right, y + destinationInsets.top, x + w, ( y + h ) - destinationInsets.bottom,
imageWidth - sourceInsets.right, sourceInsets.top, imageWidth, imageHeight - sourceInsets.bottom, false );
}
public void drawBottomRight( Graphics g )
{
g.drawImage( image, ( x + w ) - destinationInsets.right, ( y + h ) - destinationInsets.bottom, x + w, y + h, imageWidth - sourceInsets.right,
imageHeight - sourceInsets.bottom, imageWidth, imageHeight, null );
}
public void drawBottomCenter( Graphics g )
{
drawChunk( image, g, tiles, x + destinationInsets.left, ( y + h ) - destinationInsets.bottom, ( x + w ) - destinationInsets.right, y + h,
sourceInsets.left, imageHeight - sourceInsets.bottom, imageWidth - sourceInsets.right, imageHeight, true );
}
public void drawBottomLeft( Graphics g )
{
g.drawImage( image, x, ( y + h ) - destinationInsets.bottom, x + destinationInsets.left, y + h, 0, imageHeight - sourceInsets.bottom,
sourceInsets.left, imageHeight, null );
}
public void drawLeft( Graphics g )
{
drawChunk( image, g, tiles, x, y + destinationInsets.top, x + destinationInsets.left, ( y + h ) - destinationInsets.bottom, 0, sourceInsets.top,
sourceInsets.left, imageHeight - sourceInsets.bottom, false );
}
public void drawCenter( Graphics g )
{
if ( paintCenter )
g.drawImage( image, x + destinationInsets.left, y + destinationInsets.top, ( x + w ) - destinationInsets.right,
( y + h ) - destinationInsets.bottom, sourceInsets.left, sourceInsets.top, imageWidth - sourceInsets.right,
imageHeight - sourceInsets.bottom, null );
}
private void drawChunk( Image image, Graphics g, boolean tiles,
int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2,
boolean xDirection )
{
if ( tiles )
g.drawImage( image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null );
else {
int xSize = sx2 - sx1;
int ySize = sy2 - sy1;
int deltaX;
int deltaY;
if ( xDirection ) {
deltaX = xSize;
deltaY = 0;
}
else {
deltaX = 0;
deltaY = ySize;
}
for ( ; dx1 < dx2 && dy1 < dy2; dy1 += deltaY ) {
int newDX2 = Math.min( dx2, dx1 + xSize );
int newDY2 = Math.min( dy2, dy1 + ySize );
g.drawImage( image, dx1, dy1, newDX2, newDY2, sx1, sy1, ( sx1 + newDX2 ) - dx1, ( sy1 + newDY2 ) - dy1, null );
dx1 += deltaX;
}
}
}
public void setW( int w )
{
this.w = w;
}
public void setH( int h )
{
this.h = h;
}
}