PassOwnPtr<InterpolationValue> PathInterpolationFunctions::maybeConvertNeutral(const InterpolationType& type, const UnderlyingValue& underlyingValue, InterpolationType::ConversionCheckers& conversionCheckers)
{
    conversionCheckers.append(UnderlyingPathSegTypesChecker::create(type, underlyingValue));
    OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentIndexCount);
    result->set(PathArgsIndex, toInterpolableList(underlyingValue->interpolableValue()).get(PathArgsIndex)->cloneAndZero());
    result->set(PathNeutralIndex, InterpolableNumber::create(1));
    return InterpolationValue::create(type, result.release(),
        const_cast<NonInterpolableValue*>(underlyingValue->nonInterpolableValue())); // Take ref.
}
Пример #2
0
PassOwnPtr<InterpolationValue> SVGTransformListInterpolationType::maybeConvertNeutral(const UnderlyingValue& underlyingValue, ConversionCheckers& conversionCheckers) const
{
    Vector<SVGTransformType> underlyingTypes(toSVGTransformNonInterpolableValue(underlyingValue->nonInterpolableValue())->transformTypes());
    conversionCheckers.append(UnderlyingTypesChecker::create(*this, underlyingTypes));
    if (underlyingTypes.isEmpty())
        return nullptr;
    OwnPtr<InterpolationValue> result = underlyingValue->clone();
    result->mutableComponent().interpolableValue = result->interpolableValue().cloneAndZero();
    return result.release();
}
void PathInterpolationFunctions::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value)
{
    const InterpolableList& list = toInterpolableList(value.interpolableValue());
    double neutralComponent = toInterpolableNumber(list.get(PathNeutralIndex))->value();

    if (neutralComponent == 0) {
        underlyingValue.set(&value);
        return;
    }

    ASSERT(pathSegTypesMatch(
        toSVGPathNonInterpolableValue(underlyingValue->nonInterpolableValue())->pathSegTypes(),
        toSVGPathNonInterpolableValue(value.nonInterpolableValue())->pathSegTypes()));
    underlyingValue.mutableComponent().interpolableValue->scaleAndAdd(neutralComponent, value.interpolableValue());
    underlyingValue.mutableComponent().nonInterpolableValue = const_cast<NonInterpolableValue*>(value.nonInterpolableValue()); // Take ref.
}
void InvalidatableInterpolation::applyStack(const ActiveInterpolations& interpolations, InterpolationEnvironment& environment)
{
    ASSERT(!interpolations.isEmpty());
    size_t startingIndex = 0;

    // Compute the underlying value to composite onto.
    UnderlyingValue underlyingValue;
    const InvalidatableInterpolation& firstInterpolation = toInvalidatableInterpolation(*interpolations.at(startingIndex));
    if (firstInterpolation.dependsOnUnderlyingValue()) {
        underlyingValue.set(firstInterpolation.maybeConvertUnderlyingValue(environment));
    } else {
        const InterpolationValue* firstValue = firstInterpolation.ensureValidInterpolation(environment, UnderlyingValue());
        // Fast path for replace interpolations that are the only one to apply.
        if (interpolations.size() == 1) {
            if (firstValue) {
                firstInterpolation.setFlagIfInheritUsed(environment);
                firstValue->type().apply(firstValue->interpolableValue(), firstValue->nonInterpolableValue(), environment);
            }
            return;
        }
        underlyingValue.set(firstValue);
        startingIndex++;
    }

    // Composite interpolations onto the underlying value.
    bool shouldApply = false;
    for (size_t i = startingIndex; i < interpolations.size(); i++) {
        const InvalidatableInterpolation& currentInterpolation = toInvalidatableInterpolation(*interpolations.at(i));
        ASSERT(currentInterpolation.dependsOnUnderlyingValue());
        const InterpolationValue* currentValue = currentInterpolation.ensureValidInterpolation(environment, underlyingValue);
        if (!currentValue)
            continue;
        shouldApply = true;
        currentInterpolation.setFlagIfInheritUsed(environment);
        double underlyingFraction = currentInterpolation.underlyingFraction();
        if (underlyingFraction == 0 || !underlyingValue || underlyingValue->type() != currentValue->type())
            underlyingValue.set(currentValue);
        else
            currentValue->type().composite(underlyingValue, underlyingFraction, *currentValue);
    }

    if (shouldApply && underlyingValue)
        underlyingValue->type().apply(underlyingValue->interpolableValue(), underlyingValue->nonInterpolableValue(), environment);
}
void CSSLengthInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const
{
    InterpolationComponent& underlyingComponent = underlyingValue.mutableComponent();
    underlyingComponent.interpolableValue->scaleAndAdd(underlyingFraction, value.interpolableValue());
    underlyingComponent.nonInterpolableValue = CSSLengthNonInterpolableValue::merge(underlyingValue->nonInterpolableValue(), value.nonInterpolableValue());
}