// This is only used by *-image-slice properties which cannot interpolate between numbers and percentages.
// Numbers are internally represented by pixels on the ComputedStyle so we must manually type check both sides.
bool AnimatableLengthBoxAndBool::usesDefaultInterpolationWith(const AnimatableValue* value) const
{
    const AnimatableLengthBoxAndBool* lengthBoxAndBool = toAnimatableLengthBoxAndBool(value);
    if (lengthBoxAndBool->flag() != flag())
        return true;
    if (!box()->isLengthBox() || !lengthBoxAndBool->box()->isLengthBox())
        return AnimatableValue::usesDefaultInterpolation(box(), lengthBoxAndBool->box());
    const AnimatableLengthBox* boxA = toAnimatableLengthBox(box());
    const AnimatableLengthBox* boxB = toAnimatableLengthBox(lengthBoxAndBool->box());
    return !sidesHaveSameUnits(boxA->left(), boxB->left())
        || !sidesHaveSameUnits(boxA->right(), boxB->right())
        || !sidesHaveSameUnits(boxA->top(), boxB->top())
        || !sidesHaveSameUnits(boxA->bottom(), boxB->bottom());
}
bool AnimatableLengthBox::usesDefaultInterpolationWith(const AnimatableValue* other) const
{
    const AnimatableLengthBox& otherBox = toAnimatableLengthBox(*other);
    return usesDefaultInterpolation(left(), otherBox.left())
        || usesDefaultInterpolation(right(), otherBox.right())
        || usesDefaultInterpolation(top(), otherBox.top())
        || usesDefaultInterpolation(bottom(), otherBox.bottom());
}
bool AnimatableLengthBox::equalTo(const AnimatableValue* value) const
{
    const AnimatableLengthBox* lengthBox = toAnimatableLengthBox(value);
    return left()->equals(lengthBox->left())
        && right()->equals(lengthBox->right())
        && top()->equals(lengthBox->top())
        && bottom()->equals(lengthBox->bottom());
}
PassRefPtr<AnimatableValue> AnimatableLengthBox::interpolateTo(const AnimatableValue* value, double fraction) const
{
    const AnimatableLengthBox* lengthBox = toAnimatableLengthBox(value);
    return AnimatableLengthBox::create(
        AnimatableValue::interpolate(this->left(), lengthBox->left(), fraction),
        AnimatableValue::interpolate(this->right(), lengthBox->right(), fraction),
        AnimatableValue::interpolate(this->top(), lengthBox->top(), fraction),
        AnimatableValue::interpolate(this->bottom(), lengthBox->bottom(), fraction));
}
void PrintTo(const AnimatableValue& animValue, ::std::ostream* os)
{
    if (animValue.isClipPathOperation())
        PrintTo(*(toAnimatableClipPathOperation(&animValue)), os);
    else if (animValue.isColor())
        PrintTo(*(toAnimatableColor(&animValue)), os);
    else if (animValue.isDouble())
        PrintTo(*(toAnimatableDouble(&animValue)), os);
    else if (animValue.isImage())
        PrintTo(*(toAnimatableImage(&animValue)), os);
    else if (animValue.isLength())
        PrintTo(*(toAnimatableLength(&animValue)), os);
    else if (animValue.isLengthBox())
        PrintTo(*(toAnimatableLengthBox(&animValue)), os);
    else if (animValue.isLengthPoint())
        PrintTo(*(toAnimatableLengthPoint(&animValue)), os);
    else if (animValue.isLengthSize())
        PrintTo(*(toAnimatableLengthSize(&animValue)), os);
    else if (animValue.isNeutral())
        PrintTo(*(static_cast<const AnimatableNeutral*>(&animValue)), os);
    else if (animValue.isRepeatable())
        PrintTo(*(toAnimatableRepeatable(&animValue)), os);
    else if (animValue.isSVGLength())
        PrintTo(*(toAnimatableSVGLength(&animValue)), os);
    else if (animValue.isSVGPaint())
        PrintTo(*(toAnimatableSVGPaint(&animValue)), os);
    else if (animValue.isShapeValue())
        PrintTo(*(toAnimatableShapeValue(&animValue)), os);
    else if (animValue.isStrokeDasharrayList())
        PrintTo(*(toAnimatableStrokeDasharrayList(&animValue)), os);
    else if (animValue.isTransform())
        PrintTo(*(toAnimatableTransform(&animValue)), os);
    else if (animValue.isUnknown())
        PrintTo(*(toAnimatableUnknown(&animValue)), os);
    else if (animValue.isVisibility())
        PrintTo(*(toAnimatableVisibility(&animValue)), os);
    else
        *os << "Unknown AnimatableValue - update ifelse chain in AnimatableValueTestHelper.h";
}