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.
}
PassOwnPtr<InterpolationValue> CSSImageListInterpolationType::maybeConvertNeutral(const UnderlyingValue& underlyingValue, ConversionCheckers& conversionCheckers) const
{
    if (!underlyingValue) {
        conversionCheckers.append(UnderlyingImageListChecker::create(*this, nullptr));
        return nullptr;
    }
    conversionCheckers.append(UnderlyingImageListChecker::create(*this, underlyingValue->clone()));
    return underlyingValue->clone();
}
Exemple #3
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();
}
Exemple #4
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 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.
}
PassOwnPtr<InterpolationValue> InvalidatableInterpolation::convertSingleKeyframe(const PropertySpecificKeyframe& keyframe, const InterpolationEnvironment& environment, const UnderlyingValue& underlyingValue) const
{
    if (keyframe.isNeutral() && !underlyingValue)
        return nullptr;
    for (const auto& interpolationType : m_interpolationTypes) {
        if (keyframe.isNeutral() && underlyingValue->type() != *interpolationType)
            continue;
        OwnPtr<InterpolationValue> result = interpolationType->maybeConvertSingle(keyframe, environment, underlyingValue, m_conversionCheckers);
        if (result) {
            ASSERT(result->type() == *interpolationType);
            return result.release();
        }
    }
    ASSERT(keyframe.isNeutral());
    return nullptr;
}
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);
}
bool InvalidatableInterpolation::isCacheValid(const InterpolationEnvironment& environment, const UnderlyingValue& underlyingValue) const
{
    if (!m_isCached)
        return false;
    if (isNeutralKeyframeActive()) {
        if (m_cachedPairConversion && m_cachedPairConversion->isFlip())
            return false;
        // Pairwise interpolation can never happen between different InterpolationTypes, neutral values always represent the underlying value.
        if (!underlyingValue || !m_cachedValue || m_cachedValue->type() != underlyingValue->type())
            return false;
    }
    for (const auto& checker : m_conversionCheckers) {
        if (!checker->isValid(environment, underlyingValue))
            return false;
    }
    return true;
}
PassOwnPtr<PairwisePrimitiveInterpolation> InvalidatableInterpolation::maybeConvertPairwise(const InterpolationEnvironment& environment, const UnderlyingValue& underlyingValue) const
{
    ASSERT(m_currentFraction != 0 && m_currentFraction != 1);
    for (const auto& interpolationType : m_interpolationTypes) {
        if ((m_startKeyframe->isNeutral() || m_endKeyframe->isNeutral()) && (!underlyingValue || underlyingValue->type() != *interpolationType))
            continue;
        OwnPtr<PairwisePrimitiveInterpolation> pairwiseConversion = interpolationType->maybeConvertPairwise(*m_startKeyframe, *m_endKeyframe, environment, underlyingValue, m_conversionCheckers);
        if (pairwiseConversion) {
            ASSERT(pairwiseConversion->type() == *interpolationType);
            return pairwiseConversion.release();
        }
    }
    return nullptr;
}
Exemple #10
0
void SVGTransformListInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const
{
    // TODO(suzyh): Implement addition
    underlyingValue.set(&value);
}
 bool isValid(const InterpolationEnvironment&, const UnderlyingValue& underlyingValue) const final
 {
     if (!underlyingValue && !m_underlyingValue)
         return true;
     if (!underlyingValue || !m_underlyingValue)
         return false;
     return ListInterpolationFunctions::equalValues(m_underlyingValue->component(), underlyingValue->component(), CSSImageInterpolationType::equalNonInterpolableValues);
 }
void CSSImageListInterpolationType::composite(UnderlyingValue& underlyingValue, double underlyingFraction, const InterpolationValue& value) const
{
    underlyingValue.set(&value);
}
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());
}