animationbase.cpp
来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 1,080 行 · 第 1/4 页
CPP
1,080 行
/* * Copyright (C) 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "AnimationBase.h"#include "AnimationControllerPrivate.h"#include "CSSMutableStyleDeclaration.h"#include "CSSPropertyLonghand.h"#include "CSSPropertyNames.h"#include "CString.h"#include "CompositeAnimation.h"#include "Document.h"#include "EventNames.h"#include "FloatConversion.h"#include "Frame.h"#include "IdentityTransformOperation.h"#include "ImplicitAnimation.h"#include "KeyframeAnimation.h"#include "MatrixTransformOperation.h"#include "Matrix3DTransformOperation.h"#include "RenderBox.h"#include "RenderStyle.h"#include "UnitBezier.h"#include <algorithm>using namespace std;namespace WebCore {// The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the// animation, the more precision we need in the timing function result to avoid ugly discontinuities.static inline double solveEpsilon(double duration){ return 1.0 / (200.0 * duration);}static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration){ // Convert from input time to parametric value in curve, then from // that to output time. UnitBezier bezier(p1x, p1y, p2x, p2y); return bezier.solve(t, solveEpsilon(duration));}static inline int blendFunc(const AnimationBase*, int from, int to, double progress){ return int(from + (to - from) * progress);}static inline double blendFunc(const AnimationBase*, double from, double to, double progress){ return from + (to - from) * progress;}static inline float blendFunc(const AnimationBase*, float from, float to, double progress){ return narrowPrecisionToFloat(from + (to - from) * progress);}static inline Color blendFunc(const AnimationBase* anim, const Color& from, const Color& to, double progress){ // We need to preserve the state of the valid flag at the end of the animation if (progress == 1 && !to.isValid()) return Color(); return Color(blendFunc(anim, from.red(), to.red(), progress), blendFunc(anim, from.green(), to.green(), progress), blendFunc(anim, from.blue(), to.blue(), progress), blendFunc(anim, from.alpha(), to.alpha(), progress));}static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress){ return to.blend(from, progress);}static inline IntSize blendFunc(const AnimationBase* anim, const IntSize& from, const IntSize& to, double progress){ return IntSize(blendFunc(anim, from.width(), to.width(), progress), blendFunc(anim, from.height(), to.height(), progress));}static inline ShadowData* blendFunc(const AnimationBase* anim, const ShadowData* from, const ShadowData* to, double progress){ ASSERT(from && to); return new ShadowData(blendFunc(anim, from->x, to->x, progress), blendFunc(anim, from->y, to->y, progress), blendFunc(anim, from->blur, to->blur, progress), blendFunc(anim, from->color, to->color, progress));}static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress){ TransformOperations result; // If we have a transform function list, use that to do a per-function animation. Otherwise do a Matrix animation if (anim->isTransformFunctionListValid()) { unsigned fromSize = from.operations().size(); unsigned toSize = to.operations().size(); unsigned size = max(fromSize, toSize); for (unsigned i = 0; i < size; i++) { RefPtr<TransformOperation> fromOp = (i < fromSize) ? from.operations()[i].get() : 0; RefPtr<TransformOperation> toOp = (i < toSize) ? to.operations()[i].get() : 0; RefPtr<TransformOperation> blendedOp = toOp ? toOp->blend(fromOp.get(), progress) : (fromOp ? fromOp->blend(0, progress, true) : 0); if (blendedOp) result.operations().append(blendedOp); else { RefPtr<TransformOperation> identityOp = IdentityTransformOperation::create(); if (progress > 0.5) result.operations().append(toOp ? toOp : identityOp); else result.operations().append(fromOp ? fromOp : identityOp); } } } else { // Convert the TransformOperations into matrices IntSize size = anim->renderer()->isBox() ? toRenderBox(anim->renderer())->borderBoxRect().size() : IntSize(); TransformationMatrix fromT; TransformationMatrix toT; from.apply(size, fromT); to.apply(size, toT); toT.blend(fromT, progress); // Append the result result.operations().append(Matrix3DTransformOperation::create(toT)); } return result;}static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, EVisibility to, double progress){ // Any non-zero result means we consider the object to be visible. Only at 0 do we consider the object to be // invisible. The invisible value we use (HIDDEN vs. COLLAPSE) depends on the specified from/to values. double fromVal = from == VISIBLE ? 1. : 0.; double toVal = to == VISIBLE ? 1. : 0.; if (fromVal == toVal) return to; double result = blendFunc(anim, fromVal, toVal, progress); return result > 0. ? VISIBLE : (to != VISIBLE ? to : from);}class PropertyWrapperBase;static void addShorthandProperties();static PropertyWrapperBase* wrapperForProperty(int propertyID);class PropertyWrapperBase {public: PropertyWrapperBase(int prop) : m_prop(prop) { } virtual ~PropertyWrapperBase() { } virtual bool isShorthandWrapper() const { return false; } virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0; virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const = 0; int property() const { return m_prop; }#if USE(ACCELERATED_COMPOSITING) virtual bool animationIsAccelerated() const { return false; }#endifprivate: int m_prop;};template <typename T>class PropertyWrapperGetter : public PropertyWrapperBase {public: PropertyWrapperGetter(int prop, T (RenderStyle::*getter)() const) : PropertyWrapperBase(prop) , m_getter(getter) { } virtual bool equals(const RenderStyle* a, const RenderStyle* b) const { // If the style pointers are the same, don't bother doing the test. // If either is null, return false. If both are null, return true. if (!a && !b || a == b) return true; if (!a || !b) return false; return (a->*m_getter)() == (b->*m_getter)(); }protected: T (RenderStyle::*m_getter)() const;};template <typename T>class PropertyWrapper : public PropertyWrapperGetter<T> {public: PropertyWrapper(int prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T)) : PropertyWrapperGetter<T>(prop, getter) , m_setter(setter) { } virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const { (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), progress)); }protected: void (RenderStyle::*m_setter)(T);};#if USE(ACCELERATED_COMPOSITING)class PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> {public: PropertyWrapperAcceleratedOpacity() : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity) { } virtual bool animationIsAccelerated() const { return true; } virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const { float fromOpacity = a->opacity(); // This makes sure we put the object being animated into a RenderLayer during the animation dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress)); }};class PropertyWrapperAcceleratedTransform : public PropertyWrapper<const TransformOperations&> {public: PropertyWrapperAcceleratedTransform() : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform) { } virtual bool animationIsAccelerated() const { return true; } virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const { dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress)); }};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?