rikrd / geomerative

Geomerative is a library for Processing. It extends 2D geometry operations to facilitate generative geometry. Includes a TrueType font and an SVG interpreters. This library exposes the shapes (such as vector drawings or typographies) in a more approchable way. Geomerative makes it easy to access the contours, the control points and the curve points, making it easy to develop generative typography and geometry pieces in Processing.
http://www.ricardmarxer.com/geomerative
GNU General Public License v3.0
176 stars 29 forks source link

SVG loading crashes when "points" value starts with a negative symbol #9

Open euphy opened 5 years ago

euphy commented 5 years ago

Love this library, and have dug out a small problem with an SVG that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.0" id="Lager_1" xmlns:slic3r="http://slic3r.org/namespaces/slic3r" xmlns:svg="http://www.w3.org/2000/svg"
     xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 611.9 586.3"
     style="enable-background:new 0 0 611.9 586.3;" xml:space="preserve">
<style type="text/css">
    .st0{fill:#FFFFFF;}
</style>
<g>

    <polygon slic3r:type="contour" class="st0" points="-1.8,579 -1.8,579.1 -1.8,579.8 -1.8,580 -1.8,580 -1.8,580 -1.9,580 -2,580 
        -2,579.4 -2,579.1 -1.9,579  ">
    </polygon>
</g>
</svg>

The value of points in the only polygon starts with a negative number (-1.8,579) and this is caught by a branch in the part of RSVG.getPolyline() that checks for scientific notation (I think!).

        switch(charline[i])
          {
          case '-':
            if(charline[i-1] != 'e' && charline[i-1] != 'E'){
              charline=PApplet.splice(charline,' ',i);
              i++;
            }
break;

(https://github.com/rikrd/geomerative/blob/master/src/geomerative/RSVG.java#L744)

In this case, when the first char is '-', then i-1 triggers an ArrayIndexOutOfBoundsException. It looks like this in my application:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
    at geomerative.RSVG.getPolyline(Unknown Source)
    at geomerative.RSVG.elemToPolyline(Unknown Source)
    at geomerative.RSVG.elemToPolygon(Unknown Source)
    at geomerative.RSVG.elemToCompositeShape(Unknown Source)
    at geomerative.RSVG.elemToCompositeShape(Unknown Source)
    at geomerative.RSVG.toShape(Unknown Source)
    at geomerative.RG.loadShape(Unknown Source)
    at polargraphcontroller.loadShapeFromFile(polargraphcontroller.java:4574)
    at polargraphcontroller$9.run(polargraphcontroller.java:4453)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

My calling code is here: https://github.com/euphy/polargraphcontroller/blob/master/polargraphcontroller.pde#L2744

I've tried to replicate this error with your own examples in geomerative, but I'm getting a different error entirely:

with_negative_first_coord.svg does not exist or could not be read
java.lang.NullPointerException
    at processing.data.XML$1.read(XML.java:190)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at processing.data.XML.<init>(XML.java:187)
    at processing.core.PApplet.loadXML(PApplet.java:6322)
    at processing.core.PApplet.loadXML(PApplet.java:6312)
    at geomerative.RSVG.toShape(Unknown Source)
    at geomerative.RG.loadShape(Unknown Source)
    at Tutorial_16_HelloSVGtoPDF.setup(Tutorial_16_HelloSVGtoPDF.java:31)
    at processing.core.PApplet.handleDraw(PApplet.java:2361)
    at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
    at processing.core.PApplet.run(PApplet.java:2256)
    at java.lang.Thread.run(Unknown Source)

I don't see the difference between the two situations, but I can dig further if it's helpful.

I have solved this problem by changing https://github.com/rikrd/geomerative/blob/master/src/geomerative/RSVG.java#L744 to be

            if(i>0 && charline[i-1] != 'e' && charline[i-1] != 'E'){

That's adding an extra clause into the if condition: if it's greater than 0, then it's safe to look backwards for the E.

I can make a pull request for this if you'd like.

Thanks for making such a brill library!

sn

rikrd commented 5 years ago

Hi,

Indeed, it is a bug.

Please do send in a pull request if it is not too much trouble.

cheers

On Wed, Mar 13, 2019 at 12:34 AM Sandy Noble notifications@github.com wrote:

Love this library, and have dug out a small problem with an SVG that looks like this:

<?xml version="1.0" encoding="utf-8"?>

<svg version="1.0" id="Lager_1" xmlns:slic3r="http://slic3r.org/namespaces/slic3r" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 611.9 586.3" style="enable-background:new 0 0 611.9 586.3;" xml:space="preserve">

The value of points in the only polygon starts with a negative number (-1.8,579) and this is caught by a branch in the part of RSVG.getPolyline() that checks for scientific notation (I think!).

    switch(charline[i])
      {
      case '-':
        if(charline[i-1] != 'e' && charline[i-1] != 'E'){
          charline=PApplet.splice(charline,' ',i);
          i++;
        }

break;

( https://github.com/rikrd/geomerative/blob/master/src/geomerative/RSVG.java#L744 )

In this case, when the first char is '-', then i-1 triggers an ArrayIndexOutOfBoundsException. It looks like this in my application:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 at geomerative.RSVG.getPolyline(Unknown Source) at geomerative.RSVG.elemToPolyline(Unknown Source) at geomerative.RSVG.elemToPolygon(Unknown Source) at geomerative.RSVG.elemToCompositeShape(Unknown Source) at geomerative.RSVG.elemToCompositeShape(Unknown Source) at geomerative.RSVG.toShape(Unknown Source) at geomerative.RG.loadShape(Unknown Source) at polargraphcontroller.loadShapeFromFile(polargraphcontroller.java:4574) at polargraphcontroller$9.run(polargraphcontroller.java:4453) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$200(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)

My calling code is here: https://github.com/euphy/polargraphcontroller/blob/master/polargraphcontroller.pde#L2744

I've tried to replicate this error with your own examples in geomerative, but I'm getting a different error entirely:

with_negative_first_coord.svg does not exist or could not be read java.lang.NullPointerException at processing.data.XML$1.read(XML.java:190) at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.arrangeCapacity(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipString(Unknown Source) at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source) at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source) at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source) at processing.data.XML.(XML.java:187) at processing.core.PApplet.loadXML(PApplet.java:6322) at processing.core.PApplet.loadXML(PApplet.java:6312) at geomerative.RSVG.toShape(Unknown Source) at geomerative.RG.loadShape(Unknown Source) at Tutorial_16_HelloSVGtoPDF.setup(Tutorial_16_HelloSVGtoPDF.java:31) at processing.core.PApplet.handleDraw(PApplet.java:2361) at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240) at processing.core.PApplet.run(PApplet.java:2256) at java.lang.Thread.run(Unknown Source)

I don't see the difference between the two situations, but I can dig further if it's helpful.

I have solved this problem by changing https://github.com/rikrd/geomerative/blob/master/src/geomerative/RSVG.java#L744 to be

        if(i>0 && charline[i-1] != 'e' && charline[i-1] != 'E'){

That's adding an extra clause into the if condition: if it's greater than 0, then it's safe to look backwards for the E.

I can make a pull request for this if you'd like.

Thanks for making such a brill library!

sn

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rikrd/geomerative/issues/9, or mute the thread https://github.com/notifications/unsubscribe-auth/AAA73CTminw4EN3cUncLHBM-QxdFxkATks5vWDlygaJpZM4bsFpz .

-- ricard http://twitter.com/ricardmp http://www.ricardmarxer.com http://www.caligraft.com