package org.codehaus.mojo.batik;
/*
* The MIT License
*
* Copyright 2006-2008 The Codehaus.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import java.awt.Color;
import java.io.File;
import java.util.Map;
import java.util.Vector;
import org.apache.batik.apps.rasterizer.DestinationType;
import org.apache.batik.apps.rasterizer.SVGConverter;
import org.apache.batik.apps.rasterizer.SVGConverterController;
import org.apache.batik.apps.rasterizer.SVGConverterException;
import org.apache.batik.apps.rasterizer.SVGConverterSource;
import org.apache.batik.transcoder.Transcoder;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.StringUtils;
/**
* Rasterize SVGs.
*
* @author Mark Hobson <markhobson@gmail.com>
* @version $Id$
* @goal rasterize
* @phase generate-resources
*/
public class RasterizeMojo
extends AbstractMojo
implements SVGConverterController
{
// parameters -------------------------------------------------------------
/**
* The directory containing the SVG files.
*
* @parameter default-value = "${basedir}/src/main/svg"
* @required
*/
private File srcDir;
/**
* The file pattern for inclusion of SVG files.
*
* @parameter default-value = "**\/*.svg";
* @required
*/
private String srcIncludes;
/**
* The file pattern for exclusion of SVG files.
*
* @parameter
*/
private String srcExcludes;
/**
* The directory to write the rasterized SVG files.
*
* @parameter default-value = "${project.build.directory}/generated-resources/images"
* @required
*/
private File destDir;
/**
* The type of file to convert to. Valid values are <code>png</code>, <code>jpeg</code>, <code>tiff</code> or
* <code>pdf</code>.
*
* @parameter default-value = "png"
* @required
*/
private String destType;
/**
* The output width, or -1 to not constrain the width.
*
* @parameter default-value = "-1"
*/
private float width;
/**
* The output height, or -1 to not constrain the height.
*
* @parameter default-value = "-1"
*/
private float height;
/**
* The maximum output width, or -1 to not constrain the maximum width.
*
* @parameter default-value = "-1"
*/
private float maxWidth;
/**
* The maximum output height, or -1 to not constrain the maximum height.
*
* @parameter default-value = "-1"
*/
private float maxHeight;
/**
* The PNG index value. Only used when destination type is <code>png</code>. Valid values are 1, 2, 4 or 8 bits, or
* -1 to not index.
*
* @parameter default-value = "-1"
*/
private int indexed;
/**
* The JPEG encoding quality. Only used when destination type is <code>jpeg</code>. Valid values are between 0.0 and
* 0.99 inclusive, or -1 to disable setting the quality.
*
* @parameter default-value = "-1"
*/
private float quality;
/**
* The background color. Valid values are of the form <code>#rrggbb</code>.
*
* @parameter
*/
private String background;
/**
* The desired resolution, in dots-per-inch (dpi). Use -1 disable setting the dpi.
*
* @parameter default-value = "-1"
*/
private float dpi;
// Mojo methods -----------------------------------------------------------
/**
* {@inheritDoc}
*/
public void execute()
throws MojoExecutionException, MojoFailureException
{
// get src files
String[] src = getSrc( srcDir, srcIncludes, srcExcludes );
if ( src.length == 0 )
{
getLog().info( "No SVG files found" );
return;
}
// build converter
SVGConverter converter = new SVGConverter( this );
converter.setSources( src );
converter.setDst( destDir );
converter.setDestinationType( toDestinationType( destType ) );
converter.setWidth( width );
converter.setHeight( height );
converter.setMaxWidth( maxWidth );
converter.setMaxHeight( maxHeight );
converter.setIndexed( indexed );
converter.setQuality( quality );
if ( dpi != -1f )
{
converter.setPixelUnitToMillimeter( ( 2.54f / dpi ) * 10 );
}
if ( background != null )
{
converter.setBackgroundColor( toColor( background ) );
}
// log message
StringBuffer buffer = new StringBuffer();
buffer.append( "Rasterizing " ).append( src.length ).append( " image" );
if ( src.length > 1 )
{
buffer.append( "s" );
}
buffer.append( " from SVG to " );
buffer.append( converter.getDestinationType().toString() );
getLog().info( buffer.toString() );
// convert svgs
try
{
converter.execute();
}
catch ( SVGConverterException exception )
{
throw new MojoExecutionException( "Cannot rasterize SVGs", exception );
}
}
// SVGConverterController methods -----------------------------------------
/**
* {@inheritDoc}
*/
public boolean proceedWithComputedTask( Transcoder transcoder, Map hints, Vector sources, Vector dest )
{
return true;
}
/**
* {@inheritDoc}
*/
public boolean proceedWithSourceTranscoding( SVGConverterSource source, File dest )
{
return true;
}
/**
* {@inheritDoc}
*/
public boolean proceedOnSourceTranscodingFailure( SVGConverterSource source, File dest, String errorCode )
{
// unfortunately SVGConverter always dumps the stack trace here without allowing us to handle it more
// gracefully..
getLog().warn( "Cannot rasterize SVG " + source.getName() + ": " + errorCode );
return false;
}
/**
* {@inheritDoc}
*/
public void onSourceTranscodingSuccess( SVGConverterSource source, File dest )
{
getLog().debug( "Rasterized SVG " + source.getName() );
}
// private methods --------------------------------------------------------
/**
* Gets files within the specified directory according to the given patterns.
*
* @param directory the base directory that contains the files
* @param includes the fileset pattern to match for inclusion
* @param excludes the fileset pattern to match for exclusion
* @return an array of matched filenames
*/
private static String[] getSrc( File directory, String includes, String excludes )
{
DirectoryScanner scanner = new DirectoryScanner();
scanner.setBasedir( directory );
scanner.setIncludes( StringUtils.split( includes, "," ) );
if ( excludes != null )
{
scanner.setExcludes( StringUtils.split( excludes, "," ) );
}
scanner.scan();
String[] files = scanner.getIncludedFiles();
for ( int i = 0; i < files.length; i++ )
{
files[i] = new File( directory, files[i] ).toString();
}
return files;
}
/**
* Gets the <code>DestinationType</code> for the specified destination type string.
*
* @param destinationType the destination type string, either <code>png</code>, <code>jpeg</code>, <code>tiff</code>
* or <code>pdf</code>
* @return the corresponding <code>DestinationType</code> instance
* @throws MojoExecutionException if an invalid destination type string was specified
*/
private static DestinationType toDestinationType( String destinationType )
throws MojoExecutionException
{
DestinationType type;
if ( "png".equals( destinationType ) )
{
type = DestinationType.PNG;
}
else if ( "jpeg".equals( destinationType ) )
{
type = DestinationType.JPEG;
}
else if ( "tiff".equals( destinationType ) )
{
type = DestinationType.TIFF;
}
else if ( "pdf".equals( destinationType ) )
{
type = DestinationType.PDF;
}
else
{
throw new MojoExecutionException( "Invalid destination type: " + destinationType );
}
return type;
}
/**
* Gets the <code>Color</code> for the specified color string.
*
* @param color the color string, in the format <code>#rrggbb</code>
* @return the corresponding <code>Color</code> instance
* @throws MojoExecutionException if an invalid color string was specified
*/
private static Color toColor( String color )
throws MojoExecutionException
{
if ( !color.startsWith( "#" ) || color.length() != 7 )
{
throw new MojoExecutionException( "Color must be of the form #rrggbb: " + color );
}
int r = Integer.parseInt( color.substring( 1, 3 ), 16 );
int g = Integer.parseInt( color.substring( 3, 5 ), 16 );
int b = Integer.parseInt( color.substring( 5 ), 16 );
return new Color( r, g, b );
}
}