blob: aa63b354e183725b24e1fc441b9c94ceda0fc15e [file] [log] [blame]
// 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/CSSTranslateInterpolationType.h"
#include "core/animation/LengthInterpolationFunctions.h"
#include "core/css/CSSValueList.h"
#include "core/css/resolver/StyleResolverState.h"
#include "platform/transforms/TranslateTransformOperation.h"
#include "wtf/PtrUtil.h"
#include <memory>
namespace blink {
namespace {
class InheritedTranslateChecker : public InterpolationType::ConversionChecker {
public:
~InheritedTranslateChecker() {}
static std::unique_ptr<InheritedTranslateChecker> create(
PassRefPtr<TranslateTransformOperation> inheritedTranslate) {
return WTF::wrapUnique(
new InheritedTranslateChecker(std::move(inheritedTranslate)));
}
bool isValid(const InterpolationEnvironment& environment,
const InterpolationValue& underlying) const final {
const TransformOperation* inheritedTranslate =
environment.state().parentStyle()->translate();
if (m_inheritedTranslate == inheritedTranslate)
return true;
if (!m_inheritedTranslate || !inheritedTranslate)
return false;
return *m_inheritedTranslate == *inheritedTranslate;
}
private:
InheritedTranslateChecker(
PassRefPtr<TranslateTransformOperation> inheritedTranslate)
: m_inheritedTranslate(inheritedTranslate) {}
RefPtr<TransformOperation> m_inheritedTranslate;
};
enum TranslateComponentIndex : unsigned {
TranslateX,
TranslateY,
TranslateZ,
TranslateComponentIndexCount,
};
InterpolationValue createNeutralValue() {
std::unique_ptr<InterpolableList> result =
InterpolableList::create(TranslateComponentIndexCount);
result->set(TranslateX,
LengthInterpolationFunctions::createNeutralInterpolableValue());
result->set(TranslateY,
LengthInterpolationFunctions::createNeutralInterpolableValue());
result->set(TranslateZ,
LengthInterpolationFunctions::createNeutralInterpolableValue());
return InterpolationValue(std::move(result));
}
InterpolationValue convertTranslateOperation(
const TranslateTransformOperation* translate,
double zoom) {
if (!translate)
return createNeutralValue();
std::unique_ptr<InterpolableList> result =
InterpolableList::create(TranslateComponentIndexCount);
result->set(TranslateX, LengthInterpolationFunctions::maybeConvertLength(
translate->x(), zoom)
.interpolableValue);
result->set(TranslateY, LengthInterpolationFunctions::maybeConvertLength(
translate->y(), zoom)
.interpolableValue);
result->set(TranslateZ, LengthInterpolationFunctions::maybeConvertLength(
Length(translate->z(), Fixed), zoom)
.interpolableValue);
return InterpolationValue(std::move(result));
}
} // namespace
InterpolationValue CSSTranslateInterpolationType::maybeConvertNeutral(
const InterpolationValue& underlying,
ConversionCheckers&) const {
return createNeutralValue();
}
InterpolationValue CSSTranslateInterpolationType::maybeConvertInitial(
const StyleResolverState&,
ConversionCheckers&) const {
return createNeutralValue();
}
InterpolationValue CSSTranslateInterpolationType::maybeConvertInherit(
const StyleResolverState& state,
ConversionCheckers& conversionCheckers) const {
TranslateTransformOperation* inheritedTranslate =
state.parentStyle()->translate();
conversionCheckers.push_back(
InheritedTranslateChecker::create(inheritedTranslate));
return convertTranslateOperation(inheritedTranslate,
state.parentStyle()->effectiveZoom());
}
InterpolationValue CSSTranslateInterpolationType::maybeConvertValue(
const CSSValue& value,
const StyleResolverState&,
ConversionCheckers&) const {
if (!value.isBaseValueList())
return nullptr;
const CSSValueList& list = toCSSValueList(value);
if (list.length() < 1 || list.length() > 3)
return nullptr;
std::unique_ptr<InterpolableList> result =
InterpolableList::create(TranslateComponentIndexCount);
for (size_t i = 0; i < TranslateComponentIndexCount; i++) {
InterpolationValue component = nullptr;
if (i < list.length()) {
component =
LengthInterpolationFunctions::maybeConvertCSSValue(list.item(i));
if (!component)
return nullptr;
} else {
component = InterpolationValue(
LengthInterpolationFunctions::createNeutralInterpolableValue());
}
result->set(i, std::move(component.interpolableValue));
}
return InterpolationValue(std::move(result));
}
InterpolationValue
CSSTranslateInterpolationType::maybeConvertStandardPropertyUnderlyingValue(
const StyleResolverState& state) const {
return convertTranslateOperation(state.style()->translate(),
state.style()->effectiveZoom());
}
void CSSTranslateInterpolationType::applyStandardPropertyValue(
const InterpolableValue& interpolableValue,
const NonInterpolableValue*,
StyleResolverState& state) const {
const InterpolableList& list = toInterpolableList(interpolableValue);
const CSSToLengthConversionData& conversionData =
state.cssToLengthConversionData();
Length x = LengthInterpolationFunctions::createLength(
*list.get(TranslateX), nullptr, conversionData, ValueRangeAll);
Length y = LengthInterpolationFunctions::createLength(
*list.get(TranslateY), nullptr, conversionData, ValueRangeAll);
float z = LengthInterpolationFunctions::createLength(
*list.get(TranslateZ), nullptr, conversionData, ValueRangeAll)
.pixels();
RefPtr<TranslateTransformOperation> result = nullptr;
if (!x.isZero() || !y.isZero() || z != 0)
result = TranslateTransformOperation::create(
x, y, z, TransformOperation::Translate3D);
state.style()->setTranslate(result.release());
}
} // namespace blink