• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KHTML

  • khtml
  • svg
SVGAnimateElement.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 Copyright (C) 2008 Apple Inc. All rights reserved.
5
6 This file is part of the KDE project
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA.
22*/
23
24#include "config.h"
25#if ENABLE(SVG) && ENABLE(SVG_ANIMATION)
26#include "SVGAnimateElement.h"
27
28#include "ColorDistance.h"
29#include "FloatConversion.h"
30#include "SVGColor.h"
31#include "SVGParserUtilities.h"
32#include <math.h>
33
34using namespace std;
35
36namespace WebCore {
37
38SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, Document* doc)
39 : SVGAnimationElement(tagName, doc)
40 , m_propertyType(StringProperty)
41 , m_fromNumber(0)
42 , m_toNumber(0)
43 , m_animatedNumber(numeric_limits<double>::infinity())
44{
45}
46
47SVGAnimateElement::~SVGAnimateElement()
48{
49}
50
51static bool parseNumberValueAndUnit(const String& in, double& value, String& unit)
52{
53 // FIXME: These are from top of my head, figure out all property types that can be animated as numbers.
54 unsigned unitLength = 0;
55 String parse = in.stripWhiteSpace();
56 if (parse.endsWith("%"))
57 unitLength = 1;
58 else if (parse.endsWith("px") || parse.endsWith("pt") || parse.endsWith("em"))
59 unitLength = 2;
60 else if (parse.endsWith("deg") || parse.endsWith("rad"))
61 unitLength = 3;
62 else if (parse.endsWith("grad"))
63 unitLength = 4;
64 String newUnit = parse.right(unitLength);
65 String number = parse.left(parse.length() - unitLength);
66 if (!unit.isEmpty() && newUnit != unit || number.isEmpty())
67 return false;
68 UChar last = number[number.length() - 1];
69 if (last < '0' || last > '9')
70 return false;
71 unit = newUnit;
72 bool ok;
73 value = number.toDouble(&ok);
74 return ok;
75}
76
77SVGAnimateElement::PropertyType SVGAnimateElement::determinePropertyType(const String& attribute) const
78{
79 // FIXME: We need a full property table for figuring this out reliably.
80 if (hasTagName(SVGNames::animateColorTag))
81 return ColorProperty;
82 if (attribute == "color" || attribute == "fill" || attribute == "stroke")
83 return ColorProperty;
84 return NumberProperty;
85}
86
87void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
88{
89 ASSERT(percentage >= 0.f && percentage <= 1.f);
90 ASSERT(resultElement);
91 if (hasTagName(SVGNames::setTag))
92 percentage = 1.f;
93 if (!resultElement->hasTagName(SVGNames::animateTag) && !resultElement->hasTagName(SVGNames::animateColorTag)
94 && !resultElement->hasTagName(SVGNames::setTag))
95 return;
96 SVGAnimateElement* results = static_cast<SVGAnimateElement*>(resultElement);
97 // Can't accumulate over a string property.
98 if (results->m_propertyType == StringProperty && m_propertyType != StringProperty)
99 return;
100 if (m_propertyType == NumberProperty) {
101 // To animation uses contributions from the lower priority animations as the base value.
102 if (animationMode() == ToAnimation)
103 m_fromNumber = results->m_animatedNumber;
104
105 double number = (m_toNumber - m_fromNumber) * percentage + m_fromNumber;
106
107 // FIXME: This is not correct for values animation.
108 if (isAccumulated() && repeat)
109 number += m_toNumber * repeat;
110 if (isAdditive() && animationMode() != ToAnimation)
111 results->m_animatedNumber += number;
112 else
113 results->m_animatedNumber = number;
114 return;
115 }
116 if (m_propertyType == ColorProperty) {
117 if (animationMode() == ToAnimation)
118 m_fromColor = results->m_animatedColor;
119 Color color = ColorDistance(m_fromColor, m_toColor).scaledDistance(percentage).addToColorAndClamp(m_fromColor);
120 // FIXME: Accumulate colors.
121 if (isAdditive() && animationMode() != ToAnimation)
122 results->m_animatedColor = ColorDistance::addColorsAndClamp(results->m_animatedColor, color);
123 else
124 results->m_animatedColor = color;
125 return;
126 }
127 AnimationMode animationMode = this->animationMode();
128 ASSERT(animationMode == FromToAnimation || animationMode == ToAnimation || animationMode == ValuesAnimation);
129 if ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1.0f)
130 results->m_animatedString = m_toString;
131 else
132 results->m_animatedString = m_fromString;
133 // Higher priority replace animation overrides any additive results so far.
134 results->m_propertyType = StringProperty;
135}
136
137bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const String& toString)
138{
139 // FIXME: Needs more solid way determine target attribute type.
140 m_propertyType = determinePropertyType(attributeName());
141 if (m_propertyType == ColorProperty) {
142 m_fromColor = SVGColor::colorFromRGBColorString(fromString);
143 m_toColor = SVGColor::colorFromRGBColorString(toString);
144 if (m_fromColor.isValid() && m_toColor.isValid())
145 return true;
146 } else if (m_propertyType == NumberProperty) {
147 m_numberUnit = String();
148 if (parseNumberValueAndUnit(toString, m_toNumber, m_numberUnit)) {
149 // For to-animations the from number is calculated later
150 if (animationMode() == ToAnimation || parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit))
151 return true;
152 }
153 }
154 m_fromString = fromString;
155 m_toString = toString;
156 m_propertyType = StringProperty;
157 return true;
158}
159
160bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const String& byString)
161{
162 ASSERT(!hasTagName(SVGNames::setTag));
163 m_propertyType = determinePropertyType(attributeName());
164 if (m_propertyType == ColorProperty) {
165 m_fromColor = fromString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(fromString);
166 m_toColor = ColorDistance::addColorsAndClamp(m_fromColor, SVGColor::colorFromRGBColorString(byString));
167 if (!m_fromColor.isValid() || !m_toColor.isValid())
168 return false;
169 } else {
170 m_numberUnit = String();
171 m_fromNumber = 0;
172 if (!fromString.isEmpty() && !parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit))
173 return false;
174 if (!parseNumberValueAndUnit(byString, m_toNumber, m_numberUnit))
175 return false;
176 m_toNumber += m_fromNumber;
177 }
178 return true;
179}
180
181void SVGAnimateElement::resetToBaseValue(const String& baseString)
182{
183 m_animatedString = baseString;
184 m_propertyType = determinePropertyType(attributeName());
185 if (m_propertyType == ColorProperty) {
186 m_animatedColor = baseString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(baseString);
187 if (m_animatedColor.isValid())
188 return;
189 } else if (m_propertyType == NumberProperty) {
190 if (baseString.isEmpty()) {
191 m_animatedNumber = 0;
192 m_numberUnit = String();
193 return;
194 }
195 if (parseNumberValueAndUnit(baseString, m_animatedNumber, m_numberUnit))
196 return;
197 }
198 m_propertyType = StringProperty;
199}
200
201void SVGAnimateElement::applyResultsToTarget()
202{
203 String valueToApply;
204 if (m_propertyType == ColorProperty)
205 valueToApply = m_animatedColor.name();
206 else if (m_propertyType == NumberProperty)
207 valueToApply = String::number(m_animatedNumber) + m_numberUnit;
208 else
209 valueToApply = m_animatedString;
210
211 setTargetAttributeAnimatedValue(valueToApply);
212}
213
214float SVGAnimateElement::calculateDistance(const String& fromString, const String& toString)
215{
216 m_propertyType = determinePropertyType(attributeName());
217 if (m_propertyType == NumberProperty) {
218 double from;
219 double to;
220 String unit;
221 if (!parseNumberValueAndUnit(fromString, from, unit))
222 return -1.f;
223 if (!parseNumberValueAndUnit(toString, to, unit))
224 return -1.f;
225 return narrowPrecisionToFloat(fabs(to - from));
226 } else if (m_propertyType == ColorProperty) {
227 Color from = SVGColor::colorFromRGBColorString(fromString);
228 if (!from.isValid())
229 return -1.f;
230 Color to = SVGColor::colorFromRGBColorString(toString);
231 if (!to.isValid())
232 return -1.f;
233 return ColorDistance(from, to).distance();
234 }
235 return -1.f;
236}
237
238}
239
240// vim:ts=4:noet
241#endif // ENABLE(SVG)
242
ColorDistance.h
FloatConversion.h
SVGAnimateElement.h
SVGParserUtilities.h
number
QString number(KIO::filesize_t size)
ok
KGuiItem ok()
WebCore
Definition: CSSHelper.h:7
WebCore::String
DOM::DOMString String
Definition: PlatformString.h:8
WebCore::narrowPrecisionToFloat
float narrowPrecisionToFloat(T)
parse
QList< Action > parse(QSettings &ini)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KHTML

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

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal