docs: function segments2Contours(segments) {
  
      // 解析segments
      var contours = [];
      var contour = [];
      var prevX = 0;
      var prevY = 0;
      var segment;
      var args;
      var cmd;
      var relative;
      var q;
      var ql;
      var px;
      var py;
      var cubicList;
      var p1;
      var p2;
      var c1;
      var c2;
      var prevCubicC1; // 三次贝塞尔曲线前一个控制点，用于绘制`s`命令
  
      for (var i = 0, l = segments.length; i < l; i++) {
          segment = segments[i];
          cmd = segment.cmd;
          relative = segment.relative;
          args = segment.args;
  
          if (cmd === 'Z') {
              contours.push(contour);
              contour = [];
          }
          else if (cmd === 'M' || cmd === 'L') {
  
              if (args.length < 2 || args.length % 2) {
                  throw 'path `M` command needs even params';
              }
  
              // 这里可能会连续绘制，最后一个是终点
              if (relative) {
                  px = prevX;
                  py = prevY;
              }
              else {
                  px = 0;
                  py = 0;
              }
  
              for (q = 0, ql = args.length; q < ql; q += 2) {
  
                  if (relative) {
                      px += args[q];
                      py += args[q + 1];
                  }
                  else {
                      px = args[q];
                      py = args[q + 1];
                  }
  
                  contour.push({
                      x: px,
                      y: py,
                      onCurve: true
                  });
              }
  
              prevX = px;
              prevY = py;
          }
          else if (cmd === 'H') {
  
              if (relative) {
                  prevX += args[0];
              }
              else {
                  prevX = args[0];
              }
  
              contour.push({
                  x: prevX,
                  y: prevY,
                  onCurve: true
              });
          }
          else if (cmd === 'V') {
  
              if (relative) {
                  prevY += args[0];
              }
              else {
                  prevY = args[0];
              }
  
              contour.push({
                  x: prevX,
                  y: prevY,
                  onCurve: true
              });
          }
          // 二次贝塞尔
          else if (cmd === 'Q') {
  
              // 这里可能会连续绘制，最后一个是终点
              if (relative) {
                  px = prevX;
                  py = prevY;
              }
              else {
                  px = 0;
                  py = 0;
              }
  
              for (q = 0, ql = args.length; q < ql; q += 4) {
  
                  contour.push({
                      x: px + args[q],
                      y: py + args[q + 1]
                  });
                  contour.push({
                      x: px + args[q + 2],
                      y: py + args[q + 3],
                      onCurve: true
                  });
  
                  if (relative) {
                      px += args[q + 2];
                      py += args[q + 3];
                  }
                  else {
                      px = 0;
                      py = 0;
                  }
              }
  
              if (relative) {
                  prevX = px;
                  prevY = py;
              }
              else {
                  prevX = args[ql - 2];
                  prevY = args[ql - 1];
              }
          }
          // 二次贝塞尔平滑
          else if (cmd === 'T') {
  
              // 这里需要移除上一个曲线的终点
              var last = contour.pop();
  
              var pc = contour[contour.length - 1];
  
              contour.push(pc = {
                  x: 2 * last.x - pc.x,
                  y: 2 * last.y - pc.y
              });
  
              px = prevX;
              py = prevY;
  
              for (q = 0, ql = args.length - 2; q < ql; q += 2) {
  
                  if (relative) {
                      px += args[q];
                      py += args[q + 1];
                  }
                  else {
                      px = args[q];
                      py = args[q + 1];
                  }
  
                  last = {
                      x: px,
                      y: py
                  };
  
                  contour.push(pc = {
                      x: 2 * last.x - pc.x,
                      y: 2 * last.y - pc.y
                  });
              }
  
              if (relative) {
                  prevX = px + args[ql];
                  prevY = py + args[ql + 1];
              }
              else {
                  prevX = args[ql];
                  prevY = args[ql + 1];
              }
  
              contour.push({
                  x: prevX,
                  y: prevY,
                  onCurve: true
              });
  
          }
          // 三次贝塞尔
          else if (cmd === 'C') {
  
              // 这里可能会连续绘制，最后一个是终点
              cubicList = [];
  
              if (relative) {
                  px = prevX;
                  py = prevY;
              }
              else {
                  px = 0;
                  py = 0;
              }
  
              p1 = {
                  x: prevX,
                  y: prevY
              };
  
              for (q = 0, ql = args.length; q < ql; q += 6) {
  
                  c1 = {
                      x: px + args[q],
                      y: py + args[q + 1]
                  };
  
                  c2 = {
                      x: px + args[q + 2],
                      y: py + args[q + 3]
                  };
  
                  p2 = {
                      x: px + args[q + 4],
                      y: py + args[q + 5]
                  };
  
                  cubicList.push([p1, c1, c2, p2]);
  
                  p1 = p2;
  
                  if (relative) {
                      px += args[q + 4];
                      py += args[q + 5];
                  }
                  else {
                      px = 0;
                      py = 0;
                  }
              }
  
              if (relative) {
                  prevX = px;
                  prevY = py;
              }
              else {
                  prevX = args[ql - 2];
                  prevY = args[ql - 1];
              }
  
              cubic2Points(cubicList, contour);
              prevCubicC1 = cubicList[cubicList.length - 1][2];
          }
          // 三次贝塞尔平滑
          else if (cmd === 'S') {
  
              // 这里可能会连续绘制，最后一个是终点
              cubicList = [];
  
              if (relative) {
                  px = prevX;
                  py = prevY;
              }
              else {
                  px = 0;
                  py = 0;
              }
  
              // 这里需要移除上一个曲线的终点
              p1 = contour.pop();
              c1 = {
                  x: 2 * p1.x - prevCubicC1.x,
                  y: 2 * p1.y - prevCubicC1.y
              };
  
              for (q = 0, ql = args.length; q < ql; q += 4) {
  
                  c2 = {
                      x: px + args[q],
                      y: py + args[q + 1]
                  };
  
                  p2 = {
                      x: px + args[q + 2],
                      y: py + args[q + 3]
                  };
  
                  cubicList.push([p1, c1, c2, p2]);
  
                  p1 = p2;
  
                  c1 = {
                      x: 2 * p1.x - c2.x,
                      y: 2 * p1.y - c2.y
                  };
  
                  if (relative) {
                      px += args[q + 2];
                      py += args[q + 3];
                  }
                  else {
                      px = 0;
                      py = 0;
                  }
              }
  
              if (relative) {
                  prevX = px;
                  prevY = py;
              }
              else {
                  prevX = args[ql - 2];
                  prevY = args[ql - 1];
              }
  
              cubic2Points(cubicList, contour);
              prevCubicC1 = cubicList[cubicList.length - 1][2];
          }
          // 求弧度, rx, ry, angle, largeArc, sweep, ex, ey
          else if (cmd === 'A') {
  
              if (args.length !== 7) {
                  throw 'arc command params error:' + args.join(',');
              }
  
              var ex = args[5];
              var ey = args[6];
  
              if (relative) {
                  ex = prevX + ex;
                  ey = prevY + ey;
              }
  
              var path = getArc(
                  args[0], args[1],
                  args[2], args[3], args[4],
                  {x: prevX, y: prevY},
                  {x: ex, y: ey}
              );
  
              if (path && path.length > 1) {
                  for (q = 1, ql = path.length; q < ql; q++) {
                      contour.push(path[q]);
                  }
              }
  
              prevX = ex;
              prevY = ey;
          }
      }
  
      return contours;
  }