You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-commits@xmlgraphics.apache.org by ca...@apache.org on 2006/08/14 00:37:05 UTC
svn commit: r431260 - in /xmlgraphics/batik/trunk/sources/org/apache/batik:
anim/ anim/timing/ bridge/ util/
Author: cam
Date: Sun Aug 13 15:37:04 2006
New Revision: 431260
URL: http://svn.apache.org/viewvc?rev=431260&view=rev
Log:
1. The animation engine now pauses when there are no animations that need
updating.
Modified:
xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java
xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimeContainer.java
xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedDocumentRoot.java
xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedElement.java
xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationElementBridge.java
xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java
xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGSetElementBridge.java
xmlgraphics/batik/trunk/sources/org/apache/batik/util/RunnableQueue.java
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java Sun Aug 13 15:37:04 2006
@@ -122,7 +122,7 @@
/**
* Sets the current document time.
*/
- public void setCurrentTime(float t) {
+ public float setCurrentTime(float t) {
boolean p = pauseTime != 0;
unpause();
Calendar begin = timedDocumentRoot.getDocumentBeginTime();
@@ -132,7 +132,7 @@
if (p) {
pause();
}
- tick(t, true);
+ return tick(t, true);
}
/**
@@ -260,8 +260,8 @@
* @param hyperlinking whether the document should be seeked to the given
* time, as with hyperlinking
*/
- protected void tick(float time, boolean hyperlinking) {
- timedDocumentRoot.seekTo(time, hyperlinking);
+ protected float tick(float time, boolean hyperlinking) {
+ float waitTime = timedDocumentRoot.seekTo(time, hyperlinking);
Iterator i = targets.entrySet().iterator();
while (i.hasNext()) {
Map.Entry e = (Map.Entry) i.next();
@@ -339,6 +339,7 @@
}
}
}
+ return waitTime;
}
/**
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimeContainer.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimeContainer.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimeContainer.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimeContainer.java Sun Aug 13 15:37:04 2006
@@ -76,22 +76,39 @@
}
/**
- * Calculates the local simple time.
+ * Calculates the local simple time. Currently the hyperlinking parameter
+ * is ignored, so DOM timing events are fired during hyperlinking seeks.
+ * If we were following SMIL 2.1 rather than SMIL Animation, then these
+ * events would have to be surpressed.
+ *
+ * @return the number of seconds until this element becomes active again
+ * if it currently is not, {@link Float.POSITIVE_INFINITY} if this
+ * element will become active at some undetermined point in the
+ * future (because of unresolved begin times, for example) or
+ * will never become active again, or <code>0f</code> if the
+ * element is currently active.
*/
- protected void sampleAt(float parentSimpleTime, boolean hyperlinking) {
+ protected float sampleAt(float parentSimpleTime, boolean hyperlinking) {
super.sampleAt(parentSimpleTime, hyperlinking);
- sampleChildren(parentSimpleTime, hyperlinking);
+ // Maybe check the return value of the previous statement.
+ return sampleChildren(parentSimpleTime, hyperlinking);
}
/**
* Samples all the child timed elements.
*/
- protected void sampleChildren(float parentSimpleTime, boolean hyperlinking) {
+ protected float sampleChildren(float parentSimpleTime,
+ boolean hyperlinking) {
+ float mint = Float.POSITIVE_INFINITY;
Iterator i = children.iterator();
while (i.hasNext()) {
TimedElement e = (TimedElement) i.next();
- e.sampleAt(parentSimpleTime, hyperlinking);
+ float t = e.sampleAt(parentSimpleTime, hyperlinking);
+ if (t < mint) {
+ mint = t;
+ }
}
+ return mint;
}
/**
@@ -104,6 +121,14 @@
TimedElement e = (TimedElement) i.next();
e.reset(clearCurrentBegin);
}
+ }
+
+ /**
+ * Returns whether this timed element is for a constant animation (i.e., a
+ * 'set' animation.
+ */
+ protected boolean isConstantAnimation() {
+ return false;
}
/**
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedDocumentRoot.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedDocumentRoot.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedDocumentRoot.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedDocumentRoot.java Sun Aug 13 15:37:04 2006
@@ -103,16 +103,19 @@
/**
* Samples the entire timegraph at the given time.
*/
- public void seekTo(float time, boolean hyperlinking) {
+ public float seekTo(float time, boolean hyperlinking) {
lastSampleTime = time;
// Trace.enter(this, "seekTo", new Object[] { new Float(time) } ); try {
propagationFlags.clear();
// No time containers in SVG, so we don't have to worry
// about a partial ordering of timed elements to sample.
+ float mint = Float.POSITIVE_INFINITY;
TimedElement[] es = getChildren();
for (int i = 0; i < es.length; i++) {
- // System.err.print("[" + ((Test.AnimateElement) es[i]).id + "] ");
- es[i].sampleAt(time, hyperlinking);
+ float t = es[i].sampleAt(time, hyperlinking);
+ if (t < mint) {
+ mint = t;
+ }
}
boolean needsUpdates;
do {
@@ -121,10 +124,14 @@
if (es[i].shouldUpdateCurrentInterval) {
needsUpdates = true;
// System.err.print("{" + ((Test.AnimateElement) es[i]).id + "} ");
- es[i].sampleAt(time, hyperlinking);
+ float t = es[i].sampleAt(time, hyperlinking);
+ if (t < mint) {
+ mint = t;
+ }
}
}
} while (needsUpdates);
+ return mint;
// } finally { Trace.exit(); }
}
@@ -219,6 +226,15 @@
}
propagationFlags.add(it, ts);
return true;
+ }
+
+ /**
+ * Invoked by timed elements in this document to indicate that the current
+ * interval will be re-evaluated at the next sample. This should be
+ * overridden in a concrete class so that ticks can be scheduled immediately
+ * if they are currently paused due to no animations being active.
+ */
+ protected void currentIntervalWillUpdate() {
}
/**
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedElement.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedElement.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedElement.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/anim/timing/TimedElement.java Sun Aug 13 15:37:04 2006
@@ -536,8 +536,15 @@
* is ignored, so DOM timing events are fired during hyperlinking seeks.
* If we were following SMIL 2.1 rather than SMIL Animation, then these
* events would have to be surpressed.
+ *
+ * @return the number of seconds until this element becomes active again
+ * if it currently is not, {@link Float.POSITIVE_INFINITY} if this
+ * element will become active at some undetermined point in the
+ * future (because of unresolved begin times, for example) or
+ * will never become active again, or <code>0f</code> if the
+ * element is currently active.
*/
- protected void sampleAt(float parentSimpleTime, boolean hyperlinking) {
+ protected float sampleAt(float parentSimpleTime, boolean hyperlinking) {
// Trace.enter(this, "sampleAt", new Object[] { new Float(parentSimpleTime) } ); try {
float time = parentSimpleTime; // No time containers in SVG.
@@ -600,8 +607,7 @@
// begin and end times, or end the current interval and compute
// a new one.
boolean hasEnded = currentInterval != null
- && (time < currentInterval.getBegin()
- || time >= currentInterval.getEnd());
+ && time > currentInterval.getEnd();
// Fire any repeat events that should have been fired since the
// last sample.
if (currentInterval != null) {
@@ -723,6 +729,14 @@
}
lastSampleTime = time;
+ if (currentInterval != null) {
+ float t = currentInterval.getBegin() - time;
+ if (t > 0) {
+ return t;
+ }
+ return isConstantAnimation() ? currentInterval.getEnd() - time : 0;
+ }
+ return Float.POSITIVE_INFINITY;
// } finally { Trace.exit(); }
}
@@ -1240,6 +1254,7 @@
handledEvents.put(e, ts);
}
ts.add(t);
+ root.currentIntervalWillUpdate();
}
/**
@@ -1322,6 +1337,12 @@
* in document order.
*/
public abstract boolean isBefore(TimedElement other);
+
+ /**
+ * Returns whether this timed element is for a constant animation (i.e., a
+ * 'set' animation.
+ */
+ protected abstract boolean isConstantAnimation();
/**
* Creates and returns a new {@link AnimationException}.
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationElementBridge.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationElementBridge.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationElementBridge.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationElementBridge.java Sun Aug 13 15:37:04 2006
@@ -494,6 +494,13 @@
}
/**
+ * Returns whether this is a constant animation (i.e., a 'set' animation).
+ */
+ protected boolean isConstantAnimation() {
+ return false;
+ }
+
+ /**
* A TimedElement class for SVG animation elements.
*/
protected class SVGTimedElement extends TimedElement {
@@ -616,6 +623,14 @@
}
}
return super.toString();
+ }
+
+ /**
+ * Returns whether this timed element is for a constant animation (i.e.,
+ * a 'set' animation.
+ */
+ protected boolean isConstantAnimation() {
+ return SVGAnimationElementBridge.this.isConstantAnimation();
}
}
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java Sun Aug 13 15:37:04 2006
@@ -367,6 +367,28 @@
}
/**
+ * Returns the current document time.
+ */
+ public float getCurrentTime() {
+ boolean p = pauseTime != 0;
+ unpause();
+ float t = timedDocumentRoot.getCurrentTime();
+ if (p) {
+ pause();
+ }
+ return t;
+ }
+
+ /**
+ * Sets the current document time.
+ */
+ public float setCurrentTime(float t) {
+ float ret = super.setCurrentTime(t);
+ animationTickRunnable.resume();
+ return ret;
+ }
+
+ /**
* Creates a new returns a new TimedDocumentRoot object for the document.
*/
protected TimedDocumentRoot createDocumentRoot() {
@@ -534,6 +556,16 @@
public boolean isBefore(TimedElement other) {
return false;
}
+
+ /**
+ * Invoked by timed elements in this document to indicate that the
+ * current interval will be re-evaluated at the next sample.
+ */
+ protected void currentIntervalWillUpdate() {
+ if (animationTickRunnable != null) {
+ animationTickRunnable.resume();
+ }
+ }
}
/**
@@ -569,9 +601,10 @@
tick(0, false);
// animationThread = new AnimationThread();
// animationThread.start();
- animationTickRunnable = new AnimationTickRunnable();
- ctx.getUpdateManager().getUpdateRunnableQueue().setIdleRunnable
- (animationTickRunnable);
+ RunnableQueue q =
+ ctx.getUpdateManager().getUpdateRunnableQueue();
+ animationTickRunnable = new AnimationTickRunnable(q);
+ q.setIdleRunnable(animationTickRunnable);
} catch (AnimationException ex) {
throw new BridgeException(ctx, ex.getElement().getElement(),
ex.getMessage());
@@ -589,22 +622,44 @@
/**
* Idle runnable to tick the animation.
*/
- protected class AnimationTickRunnable implements Runnable {
+ protected class AnimationTickRunnable
+ implements RunnableQueue.IdleRunnable {
+
protected Calendar time = Calendar.getInstance();
double second = -1.;
int idx = -1;
int frames;
+ long waitTime;
+ RunnableQueue q;
+ public AnimationTickRunnable(RunnableQueue q) {
+ this.q = q;
+ }
+ public void resume() {
+ Object lock = q.getIteratorLock();
+ synchronized (lock) {
+ lock.notify();
+ }
+ }
+ public long getWaitTime() {
+ return waitTime;
+ }
public void run() {
try {
try {
- time.setTimeInMillis(System.currentTimeMillis());
+ long now = System.currentTimeMillis();
+ time.setTimeInMillis(now);
float t = timedDocumentRoot.convertWallclockTime(time);
if (Math.floor(t) > second) {
second = Math.floor(t);
// System.err.println("fps: " + frames);
frames = 0;
}
- tick(t, false);
+ float t2 = tick(t, false);
+ if (t2 == Float.POSITIVE_INFINITY) {
+ waitTime = Long.MAX_VALUE;
+ } else {
+ waitTime = now + (long) (t2 * 1000) - 2000;;
+ }
frames++;
} catch (AnimationException ex) {
throw new BridgeException(ctx, ex.getElement().getElement(),
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGSetElementBridge.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGSetElementBridge.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGSetElementBridge.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGSetElementBridge.java Sun Aug 13 15:37:04 2006
@@ -60,4 +60,11 @@
protected boolean canAnimateType(int type) {
return true;
}
+
+ /**
+ * Returns whether this is a constant animation (i.e., a 'set' animation).
+ */
+ protected boolean isConstantAnimation() {
+ return true;
+ }
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/util/RunnableQueue.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/util/RunnableQueue.java?rev=431260&r1=431259&r2=431260&view=diff
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/util/RunnableQueue.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/util/RunnableQueue.java Sun Aug 13 15:37:04 2006
@@ -105,9 +105,14 @@
protected volatile HaltingThread runnableQueueThread;
/**
- * The Runnable to run if the queue is empty.
+ * The {@link IdleRunnable} to run if the queue is empty.
*/
- protected Runnable idleRunnable;
+ protected IdleRunnable idleRunnable;
+
+ /**
+ * The time (in milliseconds) that the idle runnable should be run next.
+ */
+ protected long idleRunnableWaitTime;
/**
* Creates a new RunnableQueue started in a new thread.
@@ -190,6 +195,7 @@
// Thread.sleep(1);
// } catch (InterruptedException ie) { }
+ boolean usedIdleRunnable = false;
synchronized (list) {
if (state == SUSPENDING)
continue;
@@ -198,15 +204,25 @@
if (l == null) {
// No item to run, see if there is an idle runnable
// to run instead.
- if (idleRunnable != null) {
+ if (idleRunnable != null && idleRunnableWaitTime
+ < System.currentTimeMillis()) {
rable = idleRunnable;
+ usedIdleRunnable = true;
} else {
// Wait for a runnable.
try {
- list.wait();
+ if (idleRunnable != null && idleRunnableWaitTime
+ != Long.MAX_VALUE) {
+ long t = idleRunnableWaitTime
+ - System.currentTimeMillis();
+ list.wait(t);
+ } else {
+ list.wait();
+ }
} catch (InterruptedException ie) {
// just loop again.
}
+ idleRunnableWaitTime = 0;
continue; // start loop over again...
}
} else {
@@ -232,6 +248,10 @@
l.unlock();
}
runnableInvoked(rable);
+
+ if (usedIdleRunnable) {
+ idleRunnableWaitTime = idleRunnable.getWaitTime();
+ }
}
} finally {
synchronized (this) {
@@ -475,9 +495,10 @@
/**
* Sets a Runnable to be run whenever the queue is empty.
*/
- public synchronized void setIdleRunnable(Runnable r) {
+ public synchronized void setIdleRunnable(IdleRunnable r) {
synchronized (list) {
idleRunnable = r;
+ idleRunnableWaitTime = 0;
list.notify();
}
}
@@ -524,6 +545,23 @@
if (runHandler != null) {
runHandler.runnableInvoked(this, rable);
}
+ }
+
+ /**
+ * A {@link Runnable} that can also inform the caller how long it should
+ * be until it is run again.
+ */
+ public interface IdleRunnable extends Runnable {
+
+ /**
+ * Returns the system time that can be safely waited until before this
+ * {@link Runnable} is run again.
+ *
+ * @return time to wait until, <code>0</code> if no waiting can
+ * be done, or {@link Long.MAX_VALUE} if the {@link Runnable}
+ * should not be run again at this time
+ */
+ long getWaitTime();
}
/**