PathSegmentData consumeInterpolableLinetoVertical(
    const InterpolableValue& value,
    SVGPathSegType segType,
    PathCoordinates& coordinates) {
  bool isAbsolute = isAbsolutePathSegType(segType);
  PathSegmentData segment;
  segment.command = segType;
  segment.targetPoint.setY(consumeInterpolableCoordinateAxis(
      &value, isAbsolute, coordinates.currentY));
  return segment;
}
std::unique_ptr<InterpolableValue> consumeCurvetoCubicSmooth(
    const PathSegmentData& segment,
    PathCoordinates& coordinates) {
  bool isAbsolute = isAbsolutePathSegType(segment.command);
  std::unique_ptr<InterpolableList> result = InterpolableList::create(4);
  result->set(
      0, consumeControlAxis(segment.x2(), isAbsolute, coordinates.currentX));
  result->set(
      1, consumeControlAxis(segment.y2(), isAbsolute, coordinates.currentY));
  result->set(
      2, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX));
  result->set(
      3, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY));
  return std::move(result);
}
std::unique_ptr<InterpolableValue> consumeArc(const PathSegmentData& segment,
                                              PathCoordinates& coordinates) {
  bool isAbsolute = isAbsolutePathSegType(segment.command);
  std::unique_ptr<InterpolableList> result = InterpolableList::create(7);
  result->set(
      0, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX));
  result->set(
      1, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY));
  result->set(2, InterpolableNumber::create(segment.r1()));
  result->set(3, InterpolableNumber::create(segment.r2()));
  result->set(4, InterpolableNumber::create(segment.arcAngle()));
  result->set(5, InterpolableBool::create(segment.largeArcFlag()));
  result->set(6, InterpolableBool::create(segment.sweepFlag()));
  return std::move(result);
}
bool SVGPathBlender::BlendState::canBlend(const PathSegmentData& fromSeg, const PathSegmentData& toSeg)
{
    // Update state first because we'll need it if we return true below.
    m_typesAreEqual = fromSeg.command == toSeg.command;
    m_fromIsAbsolute = isAbsolutePathSegType(fromSeg.command);

    // If the types are equal, they'll blend regardless of parameters.
    if (m_typesAreEqual)
        return true;

    // Addition require segments with the same type.
    if (m_addTypesCount)
        return false;

    // Allow the segments to differ in "relativeness".
    return toAbsolutePathSegType(fromSeg.command) == toAbsolutePathSegType(toSeg.command);
}
PathSegmentData consumeInterpolableCurvetoCubicSmooth(
    const InterpolableValue& value,
    SVGPathSegType segType,
    PathCoordinates& coordinates) {
  const InterpolableList& list = toInterpolableList(value);
  bool isAbsolute = isAbsolutePathSegType(segType);
  PathSegmentData segment;
  segment.command = segType;
  segment.point2.setX(consumeInterpolableControlAxis(list.get(0), isAbsolute,
                                                     coordinates.currentX));
  segment.point2.setY(consumeInterpolableControlAxis(list.get(1), isAbsolute,
                                                     coordinates.currentY));
  segment.targetPoint.setX(consumeInterpolableCoordinateAxis(
      list.get(2), isAbsolute, coordinates.currentX));
  segment.targetPoint.setY(consumeInterpolableCoordinateAxis(
      list.get(3), isAbsolute, coordinates.currentY));
  return segment;
}
PathSegmentData consumeInterpolableArc(const InterpolableValue& value,
                                       SVGPathSegType segType,
                                       PathCoordinates& coordinates) {
  const InterpolableList& list = toInterpolableList(value);
  bool isAbsolute = isAbsolutePathSegType(segType);
  PathSegmentData segment;
  segment.command = segType;
  segment.targetPoint.setX(consumeInterpolableCoordinateAxis(
      list.get(0), isAbsolute, coordinates.currentX));
  segment.targetPoint.setY(consumeInterpolableCoordinateAxis(
      list.get(1), isAbsolute, coordinates.currentY));
  segment.arcRadii().setX(toInterpolableNumber(list.get(2))->value());
  segment.arcRadii().setY(toInterpolableNumber(list.get(3))->value());
  segment.setArcAngle(toInterpolableNumber(list.get(4))->value());
  segment.arcLarge = toInterpolableBool(list.get(5))->value();
  segment.arcSweep = toInterpolableBool(list.get(6))->value();
  return segment;
}
std::unique_ptr<InterpolableValue> consumeSingleCoordinate(
    const PathSegmentData& segment,
    PathCoordinates& coordinates) {
  bool isAbsolute = isAbsolutePathSegType(segment.command);
  std::unique_ptr<InterpolableList> result = InterpolableList::create(2);
  result->set(
      0, consumeCoordinateAxis(segment.x(), isAbsolute, coordinates.currentX));
  result->set(
      1, consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY));

  if (toAbsolutePathSegType(segment.command) == PathSegMoveToAbs) {
    // Any upcoming 'closepath' commands bring us back to the location we have
    // just moved to.
    coordinates.initialX = coordinates.currentX;
    coordinates.initialY = coordinates.currentY;
  }

  return std::move(result);
}
PathSegmentData consumeInterpolableSingleCoordinate(
    const InterpolableValue& value,
    SVGPathSegType segType,
    PathCoordinates& coordinates) {
  const InterpolableList& list = toInterpolableList(value);
  bool isAbsolute = isAbsolutePathSegType(segType);
  PathSegmentData segment;
  segment.command = segType;
  segment.targetPoint.setX(consumeInterpolableCoordinateAxis(
      list.get(0), isAbsolute, coordinates.currentX));
  segment.targetPoint.setY(consumeInterpolableCoordinateAxis(
      list.get(1), isAbsolute, coordinates.currentY));

  if (toAbsolutePathSegType(segType) == PathSegMoveToAbs) {
    // Any upcoming 'closepath' commands bring us back to the location we have
    // just moved to.
    coordinates.initialX = coordinates.currentX;
    coordinates.initialY = coordinates.currentY;
  }

  return segment;
}
std::unique_ptr<InterpolableValue> consumeLinetoVertical(
    const PathSegmentData& segment,
    PathCoordinates& coordinates) {
  bool isAbsolute = isAbsolutePathSegType(segment.command);
  return consumeCoordinateAxis(segment.y(), isAbsolute, coordinates.currentY);
}