summaryrefslogtreecommitdiffstats
path: root/ksvg/impl/SVGAnimationElementImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksvg/impl/SVGAnimationElementImpl.cpp')
-rw-r--r--ksvg/impl/SVGAnimationElementImpl.cpp463
1 files changed, 463 insertions, 0 deletions
diff --git a/ksvg/impl/SVGAnimationElementImpl.cpp b/ksvg/impl/SVGAnimationElementImpl.cpp
new file mode 100644
index 00000000..b87a9829
--- /dev/null
+++ b/ksvg/impl/SVGAnimationElementImpl.cpp
@@ -0,0 +1,463 @@
+/*
+ Copyright (C) 2001-2003 KSVG Team
+ 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 <math.h>
+
+#include <kdebug.h>
+
+#include <tqtimer.h>
+
+#include "CanvasItem.h"
+#include "SVGHelperImpl.h"
+#include "SVGDocumentImpl.h"
+#include "SVGSVGElementImpl.h"
+#include "SVGStringListImpl.h"
+#include "SVGURIReferenceImpl.h"
+#include "SVGAnimationElementImpl.h"
+
+using namespace KSVG;
+
+#include "SVGAnimationElementImpl.lut.h"
+#include "ksvg_bridge.h"
+#include "ksvg_ecma.h"
+
+SVGAnimationElementImpl::SVGAnimationElementImpl(DOM::ElementImpl *impl) : SVGElementImpl(impl), SVGTestsImpl(), SVGExternalResourcesRequiredImpl()
+{
+ KSVG_EMPTY_FLAGS
+
+ m_connected = false;
+ m_targetElement = 0;
+
+ m_values = new SVGStringListImpl();
+ m_keyTimes= new SVGStringListImpl();
+ m_keySplines = new SVGStringListImpl();
+
+ m_fill = REMOVE;
+ m_additive = REPLACE;
+ m_accumulate = ACCUMULATE_NONE;
+}
+
+SVGAnimationElementImpl::~SVGAnimationElementImpl()
+{
+ if(m_targetElement)
+ m_targetElement->deref();
+}
+
+SVGElementImpl *SVGAnimationElementImpl::targetElement() const
+{
+ if(!m_targetElement)
+ {
+ SVGAnimationElementImpl *modify = const_cast<SVGAnimationElementImpl *>(this);
+ if(!m_href.isEmpty())
+ modify->setTargetElement(ownerDoc()->getElementByIdRecursive(ownerSVGElement(), SVGURIReferenceImpl::getTarget(m_href)));
+ else if(!parentNode().isNull())
+ modify->setTargetElement(ownerDoc()->getElementFromHandle(parentNode().handle()));
+ }
+
+ return m_targetElement;
+}
+
+double SVGAnimationElementImpl::parseClockValue(const TQString &data) const
+{
+ TQString parse = data.stripWhiteSpace();
+ TQString debugOutput = "parseClockValue(" + parse + ") -> ";
+
+ if(parse == "indefinite") // Saves some time...
+ return -1;
+
+ double result;
+
+ int doublePointOne = parse.find(':');
+ int doublePointTwo = parse.find(':', doublePointOne + 1);
+
+ if(doublePointOne != -1 && doublePointTwo != -1) // Spec: "Full clock values"
+ {
+ unsigned int hours = parse.mid(0, 2).toUInt();
+ unsigned int minutes = parse.mid(3, 2).toUInt();
+ unsigned int seconds = parse.mid(6, 2).toUInt();
+ unsigned int milliseconds = 0;
+
+ result = (3600 * hours) + (60 * minutes) + seconds;
+
+ if(parse.find('.') != -1)
+ {
+ TQString temp = parse.mid(9, 2);
+ milliseconds = temp.toUInt();
+ result += (milliseconds * (1 / pow(10.0, temp.length())));
+ }
+ }
+ else if(doublePointOne != -1 && doublePointTwo == -1) // Spec: "Partial clock values"
+ {
+ unsigned int minutes = parse.mid(0, 2).toUInt();
+ unsigned int seconds = parse.mid(3, 2).toUInt();
+ unsigned int milliseconds = 0;
+
+ result = (60 * minutes) + seconds;
+
+ if(parse.find('.') != -1)
+ {
+ TQString temp = parse.mid(6, 2);
+ milliseconds = temp.toUInt();
+ result += (milliseconds * (1 / pow(10.0, temp.length())));
+ }
+ }
+ else // Spec: "Timecount values"
+ {
+ int dotPosition = parse.find('.');
+
+ if(parse.endsWith("h"))
+ {
+ if(dotPosition == -1)
+ result = parse.mid(0, parse.length() - 1).toUInt() * 3600;
+ else
+ {
+ result = parse.mid(0, dotPosition).toUInt() * 3600;
+ TQString temp = parse.mid(dotPosition + 1, parse.length() - dotPosition - 2);
+ result += (3600.0 * temp.toUInt()) * (1 / pow(10.0, temp.length()));
+ }
+ }
+ else if(parse.endsWith("min"))
+ {
+ if(dotPosition == -1)
+ result = parse.mid(0, parse.length() - 3).toUInt() * 60;
+ else
+ {
+ result = parse.mid(0, dotPosition).toUInt() * 60;
+ TQString temp = parse.mid(dotPosition + 1, parse.length() - dotPosition - 4);
+ result += (60.0 * temp.toUInt()) * (1 / pow(10.0, temp.length()));
+ }
+ }
+ else if(parse.endsWith("ms"))
+ {
+ if(dotPosition == -1)
+ result = parse.mid(0, parse.length() - 2).toUInt() / 1000.0;
+ else
+ {
+ result = parse.mid(0, dotPosition).toUInt() / 1000.0;
+ TQString temp = parse.mid(dotPosition + 1, parse.length() - dotPosition - 3);
+ result += (temp.toUInt() / 1000.0) * (1 / pow(10.0, temp.length()));
+ }
+ }
+ else if(parse.endsWith("s"))
+ {
+ if(dotPosition == -1)
+ result = parse.mid(0, parse.length() - 1).toUInt();
+ else
+ {
+ result = parse.mid(0, dotPosition).toUInt();
+ TQString temp = parse.mid(dotPosition + 1, parse.length() - dotPosition - 2);
+ result += temp.toUInt() * (1 / pow(10.0, temp.length()));
+ }
+ }
+ else
+ result = parse.toDouble();
+ }
+
+ kdDebug() << debugOutput << result << endl;
+ return result;
+}
+
+/*
+@namespace KSVG
+@begin SVGAnimationElementImpl::s_hashTable 23
+ targetElement SVGAnimationElementImpl::TargetElement DontDelete|ReadOnly
+ href SVGAnimationElementImpl::Href DontDelete|ReadOnly
+ additive SVGAnimationElementImpl::Additive DontDelete|ReadOnly
+ accumulate SVGAnimationElementImpl::Accumulate DontDelete|ReadOnly
+ attributeName SVGAnimationElementImpl::AttributeName DontDelete|ReadOnly
+ attributeType SVGAnimationElementImpl::AttributeType DontDelete|ReadOnly
+ calcMode SVGAnimationElementImpl::CalcMode DontDelete|ReadOnly
+ values SVGAnimationElementImpl::Values DontDelete|ReadOnly
+ keyTimes SVGAnimationElementImpl::KeyTimes DontDelete|ReadOnly
+ keySplines SVGAnimationElementImpl::KeySplines DontDelete|ReadOnly
+ from SVGAnimationElementImpl::From DontDelete|ReadOnly
+ to SVGAnimationElementImpl::To DontDelete|ReadOnly
+ by SVGAnimationElementImpl::By DontDelete|ReadOnly
+ begin SVGAnimationElementImpl::Begin DontDelete|ReadOnly
+ dur SVGAnimationElementImpl::Dur DontDelete|ReadOnly
+ end SVGAnimationElementImpl::End DontDelete|ReadOnly
+ min SVGAnimationElementImpl::Min DontDelete|ReadOnly
+ max SVGAnimationElementImpl::Max DontDelete|ReadOnly
+ restart SVGAnimationElementImpl::Restart DontDelete|ReadOnly
+ repeatCount SVGAnimationElementImpl::RepeatCount DontDelete|ReadOnly
+ repeatDur SVGAnimationElementImpl::RepeatDur DontDelete|ReadOnly
+ fill SVGAnimationElementImpl::Fill DontDelete|ReadOnly
+@end
+@namespace KSVG
+@begin SVGAnimationElementImplProto::s_hashTable 5
+ getStartTime SVGAnimationElementImpl::GetStartTime DontDelete|Function 0
+ getCurrentTime SVGAnimationElementImpl::GetCurrentTime DontDelete|Function 0
+ getSimpleDuration SVGAnimationElementImpl::GetSimpleDuration DontDelete|Function 0
+@end
+*/
+
+KSVG_IMPLEMENT_PROTOTYPE("SVGAnimationElement",SVGAnimationElementImplProto,SVGAnimationElementImplProtoFunc)
+
+Value SVGAnimationElementImpl::getValueProperty(ExecState *exec, int token) const
+{
+ switch(token)
+ {
+ case TargetElement:
+ return m_targetElement->cache(exec);
+ default:
+ kdWarning() << "Unhandled token in " << k_funcinfo << " : " << token << endl;
+ return Undefined();
+ }
+}
+
+void SVGAnimationElementImpl::putValueProperty(ExecState *exec, int token, const Value &value, int attr)
+{
+ // This class has just ReadOnly properties, only with the Internal flag set
+ // it's allowed to modify those.
+ if(!(attr & KJS::Internal))
+ return;
+
+ TQString val = value.toString(exec).qstring();
+ switch(token)
+ {
+ case Href:
+ m_href = val;
+ break;
+ case Additive:
+ m_additive = (val == "sum") ? SUM : REPLACE;
+ break;
+ case Accumulate:
+ m_accumulate = (val == "sum") ? ACCUMULATE_SUM : ACCUMULATE_NONE;
+ break;
+ case AttributeName:
+ m_attributeName = val;
+ break;
+ case AttributeType:
+ if(val == "css")
+ m_attributeType = CSS;
+ else if(val == "xml")
+ m_attributeType = XML;
+ else
+ m_attributeType = AUTO;
+ break;
+ case CalcMode: // FIXME: See spec for default values!!!
+ if(val == "discrete")
+ m_calcMode = DISCRETE;
+ else if(val == "linear")
+ m_calcMode = LINEAR;
+ else if(val == "spline")
+ m_calcMode = SPLINE;
+ else if(val == "paced")
+ m_calcMode = PACED;
+ break;
+ case Values:
+ SVGHelperImpl::parseSemicolonSeperatedList(m_values, val);
+ break;
+ case KeyTimes:
+ SVGHelperImpl::parseSemicolonSeperatedList(m_keyTimes, val);
+ break;
+ case KeySplines:
+ SVGHelperImpl::parseSemicolonSeperatedList(m_keySplines, val);
+ break;
+ case From:
+ m_from = val;
+ break;
+ case To:
+ m_to = val;
+ break;
+ case By:
+ m_by = val;
+ break;
+ case Begin:
+ case End:
+ {
+ // Create list
+ SVGStringListImpl *temp = new SVGStringListImpl();
+ temp->ref();
+
+ // Feed data into list
+ SVGHelperImpl::parseSemicolonSeperatedList(temp, val);
+
+ // Parse data
+ for(unsigned int i = 0; i < temp->numberOfItems(); i++)
+ {
+ TQString current = temp->getItem(i)->string();
+
+ if(current.startsWith("accessKey"))
+ {
+ // Register keyDownEventListener for the character
+ TQString character = current.mid(current.length() - 2, 1);
+
+ kdDebug() << "ACCESSKEY CHARACTER " << character << endl;
+ }
+ else if(current.startsWith("wallclock"))
+ {
+ int firstBrace = current.find("(");
+ int secondBrace = current.find(")");
+
+ TQString wallclockValue = current.mid(firstBrace + 1, secondBrace - firstBrace - 2);
+
+ kdDebug() << "WALLCLOCK VALUE " << wallclockValue << endl;
+ }
+ else if(current.contains("."))
+ {
+ int dotPosition = current.find(".");
+
+ TQString element = current.mid(0, dotPosition);
+ TQString clockValue;
+
+ if(current.contains("begin"))
+ clockValue = current.mid(dotPosition + 6);
+ else if(current.contains("end"))
+ clockValue = current.mid(dotPosition + 4);
+ else if(current.contains("repeat"))
+ clockValue = current.mid(dotPosition + 7);
+ else // DOM2 Event Reference
+ {
+ int plusMinusPosition = -1;
+
+ if(current.contains("+"))
+ plusMinusPosition = current.find("+");
+ else if(current.contains("-"))
+ plusMinusPosition = current.find("-");
+
+ TQString event = current.mid(dotPosition + 1, plusMinusPosition - dotPosition - 1);
+
+ clockValue = current.mid(dotPosition + event.length() + 1);
+ kdDebug() << "EVENT " << event << endl;
+ }
+
+ kdDebug() << "ELEMENT " << element << " CLOCKVALUE " << clockValue << endl;
+ }
+ else
+ {
+ if(token == Begin)
+ m_begin = parseClockValue(current);
+ else
+ m_end = parseClockValue(current);
+ }
+ }
+
+ temp->deref();
+
+ break;
+ }
+ case Dur:
+ m_duration = parseClockValue(val);
+ break;
+// case Min:
+// case Max:
+ case Restart:
+ if(val == "whenNotActive")
+ m_restart = WHENNOTACTIVE;
+ else if(val == "never")
+ m_restart = NEVER;
+ else
+ m_restart = ALWAYS;
+ break;
+ case RepeatCount:
+ m_repeatCount = val;
+ break;
+ case RepeatDur:
+ m_repeatDur = val;
+ break;
+ case Fill:
+ m_fill = (val == "freeze") ? FREEZE : REMOVE;
+ break;
+ default:
+ kdWarning() << "Unhandled token in " << k_funcinfo << " : " << token << endl;
+ }
+}
+
+Value SVGAnimationElementImplProtoFunc::call(ExecState *exec, Object &thisObj, const List &)
+{
+ KSVG_CHECK_THIS(SVGAnimationElementImpl)
+
+ switch(id)
+ {
+ case SVGAnimationElementImpl::GetStartTime:
+ return Number(obj->getStartTime());
+ case SVGAnimationElementImpl::GetCurrentTime:
+ return Number(obj->getCurrentTime());
+ case SVGAnimationElementImpl::GetSimpleDuration:
+ return Number(obj->getSimpleDuration());
+ default:
+ kdWarning() << "Unhandled function id in " << k_funcinfo << " : " << id << endl;
+ break;
+ }
+
+ return Undefined();
+}
+
+void SVGAnimationElementImpl::setAttributes()
+{
+ SVGElementImpl::setAttributes();
+
+ // Spec: Default value is "replace"
+ if(KSVG_TOKEN_NOT_PARSED(Additive))
+ KSVG_SET_ALT_ATTRIBUTE(Additive, "replace")
+
+ // Spec: Default value is "none"
+ if(KSVG_TOKEN_NOT_PARSED(Accumulate))
+ KSVG_SET_ALT_ATTRIBUTE(Accumulate, "none")
+
+ // Spec: Default value is "always"
+ if(KSVG_TOKEN_NOT_PARSED(Restart))
+ KSVG_SET_ALT_ATTRIBUTE(Restart, "always")
+}
+
+void SVGAnimationElementImpl::setTargetElement(SVGElementImpl *target)
+{
+ if(m_targetElement)
+ m_targetElement->deref();
+
+ m_targetElement = target;
+ m_targetElement->ref();
+}
+
+void SVGAnimationElementImpl::applyAttribute(const TQString &name, const TQString &value)
+{
+ SVGElementImpl *target = targetElement();
+ if(!target)
+ {
+ kdDebug() << k_funcinfo << " name: " << name << " value: " << value << " NO TARGET ELEMENT!" << endl;
+ return;
+ }
+
+ // The only two cases I can imagine, where combining is needed (Niko)
+ bool combine = (name == "style" || name == "transform");
+
+ if(!combine)
+ target->setAttributeInternal(name, value);
+ else
+ {
+ kdDebug() << "TODO COMBINE: " << value << " NAME " << name << endl;
+ }
+}
+
+double SVGAnimationElementImpl::getStartTime() const
+{
+ return m_begin;
+}
+
+double SVGAnimationElementImpl::getCurrentTime() const
+{
+ return 0.0;
+}
+
+double SVGAnimationElementImpl::getSimpleDuration() const
+{
+ return m_duration;
+}