• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

SVGAnimateElement.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
00003                   2004, 2005, 2006 Rob Buis <buis@kde.org>
00004     Copyright (C) 2008 Apple Inc. All rights reserved.
00005 
00006     This file is part of the KDE project
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 */
00023 
00024 #include "config.h"
00025 #if ENABLE(SVG) && ENABLE(SVG_ANIMATION)
00026 #include "SVGAnimateElement.h"
00027 
00028 #include "ColorDistance.h"
00029 #include "FloatConversion.h"
00030 #include "SVGColor.h"
00031 #include "SVGParserUtilities.h"
00032 #include <math.h>
00033 
00034 using namespace std;
00035 
00036 namespace WebCore {
00037 
00038 SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, Document* doc)
00039     : SVGAnimationElement(tagName, doc)
00040     , m_propertyType(StringProperty)
00041     , m_fromNumber(0)
00042     , m_toNumber(0)
00043     , m_animatedNumber(numeric_limits<double>::infinity())
00044 {
00045 }
00046 
00047 SVGAnimateElement::~SVGAnimateElement()
00048 {
00049 }
00050 
00051 static bool parseNumberValueAndUnit(const String& in, double& value, String& unit)
00052 {
00053     // FIXME: These are from top of my head, figure out all property types that can be animated as numbers.
00054     unsigned unitLength = 0;
00055     String parse = in.stripWhiteSpace();
00056     if (parse.endsWith("%"))
00057         unitLength = 1;
00058     else if (parse.endsWith("px") || parse.endsWith("pt") || parse.endsWith("em"))
00059         unitLength = 2;
00060     else if (parse.endsWith("deg") || parse.endsWith("rad"))
00061         unitLength = 3;
00062     else if (parse.endsWith("grad"))
00063         unitLength = 4;
00064     String newUnit = parse.right(unitLength);
00065     String number = parse.left(parse.length() - unitLength);
00066     if (!unit.isEmpty() && newUnit != unit || number.isEmpty())
00067         return false;
00068     UChar last = number[number.length() - 1];
00069     if (last < '0' || last > '9')
00070         return false;
00071     unit = newUnit;
00072     bool ok;
00073     value = number.toDouble(&ok);
00074     return ok;
00075 }
00076 
00077 SVGAnimateElement::PropertyType SVGAnimateElement::determinePropertyType(const String& attribute) const
00078 {
00079     // FIXME: We need a full property table for figuring this out reliably.
00080     if (hasTagName(SVGNames::animateColorTag))
00081         return ColorProperty;
00082     if (attribute == "color" || attribute == "fill" || attribute == "stroke")
00083         return ColorProperty;
00084     return NumberProperty;
00085 }
00086 
00087 void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
00088 {
00089     ASSERT(percentage >= 0.f && percentage <= 1.f);
00090     ASSERT(resultElement);
00091     if (hasTagName(SVGNames::setTag))
00092         percentage = 1.f;
00093     if (!resultElement->hasTagName(SVGNames::animateTag) && !resultElement->hasTagName(SVGNames::animateColorTag) 
00094         && !resultElement->hasTagName(SVGNames::setTag))
00095         return;
00096     SVGAnimateElement* results = static_cast<SVGAnimateElement*>(resultElement);
00097     // Can't accumulate over a string property.
00098     if (results->m_propertyType == StringProperty && m_propertyType != StringProperty)
00099         return;
00100     if (m_propertyType == NumberProperty) {
00101         // To animation uses contributions from the lower priority animations as the base value.
00102         if (animationMode() == ToAnimation)
00103             m_fromNumber = results->m_animatedNumber;
00104     
00105         double number = (m_toNumber - m_fromNumber) * percentage + m_fromNumber;
00106 
00107         // FIXME: This is not correct for values animation.
00108         if (isAccumulated() && repeat)
00109             number += m_toNumber * repeat;
00110         if (isAdditive() && animationMode() != ToAnimation)
00111             results->m_animatedNumber += number;
00112         else 
00113             results->m_animatedNumber = number;
00114         return;
00115     } 
00116     if (m_propertyType == ColorProperty) {
00117         if (animationMode() == ToAnimation)
00118             m_fromColor = results->m_animatedColor;
00119         Color color = ColorDistance(m_fromColor, m_toColor).scaledDistance(percentage).addToColorAndClamp(m_fromColor);
00120         // FIXME: Accumulate colors.
00121         if (isAdditive() && animationMode() != ToAnimation)
00122             results->m_animatedColor = ColorDistance::addColorsAndClamp(results->m_animatedColor, color);
00123         else
00124             results->m_animatedColor = color;
00125         return;
00126     }
00127     AnimationMode animationMode = this->animationMode();
00128     ASSERT(animationMode == FromToAnimation || animationMode == ToAnimation || animationMode == ValuesAnimation);
00129     if ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1.0f)
00130         results->m_animatedString = m_toString;
00131     else
00132         results->m_animatedString = m_fromString;
00133     // Higher priority replace animation overrides any additive results so far.
00134     results->m_propertyType = StringProperty;
00135 }
00136 
00137 bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const String& toString)
00138 {
00139     // FIXME: Needs more solid way determine target attribute type.
00140     m_propertyType = determinePropertyType(attributeName());
00141     if (m_propertyType == ColorProperty) {
00142         m_fromColor = SVGColor::colorFromRGBColorString(fromString);
00143         m_toColor = SVGColor::colorFromRGBColorString(toString);
00144         if (m_fromColor.isValid() && m_toColor.isValid())
00145             return true;
00146     } else if (m_propertyType == NumberProperty) {
00147         m_numberUnit = String();
00148         if (parseNumberValueAndUnit(toString, m_toNumber, m_numberUnit)) {
00149             // For to-animations the from number is calculated later
00150             if (animationMode() == ToAnimation || parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit))
00151                 return true;
00152         }
00153     }
00154     m_fromString = fromString;
00155     m_toString = toString;
00156     m_propertyType = StringProperty;
00157     return true;
00158 }
00159 
00160 bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const String& byString)
00161 {
00162     ASSERT(!hasTagName(SVGNames::setTag));
00163     m_propertyType = determinePropertyType(attributeName());
00164     if (m_propertyType == ColorProperty) {
00165         m_fromColor = fromString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(fromString);
00166         m_toColor = ColorDistance::addColorsAndClamp(m_fromColor, SVGColor::colorFromRGBColorString(byString));
00167         if (!m_fromColor.isValid() || !m_toColor.isValid())
00168             return false;
00169     } else {
00170         m_numberUnit = String();
00171         m_fromNumber = 0;
00172         if (!fromString.isEmpty() && !parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit))
00173             return false;
00174         if (!parseNumberValueAndUnit(byString, m_toNumber, m_numberUnit))
00175             return false;
00176         m_toNumber += m_fromNumber;
00177     }
00178     return true;
00179 }
00180 
00181 void SVGAnimateElement::resetToBaseValue(const String& baseString)
00182 {
00183     m_animatedString = baseString;
00184     m_propertyType = determinePropertyType(attributeName());
00185     if (m_propertyType == ColorProperty) {
00186         m_animatedColor = baseString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(baseString);
00187         if (m_animatedColor.isValid())
00188             return;
00189     } else if (m_propertyType == NumberProperty) {
00190         if (baseString.isEmpty()) {
00191             m_animatedNumber = 0;
00192             m_numberUnit = String();
00193             return;
00194         }
00195         if (parseNumberValueAndUnit(baseString, m_animatedNumber, m_numberUnit))
00196             return;
00197     }
00198     m_propertyType = StringProperty;
00199 }
00200     
00201 void SVGAnimateElement::applyResultsToTarget()
00202 {
00203     String valueToApply;
00204     if (m_propertyType == ColorProperty)
00205         valueToApply = m_animatedColor.name();
00206     else if (m_propertyType == NumberProperty)
00207         valueToApply = String::number(m_animatedNumber) + m_numberUnit;
00208     else
00209         valueToApply = m_animatedString;
00210     
00211     setTargetAttributeAnimatedValue(valueToApply);
00212 }
00213     
00214 float SVGAnimateElement::calculateDistance(const String& fromString, const String& toString)
00215 {
00216     m_propertyType = determinePropertyType(attributeName());
00217     if (m_propertyType == NumberProperty) {
00218         double from;
00219         double to;
00220         String unit;
00221         if (!parseNumberValueAndUnit(fromString, from, unit))
00222             return -1.f;
00223         if (!parseNumberValueAndUnit(toString, to, unit))
00224             return -1.f;
00225         return narrowPrecisionToFloat(fabs(to - from));
00226     } else if (m_propertyType == ColorProperty) {
00227         Color from = SVGColor::colorFromRGBColorString(fromString);
00228         if (!from.isValid())
00229             return -1.f;
00230         Color to = SVGColor::colorFromRGBColorString(toString);
00231         if (!to.isValid())
00232             return -1.f;
00233         return ColorDistance(from, to).distance();
00234     }
00235     return -1.f;
00236 }
00237    
00238 }
00239 
00240 // vim:ts=4:noet
00241 #endif // ENABLE(SVG)
00242 

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal