static Length createLength(double pixels, double percentage, bool hasPercentage, ValueRange range)
{
    ASSERT(hasPercentage || percentage == 0);
    if (pixels && hasPercentage)
        return Length(CalculationValue::create(PixelsAndPercent(pixels, percentage), range));
    if (hasPercentage)
        return Length(clampToRange(percentage, range), Percent);
    return Length(CSSPrimitiveValue::clampToCSSLengthRange(clampToRange(pixels, range)), Fixed);
}
PassRefPtrWillBeRawPtr<CSSValue> DoubleStyleInterpolation::interpolableValueToDouble(const InterpolableValue* value, bool isNumber, InterpolationRange clamp)
{
    ASSERT(value->isNumber());
    double doubleValue = clampToRange(toInterpolableNumber(value)->value(), clamp);

    if (isNumber)
        return CSSPrimitiveValue::create(doubleValue, CSSPrimitiveValue::UnitType::Number);
    return CSSPrimitiveValue::create(doubleValue, CSSPrimitiveValue::UnitType::Degrees);
}
Length LengthInterpolationFunctions::createLength(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue* nonInterpolableValue,
    const CSSToLengthConversionData& conversionData,
    ValueRange range) {
  const InterpolableList& interpolableList =
      toInterpolableList(interpolableValue);
  bool hasPercentage =
      CSSLengthNonInterpolableValue::hasPercentage(nonInterpolableValue);
  double pixels = 0;
  double percentage = 0;
  for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
    double value = toInterpolableNumber(*interpolableList.get(i)).value();
    if (value == 0)
      continue;
    if (i == CSSPrimitiveValue::UnitTypePercentage) {
      percentage = value;
    } else {
      CSSPrimitiveValue::UnitType type =
          CSSPrimitiveValue::lengthUnitTypeToUnitType(
              static_cast<CSSPrimitiveValue::LengthUnitType>(i));
      pixels += conversionData.zoomedComputedPixels(value, type);
    }
  }

  if (percentage != 0)
    hasPercentage = true;
  if (pixels != 0 && hasPercentage)
    return Length(
        CalculationValue::create(PixelsAndPercent(pixels, percentage), range));
  if (hasPercentage)
    return Length(clampToRange(percentage, range), Percent);
  return Length(
      CSSPrimitiveValue::clampToCSSLengthRange(clampToRange(pixels, range)),
      Fixed);
}
static PassRefPtrWillBeRawPtr<CSSValue> createCSSValue(const InterpolableList& values, bool hasPercentage, ValueRange range)
{
    RefPtrWillBeRawPtr<CSSPrimitiveValue> result;
    size_t firstUnitIndex = CSSPrimitiveValue::LengthUnitTypeCount;
    size_t unitTypeCount = 0;
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
        if ((hasPercentage && i == CSSPrimitiveValue::UnitTypePercentage) || toInterpolableNumber(values.get(i))->value()) {
            unitTypeCount++;
            if (unitTypeCount == 1)
                firstUnitIndex = i;
        }
    }
    switch (unitTypeCount) {
    case 0:
        return CSSPrimitiveValue::create(0, CSSPrimitiveValue::UnitType::Pixels);
    case 1: {
        double value = clampToRange(toInterpolableNumber(values.get(firstUnitIndex))->value(), range);
        return CSSPrimitiveValue::create(value, toUnitType(firstUnitIndex));
    }
    default:
        return CSSPrimitiveValue::create(CSSCalcValue::create(createCalcExpression(values, hasPercentage), range));
    }
}