diff options
author | avallee@chromium.org <avallee@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-24 22:51:36 +0000 |
---|---|---|
committer | avallee@chromium.org <avallee@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-24 22:51:36 +0000 |
commit | 12076fa6270fda6ea535da61cafe7116ec2e6f00 (patch) | |
tree | 4cda7c226d5fbba708df61cdb3c7c517a71f8ee9 /cc | |
parent | 565f6193e85668f26de953516dbd8a341ae2b457 (diff) | |
download | chromium_src-12076fa6270fda6ea535da61cafe7116ec2e6f00.zip chromium_src-12076fa6270fda6ea535da61cafe7116ec2e6f00.tar.gz chromium_src-12076fa6270fda6ea535da61cafe7116ec2e6f00.tar.bz2 |
Add Color animation curves.
Implement animation curves for colors.
This is the first step towards accelerating background-color animations.
+ Add ColorValueBetween to gfx::Tween.
+ Add test/color_utils which gives EXPECT_COLOR_EQ to check SkColors and
print in a sane format.
~ Fixed discrepancy between two methods of interpolating ints.
~ Factored out GetProgress into template function to simplify code in
the implementations of GetValue(double), there was a lot of duplication
there.
TESTED:
Added tests for the new KeyframedColorAnimations and AnimatedColor classes. Added tests to tweening.
R=ajuma
BUG=290234
Review URL: https://codereview.chromium.org/25901002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230856 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r-- | cc/animation/animation.cc | 3 | ||||
-rw-r--r-- | cc/animation/animation.h | 1 | ||||
-rw-r--r-- | cc/animation/animation_curve.cc | 7 | ||||
-rw-r--r-- | cc/animation/animation_curve.h | 14 | ||||
-rw-r--r-- | cc/animation/keyframed_animation_curve.cc | 91 | ||||
-rw-r--r-- | cc/animation/keyframed_animation_curve.h | 46 | ||||
-rw-r--r-- | cc/animation/keyframed_animation_curve_unittest.cc | 94 | ||||
-rw-r--r-- | cc/animation/layer_animation_controller.cc | 7 | ||||
-rw-r--r-- | cc/cc_tests.gyp | 1 | ||||
-rw-r--r-- | cc/output/filter_operation.cc | 73 | ||||
-rw-r--r-- | cc/output/filter_operations_unittest.cc | 5 |
11 files changed, 277 insertions, 65 deletions
diff --git a/cc/animation/animation.cc b/cc/animation/animation.cc index 6b45917..6b5966b 100644 --- a/cc/animation/animation.cc +++ b/cc/animation/animation.cc @@ -33,7 +33,8 @@ COMPILE_ASSERT(static_cast<int>(cc::Animation::RunStateEnumSize) == static const char* const s_targetPropertyNames[] = { "Transform", "Opacity", - "Filter" + "Filter", + "BackgroundColor" }; COMPILE_ASSERT(static_cast<int>(cc::Animation::TargetPropertyEnumSize) == diff --git a/cc/animation/animation.h b/cc/animation/animation.h index 9946298..f640318 100644 --- a/cc/animation/animation.h +++ b/cc/animation/animation.h @@ -47,6 +47,7 @@ class CC_EXPORT Animation { Transform = 0, Opacity, Filter, + BackgroundColor, // This sentinel must be last. TargetPropertyEnumSize }; diff --git a/cc/animation/animation_curve.cc b/cc/animation/animation_curve.cc index cf04da7..65c21db 100644 --- a/cc/animation/animation_curve.cc +++ b/cc/animation/animation_curve.cc @@ -8,6 +8,13 @@ namespace cc { +const ColorAnimationCurve* AnimationCurve::ToColorAnimationCurve() const { + DCHECK(Type() == AnimationCurve::Color); + return static_cast<const ColorAnimationCurve*>(this); +} + +AnimationCurve::CurveType ColorAnimationCurve::Type() const { return Color; } + const FloatAnimationCurve* AnimationCurve::ToFloatAnimationCurve() const { DCHECK(Type() == AnimationCurve::Float); return static_cast<const FloatAnimationCurve*>(this); diff --git a/cc/animation/animation_curve.h b/cc/animation/animation_curve.h index f4cdb10..f84bb1a 100644 --- a/cc/animation/animation_curve.h +++ b/cc/animation/animation_curve.h @@ -16,6 +16,7 @@ class BoxF; namespace cc { +class ColorAnimationCurve; class FilterAnimationCurve; class FloatAnimationCurve; class TransformAnimationCurve; @@ -24,7 +25,7 @@ class TransformOperations; // An animation curve is a function that returns a value given a time. class CC_EXPORT AnimationCurve { public: - enum CurveType { Float, Transform, Filter }; + enum CurveType { Color, Float, Transform, Filter }; virtual ~AnimationCurve() {} @@ -32,11 +33,22 @@ class CC_EXPORT AnimationCurve { virtual CurveType Type() const = 0; virtual scoped_ptr<AnimationCurve> Clone() const = 0; + const ColorAnimationCurve* ToColorAnimationCurve() const; const FloatAnimationCurve* ToFloatAnimationCurve() const; const TransformAnimationCurve* ToTransformAnimationCurve() const; const FilterAnimationCurve* ToFilterAnimationCurve() const; }; +class CC_EXPORT ColorAnimationCurve : public AnimationCurve { + public: + virtual ~ColorAnimationCurve() {} + + virtual SkColor GetValue(double t) const = 0; + + // Partial Animation implementation. + virtual CurveType Type() const OVERRIDE; +}; + class CC_EXPORT FloatAnimationCurve : public AnimationCurve { public: virtual ~FloatAnimationCurve() {} diff --git a/cc/animation/keyframed_animation_curve.cc b/cc/animation/keyframed_animation_curve.cc index 14dfd9c..d855dec 100644 --- a/cc/animation/keyframed_animation_curve.cc +++ b/cc/animation/keyframed_animation_curve.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/animation/keyframed_animation_curve.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/box_f.h" namespace cc { @@ -26,6 +27,17 @@ void InsertKeyframe(scoped_ptr<Keyframe> keyframe, keyframes.push_back(keyframe.Pass()); } +template <class Keyframes> +float GetProgress(double t, size_t i, const Keyframes& keyframes) { + float progress = + static_cast<float>((t - keyframes[i]->Time()) / + (keyframes[i + 1]->Time() - keyframes[i]->Time())); + + if (keyframes[i]->timing_function()) + progress = keyframes[i]->timing_function()->GetValue(progress); + return progress; +} + scoped_ptr<TimingFunction> CloneTimingFunction( const TimingFunction* timing_function) { DCHECK(timing_function); @@ -46,6 +58,31 @@ double Keyframe::Time() const { return time_; } +scoped_ptr<ColorKeyframe> ColorKeyframe::Create( + double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function) { + return make_scoped_ptr( + new ColorKeyframe(time, value, timing_function.Pass())); +} + +ColorKeyframe::ColorKeyframe(double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function) + : Keyframe(time, timing_function.Pass()), + value_(value) {} + +ColorKeyframe::~ColorKeyframe() {} + +SkColor ColorKeyframe::Value() const { return value_; } + +scoped_ptr<ColorKeyframe> ColorKeyframe::Clone() const { + scoped_ptr<TimingFunction> func; + if (timing_function()) + func = CloneTimingFunction(timing_function()); + return ColorKeyframe::Create(Time(), Value(), func.Pass()); +} + scoped_ptr<FloatKeyframe> FloatKeyframe::Create( double time, float value, @@ -127,6 +164,53 @@ scoped_ptr<FilterKeyframe> FilterKeyframe::Clone() const { return FilterKeyframe::Create(Time(), Value(), func.Pass()); } +scoped_ptr<KeyframedColorAnimationCurve> KeyframedColorAnimationCurve:: + Create() { + return make_scoped_ptr(new KeyframedColorAnimationCurve); +} + +KeyframedColorAnimationCurve::KeyframedColorAnimationCurve() {} + +KeyframedColorAnimationCurve::~KeyframedColorAnimationCurve() {} + +void KeyframedColorAnimationCurve::AddKeyframe( + scoped_ptr<ColorKeyframe> keyframe) { + InsertKeyframe(keyframe.Pass(), keyframes_); +} + +double KeyframedColorAnimationCurve::Duration() const { + return keyframes_.back()->Time() - keyframes_.front()->Time(); +} + +scoped_ptr<AnimationCurve> KeyframedColorAnimationCurve::Clone() const { + scoped_ptr<KeyframedColorAnimationCurve> to_return( + KeyframedColorAnimationCurve::Create()); + for (size_t i = 0; i < keyframes_.size(); ++i) + to_return->AddKeyframe(keyframes_[i]->Clone()); + return to_return.PassAs<AnimationCurve>(); +} + +SkColor KeyframedColorAnimationCurve::GetValue(double t) const { + if (t <= keyframes_.front()->Time()) + return keyframes_.front()->Value(); + + if (t >= keyframes_.back()->Time()) + return keyframes_.back()->Value(); + + size_t i = 0; + for (; i < keyframes_.size() - 1; ++i) { + if (t < keyframes_[i + 1]->Time()) + break; + } + + float progress = GetProgress(t, i, keyframes_); + + return gfx::Tween::ColorValueBetween( + progress, keyframes_[i]->Value(), keyframes_[i + 1]->Value()); +} + +// KeyframedFloatAnimationCurve + scoped_ptr<KeyframedFloatAnimationCurve> KeyframedFloatAnimationCurve:: Create() { return make_scoped_ptr(new KeyframedFloatAnimationCurve); @@ -166,12 +250,7 @@ float KeyframedFloatAnimationCurve::GetValue(double t) const { break; } - float progress = - static_cast<float>((t - keyframes_[i]->Time()) / - (keyframes_[i+1]->Time() - keyframes_[i]->Time())); - - if (keyframes_[i]->timing_function()) - progress = keyframes_[i]->timing_function()->GetValue(progress); + float progress = GetProgress(t, i, keyframes_); return keyframes_[i]->Value() + (keyframes_[i+1]->Value() - keyframes_[i]->Value()) * progress; diff --git a/cc/animation/keyframed_animation_curve.h b/cc/animation/keyframed_animation_curve.h index 5892dc7..4b5ac3b 100644 --- a/cc/animation/keyframed_animation_curve.h +++ b/cc/animation/keyframed_animation_curve.h @@ -31,6 +31,26 @@ class CC_EXPORT Keyframe { DISALLOW_COPY_AND_ASSIGN(Keyframe); }; +class CC_EXPORT ColorKeyframe : public Keyframe { + public: + static scoped_ptr<ColorKeyframe> Create( + double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function); + virtual ~ColorKeyframe(); + + SkColor Value() const; + + scoped_ptr<ColorKeyframe> Clone() const; + + private: + ColorKeyframe(double time, + SkColor value, + scoped_ptr<TimingFunction> timing_function); + + SkColor value_; +}; + class CC_EXPORT FloatKeyframe : public Keyframe { public: static scoped_ptr<FloatKeyframe> Create( @@ -93,6 +113,32 @@ class CC_EXPORT FilterKeyframe : public Keyframe { FilterOperations value_; }; +class CC_EXPORT KeyframedColorAnimationCurve : public ColorAnimationCurve { + public: + // It is required that the keyframes be sorted by time. + static scoped_ptr<KeyframedColorAnimationCurve> Create(); + + virtual ~KeyframedColorAnimationCurve(); + + void AddKeyframe(scoped_ptr<ColorKeyframe> keyframe); + + // AnimationCurve implementation + virtual double Duration() const OVERRIDE; + virtual scoped_ptr<AnimationCurve> Clone() const OVERRIDE; + + // BackgrounColorAnimationCurve implementation + virtual SkColor GetValue(double t) const OVERRIDE; + + private: + KeyframedColorAnimationCurve(); + + // Always sorted in order of increasing time. No two keyframes have the + // same time. + ScopedPtrVector<ColorKeyframe> keyframes_; + + DISALLOW_COPY_AND_ASSIGN(KeyframedColorAnimationCurve); +}; + class CC_EXPORT KeyframedFloatAnimationCurve : public FloatAnimationCurve { public: // It is required that the keyframes be sorted by time. diff --git a/cc/animation/keyframed_animation_curve_unittest.cc b/cc/animation/keyframed_animation_curve_unittest.cc index 7eb3b1c..63e9866 100644 --- a/cc/animation/keyframed_animation_curve_unittest.cc +++ b/cc/animation/keyframed_animation_curve_unittest.cc @@ -7,7 +7,9 @@ #include "cc/animation/transform_operations.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/box_f.h" +#include "ui/gfx/test/color_util.h" namespace cc { namespace { @@ -22,6 +24,98 @@ void ExpectBrightness(double brightness, const FilterOperations& filter) { EXPECT_FLOAT_EQ(brightness, filter.at(0).amount()); } +// Tests that a color animation with one keyframe works as expected. +TEST(KeyframedAnimationCurveTest, OneColorKeyFrame) { + SkColor color = SkColorSetARGB(255, 255, 255, 255); + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(0.5f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(1.f)); + EXPECT_SKCOLOR_EQ(color, curve->GetValue(2.f)); +} + +// Tests that a color animation with two keyframes works as expected. +TEST(KeyframedAnimationCurveTest, TwoColorKeyFrame) { + SkColor color_a = SkColorSetARGB(255, 255, 0, 0); + SkColor color_b = SkColorSetARGB(255, 0, 255, 0); + SkColor color_midpoint = gfx::Tween::ColorValueBetween(0.5, color_a, color_b); + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color_midpoint, curve->GetValue(0.5f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(2.f)); +} + +// Tests that a color animation with three keyframes works as expected. +TEST(KeyframedAnimationCurveTest, ThreeColorKeyFrame) { + SkColor color_a = SkColorSetARGB(255, 255, 0, 0); + SkColor color_b = SkColorSetARGB(255, 0, 255, 0); + SkColor color_c = SkColorSetARGB(255, 0, 0, 255); + SkColor color_midpoint1 = + gfx::Tween::ColorValueBetween(0.5, color_a, color_b); + SkColor color_midpoint2 = + gfx::Tween::ColorValueBetween(0.5, color_b, color_c); + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(2.0, color_c, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color_midpoint1, curve->GetValue(0.5f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.f)); + EXPECT_SKCOLOR_EQ(color_midpoint2, curve->GetValue(1.5f)); + EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(2.f)); + EXPECT_SKCOLOR_EQ(color_c, curve->GetValue(3.f)); +} + +// Tests that a colro animation with multiple keys at a given time works sanely. +TEST(KeyframedAnimationCurveTest, RepeatedColorKeyFrame) { + SkColor color_a = SkColorSetARGB(255, 64, 0, 0); + SkColor color_b = SkColorSetARGB(255, 192, 0, 0); + + scoped_ptr<KeyframedColorAnimationCurve> curve( + KeyframedColorAnimationCurve::Create()); + curve->AddKeyframe( + ColorKeyframe::Create(0.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_a, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(1.0, color_b, scoped_ptr<TimingFunction>())); + curve->AddKeyframe( + ColorKeyframe::Create(2.0, color_b, scoped_ptr<TimingFunction>())); + + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(-1.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.f)); + EXPECT_SKCOLOR_EQ(color_a, curve->GetValue(0.5f)); + + SkColor value = curve->GetValue(1.0f); + EXPECT_EQ(255u, SkColorGetA(value)); + int red_value = SkColorGetR(value); + EXPECT_LE(64, red_value); + EXPECT_GE(192, red_value); + + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(1.5f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(2.f)); + EXPECT_SKCOLOR_EQ(color_b, curve->GetValue(3.f)); +} + // Tests that a float animation with one keyframe works as expected. TEST(KeyframedAnimationCurveTest, OneFloatKeyframe) { scoped_ptr<KeyframedFloatAnimationCurve> curve( diff --git a/cc/animation/layer_animation_controller.cc b/cc/animation/layer_animation_controller.cc index daebc44..f720229 100644 --- a/cc/animation/layer_animation_controller.cc +++ b/cc/animation/layer_animation_controller.cc @@ -187,6 +187,8 @@ void LayerAnimationController::AccumulatePropertyUpdates( break; } + case Animation::BackgroundColor: { break; } + case Animation::TargetPropertyEnumSize: NOTREACHED(); } @@ -710,6 +712,11 @@ void LayerAnimationController::TickAnimations(double monotonic_time) { break; } + case Animation::BackgroundColor: { + // Not yet implemented. + break; + } + // Do nothing for sentinel value. case Animation::TargetPropertyEnumSize: NOTREACHED(); diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 226ab24..c0f4023 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -326,6 +326,7 @@ 'dependencies': [ '../skia/skia.gyp:skia', '../ui/gfx/gfx.gyp:gfx', + '../ui/ui.gyp:ui_test_support', ], }, ], diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc index 672dba7..50f111f 100644 --- a/cc/output/filter_operation.cc +++ b/cc/output/filter_operation.cc @@ -8,6 +8,7 @@ #include "cc/base/math_util.h" #include "cc/output/filter_operation.h" #include "third_party/skia/include/core/SkMath.h" +#include "ui/gfx/animation/tween.h" namespace cc { @@ -97,52 +98,6 @@ FilterOperation::FilterOperation(const FilterOperation& other) FilterOperation::~FilterOperation() { } -// TODO(ajuma): Define a version of gfx::Tween::ValueBetween for floats, and use -// that instead. -static float BlendFloats(float from, float to, double progress) { - return from * (1.0 - progress) + to * progress; -} - -static int BlendInts(int from, int to, double progress) { - return static_cast<int>( - MathUtil::Round(from * (1.0 - progress) + to * progress)); -} - -static uint8_t BlendColorComponents(uint8_t from, - uint8_t to, - uint8_t from_alpha, - uint8_t to_alpha, - uint8_t blended_alpha, - double progress) { - // Since progress can be outside [0, 1], blending can produce a value outside - // [0, 255]. - int blended_premultiplied = BlendInts(SkMulDiv255Round(from, from_alpha), - SkMulDiv255Round(to, to_alpha), - progress); - int blended = static_cast<int>( - MathUtil::Round(blended_premultiplied * 255.f / blended_alpha)); - return static_cast<uint8_t>(MathUtil::ClampToRange(blended, 0, 255)); -} - -static SkColor BlendSkColors(SkColor from, SkColor to, double progress) { - int from_a = SkColorGetA(from); - int to_a = SkColorGetA(to); - int blended_a = BlendInts(from_a, to_a, progress); - if (blended_a <= 0) - return SkColorSetARGB(0, 0, 0, 0); - blended_a = std::min(blended_a, 255); - - // TODO(ajuma): Use SkFourByteInterp once http://crbug.com/260369 is fixed. - uint8_t blended_r = BlendColorComponents( - SkColorGetR(from), SkColorGetR(to), from_a, to_a, blended_a, progress); - uint8_t blended_g = BlendColorComponents( - SkColorGetG(from), SkColorGetG(to), from_a, to_a, blended_a, progress); - uint8_t blended_b = BlendColorComponents( - SkColorGetB(from), SkColorGetB(to), from_a, to_a, blended_a, progress); - - return SkColorSetARGB(blended_a, blended_r, blended_g, blended_b); -} - static FilterOperation CreateNoOpFilter(FilterOperation::FilterType type) { switch (type) { case FilterOperation::GRAYSCALE: @@ -239,21 +194,25 @@ FilterOperation FilterOperation::Blend(const FilterOperation* from, } blended_filter.set_amount(ClampAmountForFilterType( - BlendFloats(from_op.amount(), to_op.amount(), progress), to_op.type())); + gfx::Tween::FloatValueBetween(progress, from_op.amount(), to_op.amount()), + to_op.type())); if (to_op.type() == FilterOperation::DROP_SHADOW) { - gfx::Point blended_offset(BlendInts(from_op.drop_shadow_offset().x(), - to_op.drop_shadow_offset().x(), - progress), - BlendInts(from_op.drop_shadow_offset().y(), - to_op.drop_shadow_offset().y(), - progress)); + gfx::Point blended_offset( + gfx::Tween::LinearIntValueBetween(progress, + from_op.drop_shadow_offset().x(), + to_op.drop_shadow_offset().x()), + gfx::Tween::LinearIntValueBetween(progress, + from_op.drop_shadow_offset().y(), + to_op.drop_shadow_offset().y())); blended_filter.set_drop_shadow_offset(blended_offset); - blended_filter.set_drop_shadow_color(BlendSkColors( - from_op.drop_shadow_color(), to_op.drop_shadow_color(), progress)); + blended_filter.set_drop_shadow_color(gfx::Tween::ColorValueBetween( + progress, from_op.drop_shadow_color(), to_op.drop_shadow_color())); } else if (to_op.type() == FilterOperation::ZOOM) { - blended_filter.set_zoom_inset(std::max( - BlendInts(from_op.zoom_inset(), to_op.zoom_inset(), progress), 0)); + blended_filter.set_zoom_inset( + std::max(gfx::Tween::LinearIntValueBetween( + from_op.zoom_inset(), to_op.zoom_inset(), progress), + 0)); } return blended_filter; diff --git a/cc/output/filter_operations_unittest.cc b/cc/output/filter_operations_unittest.cc index e975ed5..7f439b9 100644 --- a/cc/output/filter_operations_unittest.cc +++ b/cc/output/filter_operations_unittest.cc @@ -412,6 +412,11 @@ TEST(FilterOperationsTest, BlendDropShadowFilters) { gfx::Point(-2, -4), 0.f, SkColorSetARGB(0, 0, 0, 0)); EXPECT_EQ(expected, blended); + blended = FilterOperation::Blend(&from, &to, 0.25); + expected = FilterOperation::CreateDropShadowFilter( + gfx::Point(1, 1), 3.f, SkColorSetARGB(24, 32, 64, 128)); + EXPECT_EQ(expected, blended); + blended = FilterOperation::Blend(&from, &to, 0.75); expected = FilterOperation::CreateDropShadowFilter( gfx::Point(2, 4), 5.f, SkColorSetARGB(42, 30, 61, 121)); |