001/*
002 * SVG Salamander
003 * Copyright (c) 2004, Mark McKay
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or 
007 * without modification, are permitted provided that the following
008 * conditions are met:
009 *
010 *   - Redistributions of source code must retain the above 
011 *     copyright notice, this list of conditions and the following
012 *     disclaimer.
013 *   - Redistributions in binary form must reproduce the above
014 *     copyright notice, this list of conditions and the following
015 *     disclaimer in the documentation and/or other materials 
016 *     provided with the distribution.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
023 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
025 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
026 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
027 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
029 * OF THE POSSIBILITY OF SUCH DAMAGE. 
030 * 
031 * Mark McKay can be contacted at mark@kitfox.com.  Salamander and other
032 * projects can be found at http://www.kitfox.com
033 *
034 * Created on January 22, 2005, 10:30 AM
035 */
036
037package com.kitfox.svg.app.ant;
038
039import java.awt.*;
040import java.awt.image.*;
041import java.util.*;
042import java.util.regex.*;
043import java.io.*;
044import javax.imageio.*;
045
046//import com.kitfox.util.*;
047//import com.kitfox.util.indexedObject.*;
048
049import org.apache.tools.ant.*;
050import org.apache.tools.ant.types.*;
051
052import com.kitfox.svg.app.beans.*;
053import com.kitfox.svg.*;
054import com.kitfox.svg.xml.ColorTable;
055
056/**
057 * <p>Translates a group of SVG files into images.</p>
058 * 
059 * <p>Parameters:</p>
060 * <p><ul>
061 * <li/>destDir - If present, specifices a directory to write SVG files to.  Otherwise
062 * writes images to directory SVG file was found in
063 * verbose - If true, prints processing information to the console
064 * <li/>format - File format for output images.  The java core javax.imageio.ImageIO
065 * class is used for creating images, so format strings will depend on what
066 * files your system is configured to handle.  By default, "gif", "jpg" and "png"
067 * files are guaranteed to be present.  If omitted, "png" is used by default.
068 * <li/>backgroundColor - Optional background color.  Color can be specified as a standard 
069 * HTML color.  That is, as the name of a standard color such as "blue" or 
070 * "limegreen", using the # notaion as in #ff00ff for magenta, or in rgb format
071 * listing the components as in rgb(255, 192, 192) for pink.  If omitted,
072 * background is transparent.
073 * <li/>antiAlias - If set, shapes are drawn using antialiasing.  Defaults to true.
074 * <li/>interpolation - String describing image interpolation alrogithm.  Can
075 * be one of "nearest neighbor", "bilinear" or "bicubic".  Defaults to "bicubic".
076 * <li/>width - If greater than 0, determines the width of the written image.  Otherwise,
077 * the width is obtained from the SVG document.  Defaults to -1;
078 * <li/>height - If greater than 0, determines the height of the written image.  Otherwise,
079 * the height is obtained from the SVG document.  Defaults to -1.
080 * <li/>sizeToFit - If true and the width and height of the output image differ
081 * from that of the SVG image, the valid area of the SVG image will be resized 
082 * to fit the specified size.
083 * <li/>verbose - IF true, prints out diagnostic infromation about processing.  
084 * Defaults to false.
085 * </ul></p>
086 * 
087 * Example:
088 * &lt;SVGToImage destDir="${index.java}" format="jpg" verbose="true"&gt;
089 *    &lt;fileset dir="${dir1}"&gt;
090 *        &lt;include name="*.svg"/&gt;
091 *    &lt;/fileset&gt;
092 *    &lt;fileset dir="${dir2}"&gt;
093 *        &lt;include name="*.svg"/&gt;
094 *    &lt;/fileset&gt;
095 * &lt;/SVGToImage&gt;
096 * 
097 * 
098 * 
099 * @author kitfox
100 */
101public class SVGToImageAntTask extends Task
102{
103    private ArrayList filesets = new ArrayList();
104    boolean verbose = false;
105    File destDir;
106    private String format = "png";
107    Color backgroundColor = null;
108    int width = -1;
109    int height = -1;
110    boolean antiAlias = true;
111    String interpolation = "bicubic";
112    boolean clipToViewBox = false;
113    boolean sizeToFit = true;
114    
115    /** Creates a new instance of IndexLoadObjectsAntTask */
116    public SVGToImageAntTask()
117    {
118    }
119    
120    
121    public String getFormat()
122    {
123        return format;
124    }
125    
126    public void setFormat(String format)
127    {
128        this.format = format;
129    }
130    
131    public void setBackgroundColor(String bgColor)
132    {
133        this.backgroundColor = ColorTable.parseColor(bgColor);
134    }
135    
136    public void setHeight(int height)
137    {
138        this.height = height;
139    }
140    
141    public void setWidth(int width)
142    {
143        this.width = width;
144    }
145    
146    public void setAntiAlias(boolean antiAlias)
147    {
148        this.antiAlias = antiAlias;
149    }
150    
151    public void setInterpolation(String interpolation)
152    {
153        this.interpolation = interpolation;
154    }
155    
156    public void setSizeToFit(boolean sizeToFit)
157    {
158        this.sizeToFit = sizeToFit;
159    }
160    
161    public void setClipToViewBox(boolean clipToViewBox)
162    {
163        this.clipToViewBox = clipToViewBox;
164    }
165    
166    public void setVerbose(boolean verbose)
167    {
168        this.verbose = verbose;
169    }
170    
171    public void setDestDir(File destDir)
172    {
173        this.destDir = destDir;
174    }
175    
176    /**
177     * Adds a set of files.
178     */
179    public void addFileset(FileSet set)
180    {
181        filesets.add(set);
182    }
183    
184    
185    
186    public void execute()
187    {
188        if (verbose) log("Building SVG images");
189        
190        for (Iterator it = filesets.iterator(); it.hasNext();)
191        {
192            FileSet fs = (FileSet)it.next();
193            FileScanner scanner = fs.getDirectoryScanner(getProject());
194            String[] files = scanner.getIncludedFiles();
195            
196            try
197            {
198                File basedir = scanner.getBasedir();
199                
200                if (verbose) log("Scaning " + basedir);
201                
202                for (int i = 0; i < files.length; i++)
203                {
204//System.out.println("File " + files[i]);
205//System.out.println("BaseDir " + basedir);
206                    translate(basedir, files[i]);
207                }
208            }
209            catch (Exception e)
210            {
211                throw new BuildException(e);
212            }
213        }
214    }
215    
216    private void translate(File baseDir, String shortName) throws BuildException
217    {
218        File source = new File(baseDir, shortName);
219        
220        if (verbose) log("Reading file: " + source);
221        
222        Matcher matchName = Pattern.compile("(.*)\\.svg", Pattern.CASE_INSENSITIVE).matcher(shortName);
223        if (matchName.matches())
224        {
225            shortName = matchName.group(1);
226        }
227        shortName += "." + format;
228        
229        SVGIcon icon = new SVGIcon();
230        icon.setSvgURI(source.toURI());
231        icon.setAntiAlias(antiAlias);
232        if (interpolation.equals("nearest neighbor"))
233        {
234            icon.setInterpolation(SVGIcon.INTERP_NEAREST_NEIGHBOR);
235        }
236        else if (interpolation.equals("bilinear"))
237        {
238            icon.setInterpolation(SVGIcon.INTERP_BILINEAR);
239        }
240        else if (interpolation.equals("bicubic"))
241        {
242            icon.setInterpolation(SVGIcon.INTERP_BICUBIC);
243        }
244        
245        int iconWidth = width > 0 ? width : icon.getIconWidth();
246        int iconHeight = height > 0 ? height : icon.getIconHeight();
247        icon.setClipToViewbox(clipToViewBox);
248        icon.setPreferredSize(new Dimension(iconWidth, iconHeight));
249        icon.setScaleToFit(sizeToFit);
250        BufferedImage image = new BufferedImage(iconWidth, iconHeight, BufferedImage.TYPE_INT_ARGB);
251        Graphics2D g = image.createGraphics();
252        
253        if (backgroundColor != null)
254        {
255            g.setColor(backgroundColor);
256            g.fillRect(0, 0, iconWidth, iconHeight);
257        }
258        
259        g.setClip(0, 0, iconWidth, iconHeight);
260//        g.fillRect(10, 10, 100, 100);
261        icon.paintIcon(null, g, 0, 0);
262        g.dispose();
263        
264        File outFile = destDir == null ? new File(baseDir, shortName) : new File(destDir, shortName);
265        if (verbose) log("Writing file: " + outFile);
266        
267        try
268        {
269            ImageIO.write(image, format, outFile);
270        }
271        catch (IOException e)
272        {
273            log("Error writing image: " + e.getMessage());
274            throw new BuildException(e);
275        }
276        
277        
278        SVGCache.getSVGUniverse().clear();
279    }
280    
281}