protected void parsePath() {
    family = PATH;
    kind = 0;

    String pathData = element.getStringAttribute("d");
    if (pathData == null) return;
    char[] pathDataChars = pathData.toCharArray();

    StringBuffer pathBuffer = new StringBuffer();
    boolean lastSeparate = false;

    for (int i = 0; i < pathDataChars.length; i++) {
      char c = pathDataChars[i];
      boolean separate = false;

      if (c == 'M' || c == 'm' ||
          c == 'L' || c == 'l' ||
          c == 'H' || c == 'h' ||
          c == 'V' || c == 'v' ||
          c == 'C' || c == 'c' ||  // beziers
          c == 'S' || c == 's' ||
          c == 'Q' || c == 'q' ||  // quadratic beziers
          c == 'T' || c == 't' ||
          c == 'Z' || c == 'z' ||  // closepath
          c == ',') {
        separate = true;
        if (i != 0) {
          pathBuffer.append("|");
        }
      }
      if (c == 'Z' || c == 'z') {
        separate = false;
      }
      if (c == '-' && !lastSeparate) {
        pathBuffer.append("|");
      }
      if (c != ',') {
        pathBuffer.append(c); //"" + pathDataBuffer.charAt(i));
      }
      if (separate && c != ',' && c != '-') {
        pathBuffer.append("|");
      }
      lastSeparate = separate;
    }

    // use whitespace constant to get rid of extra spaces and CR or LF
    String[] pathDataKeys =
      PApplet.splitTokens(pathBuffer.toString(), "|" + WHITESPACE);
    vertices = new float[pathDataKeys.length][2];
    vertexCodes = new int[pathDataKeys.length];

    float cx = 0;
    float cy = 0;

    int i = 0;
    while (i < pathDataKeys.length) {
      char c = pathDataKeys[i].charAt(0);
      switch (c) {

      case 'M':  // M - move to (absolute)
        cx = PApplet.parseFloat(pathDataKeys[i + 1]);
        cy = PApplet.parseFloat(pathDataKeys[i + 2]);
        parsePathMoveto(cx, cy);
        i += 3;
        break;

      case 'm':  // m - move to (relative)
        cx = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        cy = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
        parsePathMoveto(cx, cy);
        i += 3;
        break;

      case 'L':
        cx = PApplet.parseFloat(pathDataKeys[i + 1]);
        cy = PApplet.parseFloat(pathDataKeys[i + 2]);
        parsePathLineto(cx, cy);
        i += 3;
        break;

      case 'l':
        cx = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        cy = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
        parsePathLineto(cx, cy);
        i += 3;
        break;

        // horizontal lineto absolute
      case 'H':
        cx = PApplet.parseFloat(pathDataKeys[i + 1]);
        parsePathLineto(cx, cy);
        i += 2;
        break;

        // horizontal lineto relative
      case 'h':
        cx = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        parsePathLineto(cx, cy);
        i += 2;
        break;

      case 'V':
        cy = PApplet.parseFloat(pathDataKeys[i + 1]);
        parsePathLineto(cx, cy);
        i += 2;
        break;

      case 'v':
        cy = cy + PApplet.parseFloat(pathDataKeys[i + 1]);
        parsePathLineto(cx, cy);
        i += 2;
        break;

        // C - curve to (absolute)
      case 'C': {
        float ctrlX1 = PApplet.parseFloat(pathDataKeys[i + 1]);
        float ctrlY1 = PApplet.parseFloat(pathDataKeys[i + 2]);
        float ctrlX2 = PApplet.parseFloat(pathDataKeys[i + 3]);
        float ctrlY2 = PApplet.parseFloat(pathDataKeys[i + 4]);
        float endX = PApplet.parseFloat(pathDataKeys[i + 5]);
        float endY = PApplet.parseFloat(pathDataKeys[i + 6]);
        parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
        cx = endX;
        cy = endY;
        i += 7;
      }
        break;

        // c - curve to (relative)
      case 'c': {
        float ctrlX1 = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        float ctrlY1 = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
        float ctrlX2 = cx + PApplet.parseFloat(pathDataKeys[i + 3]);
        float ctrlY2 = cy + PApplet.parseFloat(pathDataKeys[i + 4]);
        float endX = cx + PApplet.parseFloat(pathDataKeys[i + 5]);
        float endY = cy + PApplet.parseFloat(pathDataKeys[i + 6]);
        parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
        cx = endX;
        cy = endY;
        i += 7;
      }
        break;

        // S - curve to shorthand (absolute)
      case 'S': {
        float ppx = vertices[vertexCount-2][X];
        float ppy = vertices[vertexCount-2][Y];
        float px = vertices[vertexCount-1][X];
        float py = vertices[vertexCount-1][Y];
        float ctrlX1 = px + (px - ppx);
        float ctrlY1 = py + (py - ppy);
        float ctrlX2 = PApplet.parseFloat(pathDataKeys[i + 1]);
        float ctrlY2 = PApplet.parseFloat(pathDataKeys[i + 2]);
        float endX = PApplet.parseFloat(pathDataKeys[i + 3]);
        float endY = PApplet.parseFloat(pathDataKeys[i + 4]);
        parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
        cx = endX;
        cy = endY;
        i += 5;
      }
        break;

        // s - curve to shorthand (relative)
      case 's': {
        float ppx = vertices[vertexCount-2][X];
        float ppy = vertices[vertexCount-2][Y];
        float px = vertices[vertexCount-1][X];
        float py = vertices[vertexCount-1][Y];
        float ctrlX1 = px + (px - ppx);
        float ctrlY1 = py + (py - ppy);
        float ctrlX2 = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        float ctrlY2 = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
        float endX = cx + PApplet.parseFloat(pathDataKeys[i + 3]);
        float endY = cy + PApplet.parseFloat(pathDataKeys[i + 4]);
        parsePathCurveto(ctrlX1, ctrlY1, ctrlX2, ctrlY2, endX, endY);
        cx = endX;
        cy = endY;
        i += 5;
      }
        break;

        // Q - quadratic curve to (absolute)
      case 'Q': {
        float ctrlX = PApplet.parseFloat(pathDataKeys[i + 1]);
        float ctrlY = PApplet.parseFloat(pathDataKeys[i + 2]);
        float endX = PApplet.parseFloat(pathDataKeys[i + 3]);
        float endY = PApplet.parseFloat(pathDataKeys[i + 4]);
        parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
        cx = endX;
        cy = endY;
        i += 5;
      }
        break;

        // q - quadratic curve to (relative)
      case 'q': {
        float ctrlX = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        float ctrlY = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
        float endX = cx + PApplet.parseFloat(pathDataKeys[i + 3]);
        float endY = cy + PApplet.parseFloat(pathDataKeys[i + 4]);
        parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
        cx = endX;
        cy = endY;
        i += 5;
      }
        break;

        // T - quadratic curve to shorthand (absolute)
        // The control point is assumed to be the reflection of the
        // control point on the previous command relative to the
        // current point. (If there is no previous command or if the
        // previous command was not a Q, q, T or t, assume the control
        // point is coincident with the current point.)
      case 'T': {
        float ppx = vertices[vertexCount-2][X];
        float ppy = vertices[vertexCount-2][Y];
        float px = vertices[vertexCount-1][X];
        float py = vertices[vertexCount-1][Y];
        float ctrlX = px + (px - ppx);
        float ctrlY = py + (py - ppy);
        float endX = PApplet.parseFloat(pathDataKeys[i + 1]);
        float endY = PApplet.parseFloat(pathDataKeys[i + 2]);
        parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
        cx = endX;
        cy = endY;
        i += 3;
      }
        break;

        // t - quadratic curve to shorthand (relative)
      case 't': {
        float ppx = vertices[vertexCount-2][X];
        float ppy = vertices[vertexCount-2][Y];
        float px = vertices[vertexCount-1][X];
        float py = vertices[vertexCount-1][Y];
        float ctrlX = px + (px - ppx);
        float ctrlY = py + (py - ppy);
        float endX = cx + PApplet.parseFloat(pathDataKeys[i + 1]);
        float endY = cy + PApplet.parseFloat(pathDataKeys[i + 2]);
        parsePathQuadto(cx, cy, ctrlX, ctrlY, endX, endY);
        cx = endX;
        cy = endY;
        i += 3;
      }
        break;

      case 'Z':
      case 'z':
        close = true;
        i++;
        break;

      default:
        String parsed =
          PApplet.join(PApplet.subset(pathDataKeys, 0, i), ",");
        String unparsed =
          PApplet.join(PApplet.subset(pathDataKeys, i), ",");
        System.err.println("parsed: " + parsed);
        System.err.println("unparsed: " + unparsed);
        if (pathDataKeys[i].equals("a") || pathDataKeys[i].equals("A")) {
          String msg = "Sorry, elliptical arc support for SVG files " +
            "is not yet implemented (See bug #996 for details)";
          throw new RuntimeException(msg);
        }
        throw new RuntimeException("shape command not handled: " + pathDataKeys[i]);
      }
    }
  }


//      private void parsePathCheck(int num) {
//        if (vertexCount + num-1 >= vertices.length) {
//          //vertices = (float[][]) PApplet.expand(vertices);
//          float[][] temp = new float[vertexCount << 1][2];
//          System.arraycopy(vertices, 0, temp, 0, vertexCount);
//          vertices = temp;
//        }
//      }