| Index: third_party/WebKit/Source/core/animation/StackableInterpolation.cpp
 | 
| diff --git a/third_party/WebKit/Source/core/animation/StackableInterpolation.cpp b/third_party/WebKit/Source/core/animation/StackableInterpolation.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..1188be773e4d0e74f7fc3f6d7af4ad822d3b698f
 | 
| --- /dev/null
 | 
| +++ b/third_party/WebKit/Source/core/animation/StackableInterpolation.cpp
 | 
| @@ -0,0 +1,58 @@
 | 
| +// Copyright 2016 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +#include "core/animation/StackableInterpolation.h"
 | 
| +
 | 
| +#include "core/animation/InterpolationType.h"
 | 
| +#include "core/animation/TypedInterpolationValue.h"
 | 
| +#include "core/animation/UnderlyingValueOwner.h"
 | 
| +
 | 
| +namespace blink {
 | 
| +
 | 
| +void StackableInterpolation::applyStack(const ActiveInterpolations& interpolations, InterpolationEnvironment& environment)
 | 
| +{
 | 
| +    DCHECK(!interpolations.isEmpty());
 | 
| +    size_t startingIndex = 0;
 | 
| +
 | 
| +    // Compute the underlying value to composite onto.
 | 
| +    UnderlyingValueOwner underlyingValueOwner;
 | 
| +    const StackableInterpolation& firstInterpolation = toStackableInterpolation(*interpolations.at(startingIndex));
 | 
| +    if (firstInterpolation.dependsOnUnderlyingValue()) {
 | 
| +        underlyingValueOwner.set(firstInterpolation.maybeConvertUnderlyingValue(environment));
 | 
| +    } else {
 | 
| +        const TypedInterpolationValue* firstValue = firstInterpolation.ensureValidInterpolation(environment, underlyingValueOwner);
 | 
| +        // 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->getNonInterpolableValue(), environment);
 | 
| +            }
 | 
| +            return;
 | 
| +        }
 | 
| +        underlyingValueOwner.set(firstValue);
 | 
| +        startingIndex++;
 | 
| +    }
 | 
| +
 | 
| +    // Composite interpolations onto the underlying value.
 | 
| +    bool shouldApply = false;
 | 
| +    for (size_t i = startingIndex; i < interpolations.size(); i++) {
 | 
| +        const StackableInterpolation& currentInterpolation = toStackableInterpolation(*interpolations.at(i));
 | 
| +        DCHECK(currentInterpolation.dependsOnUnderlyingValue());
 | 
| +        const TypedInterpolationValue* currentValue = currentInterpolation.ensureValidInterpolation(environment, underlyingValueOwner);
 | 
| +        if (!currentValue)
 | 
| +            continue;
 | 
| +        shouldApply = true;
 | 
| +        currentInterpolation.setFlagIfInheritUsed(environment);
 | 
| +        double underlyingFraction = currentInterpolation.underlyingFraction();
 | 
| +        if (underlyingFraction == 0 || !underlyingValueOwner || underlyingValueOwner.type() != currentValue->type())
 | 
| +            underlyingValueOwner.set(currentValue);
 | 
| +        else
 | 
| +            currentValue->type().composite(underlyingValueOwner, underlyingFraction, currentValue->value(), currentInterpolation.m_currentFraction);
 | 
| +    }
 | 
| +
 | 
| +    if (shouldApply && underlyingValueOwner)
 | 
| +        underlyingValueOwner.type().apply(*underlyingValueOwner.value().interpolableValue, underlyingValueOwner.value().nonInterpolableValue.get(), environment);
 | 
| +}
 | 
| +
 | 
| +} // namespace blink
 | 
| 
 |