docs: function drawNonMono(
      ctx, points, start, segLen, allLen,
      dir, smoothMin, smoothMax, smooth, smoothMonotone, connectNulls
  ) {
      var prevIdx = 0;
      var idx = start;
      for (var k = 0; k < segLen; k++) {
          var p = points[idx];
          if (idx >= allLen || idx < 0) {
              break;
          }
          if (isPointNull(p)) {
              if (connectNulls) {
                  idx += dir;
                  continue;
              }
              break;
          }
  
          if (idx === start) {
              ctx[dir > 0 ? 'moveTo' : 'lineTo'](p[0], p[1]);
              v2Copy(cp0, p);
          }
          else {
              if (smooth > 0) {
                  var nextIdx = idx + dir;
                  var nextP = points[nextIdx];
                  if (connectNulls) {
                      // Find next point not null
                      while (nextP && isPointNull(points[nextIdx])) {
                          nextIdx += dir;
                          nextP = points[nextIdx];
                      }
                  }
  
                  var ratioNextSeg = 0.5;
                  var prevP = points[prevIdx];
                  var nextP = points[nextIdx];
                  // Last point
                  if (!nextP || isPointNull(nextP)) {
                      v2Copy(cp1, p);
                  }
                  else {
                      // If next data is null in not connect case
                      if (isPointNull(nextP) && !connectNulls) {
                          nextP = p;
                      }
  
                      vec2.sub(v, nextP, prevP);
  
                      var lenPrevSeg;
                      var lenNextSeg;
                      if (smoothMonotone === 'x' || smoothMonotone === 'y') {
                          var dim = smoothMonotone === 'x' ? 0 : 1;
                          lenPrevSeg = Math.abs(p[dim] - prevP[dim]);
                          lenNextSeg = Math.abs(p[dim] - nextP[dim]);
                      }
                      else {
                          lenPrevSeg = vec2.dist(p, prevP);
                          lenNextSeg = vec2.dist(p, nextP);
                      }
  
                      // Use ratio of seg length
                      ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg);
  
                      scaleAndAdd(cp1, p, v, -smooth * (1 - ratioNextSeg));
                  }
                  // Smooth constraint
                  vec2Min(cp0, cp0, smoothMax);
                  vec2Max(cp0, cp0, smoothMin);
                  vec2Min(cp1, cp1, smoothMax);
                  vec2Max(cp1, cp1, smoothMin);
  
                  ctx.bezierCurveTo(
                      cp0[0], cp0[1],
                      cp1[0], cp1[1],
                      p[0], p[1]
                  );
                  // cp0 of next segment
                  scaleAndAdd(cp0, p, v, smooth * ratioNextSeg);
              }
              else {
                  ctx.lineTo(p[0], p[1]);
              }
          }
  
          prevIdx = idx;
          idx += dir;
      }
  
      return k;
  }