blob: ffa3760c191c3152055609970958dc28031bae98 [file] [log] [blame]
// Copyright 2015 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/CSSShadowListInterpolationType.h"
#include "core/animation/ListInterpolationFunctions.h"
#include "core/animation/ShadowInterpolationFunctions.h"
#include "core/animation/ShadowListPropertyFunctions.h"
#include "core/css/CSSIdentifierValue.h"
#include "core/css/CSSValueList.h"
#include "core/css/resolver/StyleBuilder.h"
#include "core/css/resolver/StyleResolverState.h"
#include "core/style/ShadowList.h"
#include "wtf/PtrUtil.h"
#include <memory>
namespace blink {
InterpolationValue CSSShadowListInterpolationType::convertShadowList(
const ShadowList* shadowList,
double zoom) const {
if (!shadowList)
return createNeutralValue();
const ShadowDataVector& shadows = shadowList->shadows();
return ListInterpolationFunctions::createList(
shadows.size(), [&shadows, zoom](size_t index) {
return ShadowInterpolationFunctions::convertShadowData(shadows[index],
zoom);
});
}
InterpolationValue CSSShadowListInterpolationType::createNeutralValue() const {
return ListInterpolationFunctions::createEmptyList();
}
InterpolationValue CSSShadowListInterpolationType::maybeConvertNeutral(
const InterpolationValue&,
ConversionCheckers&) const {
return createNeutralValue();
}
InterpolationValue CSSShadowListInterpolationType::maybeConvertInitial(
const StyleResolverState&,
ConversionCheckers&) const {
return convertShadowList(
ShadowListPropertyFunctions::getInitialShadowList(cssProperty()), 1);
}
class ParentShadowListChecker : public InterpolationType::ConversionChecker {
public:
static std::unique_ptr<ParentShadowListChecker> create(
CSSPropertyID property,
PassRefPtr<ShadowList> shadowList) {
return wrapUnique(
new ParentShadowListChecker(property, std::move(shadowList)));
}
private:
ParentShadowListChecker(CSSPropertyID property,
PassRefPtr<ShadowList> shadowList)
: m_property(property), m_shadowList(shadowList) {}
bool isValid(const InterpolationEnvironment& environment,
const InterpolationValue& underlying) const final {
const ShadowList* parentShadowList =
ShadowListPropertyFunctions::getShadowList(
m_property, *environment.state().parentStyle());
if (!parentShadowList && !m_shadowList)
return true;
if (!parentShadowList || !m_shadowList)
return false;
return *parentShadowList == *m_shadowList;
}
const CSSPropertyID m_property;
RefPtr<ShadowList> m_shadowList;
};
InterpolationValue CSSShadowListInterpolationType::maybeConvertInherit(
const StyleResolverState& state,
ConversionCheckers& conversionCheckers) const {
if (!state.parentStyle())
return nullptr;
const ShadowList* parentShadowList =
ShadowListPropertyFunctions::getShadowList(cssProperty(),
*state.parentStyle());
conversionCheckers.append(ParentShadowListChecker::create(
cssProperty(), const_cast<ShadowList*>(parentShadowList))); // Take ref.
return convertShadowList(parentShadowList,
state.parentStyle()->effectiveZoom());
}
InterpolationValue CSSShadowListInterpolationType::maybeConvertValue(
const CSSValue& value,
const StyleResolverState&,
ConversionCheckers&) const {
if (value.isIdentifierValue() &&
toCSSIdentifierValue(value).getValueID() == CSSValueNone)
return createNeutralValue();
if (!value.isBaseValueList())
return nullptr;
const CSSValueList& valueList = toCSSValueList(value);
return ListInterpolationFunctions::createList(
valueList.length(), [&valueList](size_t index) {
return ShadowInterpolationFunctions::maybeConvertCSSValue(
valueList.item(index));
});
}
PairwiseInterpolationValue CSSShadowListInterpolationType::maybeMergeSingles(
InterpolationValue&& start,
InterpolationValue&& end) const {
return ListInterpolationFunctions::maybeMergeSingles(
std::move(start), std::move(end),
ShadowInterpolationFunctions::maybeMergeSingles);
}
InterpolationValue CSSShadowListInterpolationType::maybeConvertUnderlyingValue(
const InterpolationEnvironment& environment) const {
if (!environment.state().style())
return nullptr;
return convertShadowList(ShadowListPropertyFunctions::getShadowList(
cssProperty(), *environment.state().style()),
environment.state().style()->effectiveZoom());
}
void CSSShadowListInterpolationType::composite(
UnderlyingValueOwner& underlyingValueOwner,
double underlyingFraction,
const InterpolationValue& value,
double interpolationFraction) const {
ListInterpolationFunctions::composite(
underlyingValueOwner, underlyingFraction, *this, value,
ShadowInterpolationFunctions::nonInterpolableValuesAreCompatible,
ShadowInterpolationFunctions::composite);
}
static PassRefPtr<ShadowList> createShadowList(
const InterpolableValue& interpolableValue,
const NonInterpolableValue* nonInterpolableValue,
const StyleResolverState& state) {
const InterpolableList& interpolableList =
toInterpolableList(interpolableValue);
size_t length = interpolableList.length();
if (length == 0)
return nullptr;
const NonInterpolableList& nonInterpolableList =
toNonInterpolableList(*nonInterpolableValue);
ShadowDataVector shadows;
for (size_t i = 0; i < length; i++)
shadows.append(ShadowInterpolationFunctions::createShadowData(
*interpolableList.get(i), nonInterpolableList.get(i), state));
return ShadowList::adopt(shadows);
}
void CSSShadowListInterpolationType::apply(
const InterpolableValue& interpolableValue,
const NonInterpolableValue* nonInterpolableValue,
InterpolationEnvironment& environment) const {
ShadowListPropertyFunctions::setShadowList(
cssProperty(), *environment.state().style(),
createShadowList(interpolableValue, nonInterpolableValue,
environment.state()));
}
} // namespace blink