📄 svganimationelement.cpp
字号:
/* Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org> 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> Copyright (C) 2007 Eric Seidel <eric@webkit.org> Copyright (C) 2008 Apple Inc. All rights reserved. This file is part of the KDE project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/#include "config.h"#if ENABLE(SVG_ANIMATION)#include "SVGAnimationElement.h"#include "CSSComputedStyleDeclaration.h"#include "CSSParser.h"#include "CSSPropertyNames.h"#include "Document.h"#include "Event.h"#include "EventListener.h"#include "FloatConversion.h"#include "HTMLNames.h"#include "SVGElementInstance.h"#include "SVGNames.h"#include "SVGURIReference.h"#include "SVGUseElement.h"#include "XLinkNames.h"#include <math.h>#include <wtf/StdLibExtras.h>using namespace std;namespace WebCore { SVGAnimationElement::SVGAnimationElement(const QualifiedName& tagName, Document* doc) : SVGSMILElement(tagName, doc) , SVGTests() , SVGExternalResourcesRequired() , m_animationValid(false){}SVGAnimationElement::~SVGAnimationElement(){} static void parseKeyTimes(const String& parse, Vector<float>& result, bool verifyOrder){ result.clear(); Vector<String> parseList; parse.split(';', parseList); for (unsigned n = 0; n < parseList.size(); ++n) { String timeString = parseList[n]; bool ok; float time = timeString.toFloat(&ok); if (!ok || time < 0 || time > 1.f) goto fail; if (verifyOrder) { if (!n) { if (time != 0) goto fail; } else if (time < result.last()) goto fail; } result.append(time); } return;fail: result.clear();}static void parseKeySplines(const String& parse, Vector<UnitBezier>& result){ result.clear(); Vector<String> parseList; parse.split(';', parseList); for (unsigned n = 0; n < parseList.size(); ++n) { Vector<String> parseSpline; parseList[n].split(',', parseSpline); // The spec says the sepator is a space, all tests use commas. Weird. if (parseSpline.size() == 1) parseList[n].split(' ', parseSpline); if (parseSpline.size() != 4) goto fail; double curveValues[4]; for (unsigned i = 0; i < 4; ++i) { String parseNumber = parseSpline[i]; bool ok; curveValues[i] = parseNumber.toDouble(&ok); if (!ok || curveValues[i] < 0.0 || curveValues[i] > 1.0) goto fail; } result.append(UnitBezier(curveValues[0], curveValues[1], curveValues[2], curveValues[3])); } return;fail: result.clear();}void SVGAnimationElement::parseMappedAttribute(MappedAttribute* attr){ if (attr->name() == SVGNames::valuesAttr) attr->value().string().split(';', m_values); else if (attr->name() == SVGNames::keyTimesAttr) parseKeyTimes(attr->value(), m_keyTimes, true); else if (attr->name() == SVGNames::keyPointsAttr && hasTagName(SVGNames::animateMotionTag)) { // This is specified to be an animateMotion attribute only but it is simpler to put it here // where the other timing calculatations are. parseKeyTimes(attr->value(), m_keyPoints, false); } else if (attr->name() == SVGNames::keySplinesAttr) parseKeySplines(attr->value(), m_keySplines); else { if (SVGTests::parseMappedAttribute(attr)) return; if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) return; SVGSMILElement::parseMappedAttribute(attr); }}void SVGAnimationElement::attributeChanged(Attribute* attr, bool preserveDecls){ // Assumptions may not hold after an attribute change. m_animationValid = false; SVGSMILElement::attributeChanged(attr, preserveDecls);}float SVGAnimationElement::getStartTime() const{ return narrowPrecisionToFloat(intervalBegin().value());}float SVGAnimationElement::getCurrentTime() const{ return narrowPrecisionToFloat(elapsed().value());}float SVGAnimationElement::getSimpleDuration(ExceptionCode&) const{ return narrowPrecisionToFloat(simpleDuration().value());} bool SVGAnimationElement::beginElement(ExceptionCode& ec){ return beginElementAt(0, ec);}bool SVGAnimationElement::beginElementAt(float offset, ExceptionCode&){ addBeginTime(elapsed() + offset); return true;}bool SVGAnimationElement::endElement(ExceptionCode& ec){ return endElementAt(0, ec);}bool SVGAnimationElement::endElementAt(float offset, ExceptionCode&){ if (offset < 0) return false; addEndTime(elapsed() + offset); return true;}SVGAnimationElement::AnimationMode SVGAnimationElement::animationMode() const{ // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#AnimFuncValues if (hasTagName(SVGNames::setTag)) return ToAnimation; if (!animationPath().isEmpty()) return PathAnimation; if (hasAttribute(SVGNames::valuesAttr)) return ValuesAnimation; if (!toValue().isEmpty()) return fromValue().isEmpty() ? ToAnimation : FromToAnimation; if (!byValue().isEmpty()) return fromValue().isEmpty() ? ByAnimation : FromByAnimation; return NoAnimation;}SVGAnimationElement::CalcMode SVGAnimationElement::calcMode() const{ DEFINE_STATIC_LOCAL(const AtomicString, discrete, ("discrete")); DEFINE_STATIC_LOCAL(const AtomicString, linear, ("linear")); DEFINE_STATIC_LOCAL(const AtomicString, paced, ("paced")); DEFINE_STATIC_LOCAL(const AtomicString, spline, ("spline")); const AtomicString& value = getAttribute(SVGNames::calcModeAttr); if (value == discrete) return CalcModeDiscrete; if (value == linear) return CalcModeLinear; if (value == paced) return CalcModePaced; if (value == spline) return CalcModeSpline; return hasTagName(SVGNames::animateMotionTag) ? CalcModePaced : CalcModeLinear;}SVGAnimationElement::AttributeType SVGAnimationElement::attributeType() const{ DEFINE_STATIC_LOCAL(const AtomicString, css, ("CSS")); DEFINE_STATIC_LOCAL(const AtomicString, xml, ("XML")); const AtomicString& value = getAttribute(SVGNames::attributeTypeAttr); if (value == css) return AttributeTypeCSS; if (value == xml) return AttributeTypeXML; return AttributeTypeAuto;}String SVGAnimationElement::toValue() const{ return getAttribute(SVGNames::toAttr);}String SVGAnimationElement::byValue() const{ return getAttribute(SVGNames::byAttr);}String SVGAnimationElement::fromValue() const{ return getAttribute(SVGNames::fromAttr);}bool SVGAnimationElement::isAdditive() const{ DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum")); const AtomicString& value = getAttribute(SVGNames::additiveAttr); return value == sum || animationMode() == ByAnimation;}bool SVGAnimationElement::isAccumulated() const{ DEFINE_STATIC_LOCAL(const AtomicString, sum, ("sum")); const AtomicString& value = getAttribute(SVGNames::accumulateAttr); return value == sum && animationMode() != ToAnimation;}bool SVGAnimationElement::hasValidTarget() const{ return targetElement();} bool SVGAnimationElement::attributeIsCSS(const String& attributeName){ // FIXME: We should have a map of all SVG properties and their attribute types so we // could validate animations better. The spec is very vague about this. unsigned id = cssPropertyID(attributeName); // SVG range if (id >= CSSPropertyClipPath && id <= CSSPropertyWritingMode)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -