InterpolationComponent CSSLengthInterpolationType::maybeConvertCSSValue(const CSSValue& value)
{
    if (!value.isPrimitiveValue())
        return nullptr;

    const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);

    CSSLengthArray valueArray;
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
        valueArray.append(0);
    bool hasPercentage = false;

    if (!primitiveValue.isLength() && !primitiveValue.isPercentage() && !primitiveValue.isCalculatedPercentageWithLength())
        return nullptr;
    CSSLengthTypeArray hasType;
    hasType.ensureSize(CSSPrimitiveValue::LengthUnitTypeCount);
    primitiveValue.accumulateLengthArray(valueArray, hasType);
    hasPercentage = hasType.get(CSSPrimitiveValue::UnitTypePercentage);

    OwnPtr<InterpolableList> values = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
        values->set(i, InterpolableNumber::create(valueArray.at(i)));

    return InterpolationComponent(values.release(), CSSLengthNonInterpolableValue::create(hasPercentage));
}
 bool lengthArraysEqual(CSSLengthArray& a, CSSLengthArray& b)
 {
     for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i) {
         if (a.at(i) != b.at(i))
             return false;
     }
     return true;
 }
void CSSPrimitiveValue::accumulateLengthArray(CSSLengthArray& lengthArray, CSSLengthTypeArray& lengthTypeArray, double multiplier) const
{
    ASSERT(lengthArray.size() == LengthUnitTypeCount);

    if (type() == UnitType::Calc) {
        cssCalcValue()->accumulateLengthArray(lengthArray, lengthTypeArray, multiplier);
        return;
    }

    LengthUnitType lengthType;
    if (unitTypeToLengthUnitType(type(), lengthType)) {
        lengthArray.at(lengthType) += m_value.num * conversionToCanonicalUnitsScaleFactor(type()) * multiplier;
        lengthTypeArray.set(lengthType);
    }
}
PassOwnPtr<InterpolableValue> LengthStyleInterpolation::lengthToInterpolableValue(CSSValue* value)
{
    OwnPtr<InterpolableList> result = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
    CSSPrimitiveValue* primitive = toCSSPrimitiveValue(value);

    CSSLengthArray array;
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
        array.append(0);
    primitive->accumulateLengthArray(array);

    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
        result->set(i, InterpolableNumber::create(array.at(i)));

    return result.release();
}
static void verifyCSSCalc(String text, double value, bool valid, unsigned fontSize, unsigned viewportWidth, unsigned viewportHeight)
{
    CSSLengthArray lengthArray;
    initLengthArray(lengthArray);
    RawPtr<CSSValue> cssValue = CSSParser::parseSingleValue(CSSPropertyLeft, text);
    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(cssValue.get());
    if (primitiveValue)
        primitiveValue->accumulateLengthArray(lengthArray);
    else
        ASSERT_EQ(valid, false);
    float length = lengthArray.at(CSSPrimitiveValue::UnitTypePixels);
    length += lengthArray.at(CSSPrimitiveValue::UnitTypeFontSize) * fontSize;
    length += lengthArray.at(CSSPrimitiveValue::UnitTypeViewportWidth) * viewportWidth / 100.0;
    length += lengthArray.at(CSSPrimitiveValue::UnitTypeViewportHeight) * viewportHeight / 100.0;
    ASSERT_EQ(value, length);
}
void PrintTo(const CSSLengthArray& lengthArray, ::std::ostream* os)
{
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i)
        *os << lengthArray.at(i) << ' ';
}
static void initLengthArray(CSSLengthArray& lengthArray)
{
    lengthArray.resize(CSSPrimitiveValue::LengthUnitTypeCount);
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; ++i)
        lengthArray.at(i) = 0;
}