blob: aee4ecab48c9ca48ce1d938b1d9e933cd8ead3da [file]
/*
* Copyright (C) 2007-2023 Apple Inc. All rights reserved.
* Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved.
* Copyright (C) 2025 Sam Weinig. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#ifndef STYLE_INTERPOLATION_GENERATED_INCLUDE_TRAP
#error "Please do not include this file anywhere except from generated code."
#endif
#include "AnimationMalloc.h"
#include "StyleInterpolationFunctions.h"
#include "StyleInterpolationWrapperBase.h"
#include "StylePrimitiveKeyword+Logging.h"
#include "StylePrimitiveNumericTypes+Logging.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/text/TextStream.h>
namespace WebCore::Style::Interpolation {
// MARK: - Base Wrappers
template<typename T, typename GetterType = T>
class WrapperWithGetter : public WrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(WrapperWithGetter, Animation);
public:
WrapperWithGetter(CSSPropertyID property, GetterType (ComputedStyleProperties::*getter)() const)
: WrapperBase(property)
, m_getter(getter)
{
}
GetterType value(const RenderStyle& style) const
{
return (style.computedStyle().*m_getter)();
}
bool equals(const RenderStyle& a, const RenderStyle& b) const override
{
if (&a == &b)
return true;
return value(a) == value(b);
}
#if !LOG_DISABLED
void log(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
{
LOG_WITH_STREAM(Animations, stream << " blending " << property() << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
}
#endif
private:
GetterType (ComputedStyleProperties::*m_getter)() const;
};
template<typename T, typename GetterType = T, typename SetterType = T>
class Wrapper : public WrapperWithGetter<T, GetterType> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(Wrapper, Animation);
public:
Wrapper(CSSPropertyID property, GetterType (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(SetterType))
: WrapperWithGetter<T, GetterType>(property, getter)
, m_setter(setter)
{
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const override
{
(destination.computedStyle().*m_setter)(blendFunc(this->value(from), this->value(to), context));
}
protected:
void (ComputedStyleProperties::*m_setter)(SetterType);
};
// Deduction guide for getter/setters that return and take values.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
Wrapper(CSSPropertyID, T (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T)) -> Wrapper<T, T, T>;
// Deduction guide for getter/setters that return const references and take r-value references.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
Wrapper(CSSPropertyID, const T& (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T&&)) -> Wrapper<T, const T&, T&&>;
// MARK: - Typed Wrappers
template<typename T, typename GetterType = T, typename SetterType = T>
class StyleTypeWrapper : public WrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(StyleTypeWrapper, Animation);
public:
StyleTypeWrapper(CSSPropertyID property, GetterType (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(SetterType))
: WrapperBase(property)
, m_getter(getter)
, m_setter(setter)
{
}
bool equals(const RenderStyle& from, const RenderStyle& to) const override
{
if (&from == &to)
return true;
return Style::equalsForBlending(this->value(from), this->value(to), from, to);
}
bool canInterpolate(const RenderStyle& from, const RenderStyle& to, CompositeOperation operation) const override
{
return Style::canBlend(this->value(from), this->value(to), from, to, operation);
}
bool requiresInterpolationForAccumulativeIteration(const RenderStyle& from, const RenderStyle& to) const override
{
return Style::requiresInterpolationForAccumulativeIteration(this->value(from), this->value(to), from, to);
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const override
{
(destination.computedStyle().*m_setter)(Style::blend(this->value(from), this->value(to), from, to, context));
}
#if !LOG_DISABLED
void log(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const override
{
LOG_WITH_STREAM(Animations, stream << " blending " << property() << " from " << this->value(from) << " to " << this->value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << this->value(destination));
}
#endif
private:
GetterType value(const RenderStyle& style) const
{
return (style.computedStyle().*m_getter)();
}
GetterType (ComputedStyleProperties::*m_getter)() const;
void (ComputedStyleProperties::*m_setter)(SetterType);
};
// Deduction guide for getter/setters that return and take values.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
StyleTypeWrapper(CSSPropertyID, T (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T)) -> StyleTypeWrapper<T, T, T>;
// Deduction guide for getter/setters that return const references and take r-value references.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
StyleTypeWrapper(CSSPropertyID, const T& (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T&&)) -> StyleTypeWrapper<T, const T&, T&&>;
// Deduction guide for getter/setters that return values and take r-value references.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
StyleTypeWrapper(CSSPropertyID, T (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T&&)) -> StyleTypeWrapper<T, T, T&&>;
template<typename T> class VisitedAffectedStyleTypeWrapper final : public WrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(VisitedAffectedStyleTypeWrapper, Animation);
public:
VisitedAffectedStyleTypeWrapper(CSSPropertyID property, const T& (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(T&&), const T& (ComputedStyleProperties::*visitedGetter)() const, void (ComputedStyleProperties::*visitedSetter)(T&&))
: WrapperBase(property)
, m_wrapper(StyleTypeWrapper<T, const T&, T&&>(property, getter, setter))
, m_visitedWrapper(StyleTypeWrapper<T, const T&, T&&>(property, visitedGetter, visitedSetter))
{
}
bool equals(const RenderStyle& a, const RenderStyle& b) const override
{
return m_wrapper.equals(a, b) && m_visitedWrapper.equals(a, b);
}
bool canInterpolate(const RenderStyle& a, const RenderStyle& b, CompositeOperation operation) const override
{
const_cast<VisitedAffectedStyleTypeWrapper&>(*this).m_wrapperCanInterpolate = m_wrapper.canInterpolate(a, b, operation);
const_cast<VisitedAffectedStyleTypeWrapper&>(*this).m_visitedWrapperCanInterpolate = m_visitedWrapper.canInterpolate(a, b, operation);
return m_wrapperCanInterpolate || m_visitedWrapperCanInterpolate;
}
bool requiresInterpolationForAccumulativeIteration(const RenderStyle& a, const RenderStyle& b) const override
{
return m_wrapper.requiresInterpolationForAccumulativeIteration(a, b) && m_visitedWrapper.requiresInterpolationForAccumulativeIteration(a, b);
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const override
{
bool usesNonNormalizeDiscreteInterpolation = CSSProperty::animationUsesNonNormalizedDiscreteInterpolation(property());
auto wrapperContext = context;
wrapperContext.isDiscrete = !m_wrapperCanInterpolate;
if (!usesNonNormalizeDiscreteInterpolation)
wrapperContext.normalizeProgress();
m_wrapper.interpolate(destination, from, to, wrapperContext);
auto visitedWrapperContext = context;
visitedWrapperContext.isDiscrete = !m_visitedWrapperCanInterpolate;
if (!usesNonNormalizeDiscreteInterpolation)
visitedWrapperContext.normalizeProgress();
m_visitedWrapper.interpolate(destination, from, to, visitedWrapperContext);
}
#if !LOG_DISABLED
void log(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const override
{
m_wrapper.log(from, to, destination, progress);
m_visitedWrapper.log(from, to, destination, progress);
}
#endif
StyleTypeWrapper<T, const T&, T&&> m_wrapper;
StyleTypeWrapper<T, const T&, T&&> m_visitedWrapper;
bool m_wrapperCanInterpolate { false };
bool m_visitedWrapperCanInterpolate { false };
};
// MARK: - Discrete Wrappers
template<typename T, typename GetterType = T, typename SetterType = T> class DiscreteWrapper : public WrapperWithGetter<T, GetterType> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(DiscreteWrapper, Animation);
public:
DiscreteWrapper(CSSPropertyID property, GetterType (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(SetterType))
: WrapperWithGetter<T, GetterType>(property, getter)
, m_setter(setter)
{
}
bool canInterpolate(const RenderStyle&, const RenderStyle&, CompositeOperation) const final
{
return false;
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const override
{
ASSERT(!context.progress || context.progress == 1.0);
(destination.computedStyle().*this->m_setter)(T { this->value(context.progress ? to : from) });
}
private:
void (ComputedStyleProperties::*m_setter)(SetterType);
};
// Deduction guide for getter/setters that return and take values.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
DiscreteWrapper(CSSPropertyID, T (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T)) -> DiscreteWrapper<T, T, T>;
// Deduction guide for getter/setters that return const references and take r-value references.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
DiscreteWrapper(CSSPropertyID, const T& (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T&&)) -> DiscreteWrapper<T, const T&, T&&>;
// Deduction guide for getter/setters that return values and take r-value references.
template<typename T, typename GetterRenderStyle, typename SetterRenderStyle>
DiscreteWrapper(CSSPropertyID, T (GetterRenderStyle::*getter)() const, void (SetterRenderStyle::*setter)(T&&)) -> DiscreteWrapper<T, T, T&&>;
template<typename T>
class NonNormalizedDiscreteWrapper final : public Wrapper<T> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(NonNormalizedDiscreteWrapper, Animation);
public:
NonNormalizedDiscreteWrapper(CSSPropertyID property, T (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(T))
: Wrapper<T>(property, getter, setter)
{
}
bool canInterpolate(const RenderStyle&, const RenderStyle&, CompositeOperation) const final
{
return false;
}
};
// MARK: - Font Property Wrappers
class FontSizeWrapper final : public Wrapper<float> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(FontSizeWrapper, Animation);
public:
FontSizeWrapper()
: Wrapper<float>(CSSPropertyID::CSSPropertyFontSize, &ComputedStyleProperties::computedFontSize, &ComputedStyleProperties::setFontSize)
{
}
bool equals(const RenderStyle& a, const RenderStyle& b) const final
{
return a.specifiedFontSize() == b.specifiedFontSize();
}
};
// MARK: - Color Property Wrappers
class ColorWrapper final : public WrapperWithGetter<const WebCore::Color&> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ColorWrapper, Animation);
public:
ColorWrapper(CSSPropertyID property, const WebCore::Color& (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(WebCore::Color&&))
: WrapperWithGetter<const WebCore::Color&>(property, getter)
, m_setter(setter)
{
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const override
{
(destination.computedStyle().*m_setter)(blendFunc(value(from), value(to), context));
}
private:
void (ComputedStyleProperties::*m_setter)(WebCore::Color&&);
};
class VisitedAffectedColorWrapper final : public WrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(VisitedAffectedColorWrapper, Animation);
public:
VisitedAffectedColorWrapper(CSSPropertyID property, const WebCore::Color& (ComputedStyleProperties::*getter)() const, void (ComputedStyleProperties::*setter)(WebCore::Color&&), const WebCore::Color& (ComputedStyleProperties::*visitedGetter)() const, void (ComputedStyleProperties::*visitedSetter)(WebCore::Color&&))
: WrapperBase(property)
, m_wrapper(ColorWrapper(property, getter, setter))
, m_visitedWrapper(ColorWrapper(property, visitedGetter, visitedSetter))
{
}
bool equals(const RenderStyle& a, const RenderStyle& b) const final
{
return m_wrapper.equals(a, b) && m_visitedWrapper.equals(a, b);
}
bool requiresInterpolationForAccumulativeIteration(const RenderStyle&, const RenderStyle&) const final
{
return true;
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const final
{
m_wrapper.interpolate(destination, from, to, context);
m_visitedWrapper.interpolate(destination, from, to, context);
}
#if !LOG_DISABLED
void log(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
{
m_wrapper.log(from, to, destination, progress);
m_visitedWrapper.log(from, to, destination, progress);
}
#endif
ColorWrapper m_wrapper;
ColorWrapper m_visitedWrapper;
};
// MARK: - Other Custom Wrappers
class VisibilityWrapper final : public Wrapper<Visibility> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(VisibilityWrapper, Animation);
public:
VisibilityWrapper()
: Wrapper(CSSPropertyVisibility, &ComputedStyleProperties::visibility, &ComputedStyleProperties::setVisibility)
{
}
bool canInterpolate(const RenderStyle& from, const RenderStyle& to, CompositeOperation) const final
{
// https://drafts.csswg.org/web-animations-1/#animating-visibility
// If neither value is visible, then discrete animation is used.
return value(from) == Visibility::Visible || value(to) == Visibility::Visible;
}
};
// MARK: - CoordinatedValueList Wrappers
// Wrapper base class for an animatable property in a CoordinatedValueList
template<typename CoordinatedValueListValueType>
class CoordinatedValueListPropertyWrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(CoordinatedValueListPropertyWrapperBase, Animation);
public:
CoordinatedValueListPropertyWrapperBase(CSSPropertyID property)
: m_property(property)
{
}
virtual ~CoordinatedValueListPropertyWrapperBase() = default;
CSSPropertyID property() const { return m_property; }
virtual bool equals(const CoordinatedValueListValueType&, const CoordinatedValueListValueType&, const RenderStyle&, const RenderStyle&) const = 0;
virtual void interpolate(CoordinatedValueListValueType&, const CoordinatedValueListValueType&, const CoordinatedValueListValueType&, const RenderStyle&, const RenderStyle&, const Context&) const = 0;
virtual bool canInterpolate(const CoordinatedValueListValueType&, const CoordinatedValueListValueType&, const RenderStyle&, const RenderStyle&, CompositeOperation) const { return true; }
#if !LOG_DISABLED
virtual void log(const CoordinatedValueListValueType& destination, const CoordinatedValueListValueType&, const CoordinatedValueListValueType&, const RenderStyle&, const RenderStyle&, double) const = 0;
#endif
private:
CSSPropertyID m_property;
};
template<typename StyleType, typename CoordinatedValueListValueType>
class CoordinatedValueListPropertyStyleTypeWrapper final : public CoordinatedValueListPropertyWrapperBase<CoordinatedValueListValueType> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(CoordinatedValueListPropertyStyleTypeWrapper, Animation);
public:
CoordinatedValueListPropertyStyleTypeWrapper(CSSPropertyID property, const StyleType& (CoordinatedValueListValueType::*getter)() const, void (CoordinatedValueListValueType::*setter)(StyleType&&))
: CoordinatedValueListPropertyWrapperBase<CoordinatedValueListValueType>(property)
, m_getter(getter)
, m_setter(setter)
{
}
bool equals(const CoordinatedValueListValueType& from, const CoordinatedValueListValueType& to, const RenderStyle& fromStyle, const RenderStyle& toStyle) const override
{
if (&from == &to)
return true;
return Style::equalsForBlending(value(from), value(to), fromStyle, toStyle);
}
bool canInterpolate(const CoordinatedValueListValueType& from, const CoordinatedValueListValueType& to, const RenderStyle& fromStyle, const RenderStyle& toStyle, CompositeOperation operation) const override final
{
return Style::canBlend(value(from), value(to), fromStyle, toStyle, operation);
}
void interpolate(CoordinatedValueListValueType& destination, const CoordinatedValueListValueType& from, const CoordinatedValueListValueType& to, const RenderStyle& fromStyle, const RenderStyle& toStyle, const Context& context) const override final
{
(destination.*m_setter)(Style::blend(value(from), value(to), fromStyle, toStyle, context));
}
#if !LOG_DISABLED
void log(const CoordinatedValueListValueType& destination, const CoordinatedValueListValueType& from, const CoordinatedValueListValueType& to, const RenderStyle&, const RenderStyle&, double progress) const override final
{
LOG_WITH_STREAM(Animations, stream << " blending " << this->property() << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
}
#endif
private:
const StyleType& value(const CoordinatedValueListValueType& value) const
{
return (value.*m_getter)();
}
const StyleType& (CoordinatedValueListValueType::*m_getter)() const;
void (CoordinatedValueListValueType::*m_setter)(StyleType&&);
};
template<typename T, typename CoordinatedValueListValueType, typename GetterType = T, typename SetterType = T>
class DiscreteCoordinatedValueListPropertyWrapper final : public CoordinatedValueListPropertyWrapperBase<CoordinatedValueListValueType> {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(DiscreteCoordinatedValueListPropertyWrapper, Animation);
public:
DiscreteCoordinatedValueListPropertyWrapper(CSSPropertyID property, GetterType (CoordinatedValueListValueType::*getter)() const, void (CoordinatedValueListValueType::*setter)(SetterType))
: CoordinatedValueListPropertyWrapperBase<CoordinatedValueListValueType>(property)
, m_getter(getter)
, m_setter(setter)
{
}
bool equals(const CoordinatedValueListValueType& a, const CoordinatedValueListValueType& b, const RenderStyle&, const RenderStyle&) const final
{
return value(a) == value(b);
}
bool canInterpolate(const CoordinatedValueListValueType&, const CoordinatedValueListValueType&, const RenderStyle&, const RenderStyle&, CompositeOperation) const final
{
return false;
}
void interpolate(CoordinatedValueListValueType& destination, const CoordinatedValueListValueType& from, const CoordinatedValueListValueType& to, const RenderStyle&, const RenderStyle&, const Context& context) const final
{
ASSERT(!context.progress || context.progress == 1.0);
(destination.*m_setter)(T { context.progress ? value(to) : value(from) });
}
#if !LOG_DISABLED
void log(const CoordinatedValueListValueType& destination, const CoordinatedValueListValueType& from, const CoordinatedValueListValueType& to, const RenderStyle&, const RenderStyle&, double progress) const final
{
LOG_WITH_STREAM(Animations, stream << " blending " << this->property() << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
}
#endif
private:
GetterType value(const CoordinatedValueListValueType& list) const
{
return (list.*m_getter)();
}
GetterType (CoordinatedValueListValueType::*m_getter)() const;
void (CoordinatedValueListValueType::*m_setter)(SetterType);
};
// Deduction guide for getter/setters that return and take values.
template<typename T, typename CoordinatedValueListValueType>
DiscreteCoordinatedValueListPropertyWrapper(CSSPropertyID, T (CoordinatedValueListValueType::*getter)() const, void (CoordinatedValueListValueType::*setter)(T)) -> DiscreteCoordinatedValueListPropertyWrapper<T, CoordinatedValueListValueType, T, T>;
// Deduction guide for getter/setters that return const references and take r-value references.
template<typename T, typename CoordinatedValueListValueType>
DiscreteCoordinatedValueListPropertyWrapper(CSSPropertyID, const T& (CoordinatedValueListValueType::*getter)() const, void (CoordinatedValueListValueType::*setter)(T&&)) -> DiscreteCoordinatedValueListPropertyWrapper<T, CoordinatedValueListValueType, const T&, T&&>;
// Deduction guide for getter/setters that return values and take r-value references.
template<typename T, typename CoordinatedValueListValueType>
DiscreteCoordinatedValueListPropertyWrapper(CSSPropertyID, T (CoordinatedValueListValueType::*getter)() const, void (CoordinatedValueListValueType::*setter)(T&&)) -> DiscreteCoordinatedValueListPropertyWrapper<T, CoordinatedValueListValueType, T, T&&>;
template<typename T, typename RepeatedValueWrapper>
class CoordinatedValueListPropertyWrapper final : public WrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(CoordinatedValueListPropertyWrapper, Animation);
public:
using List = T;
using CoordinatedValueListValueType = typename List::value_type;
using ListGetter = const List& (ComputedStyleBase::*)() const;
using ListAccessor = List& (ComputedStyleBase::*)();
using ListSetter = void (ComputedStyleBase::*)(List&&);
CoordinatedValueListPropertyWrapper(CSSPropertyID property, ListGetter getter, ListAccessor accessor, ListSetter setter, RepeatedValueWrapper repeatedValueWrapper)
: WrapperBase(property)
, m_listGetter(getter)
, m_listAccessor(accessor)
, m_listSetter(setter)
, m_repeatedValueWrapper(repeatedValueWrapper)
{
}
bool equals(const RenderStyle& from, const RenderStyle& to) const final
{
if (&from == &to)
return true;
auto& fromList = (from.computedStyle().*m_listGetter)();
auto& toList = (to.computedStyle().*m_listGetter)();
auto numberOfFromValues = fromList.computedLength();
auto numberOfToValues = toList.computedLength();
auto numberOfValues = std::min(numberOfFromValues, numberOfToValues);
for (size_t i = 0; i < numberOfValues; ++i) {
auto& fromValue = fromList[i];
auto& toValue = toList[i];
if (!m_repeatedValueWrapper.equals(fromValue, toValue, from, to))
return false;
}
return true;
}
bool canInterpolate(const RenderStyle& from, const RenderStyle& to, CompositeOperation operation) const final
{
auto& fromList = (from.computedStyle().*m_listGetter)();
auto& toList = (to.computedStyle().*m_listGetter)();
auto numberOfFromValues = fromList.computedLength();
auto numberOfToValues = toList.computedLength();
auto numberOfValues = std::min(numberOfFromValues, numberOfToValues);
for (size_t i = 0; i < numberOfValues; ++i) {
auto& fromValue = fromList[i];
auto& toValue = toList[i];
// First check if the owner values allow interpolation.
if (!Style::canBlend(fromValue, toValue, from, to, operation))
return false;
// Then check if the individual property values allow interpolation.
if (!m_repeatedValueWrapper.canInterpolate(fromValue, toValue, from, to, operation))
return false;
}
return true;
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const final
{
auto* fromList = &(from.computedStyle().*m_listGetter)();
auto* toList = &(to.computedStyle().*m_listGetter)();
auto& destinationList = (destination.computedStyle().*m_listAccessor)();
if (context.isDiscrete) {
ASSERT(!context.progress || context.progress == 1.0);
auto* list = context.progress ? toList : fromList;
fromList = list;
toList = list;
}
auto numberOfFromValues = fromList->computedLength();
auto numberOfToValues = toList->computedLength();
auto numberOfDestinationValues = destinationList.computedLength();
auto numberOfValues = std::min(numberOfFromValues, numberOfToValues);
for (size_t i = 0; i < numberOfValues; ++i) {
if (i >= numberOfDestinationValues)
destinationList.append(typename List::value_type { });
m_repeatedValueWrapper.interpolate(destinationList[i], (*fromList)[i], (*toList)[i], from, to, context);
}
destinationList.prepareForUse();
}
#if !LOG_DISABLED
void log(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
{
auto& fromList = (from.computedStyle().*m_listGetter)();
auto& toList = (to.computedStyle().*m_listGetter)();
auto& destinationList = (destination.computedStyle().*m_listGetter)();
auto numberOfFromValues = fromList.computedLength();
auto numberOfToValues = toList.computedLength();
auto numberOfDestinationValues = destinationList.computedLength();
auto numberOfValues = std::min({numberOfFromValues, numberOfToValues, numberOfDestinationValues});
for (size_t i = 0; i < numberOfValues; ++i)
m_repeatedValueWrapper.log(destinationList[i], fromList[i], toList[i], from, to, progress);
}
#endif
private:
ListGetter m_listGetter;
ListAccessor m_listAccessor;
ListSetter m_listSetter;
RepeatedValueWrapper m_repeatedValueWrapper;
};
// MARK: - Shorthand Wrapper
class ShorthandWrapper final : public WrapperBase {
WTF_DEPRECATED_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ShorthandWrapper, Animation);
public:
ShorthandWrapper(CSSPropertyID property, Vector<WrapperBase*> longhandWrappers)
: WrapperBase(property)
, m_longhandWrappers(WTF::move(longhandWrappers))
{
}
bool equals(const RenderStyle& a, const RenderStyle& b) const final
{
if (&a == &b)
return true;
for (auto& wrapper : m_longhandWrappers) {
if (!wrapper->equals(a, b))
return false;
}
return true;
}
void interpolate(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const Context& context) const final
{
for (auto& wrapper : m_longhandWrappers)
wrapper->interpolate(destination, from, to, context);
}
#if !LOG_DISABLED
void log(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
{
for (auto& wrapper : m_longhandWrappers)
wrapper->log(from, to, destination, progress);
}
#endif
private:
Vector<WrapperBase*> m_longhandWrappers;
};
} // namespace WebCore::Style::Interpolation