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.
}
Exemplo n.º 2
0
void SVGNumberListInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const
{
    const InterpolableList& list = toInterpolableList(value.interpolableValue());

    if (toInterpolableList(underlyingValue->interpolableValue()).length() <= list.length())
        padWithZeroes(underlyingValue.mutableComponent().interpolableValue, list.length());

    InterpolableList& underlyingList = *toInterpolableList(underlyingValue.mutableComponent().interpolableValue.get());

    ASSERT(underlyingList.length() >= list.length());
    size_t i = 0;
    for (; i < list.length(); i++)
        underlyingList.getMutable(i)->scaleAndAdd(underlyingFraction, *list.get(i));
    for (; i < underlyingList.length(); i++)
        underlyingList.getMutable(i)->scale(underlyingFraction);
}
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);
}