Domanda

Using Batik, I am converting some SVG code to direct Java/Scala code using Java2D commands. For example, I have the following fragment:

<path
  id="path3622"
  transform="translate(0,152.36218)"
  d="m 720,94.5625 c -190.64053,0 -346.23512,150.07433 -355.0625,338.53125 235.63168,-82.12984 472.1202,-97.44221 710.0313,-1.78125 C 1065.2448,243.69491 910.03743,94.5625 720,94.5625 z"
  style="opacity:0.28999999;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
/>

I have already solved the d= bit, using a PathHandler to produce the correct GeneralPath2D. How would I go about parsing the transform and the style attributes? The transform I can imagine I can manage myself by hand, but for the style, it would be great to have a parser that gives me direct access to the fill and stroke values.

È stato utile?

Soluzione

Batik has very clumsy API and I also had to struggle with it. This is how I approached a similar problem.

import org.apache.batik.anim.dom.SVGStylableElement;

private void fill(SVGStylableElement element, String fillValue) {
    element.getStyle().setProperty("fill", fillValue, "");
}

Usage is pretty obvious. First parameter is an instance of a SVGStylableElement (see below). Second is the color value that you want to set (e.g. "#FF0000"). Note that setProperty() has also third parameter - it's can be used to set !important in CSS (I didn't need it).

So first you need to get an instance of SVGStylableElement.

import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

private Optional<SVGStylableElement> getElement(final SVGDocument svg, String id) {
    Element element = svg.getElementById(id);
    if (null == element) {
        return Optional.empty();
    }

    if (!SVGStylableElement.class.isAssignableFrom(element.getClass())) {
        return Optional.empty();
    }

    return Optional.of((SVGStylableElement) element);
}

The method above is in Java8+ style but can be re-written for older Java version if needed. You provide an instance of SVGDocument and element id (in your example that would be "path3622").

I assume that you already have an instance of SVGDocument created somehow so I omit it here. The last but required method is initialization of CSS Engine. This is kind of Batik's magic. You can find more info there https://wiki.apache.org/xmlgraphics-batik/BootSvgAndCssDom

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;

private void initializeEngine(SVGDocument svg) {
    UserAgentAdapter userAgent = new UserAgentAdapter();
    DocumentLoader loader = new DocumentLoader(userAgent);
    BridgeContext ctx = new BridgeContext(userAgent, loader);
    ctx.setDynamicState(BridgeContext.DYNAMIC);
    GVTBuilder builder = new GVTBuilder();
    builder.build(ctx, svg);
}

So remember to call this initializeEngine(...) method once just after you created instance of SVGDocument. If you don't do this, you get NPE in element.getStyle() in fill(...) method.

Just for reference, these are entries in my pom.xml that I used:

<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-svg-dom</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-anim</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-bridge</artifactId>
    <version>1.9.1</version>
</dependency>

Altri suggerimenti

How about javascript?

  var pathFill=path3622.style.fill
  var pathStroke=path3622.style.stroke
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top