bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValue& value)
{
    // FIXME: should not require resolving styles for inherit/initial/unset.
    if (value.isCSSWideKeyword())
        return true;
    if (value.isBasicShapeCircleValue())
        return interpolationRequiresStyleResolve(toCSSBasicShapeCircleValue(value));
    if (value.isBasicShapeEllipseValue())
        return interpolationRequiresStyleResolve(toCSSBasicShapeEllipseValue(value));
    if (value.isBasicShapePolygonValue())
        return interpolationRequiresStyleResolve(toCSSBasicShapePolygonValue(value));
    if (value.isBasicShapeInsetValue())
        return interpolationRequiresStyleResolve(toCSSBasicShapeInsetValue(value));
    if (value.isColorValue())
        return false;
    if (value.isStringValue() || value.isURIValue() || value.isCustomIdentValue())
        return false;
    if (value.isPrimitiveValue())
        return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value));
    if (value.isQuadValue())
        return interpolationRequiresStyleResolve(toCSSQuadValue(value));
    if (value.isValueList())
        return interpolationRequiresStyleResolve(toCSSValueList(value));
    if (value.isValuePair())
        return interpolationRequiresStyleResolve(toCSSValuePair(value));
    if (value.isImageValue())
        return interpolationRequiresStyleResolve(toCSSImageValue(value));
    if (value.isShadowValue())
        return interpolationRequiresStyleResolve(toCSSShadowValue(value));
    if (value.isSVGDocumentValue())
        return interpolationRequiresStyleResolve(toCSSSVGDocumentValue(value));
    // FIXME: consider other custom types.
    return true;
}
InterpolationValue FilterInterpolationFunctions::maybeConvertCSSFilter(
    const CSSValue& value) {
  if (value.isURIValue())
    return nullptr;

  const CSSFunctionValue& filter = toCSSFunctionValue(value);
  DCHECK_LE(filter.length(), 1u);
  FilterOperation::OperationType type =
      FilterOperationResolver::filterOperationForType(filter.functionType());
  InterpolationValue result = nullptr;

  switch (type) {
    case FilterOperation::BRIGHTNESS:
    case FilterOperation::CONTRAST:
    case FilterOperation::GRAYSCALE:
    case FilterOperation::INVERT:
    case FilterOperation::OPACITY:
    case FilterOperation::SATURATE:
    case FilterOperation::SEPIA: {
      double amount = defaultParameter(type);
      if (filter.length() == 1) {
        const CSSPrimitiveValue& firstValue =
            toCSSPrimitiveValue(filter.item(0));
        amount = firstValue.getDoubleValue();
        if (firstValue.isPercentage())
          amount /= 100;
      }
      result.interpolableValue = InterpolableNumber::create(amount);
      break;
    }

    case FilterOperation::HUE_ROTATE: {
      double angle = defaultParameter(type);
      if (filter.length() == 1)
        angle = toCSSPrimitiveValue(filter.item(0)).computeDegrees();
      result.interpolableValue = InterpolableNumber::create(angle);
      break;
    }

    case FilterOperation::BLUR: {
      if (filter.length() == 0)
        result.interpolableValue =
            LengthInterpolationFunctions::createNeutralInterpolableValue();
      else
        result =
            LengthInterpolationFunctions::maybeConvertCSSValue(filter.item(0));
      break;
    }

    case FilterOperation::DROP_SHADOW: {
      result =
          ShadowInterpolationFunctions::maybeConvertCSSValue(filter.item(0));
      break;
    }

    default:
      NOTREACHED();
      return nullptr;
  }

  if (!result)
    return nullptr;

  result.nonInterpolableValue = FilterNonInterpolableValue::create(
      type, result.nonInterpolableValue.release());
  return result;
}