-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement aspect-ratio interpolation support.
Based on the discussion in w3c/csswg-drafts#4953 aspect ratios should be interpolated by the log of their value preserving the same visual speed whether they are wide or narrow. This patch adds a new interpolation type for aspect ratios and uses it for interpolating the CSS aspect-ratio property. Bug: 1156160 Change-Id: I6cbff0abef54290de559a7625e24e3c4e1f1e0e9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2586234 Reviewed-by: Kevin Ellis <kevers@chromium.org> Reviewed-by: Xida Chen <xidachen@chromium.org> Commit-Queue: Robert Flack <flackr@chromium.org> Cr-Commit-Position: refs/heads/master@{#846135} GitOrigin-RevId: 4d02791fc5a96532045066d58ea958aed1d5b524
- Loading branch information
1 parent
fce4e16
commit 29b728b
Showing
13 changed files
with
479 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
164 changes: 164 additions & 0 deletions
164
blink/renderer/core/animation/css_aspect_ratio_interpolation_type.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
// Copyright 2021 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "third_party/blink/renderer/core/animation/css_aspect_ratio_interpolation_type.h" | ||
|
||
#include <memory> | ||
#include <utility> | ||
|
||
#include "base/memory/ptr_util.h" | ||
#include "third_party/blink/renderer/core/animation/interpolable_aspect_ratio.h" | ||
#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h" | ||
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" | ||
#include "third_party/blink/renderer/core/style/computed_style.h" | ||
#include "third_party/blink/renderer/core/style/style_aspect_ratio.h" | ||
|
||
namespace blink { | ||
|
||
class CSSAspectRatioNonInterpolableValue final : public NonInterpolableValue { | ||
public: | ||
~CSSAspectRatioNonInterpolableValue() final = default; | ||
|
||
static scoped_refptr<CSSAspectRatioNonInterpolableValue> Create( | ||
StyleAspectRatio aspect_ratio) { | ||
return base::AdoptRef( | ||
new CSSAspectRatioNonInterpolableValue(aspect_ratio.GetType())); | ||
} | ||
|
||
EAspectRatioType GetAspectRatioType() const { return type_; } | ||
|
||
bool IsCompatibleWith(const CSSAspectRatioNonInterpolableValue& other) const { | ||
if (GetAspectRatioType() == EAspectRatioType::kAuto || | ||
GetAspectRatioType() != other.GetAspectRatioType()) | ||
return false; | ||
return true; | ||
} | ||
|
||
DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); | ||
|
||
private: | ||
explicit CSSAspectRatioNonInterpolableValue(EAspectRatioType type) | ||
: type_(type) {} | ||
|
||
EAspectRatioType type_; | ||
}; | ||
|
||
DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSAspectRatioNonInterpolableValue); | ||
template <> | ||
struct DowncastTraits<CSSAspectRatioNonInterpolableValue> { | ||
static bool AllowFrom(const NonInterpolableValue* value) { | ||
return value && AllowFrom(*value); | ||
} | ||
static bool AllowFrom(const NonInterpolableValue& value) { | ||
return value.GetType() == CSSAspectRatioNonInterpolableValue::static_type_; | ||
} | ||
}; | ||
|
||
class InheritedAspectRatioChecker | ||
: public CSSInterpolationType::CSSConversionChecker { | ||
public: | ||
explicit InheritedAspectRatioChecker(StyleAspectRatio aspect_ratio) | ||
: aspect_ratio_(aspect_ratio) {} | ||
|
||
private: | ||
bool IsValid(const StyleResolverState& state, | ||
const InterpolationValue& underlying) const final { | ||
return state.ParentStyle()->AspectRatio() == aspect_ratio_; | ||
} | ||
|
||
const StyleAspectRatio aspect_ratio_; | ||
}; | ||
|
||
std::unique_ptr<InterpolableValue> | ||
CSSAspectRatioInterpolationType::CreateInterpolableAspectRatio( | ||
const StyleAspectRatio& aspect_ratio) { | ||
std::unique_ptr<InterpolableAspectRatio> result = | ||
InterpolableAspectRatio::MaybeCreate(aspect_ratio); | ||
return std::move(result); | ||
} | ||
|
||
PairwiseInterpolationValue CSSAspectRatioInterpolationType::MaybeMergeSingles( | ||
InterpolationValue&& start, | ||
InterpolationValue&& end) const { | ||
if (!To<CSSAspectRatioNonInterpolableValue>(*start.non_interpolable_value) | ||
.IsCompatibleWith(To<CSSAspectRatioNonInterpolableValue>( | ||
*end.non_interpolable_value))) { | ||
return nullptr; | ||
} | ||
return PairwiseInterpolationValue(std::move(start.interpolable_value), | ||
std::move(end.interpolable_value), | ||
std::move(start.non_interpolable_value)); | ||
} | ||
|
||
InterpolationValue CSSAspectRatioInterpolationType::MaybeConvertNeutral( | ||
const InterpolationValue& underlying, | ||
ConversionCheckers& conversion_checkers) const { | ||
return InterpolationValue(underlying.interpolable_value->CloneAndZero(), | ||
underlying.non_interpolable_value); | ||
} | ||
|
||
InterpolationValue CSSAspectRatioInterpolationType::MaybeConvertInitial( | ||
const StyleResolverState&, | ||
ConversionCheckers& conversion_checkers) const { | ||
StyleAspectRatio initial_ratio = ComputedStyle::InitialStyle().AspectRatio(); | ||
return InterpolationValue( | ||
CreateInterpolableAspectRatio(initial_ratio), | ||
CSSAspectRatioNonInterpolableValue::Create(initial_ratio)); | ||
} | ||
|
||
InterpolationValue CSSAspectRatioInterpolationType::MaybeConvertInherit( | ||
const StyleResolverState& state, | ||
ConversionCheckers& conversion_checkers) const { | ||
if (!state.ParentStyle()) | ||
return nullptr; | ||
|
||
StyleAspectRatio inherited_aspect_ratio = state.ParentStyle()->AspectRatio(); | ||
conversion_checkers.push_back( | ||
std::make_unique<InheritedAspectRatioChecker>(inherited_aspect_ratio)); | ||
if (inherited_aspect_ratio.IsAuto()) | ||
return nullptr; | ||
|
||
return InterpolationValue( | ||
CreateInterpolableAspectRatio(inherited_aspect_ratio), | ||
CSSAspectRatioNonInterpolableValue::Create(inherited_aspect_ratio)); | ||
} | ||
|
||
InterpolationValue | ||
CSSAspectRatioInterpolationType::MaybeConvertStandardPropertyUnderlyingValue( | ||
const ComputedStyle& style) const { | ||
return InterpolationValue( | ||
CreateInterpolableAspectRatio(style.AspectRatio()), | ||
CSSAspectRatioNonInterpolableValue::Create(style.AspectRatio())); | ||
} | ||
|
||
InterpolationValue CSSAspectRatioInterpolationType::MaybeConvertValue( | ||
const CSSValue& value, | ||
const StyleResolverState* state, | ||
ConversionCheckers&) const { | ||
StyleAspectRatio ratio = | ||
StyleBuilderConverter::ConvertAspectRatio(*state, value); | ||
return InterpolationValue(CreateInterpolableAspectRatio(ratio), | ||
CSSAspectRatioNonInterpolableValue::Create(ratio)); | ||
} | ||
|
||
void CSSAspectRatioInterpolationType::ApplyStandardPropertyValue( | ||
const InterpolableValue& interpolable_value, | ||
const NonInterpolableValue* non_interpolable_value, | ||
StyleResolverState& state) const { | ||
const auto& aspect_ratio = To<InterpolableAspectRatio>(interpolable_value); | ||
state.Style()->SetAspectRatio(StyleAspectRatio( | ||
To<CSSAspectRatioNonInterpolableValue>(non_interpolable_value) | ||
->GetAspectRatioType(), | ||
aspect_ratio.GetRatio())); | ||
} | ||
void CSSAspectRatioInterpolationType::Composite( | ||
UnderlyingValueOwner& underlying_value_owner, | ||
double underlying_fraction, | ||
const InterpolationValue& value, | ||
double interpolation_fraction) const { | ||
underlying_value_owner.MutableValue().interpolable_value->ScaleAndAdd( | ||
underlying_fraction, *value.interpolable_value); | ||
} | ||
|
||
} // namespace blink |
53 changes: 53 additions & 0 deletions
53
blink/renderer/core/animation/css_aspect_ratio_interpolation_type.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright 2021 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_ASPECT_RATIO_INTERPOLATION_TYPE_H_ | ||
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_ASPECT_RATIO_INTERPOLATION_TYPE_H_ | ||
|
||
#include "third_party/blink/renderer/core/animation/css_interpolation_type.h" | ||
#include "third_party/blink/renderer/core/css_value_keywords.h" | ||
|
||
namespace blink { | ||
|
||
class StyleAspectRatio; | ||
|
||
class CSSAspectRatioInterpolationType : public CSSInterpolationType { | ||
public: | ||
explicit CSSAspectRatioInterpolationType(PropertyHandle property) | ||
: CSSInterpolationType(property) { | ||
DCHECK_EQ(CSSPropertyID::kAspectRatio, | ||
property.GetCSSProperty().PropertyID()); | ||
} | ||
|
||
InterpolationValue MaybeConvertStandardPropertyUnderlyingValue( | ||
const ComputedStyle&) const final; | ||
PairwiseInterpolationValue MaybeMergeSingles( | ||
InterpolationValue&& start, | ||
InterpolationValue&& end) const final; | ||
void ApplyStandardPropertyValue(const InterpolableValue&, | ||
const NonInterpolableValue*, | ||
StyleResolverState&) const final; | ||
void Composite(UnderlyingValueOwner&, | ||
double underlying_fraction, | ||
const InterpolationValue&, | ||
double interpolation_fraction) const final; | ||
|
||
static std::unique_ptr<InterpolableValue> CreateInterpolableAspectRatio( | ||
const StyleAspectRatio&); | ||
|
||
private: | ||
InterpolationValue MaybeConvertNeutral(const InterpolationValue& underlying, | ||
ConversionCheckers&) const final; | ||
InterpolationValue MaybeConvertInitial(const StyleResolverState&, | ||
ConversionCheckers&) const final; | ||
InterpolationValue MaybeConvertInherit(const StyleResolverState&, | ||
ConversionCheckers&) const final; | ||
InterpolationValue MaybeConvertValue(const CSSValue&, | ||
const StyleResolverState*, | ||
ConversionCheckers&) const final; | ||
}; | ||
|
||
} // namespace blink | ||
|
||
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_ASPECT_RATIO_INTERPOLATION_TYPE_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
blink/renderer/core/animation/interpolable_aspect_ratio.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright 2021 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "third_party/blink/renderer/core/animation/interpolable_aspect_ratio.h" | ||
#include "third_party/blink/renderer/core/animation/interpolable_value.h" | ||
#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" | ||
#include "third_party/blink/renderer/core/style/style_aspect_ratio.h" | ||
#include "third_party/blink/renderer/platform/runtime_enabled_features.h" | ||
|
||
namespace blink { | ||
|
||
// static | ||
std::unique_ptr<InterpolableAspectRatio> InterpolableAspectRatio::MaybeCreate( | ||
const StyleAspectRatio& aspect_ratio) { | ||
if (!RuntimeEnabledFeatures::CSSAspectRatioInterpolationEnabled()) | ||
return nullptr; | ||
|
||
// Auto aspect ratio cannot be interpolated to / from. | ||
if (aspect_ratio.IsAuto()) | ||
return nullptr; | ||
return std::make_unique<InterpolableAspectRatio>(aspect_ratio.GetRatio()); | ||
} | ||
|
||
InterpolableAspectRatio::InterpolableAspectRatio( | ||
const FloatSize& aspect_ratio) { | ||
// The StyleAspectRatio::IsAuto check in MaybeCreate should return true if we | ||
// have a degenerate aspect ratio. | ||
DCHECK(aspect_ratio.Height() > 0 && aspect_ratio.Width() > 0); | ||
|
||
value_ = std::make_unique<InterpolableNumber>( | ||
log(aspect_ratio.Width() / aspect_ratio.Height())); | ||
} | ||
|
||
FloatSize InterpolableAspectRatio::GetRatio() const { | ||
return FloatSize(exp(To<InterpolableNumber>(*value_).Value()), 1); | ||
} | ||
|
||
void InterpolableAspectRatio::Scale(double scale) { | ||
value_->Scale(scale); | ||
} | ||
|
||
void InterpolableAspectRatio::Add(const InterpolableValue& other) { | ||
value_->Add(*To<InterpolableAspectRatio>(other).value_); | ||
} | ||
|
||
void InterpolableAspectRatio::AssertCanInterpolateWith( | ||
const InterpolableValue& other) const { | ||
const InterpolableAspectRatio& other_aspect_ratio = | ||
To<InterpolableAspectRatio>(other); | ||
value_->AssertCanInterpolateWith(*other_aspect_ratio.value_); | ||
} | ||
|
||
void InterpolableAspectRatio::Interpolate(const InterpolableValue& to, | ||
const double progress, | ||
InterpolableValue& result) const { | ||
const InterpolableAspectRatio& aspect_ratio_to = | ||
To<InterpolableAspectRatio>(to); | ||
InterpolableAspectRatio& aspect_ratio_result = | ||
To<InterpolableAspectRatio>(result); | ||
value_->Interpolate(*aspect_ratio_to.value_, progress, | ||
*aspect_ratio_result.value_); | ||
} | ||
|
||
} // namespace blink |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2021 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_ASPECT_RATIO_H_ | ||
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_ASPECT_RATIO_H_ | ||
|
||
#include <memory> | ||
#include "third_party/blink/renderer/core/animation/interpolable_value.h" | ||
#include "third_party/blink/renderer/core/style/style_aspect_ratio.h" | ||
|
||
namespace blink { | ||
|
||
// Represents a blink::StyleAspectRatio, converted into its logarithm for | ||
// interpolation. | ||
class CORE_EXPORT InterpolableAspectRatio final : public InterpolableValue { | ||
public: | ||
explicit InterpolableAspectRatio(const FloatSize& ratio); | ||
explicit InterpolableAspectRatio(std::unique_ptr<InterpolableValue> value) | ||
: value_(std::move(value)) {} | ||
|
||
static std::unique_ptr<InterpolableAspectRatio> MaybeCreate( | ||
const StyleAspectRatio&); | ||
|
||
FloatSize GetRatio() const; | ||
|
||
// InterpolableValue implementation: | ||
void Interpolate(const InterpolableValue& to, | ||
const double progress, | ||
InterpolableValue& result) const final; | ||
bool IsAspectRatio() const final { return true; } | ||
bool Equals(const InterpolableValue& other) const final { | ||
NOTREACHED(); | ||
return false; | ||
} | ||
void Scale(double scale) final; | ||
void Add(const InterpolableValue& other) final; | ||
void AssertCanInterpolateWith(const InterpolableValue& other) const final; | ||
|
||
private: | ||
InterpolableAspectRatio* RawClone() const final { | ||
return new InterpolableAspectRatio(value_->Clone()); | ||
} | ||
InterpolableAspectRatio* RawCloneAndZero() const final { | ||
return new InterpolableAspectRatio(value_->CloneAndZero()); | ||
} | ||
|
||
// Interpolable aspect ratio value is stored and interpolated as the log of | ||
// the real aspect ratio. | ||
std::unique_ptr<InterpolableValue> value_; | ||
}; | ||
|
||
template <> | ||
struct DowncastTraits<InterpolableAspectRatio> { | ||
static bool AllowFrom(const InterpolableValue& interpolable_value) { | ||
return interpolable_value.IsAspectRatio(); | ||
} | ||
}; | ||
|
||
} // namespace blink | ||
|
||
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_INTERPOLABLE_ASPECT_RATIO_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.