private static double readDouble(PushbackReader read) throws IOException {
   StringBuffer s = new StringBuffer();
   int count = -1;
   while (true) {
     char ch = (char) read.read();
     // skip spaces
     if (ch == ' ') continue;
     count++;
     // allow a - only if at the beginning
     if (ch == '-' && count == 0) {
       // u.p("negative number");
       s.append(ch);
       continue;
     }
     if ((ch >= '0' && ch <= '9') || ch == '.') {
       // u.p("got double part " + ch);
       s.append(ch);
     } else {
       if (ch != ',') {
         read.unread(ch);
       }
       break;
     }
   }
   return Double.parseDouble(s.toString());
 }
  private static SNode parsePathNode(Elem root) throws IOException {
    SPath path = new SPath();
    String d = root.attr("d");

    PushbackReader read = new PushbackReader(new StringReader(d));
    int count = 0;
    double x = 0;
    double y = 0;
    SPath.PathPoint prev = null;
    boolean go = true;
    while (go) {
      count++;
      char ch = (char) read.read();
      if (ch == -1) break;
      double x1, x2, y1, y2;
      u.p("ch = " + ch);
      switch (ch) {
          // absolute move
        case 'M':
          x = readDouble(read);
          y = readDouble(read);
          prev = path.moveTo(x, y);
          continue;
          // relative vertical lineto
        case 'v':
          y += readDouble(read);
          prev = path.lineTo(x, y);
          continue;
          // absolute vertical lineto
        case 'V':
          y = readDouble(read);
          prev = path.lineTo(x, y);
          continue;
          // relative horiz lineto
        case 'h':
          x += readDouble(read);
          prev = path.lineTo(x, y);
          continue;
        case 'H':
          x = readDouble(read);
          prev = path.lineTo(x, y);
          continue;
          // relative lineto
        case 'l':
          x += readDouble(read);
          y += readDouble(read);
          prev = path.lineTo(x, y);
          continue;
        case 'L':
          x = readDouble(read);
          y = readDouble(read);
          prev = path.lineTo(x, y);
          continue;
          // relative cubic curve
        case 'c':
          x1 = x + readDouble(read);
          y1 = y + readDouble(read);
          x2 = x + readDouble(read);
          y2 = y + readDouble(read);
          x += readDouble(read);
          y += readDouble(read);
          prev = path.curveTo(prev, x1, y1, x2, y2, x, y);
          continue;
          // relative shorthand curve
        case 's':
          x2 = x + readDouble(read);
          y2 = y + readDouble(read);
          x += readDouble(read);
          y += readDouble(read);
          double dx = prev.x - prev.cx1;
          double dy = prev.y - prev.cy1;
          double rx = prev.x + dx;
          double ry = prev.y + dy;
          prev = path.curveTo(prev, rx, ry, x2, y2, x, y);
          continue;
          // absolute cubic curve
        case 'C':
          x1 = readDouble(read);
          y1 = readDouble(read);
          x2 = readDouble(read);
          y2 = readDouble(read);
          x = readDouble(read);
          y = readDouble(read);
          prev = path.curveTo(prev, x1, y1, x2, y2, x, y);
          continue;
        case 'z':
          path.close();
          break;
        case ' ':
          continue;
        case '\n':
          continue;
          // end of string
        case (char) -1:
          go = false;
          break;
        default:
          u.p("unrecognized character! " + ch + " " + ((int) ch));
          go = false;
          break;
      }
    }

    parseFill(path, root);
    parseStroke(path, root);
    return path;
  }