Skip to content
carlosame edited this page Jul 9, 2024 · 6 revisions

The echosvg-svggen module can generate SVG images using an SVG-specific Graphics2D implementation. Assuming that you are familiar with Graphics2D, the following example shows the basic usage of svggen.

Basic example

First, let's have an example class that writes to a Graphics2D. Please change the used fonts if you prefer others, or your system does not have them installed.

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.TextAttribute;
import java.util.HashMap;
import java.util.Map;

/**
 * Draw text with decoration attributes.
 */
public class FontDecorationPainter {

    public void paint(Graphics2D g) {
        // Set anti-aliasing
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // Set a background color
        Color backgroundColor = new Color(0x08081a);
        g.setBackground(backgroundColor);

        // Set default font
        g.setFont(new Font("Arial", Font.BOLD, 12));

        // Create a font with the desired attributes, including STRIKETHROUGH
        Map<TextAttribute, Object> attributes = new HashMap<>();
        attributes.put(TextAttribute.FAMILY, "Helvetica");
        attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_EXTRABOLD);
        attributes.put(TextAttribute.SIZE, 20);
        attributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
        Font fontST = new Font(attributes);

        // A similar font but with UNDERLINE instead of STRIKETHROUGH
        Map<TextAttribute, Object> attributes2 = new HashMap<>(attributes);
        attributes2.remove(TextAttribute.STRIKETHROUGH);
        attributes2.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
        Font fontUL = new Font(attributes2);

        // Set the STRIKETHROUGH font and a color
        g.setFont(fontST);
        g.setPaint(new Color(0x666699));
        // Draw a string
        g.drawString("Strike Through", 10, 40);

        // Now draw with a different color and the UNDERLINE font
        g.setPaint(Color.black);
        g.setFont(fontUL);
        g.translate(0, 30);
        // Draw a new string
        g.drawString("Underline", 10, 70);
    }

}

Then we need a few svggen classes to produce the SVG.

import java.awt.Dimension;
import java.awt.Font;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;

import io.sf.carte.echosvg.svggen.SVGGeneratorContext;
import io.sf.carte.echosvg.svggen.SVGGeneratorContext.GraphicContextDefaults;
import io.sf.carte.echosvg.svggen.SVGGraphics2D;

public class SVGGraphics2DExample {

    /**
     * Generate SVG from the drawings of the <code>FontDecorationPainter</code> class.
     * 
     * @param filename the filename to write the SVG to.
     * @throws IOException in case of I/O error.
     */
    public static void generateSVG(String filename) throws IOException {
        FontDecorationPainter painter = new FontDecorationPainter();

        SVGGraphics2D g2d = createSVGGraphics2D();

        // Set some appropriate dimension
        g2d.setSVGCanvasSize(new Dimension(300, 400));

        try (FileWriter fw = new FileWriter(filename, StandardCharsets.UTF_8)) {
            painter.paint(g2d);
            g2d.stream(fw);
            fw.flush();
        }
    }

    /**
     * Creates a <code>SVGGraphics2D</code> with certain defaults.
     * 
     * @return the <code>SVGGraphics2D</code>.
     */
    static SVGGraphics2D createSVGGraphics2D() {
        // We need a Document that holds an SVG root element.
        // First obtain a DocumentBuilder as a way to get it.
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);

        DocumentBuilder builder;
        try {
            builder = factory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new IllegalStateException(e);
        }

        // Now the document which is what is needed
        Document doc = builder.newDocument();
        
        // Create a SVG DTD
        DocumentType dtd = builder.getDOMImplementation().createDocumentType("svg",
                "-//W3C//DTD SVG 1.1//EN",
                "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
        // And the root element in the SVG namespace
        Element svgRoot = doc.createElementNS("http://www.w3.org/2000/svg", "svg");

        // Append those to the document
        doc.appendChild(dtd);
        doc.appendChild(svgRoot);

        /*
         * Now the document is ready: let's create some context objects and
         * then the SVGGraphics2D.
         */

        // For simplicity, create a generator context with some defaults
        SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(doc);
        // Set a comment to put in the SVG documents, overriding the default
        ctx.setComment("Generated by My Application");

        // Create the context defaults, with a default font just in case
        GraphicContextDefaults defaults = new GraphicContextDefaults();
        defaults.setFont(new Font("Arial", Font.PLAIN, 12));
        // Set the defaults
        ctx.setGraphicContextDefaults(defaults);
        // We want *some* precision
        ctx.setPrecision(9);

        return new SVGGraphics2D(ctx, false);
    }

}

and executing the generateSVG("filename.svg") method, the SVG would be written to the filename.svg file. Note that so far we haven't used EchoSVG's DOM, as the document was produced with the JDK's built-in DOM.


Apache Batik documentation

The Batik website has detailed documentation about using svggen which you may want to read.

Clone this wiki locally