⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 276141 in webkit


Ignore:
Timestamp:
Apr 16, 2021, 9:55:43 AM (5 years ago)
Author:
graouts@webkit.org
Message:

Refactor parameters to blending functions
https://bugs.webkit.org/show_bug.cgi?id=224433

Reviewed by Dean Jackson.

Reduce the number of parameters passed to the blending functions such that we package
the client and progress together and track whether the animation is discrete instead
of computing it several times. This information is now passed as a BlendingContext
parameter, and a CSSPropertyBlendingContext private to CSSPropertyAnimation.

When we support composite operations, we'll just need to add a new member to that
struct instead of modifying all the method signatures.

Since we are modifying the method signatures, we also change the RenderStyle pointers
to references since we would never pass in a null value.

  • animation/CSSPropertyAnimation.cpp:

(WebCore::CSSPropertyBlendingContext::CSSPropertyBlendingContext):
(WebCore::blendFunc):
(WebCore::blendFilterOperations):
(WebCore::blendFilter):
(WebCore::crossfadeBlend):
(WebCore::AnimationPropertyWrapperBase::canInterpolate const):
(WebCore::PropertyWrapperGetter::value const):
(WebCore::canInterpolateCaretColor):
(WebCore::CSSPropertyAnimation::blendProperties):
(WebCore::CSSPropertyAnimation::propertiesEqual):
(WebCore::CSSPropertyAnimation::canPropertyBeInterpolated):

  • animation/CSSPropertyAnimation.h:
  • animation/KeyframeEffect.cpp:

(WebCore::KeyframeEffect::setAnimatedPropertiesInStyle):

  • css/CSSCrossfadeValue.cpp:

(WebCore::blendFunc):
(WebCore::CSSCrossfadeValue::blend const):

  • css/CSSCrossfadeValue.h:
  • css/CSSGradientValue.cpp:

(WebCore::RadialGradientAdapter::normalizeStopsAndEndpointsOutsideRange):
(WebCore::ConicGradientAdapter::normalizeStopsAndEndpointsOutsideRange):
(WebCore::CSSGradientValue::computeStops):

  • platform/Length.cpp:

(WebCore::blendMixedTypes):
(WebCore::blend):

  • platform/Length.h:
  • platform/LengthPoint.h:

(WebCore::blend):

  • platform/LengthSize.h:

(WebCore::blend):

  • platform/animation/AnimationUtilities.h:

(WebCore::blend):

  • platform/graphics/ColorBlending.cpp:

(WebCore::blend):
(WebCore::blendWithoutPremultiply):

  • platform/graphics/ColorBlending.h:
  • platform/graphics/ca/cocoa/PlatformCAFiltersCocoa.mm:

(WebCore::PlatformCAFilters::colorMatrixValueForFilter):

  • platform/graphics/filters/FilterOperation.cpp:

(WebCore::BasicColorMatrixFilterOperation::blend):
(WebCore::BasicComponentTransferFilterOperation::blend):
(WebCore::InvertLightnessFilterOperation::blend):
(WebCore::BlurFilterOperation::blend):
(WebCore::DropShadowFilterOperation::blend):

  • platform/graphics/filters/FilterOperation.h:

(WebCore::FilterOperation::blend):

  • platform/graphics/transforms/IdentityTransformOperation.h:
  • platform/graphics/transforms/Matrix3DTransformOperation.cpp:

(WebCore::createOperation):
(WebCore::Matrix3DTransformOperation::blend):

  • platform/graphics/transforms/Matrix3DTransformOperation.h:
  • platform/graphics/transforms/MatrixTransformOperation.cpp:

(WebCore::MatrixTransformOperation::blend):

  • platform/graphics/transforms/MatrixTransformOperation.h:
  • platform/graphics/transforms/PerspectiveTransformOperation.cpp:

(WebCore::PerspectiveTransformOperation::blend):

  • platform/graphics/transforms/PerspectiveTransformOperation.h:
  • platform/graphics/transforms/RotateTransformOperation.cpp:

(WebCore::RotateTransformOperation::blend):

  • platform/graphics/transforms/RotateTransformOperation.h:
  • platform/graphics/transforms/ScaleTransformOperation.cpp:

(WebCore::ScaleTransformOperation::blend):

  • platform/graphics/transforms/ScaleTransformOperation.h:
  • platform/graphics/transforms/SkewTransformOperation.cpp:

(WebCore::SkewTransformOperation::blend):

  • platform/graphics/transforms/SkewTransformOperation.h:
  • platform/graphics/transforms/TransformOperation.h:
  • platform/graphics/transforms/TransformOperations.cpp:

(WebCore::TransformOperations::blendByMatchingOperations const):
(WebCore::TransformOperations::blendByUsingMatrixInterpolation const):
(WebCore::TransformOperations::blend const):

  • platform/graphics/transforms/TransformOperations.h:
  • platform/graphics/transforms/TranslateTransformOperation.cpp:

(WebCore::TranslateTransformOperation::blend):

  • platform/graphics/transforms/TranslateTransformOperation.h:
  • rendering/style/BasicShapes.cpp:

(WebCore::BasicShapeCircle::blend const):
(WebCore::BasicShapeEllipse::blend const):
(WebCore::BasicShapePolygon::blend const):
(WebCore::BasicShapePath::blend const):
(WebCore::BasicShapeInset::blend const):

  • rendering/style/BasicShapes.h:

(WebCore::BasicShapeCenterCoordinate::blend const):
(WebCore::BasicShapeRadius::blend const):

  • style/Styleable.cpp:

(WebCore::propertyInStyleMatchesValueForTransitionInMap):
(WebCore::updateCSSTransitionsForStyleableAndProperty):

  • svg/SVGLengthValue.cpp:

(WebCore::SVGLengthValue::blend):

  • svg/SVGPathBlender.cpp:

(WebCore::blendFloatPoint):
(WebCore::SVGPathBlender::blendAnimatedDimensonalFloat):
(WebCore::SVGPathBlender::blendArcToSegment):

Location:
trunk/Source/WebCore
Files:
40 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r276138 r276141  
     12021-04-16  Antoine Quint  <graouts@webkit.org>
     2
     3        Refactor parameters to blending functions
     4        https://bugs.webkit.org/show_bug.cgi?id=224433
     5
     6        Reviewed by Dean Jackson.
     7
     8        Reduce the number of parameters passed to the blending functions such that we package
     9        the client and progress together and track whether the animation is discrete instead
     10        of computing it several times. This information is now passed as a BlendingContext
     11        parameter, and a CSSPropertyBlendingContext private to CSSPropertyAnimation.
     12
     13        When we support composite operations, we'll just need to add a new member to that
     14        struct instead of modifying all the method signatures.
     15
     16        Since we are modifying the method signatures, we also change the RenderStyle pointers
     17        to references since we would never pass in a null value.
     18
     19        * animation/CSSPropertyAnimation.cpp:
     20        (WebCore::CSSPropertyBlendingContext::CSSPropertyBlendingContext):
     21        (WebCore::blendFunc):
     22        (WebCore::blendFilterOperations):
     23        (WebCore::blendFilter):
     24        (WebCore::crossfadeBlend):
     25        (WebCore::AnimationPropertyWrapperBase::canInterpolate const):
     26        (WebCore::PropertyWrapperGetter::value const):
     27        (WebCore::canInterpolateCaretColor):
     28        (WebCore::CSSPropertyAnimation::blendProperties):
     29        (WebCore::CSSPropertyAnimation::propertiesEqual):
     30        (WebCore::CSSPropertyAnimation::canPropertyBeInterpolated):
     31        * animation/CSSPropertyAnimation.h:
     32        * animation/KeyframeEffect.cpp:
     33        (WebCore::KeyframeEffect::setAnimatedPropertiesInStyle):
     34        * css/CSSCrossfadeValue.cpp:
     35        (WebCore::blendFunc):
     36        (WebCore::CSSCrossfadeValue::blend const):
     37        * css/CSSCrossfadeValue.h:
     38        * css/CSSGradientValue.cpp:
     39        (WebCore::RadialGradientAdapter::normalizeStopsAndEndpointsOutsideRange):
     40        (WebCore::ConicGradientAdapter::normalizeStopsAndEndpointsOutsideRange):
     41        (WebCore::CSSGradientValue::computeStops):
     42        * platform/Length.cpp:
     43        (WebCore::blendMixedTypes):
     44        (WebCore::blend):
     45        * platform/Length.h:
     46        * platform/LengthPoint.h:
     47        (WebCore::blend):
     48        * platform/LengthSize.h:
     49        (WebCore::blend):
     50        * platform/animation/AnimationUtilities.h:
     51        (WebCore::blend):
     52        * platform/graphics/ColorBlending.cpp:
     53        (WebCore::blend):
     54        (WebCore::blendWithoutPremultiply):
     55        * platform/graphics/ColorBlending.h:
     56        * platform/graphics/ca/cocoa/PlatformCAFiltersCocoa.mm:
     57        (WebCore::PlatformCAFilters::colorMatrixValueForFilter):
     58        * platform/graphics/filters/FilterOperation.cpp:
     59        (WebCore::BasicColorMatrixFilterOperation::blend):
     60        (WebCore::BasicComponentTransferFilterOperation::blend):
     61        (WebCore::InvertLightnessFilterOperation::blend):
     62        (WebCore::BlurFilterOperation::blend):
     63        (WebCore::DropShadowFilterOperation::blend):
     64        * platform/graphics/filters/FilterOperation.h:
     65        (WebCore::FilterOperation::blend):
     66        * platform/graphics/transforms/IdentityTransformOperation.h:
     67        * platform/graphics/transforms/Matrix3DTransformOperation.cpp:
     68        (WebCore::createOperation):
     69        (WebCore::Matrix3DTransformOperation::blend):
     70        * platform/graphics/transforms/Matrix3DTransformOperation.h:
     71        * platform/graphics/transforms/MatrixTransformOperation.cpp:
     72        (WebCore::MatrixTransformOperation::blend):
     73        * platform/graphics/transforms/MatrixTransformOperation.h:
     74        * platform/graphics/transforms/PerspectiveTransformOperation.cpp:
     75        (WebCore::PerspectiveTransformOperation::blend):
     76        * platform/graphics/transforms/PerspectiveTransformOperation.h:
     77        * platform/graphics/transforms/RotateTransformOperation.cpp:
     78        (WebCore::RotateTransformOperation::blend):
     79        * platform/graphics/transforms/RotateTransformOperation.h:
     80        * platform/graphics/transforms/ScaleTransformOperation.cpp:
     81        (WebCore::ScaleTransformOperation::blend):
     82        * platform/graphics/transforms/ScaleTransformOperation.h:
     83        * platform/graphics/transforms/SkewTransformOperation.cpp:
     84        (WebCore::SkewTransformOperation::blend):
     85        * platform/graphics/transforms/SkewTransformOperation.h:
     86        * platform/graphics/transforms/TransformOperation.h:
     87        * platform/graphics/transforms/TransformOperations.cpp:
     88        (WebCore::TransformOperations::blendByMatchingOperations const):
     89        (WebCore::TransformOperations::blendByUsingMatrixInterpolation const):
     90        (WebCore::TransformOperations::blend const):
     91        * platform/graphics/transforms/TransformOperations.h:
     92        * platform/graphics/transforms/TranslateTransformOperation.cpp:
     93        (WebCore::TranslateTransformOperation::blend):
     94        * platform/graphics/transforms/TranslateTransformOperation.h:
     95        * rendering/style/BasicShapes.cpp:
     96        (WebCore::BasicShapeCircle::blend const):
     97        (WebCore::BasicShapeEllipse::blend const):
     98        (WebCore::BasicShapePolygon::blend const):
     99        (WebCore::BasicShapePath::blend const):
     100        (WebCore::BasicShapeInset::blend const):
     101        * rendering/style/BasicShapes.h:
     102        (WebCore::BasicShapeCenterCoordinate::blend const):
     103        (WebCore::BasicShapeRadius::blend const):
     104        * style/Styleable.cpp:
     105        (WebCore::propertyInStyleMatchesValueForTransitionInMap):
     106        (WebCore::updateCSSTransitionsForStyleableAndProperty):
     107        * svg/SVGLengthValue.cpp:
     108        (WebCore::SVGLengthValue::blend):
     109        * svg/SVGPathBlender.cpp:
     110        (WebCore::blendFloatPoint):
     111        (WebCore::SVGPathBlender::blendAnimatedDimensonalFloat):
     112        (WebCore::SVGPathBlender::blendArcToSegment):
     113
    11142021-04-16  Antoine Quint  <graouts@webkit.org>
    2115
  • trunk/Source/WebCore/animation/CSSPropertyAnimation.cpp

    r276138 r276141  
    3131#include "CSSPropertyAnimation.h"
    3232
     33#include "AnimationUtilities.h"
    3334#include "CSSComputedStyleDeclaration.h"
    3435#include "CSSCrossfadeValue.h"
     
    7172namespace WebCore {
    7273
    73 static inline int blendFunc(const CSSPropertyBlendingClient*, int from, int to, double progress)
    74 {
    75     return blend(from, to, progress);
    76 }
    77 
    78 static inline double blendFunc(const CSSPropertyBlendingClient*, double from, double to, double progress)
    79 {
    80     return blend(from, to, progress);
    81 }
    82 
    83 static inline float blendFunc(const CSSPropertyBlendingClient*, float from, float to, double progress)
    84 {
    85     return narrowPrecisionToFloat(from + (to - from) * progress);
    86 }
    87 
    88 static inline Color blendFunc(const CSSPropertyBlendingClient*, const Color& from, const Color& to, double progress)
    89 {
    90     return blend(from, to, progress);
    91 }
    92 
    93 static inline Length blendFunc(const CSSPropertyBlendingClient*, const Length& from, const Length& to, double progress, ValueRange valueRange = ValueRangeAll)
    94 {
    95     return blend(from, to, progress, valueRange);
    96 }
    97 
    98 static inline GapLength blendFunc(const CSSPropertyBlendingClient*, const GapLength& from, const GapLength& to, double progress)
     74struct CSSPropertyBlendingContext : BlendingContext {
     75    const CSSPropertyBlendingClient* client { nullptr };
     76
     77    CSSPropertyBlendingContext(double progress, bool isDiscrete, const CSSPropertyBlendingClient* client)
     78        : BlendingContext(progress, isDiscrete)
     79        , client(client)
     80    {
     81    }
     82};
     83
     84static inline int blendFunc(int from, int to, const CSSPropertyBlendingContext& context)
     85{
     86    return blend(from, to, context);
     87}
     88
     89static inline double blendFunc(double from, double to, const CSSPropertyBlendingContext& context)
     90{
     91    return blend(from, to, context);
     92}
     93
     94static inline float blendFunc(float from, float to, const CSSPropertyBlendingContext& context)
     95{
     96    return narrowPrecisionToFloat(from + (to - from) * context.progress);
     97}
     98
     99static inline Color blendFunc(const Color& from, const Color& to, const CSSPropertyBlendingContext& context)
     100{
     101    return blend(from, to, context);
     102}
     103
     104static inline Length blendFunc(const Length& from, const Length& to, const CSSPropertyBlendingContext& context, ValueRange valueRange = ValueRangeAll)
     105{
     106    return blend(from, to, context, valueRange);
     107}
     108
     109static inline GapLength blendFunc(const GapLength& from, const GapLength& to, const CSSPropertyBlendingContext& context)
    99110{
    100111    if (from.isNormal() || to.isNormal())
    101         return progress < 0.5 ? from : to;
    102     return blend(from.length(), to.length(), progress, ValueRangeNonNegative);
    103 }
    104 
    105 static inline TabSize blendFunc(const CSSPropertyBlendingClient*, const TabSize& from, const TabSize& to, double progress)
    106 {
    107     auto blendedValue = blend(from.value(), to.value(), progress);
     112        return context.progress < 0.5 ? from : to;
     113    return blend(from.length(), to.length(), context, ValueRangeNonNegative);
     114}
     115
     116static inline TabSize blendFunc(const TabSize& from, const TabSize& to, const CSSPropertyBlendingContext& context)
     117{
     118    auto blendedValue = blend(from.value(), to.value(), context);
    108119    return { blendedValue < 0 ? 0 : blendedValue, from.isSpaces() ? SpaceValueType : LengthValueType };
    109120}
    110121
    111 static inline LengthSize blendFunc(const CSSPropertyBlendingClient* client, const LengthSize& from, const LengthSize& to, double progress)
    112 {
    113     return { blendFunc(client, from.width, to.width, progress, ValueRangeNonNegative),
    114              blendFunc(client, from.height, to.height, progress, ValueRangeNonNegative) };
    115 }
    116 
    117 static inline LengthPoint blendFunc(const CSSPropertyBlendingClient*, const LengthPoint& from, const LengthPoint& to, double progress)
    118 {
    119     return blend(from, to, progress);
    120 }
    121 
    122 static inline ShadowStyle blendFunc(const CSSPropertyBlendingClient* client, ShadowStyle from, ShadowStyle to, double progress)
     122static inline LengthSize blendFunc(const LengthSize& from, const LengthSize& to, const CSSPropertyBlendingContext& context)
     123{
     124    return { blendFunc(from.width, to.width, context, ValueRangeNonNegative),
     125             blendFunc(from.height, to.height, context, ValueRangeNonNegative) };
     126}
     127
     128static inline LengthPoint blendFunc(const LengthPoint& from, const LengthPoint& to, const CSSPropertyBlendingContext& context)
     129{
     130    return blend(from, to, context);
     131}
     132
     133static inline ShadowStyle blendFunc(ShadowStyle from, ShadowStyle to, const CSSPropertyBlendingContext& context)
    123134{
    124135    if (from == to)
     
    127138    double fromVal = from == ShadowStyle::Normal ? 1 : 0;
    128139    double toVal = to == ShadowStyle::Normal ? 1 : 0;
    129     double result = blendFunc(client, fromVal, toVal, progress);
     140    double result = blendFunc(fromVal, toVal, context);
    130141    return result > 0 ? ShadowStyle::Normal : ShadowStyle::Inset;
    131142}
    132143
    133 static inline std::unique_ptr<ShadowData> blendFunc(const CSSPropertyBlendingClient* client, const ShadowData* from, const ShadowData* to, double progress)
     144static inline std::unique_ptr<ShadowData> blendFunc(const ShadowData* from, const ShadowData* to, const CSSPropertyBlendingContext& context)
    134145{
    135146    ASSERT(from && to);
    136147    ASSERT(from->style() == to->style());
    137148
    138     return makeUnique<ShadowData>(blend(from->location(), to->location(), progress),
    139         std::max(0, blend(from->radius(), to->radius(), progress)),
    140         blend(from->spread(), to->spread(), progress),
    141         blendFunc(client, from->style(), to->style(), progress),
     149    return makeUnique<ShadowData>(blend(from->location(), to->location(), context),
     150        std::max(0, blend(from->radius(), to->radius(), context)),
     151        blend(from->spread(), to->spread(), context),
     152        blendFunc(from->style(), to->style(), context),
    142153        from->isWebkitBoxShadow(),
    143         blend(from->color(), to->color(), progress));
    144 }
    145 
    146 static inline TransformOperations blendFunc(const CSSPropertyBlendingClient* client, const TransformOperations& from, const TransformOperations& to, double progress)
    147 {
    148     if (client->transformFunctionListsMatch())
    149         return to.blendByMatchingOperations(from, progress);
    150     return to.blendByUsingMatrixInterpolation(from, progress, is<RenderBox>(client->renderer()) ? downcast<RenderBox>(*client->renderer()).borderBoxRect().size() : LayoutSize());
    151 }
    152 
    153 static RefPtr<ScaleTransformOperation> blendFunc(const CSSPropertyBlendingClient* client, ScaleTransformOperation* from, ScaleTransformOperation* to, double progress)
     154        blend(from->color(), to->color(), context));
     155}
     156
     157static inline TransformOperations blendFunc(const TransformOperations& from, const TransformOperations& to, const CSSPropertyBlendingContext& context)
     158{
     159    if (context.client->transformFunctionListsMatch())
     160        return to.blendByMatchingOperations(from, context);
     161    return to.blendByUsingMatrixInterpolation(from, context, is<RenderBox>(context.client->renderer()) ? downcast<RenderBox>(*context.client->renderer()).borderBoxRect().size() : LayoutSize());
     162}
     163
     164static RefPtr<ScaleTransformOperation> blendFunc(ScaleTransformOperation* from, ScaleTransformOperation* to, const CSSPropertyBlendingContext& context)
    154165{
    155166    if (!from && !to)
     
    176187            normalizedTo = ScaleTransformOperation::create(to->x(), to->y(), TransformOperation::SCALE);
    177188        }
    178         return blendFunc(client, normalizedFrom.get(), normalizedTo.get(), progress);
    179     }
    180 
    181     auto blendedOperation = to->blend(from, progress);
     189        return blendFunc(normalizedFrom.get(), normalizedTo.get(), context);
     190    }
     191
     192    auto blendedOperation = to->blend(from, context);
    182193    if (is<ScaleTransformOperation>(blendedOperation.get())) {
    183194        auto& scale = downcast<ScaleTransformOperation>(blendedOperation.get());
     
    187198}
    188199
    189 static RefPtr<RotateTransformOperation> blendFunc(const CSSPropertyBlendingClient* client, RotateTransformOperation* from, RotateTransformOperation* to, double progress)
     200static RefPtr<RotateTransformOperation> blendFunc(RotateTransformOperation* from, RotateTransformOperation* to, const CSSPropertyBlendingContext& context)
    190201{
    191202    if (!from && !to)
     
    212223            normalizedTo = RotateTransformOperation::create(to->angle(), TransformOperation::ROTATE);
    213224        }
    214         return blendFunc(client, normalizedFrom.get(), normalizedTo.get(), progress);
    215     }
    216 
    217     auto blendedOperation = to->blend(from, progress);
     225        return blendFunc(normalizedFrom.get(), normalizedTo.get(), context);
     226    }
     227
     228    auto blendedOperation = to->blend(from, context);
    218229    if (is<RotateTransformOperation>(blendedOperation.get())) {
    219230        auto& rotate = downcast<RotateTransformOperation>(blendedOperation.get());
     
    223234}
    224235
    225 static RefPtr<TranslateTransformOperation> blendFunc(const CSSPropertyBlendingClient* client, TranslateTransformOperation* from, TranslateTransformOperation* to, double progress)
     236static RefPtr<TranslateTransformOperation> blendFunc(TranslateTransformOperation* from, TranslateTransformOperation* to, const CSSPropertyBlendingContext& context)
    226237{
    227238    if (!from && !to)
     
    248259            normalizedTo = TranslateTransformOperation::create(to->x(), to->y(), TransformOperation::TRANSLATE);
    249260        }
    250         return blendFunc(client, normalizedFrom.get(), normalizedTo.get(), progress);
    251     }
    252 
    253     Ref<TransformOperation> blendedOperation = to->blend(from, progress);
     261        return blendFunc(normalizedFrom.get(), normalizedTo.get(), context);
     262    }
     263
     264    Ref<TransformOperation> blendedOperation = to->blend(from, context);
    254265    if (is<TranslateTransformOperation>(blendedOperation.get())) {
    255266        TranslateTransformOperation& translate = downcast<TranslateTransformOperation>(blendedOperation.get());
     
    259270}
    260271
    261 static inline RefPtr<ClipPathOperation> blendFunc(const CSSPropertyBlendingClient*, ClipPathOperation* from, ClipPathOperation* to, double progress)
     272static inline RefPtr<ClipPathOperation> blendFunc(ClipPathOperation* from, ClipPathOperation* to, const CSSPropertyBlendingContext& context)
    262273{
    263274    if (!from || !to)
     
    274285        return to;
    275286
    276     return ShapeClipPathOperation::create(toShape.blend(fromShape, progress));
    277 }
    278 
    279 static inline RefPtr<ShapeValue> blendFunc(const CSSPropertyBlendingClient*, ShapeValue* from, ShapeValue* to, double progress)
    280 {
    281     if (!progress)
     287    return ShapeClipPathOperation::create(toShape.blend(fromShape, context));
     288}
     289
     290static inline RefPtr<ShapeValue> blendFunc(ShapeValue* from, ShapeValue* to, const CSSPropertyBlendingContext& context)
     291{
     292    if (!context.progress)
    282293        return from;
    283294
    284     if (progress == 1.0)
     295    if (context.progress == 1.0)
    285296        return to;
    286297
     
    288299    const BasicShape& fromShape = *from->shape();
    289300    const BasicShape& toShape = *to->shape();
    290     return ShapeValue::create(toShape.blend(fromShape, progress), to->cssBox());
    291 }
    292 
    293 static inline RefPtr<FilterOperation> blendFunc(const CSSPropertyBlendingClient*, FilterOperation* from, FilterOperation* to, double progress, bool blendToPassthrough = false)
     301    return ShapeValue::create(toShape.blend(fromShape, context), to->cssBox());
     302}
     303
     304static inline RefPtr<FilterOperation> blendFunc(FilterOperation* from, FilterOperation* to, const CSSPropertyBlendingContext& context, bool blendToPassthrough = false)
    294305{
    295306    ASSERT(to);
    296     return to->blend(from, progress, blendToPassthrough);
    297 }
    298 
    299 static inline FilterOperations blendFilterOperations(const CSSPropertyBlendingClient* client,  const FilterOperations& from, const FilterOperations& to, double progress)
     307    return to->blend(from, context, blendToPassthrough);
     308}
     309
     310static inline FilterOperations blendFilterOperations(const FilterOperations& from, const FilterOperations& to, const CSSPropertyBlendingContext& context)
    300311{
    301312    FilterOperations result;
     
    306317        RefPtr<FilterOperation> fromOp = (i < fromSize) ? from.operations()[i].get() : 0;
    307318        RefPtr<FilterOperation> toOp = (i < toSize) ? to.operations()[i].get() : 0;
    308         RefPtr<FilterOperation> blendedOp = toOp ? blendFunc(client, fromOp.get(), toOp.get(), progress) : (fromOp ? blendFunc(client, 0, fromOp.get(), progress, true) : 0);
     319        RefPtr<FilterOperation> blendedOp = toOp ? blendFunc(fromOp.get(), toOp.get(), context) : (fromOp ? blendFunc(0, fromOp.get(), context, true) : 0);
    309320        if (blendedOp)
    310321            result.operations().append(blendedOp);
    311322        else {
    312323            auto identityOp = PassthroughFilterOperation::create();
    313             if (progress > 0.5)
     324            if (context.progress > 0.5)
    314325                result.operations().append(toOp ? toOp : WTFMove(identityOp));
    315326            else
     
    320331}
    321332
    322 static inline FilterOperations blendFunc(const CSSPropertyBlendingClient* client, const FilterOperations& from, const FilterOperations& to, double progress, CSSPropertyID propertyID = CSSPropertyFilter)
     333static inline FilterOperations blendFunc(const FilterOperations& from, const FilterOperations& to, const CSSPropertyBlendingContext& context, CSSPropertyID propertyID = CSSPropertyFilter)
    323334{
    324335    FilterOperations result;
     
    329340    switch (propertyID) {
    330341    case CSSPropertyFilter:
    331         listsMatch = client->filterFunctionListsMatch();
     342        listsMatch = context.client->filterFunctionListsMatch();
    332343        break;
    333344#if ENABLE(FILTERS_LEVEL_2)
    334345    case CSSPropertyWebkitBackdropFilter:
    335         listsMatch = client->backdropFilterFunctionListsMatch();
     346        listsMatch = context.client->backdropFilterFunctionListsMatch();
    336347        break;
    337348#endif
    338349    case CSSPropertyAppleColorFilter:
    339         listsMatch = client->colorFilterFunctionListsMatch();
     350        listsMatch = context.client->colorFilterFunctionListsMatch();
    340351        break;
    341352    default:
     
    344355   
    345356    if (listsMatch)
    346         result = blendFilterOperations(client, from, to, progress);
     357        result = blendFilterOperations(from, to, context);
    347358    else {
    348359        // If the filter function lists don't match, we could try to cross-fade, but don't yet have a way to represent that in CSS.
     
    354365}
    355366
    356 static inline RefPtr<StyleImage> blendFilter(const CSSPropertyBlendingClient* client, CachedImage* image, const FilterOperations& from, const FilterOperations& to, double progress)
     367static inline RefPtr<StyleImage> blendFilter(CachedImage* image, const FilterOperations& from, const FilterOperations& to, const CSSPropertyBlendingContext& context)
    357368{
    358369    ASSERT(image);
    359     FilterOperations filterResult = blendFilterOperations(client, from, to, progress);
     370    FilterOperations filterResult = blendFilterOperations(from, to, context);
    360371
    361372    auto imageValue = CSSImageValue::create(*image);
    362     auto filterValue = ComputedStyleExtractor::valueForFilter(client->currentStyle(), filterResult, DoNotAdjustPixelValues);
     373    auto filterValue = ComputedStyleExtractor::valueForFilter(context.client->currentStyle(), filterResult, DoNotAdjustPixelValues);
    363374
    364375    auto result = CSSFilterImageValue::create(WTFMove(imageValue), WTFMove(filterValue));
     
    367378}
    368379
    369 static inline Visibility blendFunc(const CSSPropertyBlendingClient* client, Visibility from, Visibility to, double progress)
     380static inline Visibility blendFunc(Visibility from, Visibility to, const CSSPropertyBlendingContext& context)
    370381{
    371382    // Any non-zero result means we consider the object to be visible. Only at 0 do we consider the object to be
     
    375386    if (fromVal == toVal)
    376387        return to;
    377     double result = blendFunc(client, fromVal, toVal, progress);
     388    double result = blendFunc(fromVal, toVal, context);
    378389    return result > 0. ? Visibility::Visible : (to != Visibility::Visible ? to : from);
    379390}
    380391
    381 static inline TextUnderlineOffset blendFunc(const CSSPropertyBlendingClient* client, const TextUnderlineOffset& from, const TextUnderlineOffset& to, double progress)
     392static inline TextUnderlineOffset blendFunc(const TextUnderlineOffset& from, const TextUnderlineOffset& to, const CSSPropertyBlendingContext& context)
    382393{
    383394    if (from.isLength() && to.isLength())
    384         return TextUnderlineOffset::createWithLength(blendFunc(client, from.lengthValue(), to.lengthValue(), progress));
     395        return TextUnderlineOffset::createWithLength(blendFunc(from.lengthValue(), to.lengthValue(), context));
    385396    return TextUnderlineOffset::createWithAuto();
    386397}
    387398
    388 static inline TextDecorationThickness blendFunc(const CSSPropertyBlendingClient* client, const TextDecorationThickness& from, const TextDecorationThickness& to, double progress)
     399static inline TextDecorationThickness blendFunc(const TextDecorationThickness& from, const TextDecorationThickness& to, const CSSPropertyBlendingContext& context)
    389400{
    390401    if (from.isLength() && to.isLength())
    391         return TextDecorationThickness::createWithLength(blendFunc(client, from.lengthValue(), to.lengthValue(), progress));
     402        return TextDecorationThickness::createWithLength(blendFunc(from.lengthValue(), to.lengthValue(), context));
    392403    return TextDecorationThickness::createWithAuto();
    393404}
    394405
    395 static inline LengthBox blendFunc(const CSSPropertyBlendingClient* client, const LengthBox& from, const LengthBox& to, double progress, ValueRange valueRange = ValueRangeNonNegative)
    396 {
    397     LengthBox result(blendFunc(client, from.top(), to.top(), progress, valueRange),
    398                      blendFunc(client, from.right(), to.right(), progress, valueRange),
    399                      blendFunc(client, from.bottom(), to.bottom(), progress, valueRange),
    400                      blendFunc(client, from.left(), to.left(), progress, valueRange));
     406static inline LengthBox blendFunc(const LengthBox& from, const LengthBox& to, const CSSPropertyBlendingContext& context, ValueRange valueRange = ValueRangeNonNegative)
     407{
     408    LengthBox result(blendFunc(from.top(), to.top(), context, valueRange),
     409                     blendFunc(from.right(), to.right(), context, valueRange),
     410                     blendFunc(from.bottom(), to.bottom(), context, valueRange),
     411                     blendFunc(from.left(), to.left(), context, valueRange));
    401412    return result;
    402413}
    403414
    404 static inline SVGLengthValue blendFunc(const CSSPropertyBlendingClient*, const SVGLengthValue& from, const SVGLengthValue& to, double progress)
    405 {
    406     return SVGLengthValue::blend(from, to, narrowPrecisionToFloat(progress));
    407 }
    408 
    409 static inline Vector<SVGLengthValue> blendFunc(const CSSPropertyBlendingClient*, const Vector<SVGLengthValue>& from, const Vector<SVGLengthValue>& to, double progress)
     415static inline SVGLengthValue blendFunc(const SVGLengthValue& from, const SVGLengthValue& to, const CSSPropertyBlendingContext& context)
     416{
     417    return SVGLengthValue::blend(from, to, narrowPrecisionToFloat(context.progress));
     418}
     419
     420static inline Vector<SVGLengthValue> blendFunc(const Vector<SVGLengthValue>& from, const Vector<SVGLengthValue>& to, const CSSPropertyBlendingContext& context)
    410421{
    411422    size_t fromLength = from.size();
    412423    size_t toLength = to.size();
    413424    if (!fromLength)
    414         return !progress ? from : to;
     425        return !context.progress ? from : to;
    415426    if (!toLength)
    416         return progress == 1 ? from : to;
     427        return context.progress == 1 ? from : to;
    417428    size_t resultLength = fromLength;
    418429    if (fromLength != toLength) {
     
    424435    Vector<SVGLengthValue> result(resultLength);
    425436    for (size_t i = 0; i < resultLength; ++i)
    426         result[i] = SVGLengthValue::blend(from[i % fromLength], to[i % toLength], narrowPrecisionToFloat(progress));
     437        result[i] = SVGLengthValue::blend(from[i % fromLength], to[i % toLength], narrowPrecisionToFloat(context.progress));
    427438    return result;
    428439}
    429440
    430 static inline RefPtr<StyleImage> crossfadeBlend(const CSSPropertyBlendingClient*, StyleCachedImage* fromStyleImage, StyleCachedImage* toStyleImage, double progress)
     441static inline RefPtr<StyleImage> crossfadeBlend(StyleCachedImage* fromStyleImage, StyleCachedImage* toStyleImage, const CSSPropertyBlendingContext& context)
    431442{
    432443    // If progress is at one of the extremes, we want getComputedStyle to show the image,
    433444    // not a completed cross-fade, so we hand back one of the existing images.
    434     if (!progress)
     445    if (!context.progress)
    435446        return fromStyleImage;
    436     if (progress == 1)
     447    if (context.progress == 1)
    437448        return toStyleImage;
    438449    if (!fromStyleImage->cachedImage() || !toStyleImage->cachedImage())
     
    441452    auto fromImageValue = CSSImageValue::create(*fromStyleImage->cachedImage());
    442453    auto toImageValue = CSSImageValue::create(*toStyleImage->cachedImage());
    443     auto percentageValue = CSSPrimitiveValue::create(progress, CSSUnitType::CSS_NUMBER);
     454    auto percentageValue = CSSPrimitiveValue::create(context.progress, CSSUnitType::CSS_NUMBER);
    444455
    445456    auto crossfadeValue = CSSCrossfadeValue::create(WTFMove(fromImageValue), WTFMove(toImageValue), WTFMove(percentageValue));
     
    447458}
    448459
    449 static inline RefPtr<StyleImage> blendFunc(const CSSPropertyBlendingClient* client, StyleImage* from, StyleImage* to, double progress)
    450 {
    451     if (!progress)
     460static inline RefPtr<StyleImage> blendFunc(StyleImage* from, StyleImage* to, const CSSPropertyBlendingContext& context)
     461{
     462    if (!context.progress)
    452463        return from;
    453464
    454     if (progress == 1.0)
     465    if (context.progress == 1.0)
    455466        return to;
    456467
     
    474485            CSSFilterImageValue& toFilter = downcast<CSSFilterImageValue>(toGenerated);
    475486            if (fromFilter.equalInputImages(toFilter) && fromFilter.cachedImage())
    476                 return blendFilter(client, fromFilter.cachedImage(), fromFilter.filterOperations(), toFilter.filterOperations(), progress);
     487                return blendFilter(fromFilter.cachedImage(), fromFilter.filterOperations(), toFilter.filterOperations(), context);
    477488        }
    478489
     
    481492            CSSCrossfadeValue& toCrossfade = downcast<CSSCrossfadeValue>(toGenerated);
    482493            if (fromCrossfade.equalInputImages(toCrossfade)) {
    483                 if (auto crossfadeBlend = toCrossfade.blend(fromCrossfade, progress))
     494                if (auto crossfadeBlend = toCrossfade.blend(fromCrossfade, context))
    484495                    return StyleGeneratedImage::create(*crossfadeBlend);
    485496            }
     
    493504            CSSFilterImageValue& fromFilter = downcast<CSSFilterImageValue>(fromGenerated);
    494505            if (fromFilter.cachedImage() && downcast<StyleCachedImage>(*to).cachedImage() == fromFilter.cachedImage())
    495                 return blendFilter(client, fromFilter.cachedImage(), fromFilter.filterOperations(), FilterOperations(), progress);
     506                return blendFilter(fromFilter.cachedImage(), fromFilter.filterOperations(), FilterOperations(), context);
    496507        }
    497508        // FIXME: Add interpolation between cross-fade and image source.
     
    501512            CSSFilterImageValue& toFilter = downcast<CSSFilterImageValue>(toGenerated);
    502513            if (toFilter.cachedImage() && downcast<StyleCachedImage>(*from).cachedImage() == toFilter.cachedImage())
    503                 return blendFilter(client, toFilter.cachedImage(), FilterOperations(), toFilter.filterOperations(), progress);
     514                return blendFilter(toFilter.cachedImage(), FilterOperations(), toFilter.filterOperations(), context);
    504515        }
    505516        // FIXME: Add interpolation between image source and cross-fade.
     
    509520    // https://bugs.webkit.org/show_bug.cgi?id=78293
    510521    if (is<StyleCachedImage>(*from) && is<StyleCachedImage>(*to))
    511         return crossfadeBlend(client, downcast<StyleCachedImage>(from), downcast<StyleCachedImage>(to), progress);
     522        return crossfadeBlend(downcast<StyleCachedImage>(from), downcast<StyleCachedImage>(to), context);
    512523
    513524    return to;
    514525}
    515526
    516 static inline NinePieceImage blendFunc(const CSSPropertyBlendingClient* client, const NinePieceImage& from, const NinePieceImage& to, double progress)
     527static inline NinePieceImage blendFunc(const NinePieceImage& from, const NinePieceImage& to, const CSSPropertyBlendingContext& context)
    517528{
    518529    if (!from.hasImage() || !to.hasImage())
     
    524535        return to;
    525536
    526     if (auto* renderer = client->renderer()) {
     537    if (auto* renderer = context.client->renderer()) {
    527538        if (from.image()->imageSize(renderer, 1.0) != to.image()->imageSize(renderer, 1.0))
    528539            return to;
    529540    }
    530541
    531     return NinePieceImage(blendFunc(client, from.image(), to.image(), progress),
     542    return NinePieceImage(blendFunc(from.image(), to.image(), context),
    532543        from.imageSlices(), from.fill(), from.borderSlices(), from.outset(), from.horizontalRule(), from.verticalRule());
    533544}
     
    535546#if ENABLE(VARIATION_FONTS)
    536547
    537 static inline FontVariationSettings blendFunc(const CSSPropertyBlendingClient* client, const FontVariationSettings& from, const FontVariationSettings& to, double progress)
    538 {
    539     if (!progress)
     548static inline FontVariationSettings blendFunc(const FontVariationSettings& from, const FontVariationSettings& to, const CSSPropertyBlendingContext& context)
     549{
     550    if (!context.progress)
    540551        return from;
    541552
    542     if (progress == 1.0)
     553    if (context.progress == 1.0)
    543554        return to;
    544555
     
    550561        auto& toItem = to.at(i);
    551562        ASSERT(fromItem.tag() == toItem.tag());
    552         float interpolated = blendFunc(client, fromItem.value(), toItem.value(), progress);
     563        float interpolated = blendFunc(fromItem.value(), toItem.value(), context);
    553564        result.insert({ fromItem.tag(), interpolated });
    554565    }
     
    558569#endif
    559570
    560 static inline FontSelectionValue blendFunc(const CSSPropertyBlendingClient* client, FontSelectionValue from, FontSelectionValue to, double progress)
    561 {
    562     return FontSelectionValue(std::max(0.0f, blendFunc(client, static_cast<float>(from), static_cast<float>(to), progress)));
    563 }
    564 
    565 static inline Optional<FontSelectionValue> blendFunc(const CSSPropertyBlendingClient* client, Optional<FontSelectionValue> from, Optional<FontSelectionValue> to, double progress)
    566 {
    567     return blendFunc(client, *from, *to, progress);
     571static inline FontSelectionValue blendFunc(FontSelectionValue from, FontSelectionValue to, const CSSPropertyBlendingContext& context)
     572{
     573    return FontSelectionValue(std::max(0.0f, blendFunc(static_cast<float>(from), static_cast<float>(to), context)));
     574}
     575
     576static inline Optional<FontSelectionValue> blendFunc(Optional<FontSelectionValue> from, Optional<FontSelectionValue> to, const CSSPropertyBlendingContext& context)
     577{
     578    return blendFunc(*from, *to, context);
    568579}
    569580
     
    579590
    580591    virtual bool isShorthandWrapper() const { return false; }
    581     virtual bool equals(const RenderStyle*, const RenderStyle*) const = 0;
    582     virtual bool canInterpolate(const RenderStyle*, const RenderStyle*) const { return true; }
    583     virtual void blend(const CSSPropertyBlendingClient*, RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0;
     592    virtual bool equals(const RenderStyle&, const RenderStyle&) const = 0;
     593    virtual bool canInterpolate(const RenderStyle&, const RenderStyle&) const { return true; }
     594    virtual void blend(RenderStyle&, const RenderStyle&, const RenderStyle&, const CSSPropertyBlendingContext&) const = 0;
    584595   
    585596#if !LOG_DISABLED
    586     virtual void logBlend(const RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0;
     597    virtual void logBlend(const RenderStyle&, const RenderStyle&, const RenderStyle&, double) const = 0;
    587598#endif
    588599
     
    605616    }
    606617
    607     T value(const RenderStyle* style) const
    608     {
    609         return (style->*m_getter)();
    610     }
    611 
    612 private:
    613     bool equals(const RenderStyle* a, const RenderStyle* b) const override
    614     {
    615         if (a == b)
     618    T value(const RenderStyle& style) const
     619    {
     620        return (style.*m_getter)();
     621    }
     622
     623private:
     624    bool equals(const RenderStyle& a, const RenderStyle& b) const override
     625    {
     626        if (&a == &b)
    616627            return true;
    617         if (!a || !b)
    618             return false;
    619628        return value(a) == value(b);
    620629    }
    621630
    622631#if !LOG_DISABLED
    623     void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* result, double progress) const final
    624     {
    625         LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
     632    void logBlend(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
     633    {
     634        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
    626635    }
    627636#endif
     
    640649    }
    641650
    642     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const override
    643     {
    644         (destination->*m_setter)(blendFunc(client, this->value(from), this->value(to), progress));
     651    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const override
     652    {
     653        (destination.*m_setter)(blendFunc(this->value(from), this->value(to), context));
    645654    }
    646655
     
    659668
    660669private:
    661     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    662     {
    663         auto blendedValue = blendFunc(client, this->value(from), this->value(to), progress);
    664         (destination->*this->m_setter)(blendedValue > 1 ? blendedValue : 1);
     670    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     671    {
     672        auto blendedValue = blendFunc(this->value(from), this->value(to), context);
     673        (destination.*this->m_setter)(blendedValue > 1 ? blendedValue : 1);
    665674    }
    666675};
     
    677686
    678687private:
    679     bool canInterpolate(const RenderStyle*, const RenderStyle*) const final { return false; }
    680 
    681     void blend(const CSSPropertyBlendingClient*, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    682     {
    683         ASSERT(!progress || progress == 1.0);
    684         (destination->*this->m_setter)(this->value(progress ? to : from));
     688    bool canInterpolate(const RenderStyle&, const RenderStyle&) const final { return false; }
     689
     690    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     691    {
     692        ASSERT(!context.progress || context.progress == 1.0);
     693        (destination.*this->m_setter)(this->value(context.progress ? to : from));
    685694    }
    686695
     
    699708
    700709private:
    701     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    702     {
    703         (destination->*this->m_setter)(blendFunc(client, this->value(from), this->value(to), progress));
     710    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     711    {
     712        (destination.*this->m_setter)(blendFunc(this->value(from), this->value(to), context));
    704713    }
    705714
     
    740749
    741750protected:
    742     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const override
     751    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const override
    743752    {
    744753        return canInterpolateLengths(value(from), value(to), m_flags.contains(Flags::IsLengthPercentage));
    745754    }
    746755
    747     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const override
     756    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const override
    748757    {
    749758        auto valueRange = m_flags.contains(Flags::NegativeLengthsAreInvalid) ? ValueRangeNonNegative : ValueRangeAll;
    750         (destination->*m_setter)(blendFunc(client, value(from), value(to), progress, valueRange));
     759        (destination.*m_setter)(blendFunc(value(from), value(to), context, valueRange));
    751760    }
    752761
     
    781790
    782791private:
    783     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    784     {
    785         (destination->*m_setter)(blendFunc(client, value(from), value(to), progress));
     792    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     793    {
     794        (destination.*m_setter)(blendFunc(value(from), value(to), context));
    786795    }
    787796
     
    800809
    801810private:
    802     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
     811    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
    803812    {
    804813        return canInterpolateLengthVariants(this->value(from), this->value(to));
    805814    }
    806815
    807     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    808     {
    809         (destination->*m_setter)(blendFunc(client, this->value(from), this->value(to), progress));
     816    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     817    {
     818        (destination.*m_setter)(blendFunc(this->value(from), this->value(to), context));
    810819    }
    811820
     
    829838
    830839private:
    831     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    832     {
    833         if (m_flags.contains(Flags::UsesFillKeyword) && from->borderImage().fill() != to->borderImage().fill())
     840    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     841    {
     842        if (m_flags.contains(Flags::UsesFillKeyword) && from.borderImage().fill() != to.borderImage().fill())
    834843            return false;
    835844
     
    843852    }
    844853
    845     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
     854    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
    846855    {
    847856        if (m_flags.contains(Flags::UsesFillKeyword))
    848             destination->setBorderImageSliceFill((!progress || canInterpolate(from, to) ? from : to)->borderImage().fill());
    849         if (!canInterpolate(from, to)) {
     857            destination.setBorderImageSliceFill((!context.progress || !context.isDiscrete ? from : to).borderImage().fill());
     858        if (context.isDiscrete) {
    850859            // It is important we have this non-interpolated shortcut because certain CSS properties
    851860            // represented as a LengthBox, such as border-image-slice, don't know how to deal with
    852861            // calculated Length values, see for instance valueForImageSliceSide(const Length&).
    853             (destination->*m_setter)(progress ? LengthBox(value(to)) : LengthBox(value(from)));
     862            (destination.*m_setter)(context.progress ? LengthBox(value(to)) : LengthBox(value(from)));
    854863            return;
    855864        }
    856865        auto valueRange = m_flags.contains(Flags::AllowsNegativeValues) ? ValueRangeAll : ValueRangeNonNegative;
    857         (destination->*m_setter)(blendFunc(client, value(from), value(to), progress, valueRange));
     866        (destination.*m_setter)(blendFunc(value(from), value(to), context, valueRange));
    858867    }
    859868
     
    871880
    872881private:
    873     bool equals(const RenderStyle* a, const RenderStyle* b) const final
     882    bool equals(const RenderStyle& a, const RenderStyle& b) const final
    874883    {
    875884        // If the style pointers are the same, don't bother doing the test.
    876         // If either is null, return false. If both are null, return true.
    877         if (a == b)
     885        if (&a == &b)
    878886            return true;
    879         if (!a || !b)
    880             return false;
    881887
    882888        auto* clipPathA = value(a);
     
    900906
    901907private:
    902     bool equals(const RenderStyle* a, const RenderStyle* b) const final
     908    bool equals(const RenderStyle& a, const RenderStyle& b) const final
    903909    {
    904910        // If the style pointers are the same, don't bother doing the test.
    905         // If either is null, return false. If both are null, return true.
    906         if (a == b)
     911        if (&a == &b)
    907912            return true;
    908         if (!a || !b)
    909             return false;
    910913        return value(a) == value(b);
    911914    }
    912915
    913     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
     916    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
    914917    {
    915918        auto fromVariationSettings = value(from);
     
    939942
    940943private:
    941     bool equals(const RenderStyle* a, const RenderStyle* b) const final
     944    bool equals(const RenderStyle& a, const RenderStyle& b) const final
    942945    {
    943946        // If the style pointers are the same, don't bother doing the test.
    944         // If either is null, return false. If both are null, return true.
    945         if (a == b)
     947        if (&a == &b)
    946948            return true;
    947         if (!a || !b)
    948             return false;
    949949
    950950        auto* shapeA = value(a);
     
    957957    }
    958958
    959     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
     959    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
    960960    {
    961961        auto* fromShape = value(from);
     
    984984
    985985private:
    986     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    987     {
    988         if (a == b)
     986    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     987    {
     988        if (&a == &b)
    989989            return true;
    990         if (!a || !b)
    991             return false;
    992990
    993991        auto* imageA = value(a);
     
    996994    }
    997995
    998     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
     996    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
    999997    {
    1000998        return value(from) && value(to);
     
    10271025    bool animationIsAccelerated() const final { return true; }
    10281026
    1029     bool equals(const RenderStyle* a, const RenderStyle* b) const final
     1027    bool equals(const RenderStyle& a, const RenderStyle& b) const final
    10301028    {
    10311029        return arePointingToEqualData(this->value(a), this->value(b));
     
    10511049    }
    10521050
    1053     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1054     {
    1055         (destination->*m_setter)(blendFunc(client, value(from), value(to), progress, property()));
     1051    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1052    {
     1053        (destination.*m_setter)(blendFunc(value(from), value(to), context, property()));
    10561054    }
    10571055};
     
    10921090
    10931091private:
    1094     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1095     {
    1096         if (a == b)
     1092    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1093    {
     1094        if (&a == &b)
    10971095            return true;
    1098         if (!a || !b)
    1099             return false;
    1100 
    1101         const ShadowData* shadowA = (a->*m_getter)();
    1102         const ShadowData* shadowB = (b->*m_getter)();
     1096
     1097        const ShadowData* shadowA = (a.*m_getter)();
     1098        const ShadowData* shadowB = (b.*m_getter)();
    11031099
    11041100        while (true) {
     
    11211117    }
    11221118
    1123     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    1124     {
    1125         const ShadowData* fromShadow = (from->*m_getter)();
    1126         const ShadowData* toShadow = (to->*m_getter)();
     1119    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1120    {
     1121        const ShadowData* fromShadow = (from.*m_getter)();
     1122        const ShadowData* toShadow = (to.*m_getter)();
    11271123
    11281124        // The only scenario where we can't interpolate is if specified items don't have the same shadow style.
     
    11371133    }
    11381134
    1139     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1140     {
    1141         const ShadowData* fromShadow = (from->*m_getter)();
    1142         const ShadowData* toShadow = (to->*m_getter)();
    1143 
    1144         if (!canInterpolate(from, to)) {
    1145             ASSERT(!progress || progress == 1.0);
    1146             auto* shadow = progress ? toShadow : fromShadow;
    1147             (destination->*m_setter)(shadow ? makeUnique<ShadowData>(*shadow) : nullptr, false);
     1135    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1136    {
     1137        const ShadowData* fromShadow = (from.*m_getter)();
     1138        const ShadowData* toShadow = (to.*m_getter)();
     1139
     1140        if (context.isDiscrete) {
     1141            ASSERT(!context.progress || context.progress == 1.0);
     1142            auto* shadow = context.progress ? toShadow : fromShadow;
     1143            (destination.*m_setter)(shadow ? makeUnique<ShadowData>(*shadow) : nullptr, false);
    11481144            return;
    11491145        }
     
    11531149
    11541150        if (fromLength == toLength || (fromLength <= 1 && toLength <= 1)) {
    1155             (destination->*m_setter)(blendSimpleOrMatchedShadowLists(client, progress, fromShadow, toShadow), false);
     1151            (destination.*m_setter)(blendSimpleOrMatchedShadowLists(fromShadow, toShadow, context), false);
    11561152            return;
    11571153        }
    11581154
    1159         (destination->*m_setter)(blendMismatchedShadowLists(client, progress, fromShadow, toShadow, fromLength, toLength), false);
     1155        (destination.*m_setter)(blendMismatchedShadowLists(fromShadow, toShadow, fromLength, toLength, context), false);
    11601156    }
    11611157
    11621158#if !LOG_DISABLED
    1163     void logBlend(const RenderStyle*, const RenderStyle*, const RenderStyle*, double progress) const final
     1159    void logBlend(const RenderStyle&, const RenderStyle&, const RenderStyle&, double progress) const final
    11641160    {
    11651161        // FIXME: better logging.
     
    11681164#endif
    11691165
    1170     std::unique_ptr<ShadowData> blendSimpleOrMatchedShadowLists(const CSSPropertyBlendingClient* client, double progress, const ShadowData* shadowA, const ShadowData* shadowB) const
     1166    std::unique_ptr<ShadowData> blendSimpleOrMatchedShadowLists(const ShadowData* shadowA, const ShadowData* shadowB, const CSSPropertyBlendingContext& context) const
    11711167    {
    11721168        std::unique_ptr<ShadowData> newShadowData;
     
    11771173            const ShadowData* dstShadow = shadowForBlending(shadowB, shadowA);
    11781174
    1179             std::unique_ptr<ShadowData> blendedShadow = blendFunc(client, srcShadow, dstShadow, progress);
     1175            std::unique_ptr<ShadowData> blendedShadow = blendFunc(srcShadow, dstShadow, context);
    11801176            ShadowData* blendedShadowPtr = blendedShadow.get();
    11811177
     
    11941190    }
    11951191
    1196     std::unique_ptr<ShadowData> blendMismatchedShadowLists(const CSSPropertyBlendingClient* client, double progress, const ShadowData* shadowA, const ShadowData* shadowB, int fromLength, int toLength) const
     1192    std::unique_ptr<ShadowData> blendMismatchedShadowLists(const ShadowData* shadowA, const ShadowData* shadowB, int fromLength, int toLength, const CSSPropertyBlendingContext& context) const
    11971193    {
    11981194        // The shadows in ShadowData are stored in reverse order, so when animating mismatched lists,
     
    12201216            const ShadowData* dstShadow = shadowForBlending(toShadow, fromShadow);
    12211217
    1222             std::unique_ptr<ShadowData> blendedShadow = blendFunc(client, srcShadow, dstShadow, progress);
     1218            std::unique_ptr<ShadowData> blendedShadow = blendFunc(srcShadow, dstShadow, context);
    12231219            // Insert at the start of the list to preserve the order.
    12241220            blendedShadow->setNext(WTFMove(newShadowData));
     
    12441240
    12451241private:
    1246     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1247     {
    1248         if (a == b)
     1242    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1243    {
     1244        if (&a == &b)
    12491245            return true;
    1250         if (!a || !b)
    1251             return false;
    12521246
    12531247        Color fromColor = value(a);
     
    12581252
    12591253        if (!fromColor.isValid())
    1260             fromColor = a->color();
     1254            fromColor = a.color();
    12611255        if (!toColor.isValid())
    1262             toColor = b->color();
     1256            toColor = b.color();
    12631257
    12641258        return fromColor == toColor;
    12651259    }
    12661260
    1267     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
     1261    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
    12681262    {
    12691263        Color fromColor = value(from);
     
    12741268
    12751269        if (!fromColor.isValid())
    1276             fromColor = from->color();
     1270            fromColor = from.color();
    12771271        if (!toColor.isValid())
    1278             toColor = to->color();
    1279         (destination->*m_setter)(blendFunc(client, fromColor, toColor, progress));
    1280     }
    1281 
    1282     Color value(const RenderStyle* style) const
    1283     {
    1284         return (style->*m_getter)();
     1272            toColor = to.color();
     1273        (destination.*m_setter)(blendFunc(fromColor, toColor, context));
     1274    }
     1275
     1276    Color value(const RenderStyle& style) const
     1277    {
     1278        return (style.*m_getter)();
    12851279    }
    12861280
    12871281#if !LOG_DISABLED
    1288     void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* result, double progress) const final
     1282    void logBlend(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
    12891283    {
    12901284        // FIXME: better logging.
    1291         LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
     1285        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
    12921286    }
    12931287#endif
     
    13161310
    13171311protected:
    1318     bool equals(const RenderStyle* a, const RenderStyle* b) const override
     1312    bool equals(const RenderStyle& a, const RenderStyle& b) const override
    13191313    {
    13201314        return m_wrapper->equals(a, b) && m_visitedWrapper->equals(a, b);
    13211315    }
    13221316
    1323     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const override
    1324     {
    1325         m_wrapper->blend(client, destination, from, to, progress);
    1326         m_visitedWrapper->blend(client, destination, from, to, progress);
     1317    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const override
     1318    {
     1319        m_wrapper->blend(destination, from, to, context);
     1320        m_visitedWrapper->blend(destination, from, to, context);
    13271321    }
    13281322
     
    13321326private:
    13331327#if !LOG_DISABLED
    1334     void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* result, double progress) const final
    1335     {
    1336         m_wrapper->logBlend(from, to, result, progress);
    1337         m_visitedWrapper->logBlend(from, to, result, progress);
     1328    void logBlend(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
     1329    {
     1330        m_wrapper->logBlend(from, to, destination, progress);
     1331        m_visitedWrapper->logBlend(from, to, destination, progress);
    13381332    }
    13391333#endif
    13401334};
    13411335
    1342 static bool canInterpolateCaretColor(const RenderStyle* from, const RenderStyle* to, bool visited)
     1336static bool canInterpolateCaretColor(const RenderStyle& from, const RenderStyle& to, bool visited)
    13431337{
    13441338    if (visited)
    1345         return !from->hasVisitedLinkAutoCaretColor() && !to->hasVisitedLinkAutoCaretColor();
    1346     return !from->hasAutoCaretColor() && !to->hasAutoCaretColor();
     1339        return !from.hasVisitedLinkAutoCaretColor() && !to.hasVisitedLinkAutoCaretColor();
     1340    return !from.hasAutoCaretColor() && !to.hasAutoCaretColor();
    13471341}
    13481342
     
    13561350
    13571351private:
    1358     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1359     {
    1360         return a->hasAutoCaretColor() == b->hasAutoCaretColor()
    1361             && a->hasVisitedLinkAutoCaretColor() == b->hasVisitedLinkAutoCaretColor()
     1352    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1353    {
     1354        return a.hasAutoCaretColor() == b.hasAutoCaretColor()
     1355            && a.hasVisitedLinkAutoCaretColor() == b.hasVisitedLinkAutoCaretColor()
    13621356            && PropertyWrapperVisitedAffectedColor::equals(a, b);
    13631357    }
    13641358
    1365     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
     1359    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
    13661360    {
    13671361        return canInterpolateCaretColor(from, to, false) || canInterpolateCaretColor(from, to, true);
    13681362    }
    13691363
    1370     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
     1364    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
    13711365    {
    13721366        if (canInterpolateCaretColor(from, to, false))
    1373             m_wrapper->blend(client, destination, from, to, progress);
     1367            m_wrapper->blend(destination, from, to, context);
    13741368        else {
    1375             auto* blendingRenderStyle = progress < 0.5 ? from : to;
    1376             if (blendingRenderStyle->hasAutoCaretColor())
    1377                 destination->setHasAutoCaretColor();
     1369            auto& blendingRenderStyle = context.progress < 0.5 ? from : to;
     1370            if (blendingRenderStyle.hasAutoCaretColor())
     1371                destination.setHasAutoCaretColor();
    13781372            else
    1379                 destination->setCaretColor(blendingRenderStyle->caretColor());
     1373                destination.setCaretColor(blendingRenderStyle.caretColor());
    13801374        }
    13811375
    13821376        if (canInterpolateCaretColor(from, to, true))
    1383             m_visitedWrapper->blend(client, destination, from, to, progress);
     1377            m_visitedWrapper->blend(destination, from, to, context);
    13841378        else {
    1385             auto* blendingRenderStyle = progress < 0.5 ? from : to;
    1386             if (blendingRenderStyle->hasVisitedLinkAutoCaretColor())
    1387                 destination->setHasVisitedLinkAutoCaretColor();
     1379            auto& blendingRenderStyle = context.progress < 0.5 ? from : to;
     1380            if (blendingRenderStyle.hasVisitedLinkAutoCaretColor())
     1381                destination.setHasVisitedLinkAutoCaretColor();
    13881382            else
    1389                 destination->setVisitedLinkCaretColor(blendingRenderStyle->visitedLinkCaretColor());
     1383                destination.setVisitedLinkCaretColor(blendingRenderStyle.visitedLinkCaretColor());
    13901384        }
    13911385    }
     
    14051399
    14061400    virtual bool equals(const FillLayer*, const FillLayer*) const = 0;
    1407     virtual void blend(const CSSPropertyBlendingClient*, FillLayer*, const FillLayer*, const FillLayer*, double) const = 0;
     1401    virtual void blend(FillLayer*, const FillLayer*, const FillLayer*, const CSSPropertyBlendingContext&) const = 0;
    14081402    virtual bool canInterpolate(const FillLayer*, const FillLayer*) const { return true; }
    14091403
    14101404#if !LOG_DISABLED
    1411     virtual void logBlend(const FillLayer* result, const FillLayer*, const FillLayer*, double) const = 0;
     1405    virtual void logBlend(const FillLayer* destination, const FillLayer*, const FillLayer*, double) const = 0;
    14121406#endif
    14131407
     
    14431437
    14441438#if !LOG_DISABLED
    1445     void logBlend(const FillLayer* result, const FillLayer* from, const FillLayer* to, double progress) const override
    1446     {
    1447         LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
     1439    void logBlend(const FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const override
     1440    {
     1441        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
    14481442    }
    14491443#endif
     
    14641458
    14651459private:
    1466     void blend(const CSSPropertyBlendingClient* client, FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const final
    1467     {
    1468         (destination->*this->m_setter)(blendFunc(client, this->value(from), this->value(to), progress));
     1460    void blend(FillLayer* destination, const FillLayer* from, const FillLayer* to, const CSSPropertyBlendingContext& context) const final
     1461    {
     1462        (destination->*this->m_setter)(blendFunc(this->value(from), this->value(to), context));
    14691463    }
    14701464
     
    14751469
    14761470#if !LOG_DISABLED
    1477     void logBlend(const FillLayer* result, const FillLayer* from, const FillLayer* to, double progress) const final
     1471    void logBlend(const FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const final
    14781472    {
    14791473        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(FillLayerPropertyWrapperGetter<const T&>::property())
    14801474            << " from " << FillLayerPropertyWrapperGetter<const T&>::value(from)
    14811475            << " to " << FillLayerPropertyWrapperGetter<const T&>::value(to)
    1482             << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << FillLayerPropertyWrapperGetter<const T&>::value(result));
     1476            << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << FillLayerPropertyWrapperGetter<const T&>::value(destination));
    14831477    }
    14841478#endif
     
    15161510    }
    15171511
    1518     void blend(const CSSPropertyBlendingClient* client, FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const final
     1512    void blend(FillLayer* destination, const FillLayer* from, const FillLayer* to, const CSSPropertyBlendingContext& context) const final
    15191513    {
    15201514        auto fromLength = value(from);
     
    15341528        }
    15351529
    1536         (destination->*m_lengthSetter)(blendFunc(client, fromLength, toLength, progress));
     1530        (destination->*m_lengthSetter)(blendFunc(fromLength, toLength, context));
    15371531    }
    15381532
    15391533#if !LOG_DISABLED
    1540     void logBlend(const FillLayer* result, const FillLayer* from, const FillLayer* to, double progress) const final
    1541     {
    1542         LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
     1534    void logBlend(const FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const final
     1535    {
     1536        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
    15431537    }
    15441538#endif
     
    15611555
    15621556private:
    1563     void blend(const CSSPropertyBlendingClient* client, FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const final
    1564     {
    1565         (destination->*this->m_setter)(blendFunc(client, this->value(from), this->value(to), progress));
     1557    void blend(FillLayer* destination, const FillLayer* from, const FillLayer* to, const CSSPropertyBlendingContext& context) const final
     1558    {
     1559        (destination->*this->m_setter)(blendFunc(this->value(from), this->value(to), context));
    15661560    }
    15671561
    15681562#if !LOG_DISABLED
    1569     void logBlend(const FillLayer* result, const FillLayer* from, const FillLayer* to, double progress) const override
     1563    void logBlend(const FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const override
    15701564    {
    15711565        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(FillLayerPropertyWrapperGetter<T*>::property())
    15721566            << " from " << FillLayerPropertyWrapperGetter<T*>::value(from)
    15731567            << " to " << FillLayerPropertyWrapperGetter<T*>::value(to)
    1574             << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << FillLayerPropertyWrapperGetter<T*>::value(result));
     1568            << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << FillLayerPropertyWrapperGetter<T*>::value(destination));
    15751569    }
    15761570#endif
     
    16031597
    16041598#if !LOG_DISABLED
    1605     void logBlend(const FillLayer* result, const FillLayer* from, const FillLayer* to, double progress) const final
    1606     {
    1607         LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << value(from) << " to " << value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(result));
     1599    void logBlend(const FillLayer* destination, const FillLayer* from, const FillLayer* to, double progress) const final
     1600    {
     1601        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(this->property()) << " from " << this->value(from) << " to " << this->value(to) << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << value(destination));
    16081602    }
    16091603#endif
     
    16441638
    16451639private:
    1646     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1647     {
    1648         if (a == b)
     1640    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1641    {
     1642        if (&a == &b)
    16491643            return true;
    1650         if (!a || !b)
    1651             return false;
    1652 
    1653         auto* fromLayer = &(a->*m_layersGetter)();
    1654         auto* toLayer = &(b->*m_layersGetter)();
     1644
     1645        auto* fromLayer = &(a.*m_layersGetter)();
     1646        auto* toLayer = &(b.*m_layersGetter)();
    16551647
    16561648        while (fromLayer && toLayer) {
     
    16651657    }
    16661658
    1667     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    1668     {
    1669         auto* fromLayer = &(from->*m_layersGetter)();
    1670         auto* toLayer = &(to->*m_layersGetter)();
     1659    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1660    {
     1661        auto* fromLayer = &(from.*m_layersGetter)();
     1662        auto* toLayer = &(to.*m_layersGetter)();
    16711663
    16721664        while (fromLayer && toLayer) {
     
    16841676    }
    16851677
    1686     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1687     {
    1688         auto* fromLayer = &(from->*m_layersGetter)();
    1689         auto* toLayer = &(to->*m_layersGetter)();
    1690         auto* dstLayer = &(destination->*m_layersAccessor)();
     1678    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1679    {
     1680        auto* fromLayer = &(from.*m_layersGetter)();
     1681        auto* toLayer = &(to.*m_layersGetter)();
     1682        auto* dstLayer = &(destination.*m_layersAccessor)();
    16911683
    16921684        while (fromLayer && toLayer && dstLayer) {
    1693             dstLayer->setSizeType((progress ? toLayer : fromLayer)->sizeType());
    1694             m_fillLayerPropertyWrapper->blend(client, dstLayer, fromLayer, toLayer, progress);
     1685            dstLayer->setSizeType((context.progress ? toLayer : fromLayer)->sizeType());
     1686            m_fillLayerPropertyWrapper->blend(dstLayer, fromLayer, toLayer, context);
    16951687            fromLayer = fromLayer->next();
    16961688            toLayer = toLayer->next();
     
    17001692
    17011693#if !LOG_DISABLED
    1702     void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* result, double progress) const final
    1703     {
    1704         auto* fromLayer = &(from->*m_layersGetter)();
    1705         auto* toLayer = &(to->*m_layersGetter)();
    1706         auto* dstLayer = &(result->*m_layersGetter)();
     1694    void logBlend(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
     1695    {
     1696        auto* fromLayer = &(from.*m_layersGetter)();
     1697        auto* toLayer = &(to.*m_layersGetter)();
     1698        auto* dstLayer = &(destination.*m_layersGetter)();
    17071699
    17081700        while (fromLayer && toLayer && dstLayer) {
     
    17341726
    17351727private:
    1736     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1737     {
    1738         if (a == b)
     1728    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1729    {
     1730        if (&a == &b)
    17391731            return true;
    1740         if (!a || !b)
    1741             return false;
    17421732
    17431733        for (auto& wrapper : m_propertyWrappers) {
     
    17481738    }
    17491739
    1750     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
     1740    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
    17511741    {
    17521742        for (auto& wrapper : m_propertyWrappers)
    1753             wrapper->blend(client, destination, from, to, progress);
     1743            wrapper->blend(destination, from, to, context);
    17541744    }
    17551745
    17561746#if !LOG_DISABLED
    1757     void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* destination, double progress) const final
     1747    void logBlend(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
    17581748    {
    17591749        for (auto& wrapper : m_propertyWrappers)
     
    17741764
    17751765private:
    1776     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1777     {
    1778         if (a == b)
     1766    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1767    {
     1768        if (&a == &b)
    17791769            return true;
    1780         if (!a || !b)
    1781             return false;
    1782 
    1783         return a->flexBasis() == b->flexBasis() && a->flexGrow() == b->flexGrow() && a->flexShrink() == b->flexShrink();
    1784     }
    1785 
    1786     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    1787     {
    1788         return from->flexGrow() != to->flexGrow() && from->flexShrink() != to->flexShrink() && canInterpolateLengths(from->flexBasis(), to->flexBasis(), false);
    1789     }
    1790 
    1791     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1792     {
    1793         destination->setFlexBasis(blendFunc(client, from->flexBasis(), to->flexBasis(), progress));
    1794         destination->setFlexGrow(blendFunc(client, from->flexGrow(), to->flexGrow(), progress));
    1795         destination->setFlexShrink(blendFunc(client, from->flexShrink(), to->flexShrink(), progress));
     1770
     1771        return a.flexBasis() == b.flexBasis() && a.flexGrow() == b.flexGrow() && a.flexShrink() == b.flexShrink();
     1772    }
     1773
     1774    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1775    {
     1776        return from.flexGrow() != to.flexGrow() && from.flexShrink() != to.flexShrink() && canInterpolateLengths(from.flexBasis(), to.flexBasis(), false);
     1777    }
     1778
     1779    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1780    {
     1781        destination.setFlexBasis(blendFunc(from.flexBasis(), to.flexBasis(), context));
     1782        destination.setFlexGrow(blendFunc(from.flexGrow(), to.flexGrow(), context));
     1783        destination.setFlexShrink(blendFunc(from.flexShrink(), to.flexShrink(), context));
    17961784    }
    17971785
    17981786#if !LOG_DISABLED
    1799     void logBlend(const RenderStyle*, const RenderStyle*, const RenderStyle*, double progress) const final
     1787    void logBlend(const RenderStyle&, const RenderStyle&, const RenderStyle&, double progress) const final
    18001788    {
    18011789        // FIXME: better logging.
     
    18171805
    18181806private:
    1819     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    1820     {
    1821         if (a == b)
     1807    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     1808    {
     1809        if (&a == &b)
    18221810            return true;
    1823         if (!a || !b)
    1824             return false;
    1825 
    1826         if ((a->*m_paintTypeGetter)() != (b->*m_paintTypeGetter)())
     1811
     1812        if ((a.*m_paintTypeGetter)() != (b.*m_paintTypeGetter)())
    18271813            return false;
    18281814
     
    18301816        // For everything else we must return true for this method, otherwise
    18311817        // we will try to animate between values forever.
    1832         if ((a->*m_paintTypeGetter)() == SVGPaintType::RGBColor) {
    1833             Color fromColor = (a->*m_getter)();
    1834             Color toColor = (b->*m_getter)();
     1818        if ((a.*m_paintTypeGetter)() == SVGPaintType::RGBColor) {
     1819            Color fromColor = (a.*m_getter)();
     1820            Color toColor = (b.*m_getter)();
    18351821
    18361822            if (!fromColor.isValid() && !toColor.isValid())
     
    18471833    }
    18481834
    1849     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1850     {
    1851         if ((from->*m_paintTypeGetter)() != SVGPaintType::RGBColor
    1852             || (to->*m_paintTypeGetter)() != SVGPaintType::RGBColor)
     1835    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1836    {
     1837        if ((from.*m_paintTypeGetter)() != SVGPaintType::RGBColor
     1838            || (to.*m_paintTypeGetter)() != SVGPaintType::RGBColor)
    18531839            return;
    18541840
    1855         Color fromColor = (from->*m_getter)();
    1856         Color toColor = (to->*m_getter)();
     1841        Color fromColor = (from.*m_getter)();
     1842        Color toColor = (to.*m_getter)();
    18571843
    18581844        if (!fromColor.isValid() && !toColor.isValid())
     
    18631849        if (!toColor.isValid())
    18641850            toColor = Color();
    1865         (destination->*m_setter)(blendFunc(client, fromColor, toColor, progress));
     1851        (destination.*m_setter)(blendFunc(fromColor, toColor, context));
    18661852    }
    18671853
    18681854#if !LOG_DISABLED
    1869     void logBlend(const RenderStyle*, const RenderStyle*, const RenderStyle*, double progress) const final
     1855    void logBlend(const RenderStyle&, const RenderStyle&, const RenderStyle&, double progress) const final
    18701856    {
    18711857        // FIXME: better logging.
     
    18881874
    18891875private:
    1890     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    1891     {
    1892         return from->fontItalic() && to->fontItalic() && from->fontDescription().fontStyleAxis() == FontStyleAxis::slnt && to->fontDescription().fontStyleAxis() == FontStyleAxis::slnt;
    1893     }
    1894 
    1895     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1896     {
    1897         auto discrete = !canInterpolate(from, to);
    1898 
     1876    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1877    {
     1878        return from.fontItalic() && to.fontItalic() && from.fontDescription().fontStyleAxis() == FontStyleAxis::slnt && to.fontDescription().fontStyleAxis() == FontStyleAxis::slnt;
     1879    }
     1880
     1881    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1882    {
    18991883        auto blendedStyleAxis = FontStyleAxis::slnt;
    1900         if (discrete)
    1901             blendedStyleAxis = (progress < 0.5 ? from : to)->fontDescription().fontStyleAxis();
    1902 
    1903         auto fromFontItalic = from->fontItalic();
    1904         auto toFontItalic = to->fontItalic();
    1905         auto blendedFontItalic = progress < 0.5 ? fromFontItalic : toFontItalic;
    1906         if (!discrete)
    1907             blendedFontItalic = blendFunc(client, fromFontItalic, toFontItalic, progress);
    1908 
    1909         FontSelector* currentFontSelector = destination->fontCascade().fontSelector();
    1910         auto description = destination->fontDescription();
     1884        if (context.isDiscrete)
     1885            blendedStyleAxis = (context.progress < 0.5 ? from : to).fontDescription().fontStyleAxis();
     1886
     1887        auto fromFontItalic = from.fontItalic();
     1888        auto toFontItalic = to.fontItalic();
     1889        auto blendedFontItalic = context.progress < 0.5 ? fromFontItalic : toFontItalic;
     1890        if (!context.isDiscrete)
     1891            blendedFontItalic = blendFunc(fromFontItalic, toFontItalic, context);
     1892
     1893        auto* currentFontSelector = destination.fontCascade().fontSelector();
     1894        auto description = destination.fontDescription();
    19111895        description.setItalic(blendedFontItalic);
    19121896        description.setFontStyleAxis(blendedStyleAxis);
    1913         destination->setFontDescription(WTFMove(description));
    1914         destination->fontCascade().update(currentFontSelector);
     1897        destination.setFontDescription(WTFMove(description));
     1898        destination.fontCascade().update(currentFontSelector);
    19151899    }
    19161900};
     
    19291913
    19301914private:
    1931     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    1932     {
    1933         return !(from->*m_autoGetter)() && !(to->*m_autoGetter)();
    1934     }
    1935 
    1936     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1937     {
    1938         auto blendedValue = blendFunc(client, this->value(from), this->value(to), progress);
     1915    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1916    {
     1917        return !(from.*m_autoGetter)() && !(to.*m_autoGetter)();
     1918    }
     1919
     1920    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1921    {
     1922        auto blendedValue = blendFunc(this->value(from), this->value(to), context);
    19391923        if (m_minValue)
    19401924            blendedValue = blendedValue > *m_minValue ? blendedValue : *m_minValue;
    1941         (destination->*this->m_setter)(blendedValue);
    1942 
    1943         if (canInterpolate(from, to))
     1925        (destination.*this->m_setter)(blendedValue);
     1926
     1927        if (!context.isDiscrete)
    19441928            return;
    19451929
    1946         ASSERT(!progress || progress == 1.0);
    1947         if (!progress) {
    1948             if ((from->*m_autoGetter)())
    1949                 (destination->*m_autoSetter)();
     1930        ASSERT(!context.progress || context.progress == 1.0);
     1931        if (!context.progress) {
     1932            if ((from.*m_autoGetter)())
     1933                (destination.*m_autoSetter)();
    19501934        } else {
    1951             if ((to->*m_autoGetter)())
    1952                 (destination->*m_autoSetter)();
     1935            if ((to.*m_autoGetter)())
     1936                (destination.*m_autoSetter)();
    19531937        }
    19541938    }
     
    19681952
    19691953protected:
    1970     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const override
    1971     {
    1972         auto blendedValue = blendFunc(client, value(from), value(to), progress);
    1973         (destination->*m_setter)(blendedValue > 0 ? blendedValue : 0);
     1954    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const override
     1955    {
     1956        auto blendedValue = blendFunc(value(from), value(to), context);
     1957        (destination.*m_setter)(blendedValue > 0 ? blendedValue : 0);
    19741958    }
    19751959};
     
    19841968
    19851969private:
    1986     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    1987     {
    1988         return from->verticalAlign() == VerticalAlign::Length && to->verticalAlign() == VerticalAlign::Length && LengthPropertyWrapper::canInterpolate(from, to);
    1989     }
    1990 
    1991     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    1992     {
    1993         LengthPropertyWrapper::blend(client, destination, from, to, progress);
    1994         auto* blendingStyle = !canInterpolate(from, to) && progress ? to : from;
    1995         destination->setVerticalAlign(blendingStyle->verticalAlign());
     1970    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1971    {
     1972        return from.verticalAlign() == VerticalAlign::Length && to.verticalAlign() == VerticalAlign::Length && LengthPropertyWrapper::canInterpolate(from, to);
     1973    }
     1974
     1975    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     1976    {
     1977        LengthPropertyWrapper::blend(destination, from, to, context);
     1978        auto& blendingStyle = context.isDiscrete && context.progress ? to : from;
     1979        destination.setVerticalAlign(blendingStyle.verticalAlign());
    19961980    }
    19971981};
     
    20061990
    20071991private:
    2008     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    2009     {
    2010         if (from->textIndentLine() != to->textIndentLine())
     1992    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     1993    {
     1994        if (from.textIndentLine() != to.textIndentLine())
    20111995            return false;
    2012         if (from->textIndentType() != to->textIndentType())
     1996        if (from.textIndentType() != to.textIndentType())
    20131997            return false;
    20141998        return LengthPropertyWrapper::canInterpolate(from, to);
    20151999    }
    20162000
    2017     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    2018     {
    2019         auto* blendingStyle = !canInterpolate(from, to) && progress ? to : from;
    2020         destination->setTextIndentLine(blendingStyle->textIndentLine());
    2021         destination->setTextIndentType(blendingStyle->textIndentType());
    2022         LengthPropertyWrapper::blend(client, destination, from, to, progress);
     2001    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     2002    {
     2003        auto& blendingStyle = context.isDiscrete && context.progress ? to : from;
     2004        destination.setTextIndentLine(blendingStyle.textIndentLine());
     2005        destination.setTextIndentType(blendingStyle.textIndentType());
     2006        LengthPropertyWrapper::blend(destination, from, to, context);
    20232007    }
    20242008};
     
    20332017
    20342018private:
    2035     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    2036     {
    2037         if (!from->hasPerspective() || !to->hasPerspective())
     2019    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     2020    {
     2021        if (!from.hasPerspective() || !to.hasPerspective())
    20382022            return false;
    20392023        return NonNegativeFloatPropertyWrapper::canInterpolate(from, to);
    20402024    }
    20412025
    2042     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    2043     {
    2044         if (!canInterpolate(from, to))
    2045             (destination->*m_setter)(progress ? value(to) : value(from));
     2026    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     2027    {
     2028        if (context.isDiscrete)
     2029            (destination.*m_setter)(context.progress ? value(to) : value(from));
    20462030        else
    2047             NonNegativeFloatPropertyWrapper::blend(client, destination, from, to, progress);
     2031            NonNegativeFloatPropertyWrapper::blend(destination, from, to, context);
    20482032    }
    20492033};
     
    20582042
    20592043private:
    2060     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
     2044    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
    20612045    {
    20622046        return value(from).isSpaces() == value(to).isSpaces();
    20632047    }
    20642048
    2065     void blend(const CSSPropertyBlendingClient* client, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    2066     {
    2067         if (!canInterpolate(from, to))
    2068             (destination->*m_setter)(progress ? value(to) : value(from));
     2049    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     2050    {
     2051        if (context.isDiscrete)
     2052            (destination.*m_setter)(context.progress ? value(to) : value(from));
    20692053        else
    2070             PropertyWrapper::blend(client, destination, from, to, progress);
     2054            PropertyWrapper::blend(destination, from, to, context);
    20712055    }
    20722056};
     
    20802064    }
    20812065
    2082     bool equals(const RenderStyle* a, const RenderStyle* b) const final
    2083     {
    2084         if (a == b)
     2066    bool equals(const RenderStyle& a, const RenderStyle& b) const final
     2067    {
     2068        if (&a == &b)
    20852069            return true;
    2086         if (!a || !b)
    2087             return false;
    2088 
    2089         return a->aspectRatioType() == b->aspectRatioType() && a->aspectRatioWidth() == b->aspectRatioWidth() && a->aspectRatioHeight() == b->aspectRatioHeight();
    2090     }
    2091 
    2092     bool canInterpolate(const RenderStyle* from, const RenderStyle* to) const final
    2093     {
    2094         return (from->aspectRatioType() == AspectRatioType::Ratio && to->aspectRatioType() == AspectRatioType::Ratio) || (from->aspectRatioType() == AspectRatioType::AutoAndRatio && to->aspectRatioType() == AspectRatioType::AutoAndRatio);
     2070
     2071        return a.aspectRatioType() == b.aspectRatioType() && a.aspectRatioWidth() == b.aspectRatioWidth() && a.aspectRatioHeight() == b.aspectRatioHeight();
     2072    }
     2073
     2074    bool canInterpolate(const RenderStyle& from, const RenderStyle& to) const final
     2075    {
     2076        return (from.aspectRatioType() == AspectRatioType::Ratio && to.aspectRatioType() == AspectRatioType::Ratio) || (from.aspectRatioType() == AspectRatioType::AutoAndRatio && to.aspectRatioType() == AspectRatioType::AutoAndRatio);
    20952077    }
    20962078
    20972079#if !LOG_DISABLED
    2098     void logBlend(const RenderStyle* from, const RenderStyle* to, const RenderStyle* result, double progress) const final
    2099     {
    2100         LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << from->logicalAspectRatio() << " to " << to->logicalAspectRatio() << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << result->logicalAspectRatio());
     2080    void logBlend(const RenderStyle& from, const RenderStyle& to, const RenderStyle& destination, double progress) const final
     2081    {
     2082        LOG_WITH_STREAM(Animations, stream << "  blending " << getPropertyName(property()) << " from " << from.logicalAspectRatio() << " to " << to.logicalAspectRatio() << " at " << TextStream::FormatNumberRespectingIntegers(progress) << " -> " << destination.logicalAspectRatio());
    21012083    }
    21022084#endif
    21032085
    2104     void blend(const CSSPropertyBlendingClient*, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress) const final
    2105     {
    2106         destination->setAspectRatioType(progress < 0.5 ? from->aspectRatioType() : to->aspectRatioType());
    2107         if (canInterpolate(from, to)) {
    2108             auto aspectRatioDst = WebCore::blend(log(from->logicalAspectRatio()), log(to->logicalAspectRatio()), progress);
    2109             destination->setAspectRatio(exp(aspectRatioDst), 1);
     2086    void blend(RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, const CSSPropertyBlendingContext& context) const final
     2087    {
     2088        destination.setAspectRatioType(context.progress < 0.5 ? from.aspectRatioType() : to.aspectRatioType());
     2089        if (!context.isDiscrete) {
     2090            auto aspectRatioDst = WebCore::blend(log(from.logicalAspectRatio()), log(to.logicalAspectRatio()), context);
     2091            destination.setAspectRatio(exp(aspectRatioDst), 1);
    21102092            return;
    21112093        }
    21122094        // For auto/auto-zero aspect-ratio we use discrete values, we can't use general
    21132095        // logic since logicalAspectRatio asserts on aspect-ratio type.
    2114         ASSERT(!progress || progress == 1);
    2115         auto* applicableStyle = progress ? to : from;
    2116         destination->setAspectRatio(applicableStyle->aspectRatioWidth(), applicableStyle->aspectRatioHeight());
     2096        ASSERT(!context.progress || context.progress == 1);
     2097        auto& applicableStyle = context.progress ? to : from;
     2098        destination.setAspectRatio(applicableStyle.aspectRatioWidth(), applicableStyle.aspectRatioHeight());
    21172099    }
    21182100};
     
    25142496}
    25152497
    2516 void CSSPropertyAnimation::blendProperties(const CSSPropertyBlendingClient* client, CSSPropertyID property, RenderStyle* destination, const RenderStyle* from, const RenderStyle* to, double progress)
     2498void CSSPropertyAnimation::blendProperties(const CSSPropertyBlendingClient* client, CSSPropertyID property, RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, double progress)
    25172499{
    25182500    ASSERT(property != CSSPropertyInvalid);
     
    25212503    if (wrapper) {
    25222504        // https://drafts.csswg.org/web-animations-1/#discrete
    2523         // The propertys values cannot be meaningfully combined, thus it is not additive and
     2505        // The property's values cannot be meaningfully combined, thus it is not additive and
    25242506        // interpolation swaps from Va to Vb at 50% (p=0.5).
    2525         if (!wrapper->canInterpolate(from, to))
     2507        auto isDiscrete = !wrapper->canInterpolate(from, to);
     2508        if (isDiscrete)
    25262509            progress = progress < 0.5 ? 0 : 1;
    2527         wrapper->blend(client, destination, from, to, progress);
     2510        wrapper->blend(destination, from, to, { progress, isDiscrete, client });
    25282511#if !LOG_DISABLED
    25292512        wrapper->logBlend(from, to, destination, progress);
     
    25552538}
    25562539
    2557 bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID property, const RenderStyle* a, const RenderStyle* b)
     2540bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID property, const RenderStyle& a, const RenderStyle& b)
    25582541{
    25592542    AnimationPropertyWrapperBase* wrapper = CSSPropertyAnimationWrapperMap::singleton().wrapperForProperty(property);
     
    25632546}
    25642547
    2565 bool CSSPropertyAnimation::canPropertyBeInterpolated(CSSPropertyID property, const RenderStyle* from, const RenderStyle* to)
     2548bool CSSPropertyAnimation::canPropertyBeInterpolated(CSSPropertyID property, const RenderStyle& from, const RenderStyle& to)
    25662549{
    25672550    AnimationPropertyWrapperBase* wrapper = CSSPropertyAnimationWrapperMap::singleton().wrapperForProperty(property);
  • trunk/Source/WebCore/animation/CSSPropertyAnimation.h

    r267188 r276141  
    4141    static bool isPropertyAnimatable(CSSPropertyID);
    4242    static bool animationOfPropertyIsAccelerated(CSSPropertyID);
    43     static bool propertiesEqual(CSSPropertyID, const RenderStyle* a, const RenderStyle* b);
    44     static bool canPropertyBeInterpolated(CSSPropertyID, const RenderStyle* a, const RenderStyle* b);
     43    static bool propertiesEqual(CSSPropertyID, const RenderStyle& a, const RenderStyle& b);
     44    static bool canPropertyBeInterpolated(CSSPropertyID, const RenderStyle& a, const RenderStyle& b);
    4545    static CSSPropertyID getPropertyAtIndex(int, Optional<bool>& isShorthand);
    4646    static int getNumProperties();
     
    4848    static HashSet<CSSPropertyID> animatableShorthandsAffectingProperty(CSSPropertyID);
    4949
    50     // Return true if we need to start software animation timers
    51     static void blendProperties(const CSSPropertyBlendingClient*, CSSPropertyID, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress);
     50    static void blendProperties(const CSSPropertyBlendingClient*, CSSPropertyID, RenderStyle& destination, const RenderStyle& from, const RenderStyle& to, double progress);
    5251};
    5352
  • trunk/Source/WebCore/animation/KeyframeEffect.cpp

    r274165 r276141  
    14191419    if (m_blendingKeyframesSource == BlendingKeyframesSource::CSSTransition) {
    14201420        ASSERT(properties.size() == 1);
    1421         CSSPropertyAnimation::blendProperties(this, *properties.begin(), &targetStyle, m_blendingKeyframes[0].style(), m_blendingKeyframes[1].style(), iterationProgress);
     1421        CSSPropertyAnimation::blendProperties(this, *properties.begin(), targetStyle, *m_blendingKeyframes[0].style(), *m_blendingKeyframes[1].style(), iterationProgress);
    14221422        return;
    14231423    }
     
    15331533            auto keyframeIndex = intervalEndpoints[0];
    15341534            auto keyframeStyle = !keyframeIndex ? &targetStyle : m_blendingKeyframes[keyframeIndex.value()].style();
    1535             CSSPropertyAnimation::blendProperties(this, cssPropertyId, &targetStyle, keyframeStyle, keyframeStyle, 0);
     1535            CSSPropertyAnimation::blendProperties(this, cssPropertyId, targetStyle, *keyframeStyle, *keyframeStyle, 0);
    15361536            continue;
    15371537        }
     
    15641564        auto startStyle = !startKeyframeIndex ? &targetStyle : m_blendingKeyframes[startKeyframeIndex.value()].style();
    15651565        auto endStyle = !endKeyframeIndex ? &targetStyle : m_blendingKeyframes[endKeyframeIndex.value()].style();
    1566         CSSPropertyAnimation::blendProperties(this, cssPropertyId, &targetStyle, startStyle, endStyle, transformedDistance);
     1566        CSSPropertyAnimation::blendProperties(this, cssPropertyId, targetStyle, *startStyle, *endStyle, transformedDistance);
    15671567    }
    15681568}
  • trunk/Source/WebCore/css/CSSCrossfadeValue.cpp

    r252392 r276141  
    3939namespace WebCore {
    4040
    41 static inline double blendFunc(double from, double to, double progress)
    42 {
    43     return blend(from, to, progress);
     41static inline double blendFunc(double from, double to, const BlendingContext& context)
     42{
     43    return blend(from, to, context);
    4444}
    4545
     
    203203}
    204204
    205 RefPtr<CSSCrossfadeValue> CSSCrossfadeValue::blend(const CSSCrossfadeValue& from, double progress) const
     205RefPtr<CSSCrossfadeValue> CSSCrossfadeValue::blend(const CSSCrossfadeValue& from, const BlendingContext& context) const
    206206{
    207207    ASSERT(equalInputImages(from));
     
    219219    if (m_percentageValue->isPercentage())
    220220        toPercentage /= 100.0;
    221     auto percentageValue = CSSPrimitiveValue::create(blendFunc(fromPercentage, toPercentage, progress), CSSUnitType::CSS_NUMBER);
     221    auto percentageValue = CSSPrimitiveValue::create(blendFunc(fromPercentage, toPercentage, context), CSSUnitType::CSS_NUMBER);
    222222
    223223    return CSSCrossfadeValue::create(WTFMove(fromImageValue), WTFMove(toImageValue), WTFMove(percentageValue), from.isPrefixed() && isPrefixed());
  • trunk/Source/WebCore/css/CSSCrossfadeValue.h

    r218501 r276141  
    3333namespace WebCore {
    3434
     35struct BlendingContext;
    3536class CSSPrimitiveValue;
    3637
     
    5556    bool traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const;
    5657
    57     RefPtr<CSSCrossfadeValue> blend(const CSSCrossfadeValue&, double) const;
     58    RefPtr<CSSCrossfadeValue> blend(const CSSCrossfadeValue&, const BlendingContext&) const;
    5859
    5960    bool equals(const CSSCrossfadeValue&) const;
  • trunk/Source/WebCore/css/CSSGradientValue.cpp

    r276002 r276141  
    2727#include "CSSGradientValue.h"
    2828
     29#include "AnimationUtilities.h"
    2930#include "CSSCalculationValue.h"
    3031#include "CSSToLengthConversionData.h"
     
    206207                float interStopProportion = -prevOffset / (nextOffset - prevOffset);
    207208                // FIXME: when we interpolate gradients using premultiplied colors, this should do premultiplication.
    208                 Color blendedColor = blend(stops[firstZeroOrGreaterIndex - 1].color, stops[firstZeroOrGreaterIndex].color, interStopProportion);
     209                Color blendedColor = blend(stops[firstZeroOrGreaterIndex - 1].color, stops[firstZeroOrGreaterIndex].color, { interStopProportion });
    209210
    210211                // Clamp the positions to 0 and set the color.
     
    257258                float interStopProportion = -previousOffset / (nextOffset - previousOffset);
    258259                // FIXME: when we interpolate gradients using premultiplied colors, this should do premultiplication.
    259                 Color blendedColor = blend(stops[index - 1].color, stops[index].color, interStopProportion);
     260                Color blendedColor = blend(stops[index - 1].color, stops[index].color, { interStopProportion });
    260261
    261262                // Clamp the positions to 0 and set the color.
     
    287288                float interStopProportion = (1 - previousOffset) / (nextOffset - previousOffset);
    288289                // FIXME: when we interpolate gradients using premultiplied colors, this should do premultiplication.
    289                 Color blendedColor = blend(stops[index].color, stops[index + 1].color, interStopProportion);
     290                Color blendedColor = blend(stops[index].color, stops[index + 1].color, { interStopProportion });
    290291
    291292                // Clamp the positions to 1 and set the color.
     
    486487            float multiplier = std::pow(relativeOffset, std::log(.5f) / std::log(midpoint));
    487488            // FIXME: Why not premultiply here?
    488             newStops[y].color = blendWithoutPremultiply(color1, color2, multiplier);
     489            newStops[y].color = blendWithoutPremultiply(color1, color2, { multiplier });
    489490        }
    490491
  • trunk/Source/WebCore/platform/Length.cpp

    r276138 r276141  
    2626#include "Length.h"
    2727
     28#include "AnimationUtilities.h"
    2829#include "CalculationValue.h"
    2930#include <wtf/ASCIICType.h>
     
    295296}
    296297
    297 static Length blendMixedTypes(const Length& from, const Length& to, double progress)
    298 {
    299     if (!to.isCalculated() && !from.isPercent() && (progress == 1 || from.isZero()))
    300         return blend(Length(0, to.type()), to, progress);
    301 
    302     if (!from.isCalculated() && !to.isPercent() && (!progress || to.isZero()))
    303         return blend(from, Length(0, from.type()), progress);
    304 
    305     auto blend = makeUnique<CalcExpressionBlendLength>(from, to, progress);
     298static Length blendMixedTypes(const Length& from, const Length& to, const BlendingContext& context)
     299{
     300    if (!to.isCalculated() && !from.isPercent() && (context.progress == 1 || from.isZero()))
     301        return blend(Length(0, to.type()), to, context);
     302
     303    if (!from.isCalculated() && !to.isPercent() && (!context.progress || to.isZero()))
     304        return blend(from, Length(0, from.type()), context);
     305
     306    auto blend = makeUnique<CalcExpressionBlendLength>(from, to, context.progress);
    306307    return Length(CalculationValue::create(WTFMove(blend), ValueRangeAll));
    307308}
    308309
    309 Length blend(const Length& from, const Length& to, double progress)
     310Length blend(const Length& from, const Length& to, const BlendingContext& context)
    310311{
    311312    if ((from.isAuto() || to.isAuto()) || (from.isUndefined() || to.isUndefined()))
    312         return progress < 0.5 ? from : to;
     313        return context.progress < 0.5 ? from : to;
    313314
    314315    if (from.isCalculated() || to.isCalculated() || (from.type() != to.type()))
    315         return blendMixedTypes(from, to, progress);
    316 
    317     if (!progress)
     316        return blendMixedTypes(from, to, context);
     317
     318    if (!context.progress)
    318319        return from;
    319320
    320     if (progress == 1)
     321    if (context.progress == 1)
    321322        return to;
    322323
     
    328329        float fromPercent = from.isZero() ? 0 : from.percent();
    329330        float toPercent = to.isZero() ? 0 : to.percent();
    330         return Length(WebCore::blend(fromPercent, toPercent, progress), LengthType::Percent);
     331        return Length(WebCore::blend(fromPercent, toPercent, context), LengthType::Percent);
    331332    }
    332333
    333334    float fromValue = from.isZero() ? 0 : from.value();
    334335    float toValue = to.isZero() ? 0 : to.value();
    335     return Length(WebCore::blend(fromValue, toValue, progress), resultType);
    336 }
    337 
    338 Length blend(const Length& from, const Length& to, double progress, ValueRange valueRange)
    339 {
    340     auto blended = blend(from, to, progress);
     336    return Length(WebCore::blend(fromValue, toValue, context), resultType);
     337}
     338
     339Length blend(const Length& from, const Length& to, const BlendingContext& context, ValueRange valueRange)
     340{
     341    auto blended = blend(from, to, context);
    341342    if (valueRange == ValueRangeNonNegative && blended.isNegative())
    342343        return { 0, from.isZero () ? to.type() : from.type() };
  • trunk/Source/WebCore/platform/Length.h

    r273635 r276141  
    5050};
    5151
     52struct BlendingContext;
    5253class CalculationValue;
    5354
     
    138139
    139140// Blend two lengths to produce a new length that is in between them. Used for animation.
    140 Length blend(const Length& from, const Length& to, double progress);
    141 Length blend(const Length& from, const Length& to, double progress, ValueRange);
     141Length blend(const Length& from, const Length& to, const BlendingContext&);
     142Length blend(const Length& from, const Length& to, const BlendingContext&, ValueRange);
    142143
    143144UniqueArray<Length> newCoordsArray(const String&, int& length);
  • trunk/Source/WebCore/platform/LengthPoint.h

    r261585 r276141  
    2929
    3030namespace WebCore {
     31
     32struct BlendingContext;
    3133
    3234struct LengthPoint {
     
    6466};
    6567
    66 inline LengthPoint blend(const LengthPoint& from, const LengthPoint& to, double progress)
     68inline LengthPoint blend(const LengthPoint& from, const LengthPoint& to, const BlendingContext& context)
    6769{
    68     return LengthPoint(blend(from.x(), to.x(), progress), blend(from.y(), to.y(), progress));
     70    return LengthPoint(blend(from.x(), to.x(), context), blend(from.y(), to.y(), context));
    6971}
    7072
  • trunk/Source/WebCore/platform/LengthSize.h

    r251207 r276141  
    2424namespace WebCore {
    2525
     26struct BlendingContext;
     27
    2628struct LengthSize {
    2729    Length width;
     
    3739}
    3840
    39 inline LengthSize blend(const LengthSize& from, const LengthSize& to, double progress)
     41inline LengthSize blend(const LengthSize& from, const LengthSize& to, const BlendingContext& context)
    4042{
    41     return { blend(from.width, to.width, progress), blend(from.height, to.height, progress) };
     43    return { blend(from.width, to.width, context), blend(from.height, to.height, context) };
    4244}
    4345
  • trunk/Source/WebCore/platform/animation/AnimationUtilities.h

    r275272 r276141  
    3131namespace WebCore {
    3232
    33 inline int blend(int from, int to, double progress)
     33struct BlendingContext {
     34    double progress { 0 };
     35    bool isDiscrete { false };
     36};
     37
     38inline int blend(int from, int to, const BlendingContext& context)
    3439
    35     return static_cast<int>(lround(static_cast<double>(from) + static_cast<double>(to - from) * progress));
     40    return static_cast<int>(lround(static_cast<double>(from) + static_cast<double>(to - from) * context.progress));
    3641}
    3742
    38 inline unsigned blend(unsigned from, unsigned to, double progress)
     43inline unsigned blend(unsigned from, unsigned to, const BlendingContext& context)
    3944{
    40     return static_cast<unsigned>(lround(to > from ? static_cast<double>(from) + static_cast<double>(to - from) * progress : static_cast<double>(from) - static_cast<double>(from - to) * progress));
     45    return static_cast<unsigned>(lround(to > from ? static_cast<double>(from) + static_cast<double>(to - from) * context.progress : static_cast<double>(from) - static_cast<double>(from - to) * context.progress));
    4146}
    4247
    43 inline double blend(double from, double to, double progress)
     48inline double blend(double from, double to, const BlendingContext& context)
    4449
    45     return from + (to - from) * progress;
     50    return from + (to - from) * context.progress;
    4651}
    4752
    48 inline float blend(float from, float to, double progress)
     53inline float blend(float from, float to, const BlendingContext& context)
    4954
    50     return static_cast<float>(from + (to - from) * progress);
     55    return static_cast<float>(from + (to - from) * context.progress);
    5156}
    5257
    53 inline LayoutUnit blend(LayoutUnit from, LayoutUnit to, double progress)
     58inline LayoutUnit blend(LayoutUnit from, LayoutUnit to, const BlendingContext& context)
    5459{
    55     return LayoutUnit(blend(from.toFloat(), to.toFloat(), progress));
     60    return LayoutUnit(blend(from.toFloat(), to.toFloat(), context));
    5661}
    5762
    58 inline IntPoint blend(const IntPoint& from, const IntPoint& to, double progress)
     63inline IntPoint blend(const IntPoint& from, const IntPoint& to, const BlendingContext& context)
    5964{
    60     return IntPoint(blend(from.x(), to.x(), progress),
    61         blend(from.y(), to.y(), progress));
     65    return IntPoint(blend(from.x(), to.x(), context),
     66        blend(from.y(), to.y(), context));
    6267}
    6368
    64 inline LayoutPoint blend(const LayoutPoint& from, const LayoutPoint& to, double progress)
     69inline LayoutPoint blend(const LayoutPoint& from, const LayoutPoint& to, const BlendingContext& context)
    6570{
    66     return LayoutPoint(blend(from.x(), to.x(), progress),
    67         blend(from.y(), to.y(), progress));
     71    return LayoutPoint(blend(from.x(), to.x(), context),
     72        blend(from.y(), to.y(), context));
    6873}
    6974
  • trunk/Source/WebCore/platform/graphics/ColorBlending.cpp

    r274408 r276141  
    9191}
    9292
    93 Color blend(const Color& from, const Color& to, double progress)
     93Color blend(const Color& from, const Color& to, const BlendingContext& context)
    9494{
    9595    // FIXME: ExtendedColor - needs to handle color spaces.
    9696    // We need to preserve the state of the valid flag at the end of the animation
    97     if (progress == 1 && !to.isValid())
     97    if (context.progress == 1 && !to.isValid())
    9898        return { };
    9999
     
    102102
    103103    auto premultipliedBlended = makeFromComponentsClamping<SRGBA<float>>(
    104         WebCore::blend(premultipliedFrom.red, premultipliedTo.red, progress),
    105         WebCore::blend(premultipliedFrom.green, premultipliedTo.green, progress),
    106         WebCore::blend(premultipliedFrom.blue, premultipliedTo.blue, progress),
    107         WebCore::blend(premultipliedFrom.alpha, premultipliedTo.alpha, progress)
     104        WebCore::blend(premultipliedFrom.red, premultipliedTo.red, context),
     105        WebCore::blend(premultipliedFrom.green, premultipliedTo.green, context),
     106        WebCore::blend(premultipliedFrom.blue, premultipliedTo.blue, context),
     107        WebCore::blend(premultipliedFrom.alpha, premultipliedTo.alpha, context)
    108108    );
    109109
     
    111111}
    112112
    113 Color blendWithoutPremultiply(const Color& from, const Color& to, double progress)
     113Color blendWithoutPremultiply(const Color& from, const Color& to, const BlendingContext& context)
    114114{
    115115    // FIXME: ExtendedColor - needs to handle color spaces.
    116116    // We need to preserve the state of the valid flag at the end of the animation
    117     if (progress == 1 && !to.isValid())
     117    if (context.progress == 1 && !to.isValid())
    118118        return { };
    119119
     
    122122
    123123    auto blended = makeFromComponentsClamping<SRGBA<float>>(
    124         WebCore::blend(fromSRGB.red, toSRGB.red, progress),
    125         WebCore::blend(fromSRGB.green, toSRGB.green, progress),
    126         WebCore::blend(fromSRGB.blue, toSRGB.blue, progress),
    127         WebCore::blend(fromSRGB.alpha, toSRGB.alpha, progress)
     124        WebCore::blend(fromSRGB.red, toSRGB.red, context),
     125        WebCore::blend(fromSRGB.green, toSRGB.green, context),
     126        WebCore::blend(fromSRGB.blue, toSRGB.blue, context),
     127        WebCore::blend(fromSRGB.alpha, toSRGB.alpha, context)
    128128    );
    129129
  • trunk/Source/WebCore/platform/graphics/ColorBlending.h

    r263776 r276141  
    2828namespace WebCore {
    2929
     30struct BlendingContext;
    3031class Color;
    3132
     
    3839Color blendWithWhite(const Color&);
    3940
    40 Color blend(const Color& from, const Color& to, double progress);
    41 Color blendWithoutPremultiply(const Color& from, const Color& to, double progress);
     41Color blend(const Color& from, const Color& to, const BlendingContext&);
     42Color blendWithoutPremultiply(const Color& from, const Color& to, const BlendingContext&);
    4243
    4344}
  • trunk/Source/WebCore/platform/graphics/ca/cocoa/PlatformCAFiltersCocoa.mm

    r272760 r276141  
    464464        double t = filterOperation ? downcast<BasicColorMatrixFilterOperation>(*filterOperation).amount() : 0;
    465465        t = std::min(std::max(0.0, t), 1.0);
     466        BlendingContext context { t };
    466467        CAColorMatrix colorMatrix = {
    467             static_cast<float>(WebCore::blend(sepiaNoneConstants[0][0], sepiaFullConstants[0][0], t)),
    468             static_cast<float>(WebCore::blend(sepiaNoneConstants[0][1], sepiaFullConstants[0][1], t)),
    469             static_cast<float>(WebCore::blend(sepiaNoneConstants[0][2], sepiaFullConstants[0][2], t)), 0, 0,
     468            static_cast<float>(WebCore::blend(sepiaNoneConstants[0][0], sepiaFullConstants[0][0], context)),
     469            static_cast<float>(WebCore::blend(sepiaNoneConstants[0][1], sepiaFullConstants[0][1], context)),
     470            static_cast<float>(WebCore::blend(sepiaNoneConstants[0][2], sepiaFullConstants[0][2], context)), 0, 0,
    470471           
    471             static_cast<float>(WebCore::blend(sepiaNoneConstants[1][0], sepiaFullConstants[1][0], t)),
    472             static_cast<float>(WebCore::blend(sepiaNoneConstants[1][1], sepiaFullConstants[1][1], t)),
    473             static_cast<float>(WebCore::blend(sepiaNoneConstants[1][2], sepiaFullConstants[1][2], t)), 0, 0,
     472            static_cast<float>(WebCore::blend(sepiaNoneConstants[1][0], sepiaFullConstants[1][0], context)),
     473            static_cast<float>(WebCore::blend(sepiaNoneConstants[1][1], sepiaFullConstants[1][1], context)),
     474            static_cast<float>(WebCore::blend(sepiaNoneConstants[1][2], sepiaFullConstants[1][2], context)), 0, 0,
    474475           
    475             static_cast<float>(WebCore::blend(sepiaNoneConstants[2][0], sepiaFullConstants[2][0], t)),
    476             static_cast<float>(WebCore::blend(sepiaNoneConstants[2][1], sepiaFullConstants[2][1], t)),
    477             static_cast<float>(WebCore::blend(sepiaNoneConstants[2][2], sepiaFullConstants[2][2], t)), 0, 0,
     476            static_cast<float>(WebCore::blend(sepiaNoneConstants[2][0], sepiaFullConstants[2][0], context)),
     477            static_cast<float>(WebCore::blend(sepiaNoneConstants[2][1], sepiaFullConstants[2][1], context)),
     478            static_cast<float>(WebCore::blend(sepiaNoneConstants[2][2], sepiaFullConstants[2][2], context)), 0, 0,
    478479            0, 0, 0, 1, 0
    479480        };
  • trunk/Source/WebCore/platform/graphics/filters/FilterOperation.cpp

    r275206 r276141  
    7575}
    7676
    77 RefPtr<FilterOperation> BasicColorMatrixFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
     77RefPtr<FilterOperation> BasicColorMatrixFilterOperation::blend(const FilterOperation* from, const BlendingContext& context, bool blendToPassthrough)
    7878{
    7979    if (from && !from->isSameType(*this))
     
    8181   
    8282    if (blendToPassthrough)
    83         return BasicColorMatrixFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), progress), m_type);
     83        return BasicColorMatrixFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), context), m_type);
    8484       
    8585    const BasicColorMatrixFilterOperation* fromOperation = downcast<BasicColorMatrixFilterOperation>(from);
    8686    double fromAmount = fromOperation ? fromOperation->amount() : passthroughAmount();
    87     return BasicColorMatrixFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
     87    return BasicColorMatrixFilterOperation::create(WebCore::blend(fromAmount, m_amount, context), m_type);
    8888}
    8989
     
    138138}
    139139
    140 RefPtr<FilterOperation> BasicComponentTransferFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
     140RefPtr<FilterOperation> BasicComponentTransferFilterOperation::blend(const FilterOperation* from, const BlendingContext& context, bool blendToPassthrough)
    141141{
    142142    if (from && !from->isSameType(*this))
     
    144144   
    145145    if (blendToPassthrough)
    146         return BasicComponentTransferFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), progress), m_type);
     146        return BasicComponentTransferFilterOperation::create(WebCore::blend(m_amount, passthroughAmount(), context), m_type);
    147147       
    148148    const BasicComponentTransferFilterOperation* fromOperation = downcast<BasicComponentTransferFilterOperation>(from);
    149149    double fromAmount = fromOperation ? fromOperation->amount() : passthroughAmount();
    150     return BasicComponentTransferFilterOperation::create(WebCore::blend(fromAmount, m_amount, progress), m_type);
     150    return BasicComponentTransferFilterOperation::create(WebCore::blend(fromAmount, m_amount, context), m_type);
    151151}
    152152
     
    216216}
    217217   
    218 RefPtr<FilterOperation> InvertLightnessFilterOperation::blend(const FilterOperation* from, double, bool)
     218RefPtr<FilterOperation> InvertLightnessFilterOperation::blend(const FilterOperation* from, const BlendingContext&, bool)
    219219{
    220220    if (from && !from->isSameType(*this))
     
    332332}
    333333   
    334 RefPtr<FilterOperation> BlurFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
     334RefPtr<FilterOperation> BlurFilterOperation::blend(const FilterOperation* from, const BlendingContext& context, bool blendToPassthrough)
    335335{
    336336    if (from && !from->isSameType(*this))
     
    340340
    341341    if (blendToPassthrough)
    342         return BlurFilterOperation::create(WebCore::blend(m_stdDeviation, Length(lengthType), progress));
     342        return BlurFilterOperation::create(WebCore::blend(m_stdDeviation, Length(lengthType), context));
    343343
    344344    const BlurFilterOperation* fromOperation = downcast<BlurFilterOperation>(from);
    345345    Length fromLength = fromOperation ? fromOperation->m_stdDeviation : Length(lengthType);
    346     return BlurFilterOperation::create(WebCore::blend(fromLength, m_stdDeviation, progress));
     346    return BlurFilterOperation::create(WebCore::blend(fromLength, m_stdDeviation, context));
    347347}
    348348   
     
    355355}
    356356   
    357 RefPtr<FilterOperation> DropShadowFilterOperation::blend(const FilterOperation* from, double progress, bool blendToPassthrough)
     357RefPtr<FilterOperation> DropShadowFilterOperation::blend(const FilterOperation* from, const BlendingContext& context, bool blendToPassthrough)
    358358{
    359359    if (from && !from->isSameType(*this))
     
    362362    if (blendToPassthrough)
    363363        return DropShadowFilterOperation::create(
    364             WebCore::blend(m_location, IntPoint(), progress),
    365             WebCore::blend(m_stdDeviation, 0, progress),
    366             WebCore::blend(m_color, Color::transparentBlack, progress));
     364            WebCore::blend(m_location, IntPoint(), context),
     365            WebCore::blend(m_stdDeviation, 0, context),
     366            WebCore::blend(m_color, Color::transparentBlack, context));
    367367
    368368    const DropShadowFilterOperation* fromOperation = downcast<DropShadowFilterOperation>(from);
     
    372372   
    373373    return DropShadowFilterOperation::create(
    374         WebCore::blend(fromLocation, m_location, progress),
    375         WebCore::blend(fromStdDeviation, m_stdDeviation, progress),
    376         WebCore::blend(fromColor, m_color, progress));
     374        WebCore::blend(fromLocation, m_location, context),
     375        WebCore::blend(fromStdDeviation, m_stdDeviation, context),
     376        WebCore::blend(fromColor, m_color, context));
    377377}
    378378
  • trunk/Source/WebCore/platform/graphics/filters/FilterOperation.h

    r272731 r276141  
    4343// CSS Filters
    4444
     45struct BlendingContext;
    4546class CachedResourceLoader;
    4647class CachedSVGDocumentReference;
     
    7576    bool operator!=(const FilterOperation& o) const { return !(*this == o); }
    7677
    77     virtual RefPtr<FilterOperation> blend(const FilterOperation* /*from*/, double /*progress*/, bool /*blendToPassthrough*/ = false)
     78    virtual RefPtr<FilterOperation> blend(const FilterOperation* /*from*/, const BlendingContext&, bool /*blendToPassthrough*/ = false)
    7879    {
    7980        return nullptr;
     
    216217    double amount() const { return m_amount; }
    217218
    218     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
     219    RefPtr<FilterOperation> blend(const FilterOperation* from, const BlendingContext&, bool blendToPassthrough = false) override;
    219220
    220221private:
     
    251252    bool affectsOpacity() const override { return m_type == OPACITY; }
    252253
    253     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
     254    RefPtr<FilterOperation> blend(const FilterOperation* from, const BlendingContext&, bool blendToPassthrough = false) override;
    254255
    255256private:
     
    281282    }
    282283
    283     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
     284    RefPtr<FilterOperation> blend(const FilterOperation* from, const BlendingContext&, bool blendToPassthrough = false) override;
    284285
    285286private:
     
    312313    bool movesPixels() const override { return true; }
    313314
    314     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
     315    RefPtr<FilterOperation> blend(const FilterOperation* from, const BlendingContext&, bool blendToPassthrough = false) override;
    315316
    316317private:
     
    347348    bool movesPixels() const override { return true; }
    348349
    349     RefPtr<FilterOperation> blend(const FilterOperation* from, double progress, bool blendToPassthrough = false) override;
     350    RefPtr<FilterOperation> blend(const FilterOperation* from, const BlendingContext&, bool blendToPassthrough = false) override;
    350351
    351352private:
  • trunk/Source/WebCore/platform/graphics/transforms/IdentityTransformOperation.h

    r220503 r276141  
    3030namespace WebCore {
    3131
     32struct BlendingContext;
     33
    3234class IdentityTransformOperation final : public TransformOperation {
    3335public:
     
    5557    }
    5658
    57     Ref<TransformOperation> blend(const TransformOperation*, double, bool = false) override
     59    Ref<TransformOperation> blend(const TransformOperation*, const BlendingContext&, bool = false) override
    5860    {
    5961        return *this;
  • trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.cpp

    r234330 r276141  
    2727#include "Matrix3DTransformOperation.h"
    2828
     29#include "AnimationUtilities.h"
    2930#include <algorithm>
    3031#include <wtf/text/TextStream.h>
     
    3738}
    3839
    39 static Ref<TransformOperation> createOperation(TransformationMatrix& to, TransformationMatrix& from, double progress)
     40static Ref<TransformOperation> createOperation(TransformationMatrix& to, TransformationMatrix& from, const BlendingContext& context)
    4041{
    41     to.blend(from, progress);
     42    to.blend(from, context.progress);
    4243    return Matrix3DTransformOperation::create(to);
    4344}
    4445
    45 Ref<TransformOperation> Matrix3DTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     46Ref<TransformOperation> Matrix3DTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    4647{
    4748    if (from && !from->isSameType(*this))
     
    5859
    5960    if (blendToIdentity)
    60         return createOperation(fromT, toT, progress);
    61     return createOperation(toT, fromT, progress);
     61        return createOperation(fromT, toT, context);
     62    return createOperation(toT, fromT, context);
    6263}
    6364
  • trunk/Source/WebCore/platform/graphics/transforms/Matrix3DTransformOperation.h

    r234330 r276141  
    3131namespace WebCore {
    3232
     33struct BlendingContext;
     34
    3335class Matrix3DTransformOperation final : public TransformOperation {
    3436public:
     
    5961    }
    6062
    61     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) override;
     63    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) override;
    6264   
    6365    void dump(WTF::TextStream&) const final;
  • trunk/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.cpp

    r223476 r276141  
    2323#include "MatrixTransformOperation.h"
    2424
     25#include "AnimationUtilities.h"
    2526#include <algorithm>
    2627#include <wtf/text/TextStream.h>
     
    3637}
    3738
    38 Ref<TransformOperation> MatrixTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     39Ref<TransformOperation> MatrixTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    3940{
    40     auto createOperation = [] (TransformationMatrix& to, TransformationMatrix& from, double progress) {
    41         to.blend(from, progress);
     41    auto createOperation = [] (TransformationMatrix& to, TransformationMatrix& from, const BlendingContext& context) {
     42        to.blend(from, context.progress);
    4243        return MatrixTransformOperation::create(to);
    4344    };
     
    5556
    5657    if (blendToIdentity)
    57         return createOperation(fromT, toT, progress);
    58     return createOperation(toT, fromT, progress);
     58        return createOperation(fromT, toT, context);
     59    return createOperation(toT, fromT, context);
    5960}
    6061
  • trunk/Source/WebCore/platform/graphics/transforms/MatrixTransformOperation.h

    r220503 r276141  
    3030
    3131namespace WebCore {
     32
     33struct BlendingContext;
    3234
    3335class MatrixTransformOperation final : public TransformOperation {
     
    6365    }
    6466
    65     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) override;
     67    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) override;
    6668
    6769    void dump(WTF::TextStream&) const final;
  • trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.cpp

    r272805 r276141  
    4040}
    4141
    42 Ref<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     42Ref<TransformOperation> PerspectiveTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    4343{
    4444    if (from && !from->isSameType(*this))
     
    4747    if (blendToIdentity) {
    4848        double p = floatValueForLength(m_p, 1);
    49         p = WebCore::blend(p, 1.0, progress); // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
     49        p = WebCore::blend(p, 1.0, context); // FIXME: this seems wrong. https://bugs.webkit.org/show_bug.cgi?id=52700
    5050        return PerspectiveTransformOperation::create(Length(clampToPositiveInteger(p), LengthType::Fixed));
    5151    }
     
    5959    fromT.applyPerspective(floatValueForLength(fromP, 1));
    6060    toT.applyPerspective(floatValueForLength(toP, 1));
    61     toT.blend(fromT, progress);
     61    toT.blend(fromT, context.progress);
    6262    TransformationMatrix::Decomposed4Type decomp;
    6363    toT.decompose4(decomp);
  • trunk/Source/WebCore/platform/graphics/transforms/PerspectiveTransformOperation.h

    r234330 r276141  
    3333namespace WebCore {
    3434
     35struct BlendingContext;
     36
    3537class PerspectiveTransformOperation final : public TransformOperation {
    3638public:
     
    6062    }
    6163
    62     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) override;
     64    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) override;
    6365
    6466    void dump(WTF::TextStream&) const final;
  • trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.cpp

    r255559 r276141  
    3838}
    3939
    40 Ref<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     40Ref<TransformOperation> RotateTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    4141{
    4242    if (from && !from->isSameType(*this))
     
    4444   
    4545    if (blendToIdentity)
    46         return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * progress, type());
     46        return RotateTransformOperation::create(m_x, m_y, m_z, m_angle - m_angle * context.progress, type());
    4747   
    4848    const RotateTransformOperation* fromOp = downcast<RotateTransformOperation>(from);
     
    5656                                                fromOp ? fromOp->m_y : m_y,
    5757                                                fromOp ? fromOp->m_z : m_z,
    58                                                 WebCore::blend(fromAngle, m_angle, progress), type());
     58                                                WebCore::blend(fromAngle, m_angle, context), type());
    5959    }
    6060
     
    7575   
    7676    // Blend them
    77     toT.blend(fromT, progress);
     77    toT.blend(fromT, context.progress);
    7878   
    7979    // Extract the result as a quaternion
  • trunk/Source/WebCore/platform/graphics/transforms/RotateTransformOperation.h

    r268547 r276141  
    3030namespace WebCore {
    3131
     32struct BlendingContext;
     33
    3234class RotateTransformOperation final : public TransformOperation {
    3335public:
     
    5456    bool operator==(const TransformOperation&) const override;
    5557
    56     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) final;
     58    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) final;
    5759
    5860    bool isIdentity() const final { return !m_angle; }
  • trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.cpp

    r220503 r276141  
    3636}
    3737
    38 Ref<TransformOperation> ScaleTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     38Ref<TransformOperation> ScaleTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    3939{
    4040    if (from && !from->isSameType(*this))
     
    4242   
    4343    if (blendToIdentity)
    44         return ScaleTransformOperation::create(WebCore::blend(m_x, 1.0, progress),
    45                                                WebCore::blend(m_y, 1.0, progress),
    46                                                WebCore::blend(m_z, 1.0, progress), type());
     44        return ScaleTransformOperation::create(WebCore::blend(m_x, 1.0, context),
     45                                               WebCore::blend(m_y, 1.0, context),
     46                                               WebCore::blend(m_z, 1.0, context), type());
    4747   
    4848    const ScaleTransformOperation* fromOp = downcast<ScaleTransformOperation>(from);
     
    5050    double fromY = fromOp ? fromOp->m_y : 1.0;
    5151    double fromZ = fromOp ? fromOp->m_z : 1.0;
    52     return ScaleTransformOperation::create(WebCore::blend(fromX, m_x, progress),
    53                                            WebCore::blend(fromY, m_y, progress),
    54                                            WebCore::blend(fromZ, m_z, progress), type());
     52    return ScaleTransformOperation::create(WebCore::blend(fromX, m_x, context),
     53                                           WebCore::blend(fromY, m_y, context),
     54                                           WebCore::blend(fromZ, m_z, context), type());
    5555}
    5656
  • trunk/Source/WebCore/platform/graphics/transforms/ScaleTransformOperation.h

    r268547 r276141  
    3030namespace WebCore {
    3131
     32struct BlendingContext;
     33
    3234class ScaleTransformOperation final : public TransformOperation {
    3335public:
     
    5355    bool operator==(const TransformOperation&) const final;
    5456
    55     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) final;
     57    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) final;
    5658
    5759    bool isIdentity() const final { return m_x == 1 &&  m_y == 1 &&  m_z == 1; }
  • trunk/Source/WebCore/platform/graphics/transforms/SkewTransformOperation.cpp

    r220503 r276141  
    3636}
    3737
    38 Ref<TransformOperation> SkewTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     38Ref<TransformOperation> SkewTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    3939{
    4040    if (from && !from->isSameType(*this))
     
    4242   
    4343    if (blendToIdentity)
    44         return SkewTransformOperation::create(WebCore::blend(m_angleX, 0.0, progress), WebCore::blend(m_angleY, 0.0, progress), type());
     44        return SkewTransformOperation::create(WebCore::blend(m_angleX, 0.0, context), WebCore::blend(m_angleY, 0.0, context), type());
    4545   
    4646    const SkewTransformOperation* fromOp = downcast<SkewTransformOperation>(from);
    4747    double fromAngleX = fromOp ? fromOp->m_angleX : 0;
    4848    double fromAngleY = fromOp ? fromOp->m_angleY : 0;
    49     return SkewTransformOperation::create(WebCore::blend(fromAngleX, m_angleX, progress), WebCore::blend(fromAngleY, m_angleY, progress), type());
     49    return SkewTransformOperation::create(WebCore::blend(fromAngleX, m_angleX, context), WebCore::blend(fromAngleY, m_angleY, context), type());
    5050}
    5151
  • trunk/Source/WebCore/platform/graphics/transforms/SkewTransformOperation.h

    r220503 r276141  
    3030namespace WebCore {
    3131
     32struct BlendingContext;
     33
    3234class SkewTransformOperation final : public TransformOperation {
    3335public:
     
    5759    }
    5860
    59     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) override;
     61    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) override;
    6062
    6163    void dump(WTF::TextStream&) const final;
  • trunk/Source/WebCore/platform/graphics/transforms/TransformOperation.h

    r234330 r276141  
    3333namespace WebCore {
    3434
    35 // CSS Transforms (may become part of CSS3)
     35struct BlendingContext;
    3636
    3737class TransformOperation : public RefCounted<TransformOperation> {
     
    6868    virtual bool apply(TransformationMatrix&, const FloatSize& borderBoxSize) const = 0;
    6969
    70     virtual Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) = 0;
     70    virtual Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) = 0;
    7171
    7272    OperationType type() const { return m_type; }
  • trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.cpp

    r239535 r276141  
    2323#include "TransformOperations.h"
    2424
     25#include "AnimationUtilities.h"
    2526#include "IdentityTransformOperation.h"
    2627#include "Matrix3DTransformOperation.h"
     
    7475}
    7576
    76 TransformOperations TransformOperations::blendByMatchingOperations(const TransformOperations& from, const double& progress) const
     77TransformOperations TransformOperations::blendByMatchingOperations(const TransformOperations& from, const BlendingContext& context) const
    7778{
    7879    TransformOperations result;
     
    8485        RefPtr<TransformOperation> fromOperation = (i < fromSize) ? from.operations()[i].get() : nullptr;
    8586        RefPtr<TransformOperation> toOperation = (i < toSize) ? operations()[i].get() : nullptr;
    86         RefPtr<TransformOperation> blendedOperation = toOperation ? toOperation->blend(fromOperation.get(), progress) : (fromOperation ? RefPtr<TransformOperation>(fromOperation->blend(nullptr, progress, true)) : nullptr);
     87        RefPtr<TransformOperation> blendedOperation = toOperation ? toOperation->blend(fromOperation.get(), context) : (fromOperation ? RefPtr<TransformOperation>(fromOperation->blend(nullptr, context, true)) : nullptr);
    8788        if (blendedOperation)
    8889            result.operations().append(blendedOperation);
    8990        else {
    9091            auto identityOperation = IdentityTransformOperation::create();
    91             if (progress > 0.5)
     92            if (context.progress > 0.5)
    9293                result.operations().append(toOperation ? toOperation : WTFMove(identityOperation));
    9394            else
     
    99100}
    100101
    101 TransformOperations TransformOperations::blendByUsingMatrixInterpolation(const TransformOperations& from, double progress, const LayoutSize& size) const
     102TransformOperations TransformOperations::blendByUsingMatrixInterpolation(const TransformOperations& from, const BlendingContext& context, const LayoutSize& size) const
    102103{
    103104    TransformOperations result;
     
    109110    apply(size, toTransform);
    110111
    111     toTransform.blend(fromTransform, progress);
     112    toTransform.blend(fromTransform, context.progress);
    112113
    113114    // Append the result
     
    117118}
    118119
    119 TransformOperations TransformOperations::blend(const TransformOperations& from, double progress, const LayoutSize& size) const
     120TransformOperations TransformOperations::blend(const TransformOperations& from, const BlendingContext& context, const LayoutSize& size) const
    120121{
    121122    if (from == *this)
     
    123124
    124125    if (from.size() && from.operationsMatch(*this))
    125         return blendByMatchingOperations(from, progress);
     126        return blendByMatchingOperations(from, context);
    126127
    127     return blendByUsingMatrixInterpolation(from, progress, size);
     128    return blendByUsingMatrixInterpolation(from, context, size);
    128129}
    129130
  • trunk/Source/WebCore/platform/graphics/transforms/TransformOperations.h

    r247504 r276141  
    3131
    3232namespace WebCore {
     33
     34struct BlendingContext;
    3335
    3436class TransformOperations {
     
    8486    const TransformOperation* at(size_t index) const { return index < m_operations.size() ? m_operations.at(index).get() : 0; }
    8587
    86     TransformOperations blendByMatchingOperations(const TransformOperations& from, const double& progress) const;
    87     TransformOperations blendByUsingMatrixInterpolation(const TransformOperations& from, double progress, const LayoutSize&) const;
    88     TransformOperations blend(const TransformOperations& from, double progress, const LayoutSize&) const;
     88    TransformOperations blendByMatchingOperations(const TransformOperations& from, const BlendingContext&) const;
     89    TransformOperations blendByUsingMatrixInterpolation(const TransformOperations& from, const BlendingContext&, const LayoutSize&) const;
     90    TransformOperations blend(const TransformOperations& from, const BlendingContext&, const LayoutSize&) const;
    8991
    9092private:
  • trunk/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.cpp

    r272805 r276141  
    2323#include "TranslateTransformOperation.h"
    2424
     25#include "AnimationUtilities.h"
    2526#include "FloatConversion.h"
    2627#include <wtf/text/TextStream.h>
     
    3637}
    3738
    38 Ref<TransformOperation> TranslateTransformOperation::blend(const TransformOperation* from, double progress, bool blendToIdentity)
     39Ref<TransformOperation> TranslateTransformOperation::blend(const TransformOperation* from, const BlendingContext& context, bool blendToIdentity)
    3940{
    4041    if (from && !from->isSameType(*this))
     
    4344    Length zeroLength(0, LengthType::Fixed);
    4445    if (blendToIdentity)
    45         return TranslateTransformOperation::create(WebCore::blend(m_x, zeroLength, progress), WebCore::blend(m_y, zeroLength, progress), WebCore::blend(m_z, zeroLength, progress), type());
     46        return TranslateTransformOperation::create(WebCore::blend(m_x, zeroLength, context), WebCore::blend(m_y, zeroLength, context), WebCore::blend(m_z, zeroLength, context), type());
    4647
    4748    const TranslateTransformOperation* fromOp = downcast<TranslateTransformOperation>(from);
     
    4950    Length fromY = fromOp ? fromOp->m_y : zeroLength;
    5051    Length fromZ = fromOp ? fromOp->m_z : zeroLength;
    51     return TranslateTransformOperation::create(WebCore::blend(fromX, x(), progress), WebCore::blend(fromY, y(), progress), WebCore::blend(fromZ, z(), progress), type());
     52    return TranslateTransformOperation::create(WebCore::blend(fromX, x(), context), WebCore::blend(fromY, y(), context), WebCore::blend(fromZ, z(), context), type());
    5253}
    5354
  • trunk/Source/WebCore/platform/graphics/transforms/TranslateTransformOperation.h

    r272805 r276141  
    3131
    3232namespace WebCore {
     33
     34struct BlendingContext;
    3335
    3436class TranslateTransformOperation final : public TransformOperation {
     
    6769    bool operator==(const TransformOperation&) const final;
    6870
    69     Ref<TransformOperation> blend(const TransformOperation* from, double progress, bool blendToIdentity = false) final;
     71    Ref<TransformOperation> blend(const TransformOperation* from, const BlendingContext&, bool blendToIdentity = false) final;
    7072
    7173    bool isRepresentableIn2D() const final { return m_z.isZero(); }
  • trunk/Source/WebCore/rendering/style/BasicShapes.cpp

    r272805 r276141  
    3131#include "BasicShapes.h"
    3232
     33#include "AnimationUtilities.h"
    3334#include "BasicShapeFunctions.h"
    3435#include "CalculationValue.h"
     
    190191}
    191192
    192 Ref<BasicShape> BasicShapeCircle::blend(const BasicShape& other, double progress) const
     193Ref<BasicShape> BasicShapeCircle::blend(const BasicShape& other, const BlendingContext& context) const
    193194{
    194195    ASSERT(type() == other.type());
     
    196197    auto result =  BasicShapeCircle::create();
    197198
    198     result->setCenterX(m_centerX.blend(otherCircle.centerX(), progress));
    199     result->setCenterY(m_centerY.blend(otherCircle.centerY(), progress));
    200     result->setRadius(m_radius.blend(otherCircle.radius(), progress));
     199    result->setCenterX(m_centerX.blend(otherCircle.centerX(), context));
     200    result->setCenterY(m_centerY.blend(otherCircle.centerY(), context));
     201    result->setRadius(m_radius.blend(otherCircle.radius(), context));
    201202    return result;
    202203}
     
    253254}
    254255
    255 Ref<BasicShape> BasicShapeEllipse::blend(const BasicShape& other, double progress) const
     256Ref<BasicShape> BasicShapeEllipse::blend(const BasicShape& other, const BlendingContext& context) const
    256257{
    257258    ASSERT(type() == other.type());
     
    268269    }
    269270
    270     result->setCenterX(m_centerX.blend(otherEllipse.centerX(), progress));
    271     result->setCenterY(m_centerY.blend(otherEllipse.centerY(), progress));
    272     result->setRadiusX(m_radiusX.blend(otherEllipse.radiusX(), progress));
    273     result->setRadiusY(m_radiusY.blend(otherEllipse.radiusY(), progress));
     271    result->setCenterX(m_centerX.blend(otherEllipse.centerX(), context));
     272    result->setCenterY(m_centerY.blend(otherEllipse.centerY(), context));
     273    result->setRadiusX(m_radiusX.blend(otherEllipse.radiusX(), context));
     274    result->setRadiusY(m_radiusY.blend(otherEllipse.radiusY(), context));
    274275    return result;
    275276}
     
    316317}
    317318
    318 Ref<BasicShape> BasicShapePolygon::blend(const BasicShape& other, double progress) const
     319Ref<BasicShape> BasicShapePolygon::blend(const BasicShape& other, const BlendingContext& context) const
    319320{
    320321    ASSERT(type() == other.type());
     
    333334    for (size_t i = 0; i < length; i = i + 2) {
    334335        result->appendPoint(
    335             WebCore::blend(otherPolygon.values().at(i), m_values.at(i), progress),
    336             WebCore::blend(otherPolygon.values().at(i + 1), m_values.at(i + 1), progress));
     336            WebCore::blend(otherPolygon.values().at(i), m_values.at(i), context),
     337            WebCore::blend(otherPolygon.values().at(i + 1), m_values.at(i + 1), context));
    337338    }
    338339
     
    374375}
    375376
    376 Ref<BasicShape> BasicShapePath::blend(const BasicShape& from, double progress) const
     377Ref<BasicShape> BasicShapePath::blend(const BasicShape& from, const BlendingContext& context) const
    377378{
    378379    ASSERT(type() == from.type());
     
    381382
    382383    auto resultingPathBytes = makeUnique<SVGPathByteStream>();
    383     buildAnimatedSVGPathByteStream(*fromPath.m_byteStream, *m_byteStream, *resultingPathBytes, progress);
     384    buildAnimatedSVGPathByteStream(*fromPath.m_byteStream, *m_byteStream, *resultingPathBytes, context.progress);
    384385    auto result = BasicShapePath::create(WTFMove(resultingPathBytes));
    385386    result->setWindRule(windRule());
     
    431432}
    432433
    433 Ref<BasicShape> BasicShapeInset::blend(const BasicShape& from, double progress) const
     434Ref<BasicShape> BasicShapeInset::blend(const BasicShape& from, const BlendingContext& context) const
    434435{
    435436    ASSERT(type() == from.type());
     
    437438    auto& fromInset = downcast<BasicShapeInset>(from);
    438439    auto result =  BasicShapeInset::create();
    439     result->setTop(WebCore::blend(fromInset.top(), top(), progress));
    440     result->setRight(WebCore::blend(fromInset.right(), right(), progress));
    441     result->setBottom(WebCore::blend(fromInset.bottom(), bottom(), progress));
    442     result->setLeft(WebCore::blend(fromInset.left(), left(), progress));
    443 
    444     result->setTopLeftRadius(WebCore::blend(fromInset.topLeftRadius(), topLeftRadius(), progress));
    445     result->setTopRightRadius(WebCore::blend(fromInset.topRightRadius(), topRightRadius(), progress));
    446     result->setBottomRightRadius(WebCore::blend(fromInset.bottomRightRadius(), bottomRightRadius(), progress));
    447     result->setBottomLeftRadius(WebCore::blend(fromInset.bottomLeftRadius(), bottomLeftRadius(), progress));
     440    result->setTop(WebCore::blend(fromInset.top(), top(), context));
     441    result->setRight(WebCore::blend(fromInset.right(), right(), context));
     442    result->setBottom(WebCore::blend(fromInset.bottom(), bottom(), context));
     443    result->setLeft(WebCore::blend(fromInset.left(), left(), context));
     444
     445    result->setTopLeftRadius(WebCore::blend(fromInset.topLeftRadius(), topLeftRadius(), context));
     446    result->setTopRightRadius(WebCore::blend(fromInset.topRightRadius(), topRightRadius(), context));
     447    result->setBottomRightRadius(WebCore::blend(fromInset.bottomRightRadius(), bottomRightRadius(), context));
     448    result->setBottomLeftRadius(WebCore::blend(fromInset.bottomLeftRadius(), bottomLeftRadius(), context));
    448449
    449450    return result;
  • trunk/Source/WebCore/rendering/style/BasicShapes.h

    r272805 r276141  
    4444namespace WebCore {
    4545
     46struct BlendingContext;
    4647class FloatRect;
    4748class Path;
     
    6768
    6869    virtual bool canBlend(const BasicShape&) const = 0;
    69     virtual Ref<BasicShape> blend(const BasicShape& from, double) const = 0;
     70    virtual Ref<BasicShape> blend(const BasicShape& from, const BlendingContext&) const = 0;
    7071
    7172    virtual bool operator==(const BasicShape&) const = 0;
     
    9798    const Length& computedLength() const { return m_computedLength; }
    9899
    99     BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& from, double progress) const
    100     {
    101         return BasicShapeCenterCoordinate(TopLeft, WebCore::blend(from.m_computedLength, m_computedLength, progress));
     100    BasicShapeCenterCoordinate blend(const BasicShapeCenterCoordinate& from, const BlendingContext& context) const
     101    {
     102        return BasicShapeCenterCoordinate(TopLeft, WebCore::blend(from.m_computedLength, m_computedLength, context));
    102103    }
    103104   
     
    145146    }
    146147
    147     BasicShapeRadius blend(const BasicShapeRadius& from, double progress) const
     148    BasicShapeRadius blend(const BasicShapeRadius& from, const BlendingContext& context) const
    148149    {
    149150        if (m_type != Value || from.type() != Value)
    150151            return BasicShapeRadius(from);
    151152
    152         return BasicShapeRadius(WebCore::blend(from.value(), value(), progress));
     153        return BasicShapeRadius(WebCore::blend(from.value(), value(), context));
    153154    }
    154155   
     
    184185
    185186    bool canBlend(const BasicShape&) const override;
    186     Ref<BasicShape> blend(const BasicShape& from, double) const override;
     187    Ref<BasicShape> blend(const BasicShape& from, const BlendingContext&) const override;
    187188
    188189    bool operator==(const BasicShape&) const override;
     
    218219
    219220    bool canBlend(const BasicShape&) const override;
    220     Ref<BasicShape> blend(const BasicShape& from, double) const override;
     221    Ref<BasicShape> blend(const BasicShape& from, const BlendingContext&) const override;
    221222
    222223    bool operator==(const BasicShape&) const override;
     
    251252
    252253    bool canBlend(const BasicShape&) const override;
    253     Ref<BasicShape> blend(const BasicShape& from, double) const override;
     254    Ref<BasicShape> blend(const BasicShape& from, const BlendingContext&) const override;
    254255
    255256    bool operator==(const BasicShape&) const override;
     
    283284
    284285    bool canBlend(const BasicShape&) const override;
    285     Ref<BasicShape> blend(const BasicShape& from, double) const override;
     286    Ref<BasicShape> blend(const BasicShape& from, const BlendingContext&) const override;
    286287
    287288    bool operator==(const BasicShape&) const override;
     
    326327
    327328    bool canBlend(const BasicShape&) const override;
    328     Ref<BasicShape> blend(const BasicShape& from, double) const override;
     329    Ref<BasicShape> blend(const BasicShape& from, const BlendingContext&) const override;
    329330
    330331    bool operator==(const BasicShape&) const override;
  • trunk/Source/WebCore/style/Styleable.cpp

    r275422 r276141  
    235235{
    236236    if (auto* transition = transitions.get(property)) {
    237         if (CSSPropertyAnimation::propertiesEqual(property, &style, &transition->targetStyle()))
     237        if (CSSPropertyAnimation::propertiesEqual(property, style, transition->targetStyle()))
    238238            return true;
    239239    }
     
    357357
    358358    if (!styleable.hasRunningTransitionForProperty(property)
    359         && !CSSPropertyAnimation::propertiesEqual(property, &beforeChangeStyle, &afterChangeStyle)
    360         && CSSPropertyAnimation::canPropertyBeInterpolated(property, &beforeChangeStyle, &afterChangeStyle)
     359        && !CSSPropertyAnimation::propertiesEqual(property, beforeChangeStyle, afterChangeStyle)
     360        && CSSPropertyAnimation::canPropertyBeInterpolated(property, beforeChangeStyle, afterChangeStyle)
    361361        && !propertyInStyleMatchesValueForTransitionInMap(property, afterChangeStyle, styleable.ensureCompletedTransitionsByProperty())
    362362        && matchingBackingAnimation && transitionCombinedDuration(matchingBackingAnimation) > 0) {
     
    404404        // 4. If the element has a running transition for the property, there is a matching transition-property value, and the end value of the running
    405405        //    transition is not equal to the value of the property in the after-change style, then:
    406         if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle) || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &currentStyle, &afterChangeStyle)) {
     406        if (CSSPropertyAnimation::propertiesEqual(property, previouslyRunningTransitionCurrentStyle, afterChangeStyle) || !CSSPropertyAnimation::canPropertyBeInterpolated(property, currentStyle, afterChangeStyle)) {
    407407            // 1. If the current value of the property in the running transition is equal to the value of the property in the after-change style,
    408408            //    or if these two values cannot be interpolated, then implementations must cancel the running transition.
    409409            previouslyRunningTransition->cancelFromStyle();
    410         } else if (transitionCombinedDuration(matchingBackingAnimation) <= 0.0 || !CSSPropertyAnimation::canPropertyBeInterpolated(property, &previouslyRunningTransitionCurrentStyle, &afterChangeStyle)) {
     410        } else if (transitionCombinedDuration(matchingBackingAnimation) <= 0.0 || !CSSPropertyAnimation::canPropertyBeInterpolated(property, previouslyRunningTransitionCurrentStyle, afterChangeStyle)) {
    411411            // 2. Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the running transition
    412412            //    cannot be interpolated with the value of the property in the after-change style, then implementations must cancel the running transition.
    413413            previouslyRunningTransition->cancelFromStyle();
    414         } else if (CSSPropertyAnimation::propertiesEqual(property, &previouslyRunningTransition->reversingAdjustedStartStyle(), &afterChangeStyle)) {
     414        } else if (CSSPropertyAnimation::propertiesEqual(property, previouslyRunningTransition->reversingAdjustedStartStyle(), afterChangeStyle)) {
    415415            // 3. Otherwise, if the reversing-adjusted start value of the running transition is the same as the value of the property in the after-change
    416416            //    style (see the section on reversing of transitions for why these case exists), implementations must cancel the running transition
  • trunk/Source/WebCore/svg/SVGLengthValue.cpp

    r263617 r276141  
    215215        auto fromPercent = from.valueAsPercentage() * 100;
    216216        auto toPercent = to.valueAsPercentage() * 100;
    217         return { WebCore::blend(fromPercent, toPercent, progress), SVGLengthType::Percentage };
     217        return { WebCore::blend(fromPercent, toPercent, { progress }), SVGLengthType::Percentage };
    218218    }
    219219
     
    221221        auto fromValue = from.valueInSpecifiedUnits();
    222222        auto toValue = to.valueInSpecifiedUnits();
    223         return { WebCore::blend(fromValue, toValue, progress), to.isZero() ? from.lengthType() : to.lengthType() };
     223        return { WebCore::blend(fromValue, toValue, { progress }), to.isZero() ? from.lengthType() : to.lengthType() };
    224224    }
    225225
     
    234234
    235235    float toValue = to.valueInSpecifiedUnits();
    236     return { WebCore::blend(fromValue.releaseReturnValue(), toValue, progress), to.lengthType() };
     236    return { WebCore::blend(fromValue.releaseReturnValue(), toValue, { progress }), to.lengthType() };
    237237}
    238238
  • trunk/Source/WebCore/svg/SVGPathBlender.cpp

    r267470 r276141  
    5858static inline FloatPoint blendFloatPoint(const FloatPoint& a, const FloatPoint& b, float progress)
    5959{
    60     return FloatPoint(blend(a.x(), b.x(), progress), blend(a.y(), b.y(), progress));
     60    BlendingContext context { progress };
     61    return FloatPoint(blend(a.x(), b.x(), context), blend(a.y(), b.y(), context));
    6162}
    6263
     
    6970
    7071    if (m_fromMode == m_toMode)
    71         return blend(from, to, progress);
     72        return blend(from, to, { progress });
    7273   
    7374    float fromValue = blendMode == BlendHorizontal ? m_fromCurrentPoint.x() : m_fromCurrentPoint.y();
     
    7576
    7677    // Transform toY to the coordinate mode of fromY
    77     float animValue = blend(from, m_fromMode == AbsoluteCoordinates ? to + toValue : to - toValue, progress);
     78    float animValue = blend(from, m_fromMode == AbsoluteCoordinates ? to + toValue : to - toValue, { progress });
    7879   
    7980    if (m_isInFirstHalfOfAnimation)
     
    8182   
    8283    // Transform the animated point to the coordinate mode, needed for the current progress.
    83     float currentValue = blend(fromValue, toValue, progress);
     84    float currentValue = blend(fromValue, toValue, { progress });
    8485    return m_toMode == AbsoluteCoordinates ? animValue + currentValue : animValue - currentValue;
    8586}
     
    303304            m_fromMode);
    304305    } else {
    305         m_consumer->arcTo(blend(from.rx, to.rx, progress),
    306             blend(from.ry, to.ry, progress),
    307             blend(from.angle, to.angle, progress),
     306        BlendingContext context { progress };
     307        m_consumer->arcTo(blend(from.rx, to.rx, context),
     308            blend(from.ry, to.ry, context),
     309            blend(from.angle, to.angle, context),
    308310            m_isInFirstHalfOfAnimation ? from.largeArc : to.largeArc,
    309311            m_isInFirstHalfOfAnimation ? from.sweep : to.sweep,
Note: See TracChangeset for help on using the changeset viewer.