将项添加到现有的svg图像

时间:2013-02-11 17:57:08

标签: java svg batik plantuml

大家下午好;

我目前正在研究Java项目,尝试创建一个桌面工具。我的问题是我现在使用框架(plantuml)来获取svg格式的图形。但是,我想在svg输出中更改现有项(或我们可以说的组件)并以另一种方式显示它(例如添加细节)。我对此做了一些研究,我发现有两个框架可以帮助我实现目标;

1。)http://xmlgraphics.apache.org/batik/ 2.)http://svgsalamander.java.net/

问题; 有没有其他框架可以帮助我操纵现有的svg? 我应该使用哪一个,我应该如何使用我有点迷失。我不知道从哪里开始。

假设是:我无法改变有关植物的任何信息。所以我只有一个.svg格式的图像。

问候......

2 个答案:

答案 0 :(得分:2)

我听说过Batik,我知道它很受欢迎,但我从未使用它。在过去,我不得不在程序中以编程方式生成/更改SVG几次,使用Java,Javascript或C ++。我总是手工完成,这意味着:

  • 使用Java的标准org.w3c.dom或其他一些DOM库;
  • 使用Java的标准org.xml.sax或其他一些SAX库。

SVG是一个XML应用程序,因此使用上面列出的两个通用XML API进行操作非常容易。您基本上加载SVG文件并通过调用API的适当方法开始添加/删除/更改元素。

这是使用SAX for Java的一个小例子。我意识到我有点生疏;代码似乎工作,但SAX / XML / Java Gurus的清理是受欢迎的。它运行在使用Inkscape生成的SVG文件上,Inkscape是一个矢量编辑程序,但这里讨论的概念适用于任何SVG(甚至是一般的XML)文档。基本上它通过改变XML元素流来工作;它会在图纸中的每个对象附近插入渐进式标签。

SAX是基于事件的;在XML解析期间引发事件。该代码处理3个不同的事件:

  • startDocument 在XML文档的开头引发;我们使用此事件来重置渐进式计数器。
  • startElement 在XML元素的开头引发;如果元素是路径(在SVG中描述形状的常用元素),我们会注意到它的位置( cx cy ;限定符 sodipodi 是Inkscape的旧名称。
  • endElement 在XML元素的末尾引发;如果元素是路径,我们引发自己导致生成标签的事件。我们使用SVG元素文本将标签添加到文档中。

    import java.io.File;
    import java.io.FileInputStream;
    
    import javax.xml.transform.Result;
    import javax.xml.transform.sax.SAXTransformerFactory;
    import javax.xml.transform.sax.TransformerHandler;
    import javax.xml.transform.stream.StreamResult;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.InputSource;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLFilter;
    import org.xml.sax.XMLReader;
    import org.xml.sax.helpers.AttributesImpl;
    import org.xml.sax.helpers.XMLFilterImpl;
    import org.xml.sax.helpers.XMLReaderFactory;
    
    public class SVGMod {
    
      public static void main(String argv[]) {
    
        try {
            SAXTransformerFactory factory = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
            TransformerHandler serializer = factory.newTransformerHandler();
            Result result = new StreamResult(new File("Output.svg"));
            serializer.setResult(result);
    
            XMLReader reader = XMLReaderFactory.createXMLReader();
            reader.setFeature("http://xml.org/sax/features/namespaces", true);
            reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
    
            XMLFilter filter = new XMLFilterImpl() {
    
                private int x;
                private int y;
                private int cnt;
    
                @Override
                public void startDocument() throws SAXException {
                    super.startDocument();
    
                    cnt = 0;
                }
    
                @Override
                public void startElement(String uri, String localName,
                        String qName, Attributes atts) throws SAXException {
                    super.startElement(uri, localName, qName, atts);
    
                    if (qName.equals("path")) {
                        int xIndex = atts.getIndex("sodipodi:cx");
                        int yIndex = atts.getIndex("sodipodi:cy");
    
                        if (xIndex != -1 && yIndex != -1) {
                            x = (int)Float.parseFloat(atts.getValue(xIndex));
                            y = (int)Float.parseFloat(atts.getValue(yIndex));
                            ++cnt;
                        }
                    }
                }
    
                @Override
                public void endElement(String uri, String localName,
                        String qName) throws SAXException {
                    super.endElement(uri, localName, qName);
    
                    if (qName.equals("path")) {
                        AttributesImpl atts = new AttributesImpl();
                        atts.addAttribute(uri, "", "x", "CDATA", new Integer(x).toString());
                        atts.addAttribute(uri, "", "y", "CDATA", new Integer(y).toString());
                        atts.addAttribute(uri, "", "fill", "CDATA", "red");
                        super.startElement(uri, "", "text", atts);
                        char[] chars = ("Object #: " + cnt).toCharArray();
                        super.characters(chars, 0, chars.length);
                        super.endElement(uri, "", "text");
                    }
                }
            };
            filter.setContentHandler(serializer);
            filter.setParent(reader);
    
            filter.parse(new InputSource(new FileInputStream("Input.svg")));
        } catch (Exception e) {
            e.printStackTrace();
        }
      } 
    }
    

答案 1 :(得分:0)

您可能想要修改PlantUML路线。 在PlantUML论坛中 * http://sourceforge.net/apps/phpbb/plantuml/viewforum.php?f=1 你可以要求一个插件架构,允许沿着PlantUML修改svg。通过这种方式,您的更改将比PlantUML更加“兼容”,而不仅仅是您自己的修改方法。