css4j / echosvg

SVG implementation in the Java™ Language, fork of Apache Batik, supporting level 4 selectors and colors.
Apache License 2.0
39 stars 2 forks source link

BridgeException: Cannot find the referenced element #80

Closed ghost closed 1 year ago

ghost commented 1 year ago

Replicate

  1. Create an SVG file with an unused reference. This can happen by editing an SVG created in Adobe Illustrator with Inkscape and removing objects. See e.svg.txt. Essentially:

    <clipPath
     id="SVGID_00000145770309263158979710000005844928936766913719_">
    <use
     xlink:href="#SVGID_00000072257059765744298700000011011170644502566322_"
     id="use3" />
    </clipPath>
  2. Rasterize the file using EchoSVG.

Expected

The unused reference is ignored and rasterizing continues. This is the behaviour that Inkscape takes, which permits it to load the image:

e

Actual

Exception is thrown and the image is not rasterized.

io.sf.carte.echosvg.bridge.BridgeException: file:community.svg:-1
Cannot find the referenced element:
"#SVGID_00000072257059765744298700000011011170644502566322_"
specified on the element <use> - may be a problem of 'id'

The root cause is BridgeContext.java, line 752, where it is assumed incorrectly that all such Element instances have a valid Node reference:

Node ref = ur.getNode(uri, e);
if (ref == null) {
  throw new BridgeException(this, e, ERR_URI_BAD_TARGET, new Object[] { uri });

This exception is caught by SVGAbstractTransformer at line 261 and wrapped into a new exception:

throw new TranscoderException(ex);

By the time it is wrapped and re-thrown as a TranscoderException, it's too late to intervene. Perhaps instead of creating a BridgeException, there needs to be an UndefinedReferenceException subclass of BridgeException? That way the exception can still be caught by SVGAbstractTransformer yet passed along to the ErrorHandler instead of being wrapped and re-thrown?

Another idea would be to create an "Empty" node/element to represent a missing reference, but that would needlessly clutter the DOM or have any number of unintended side-effects, I imagine, because getReferencedNode is used in many places.

carlosame commented 1 year ago

Filed a PR that closes this.