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 2007/02/02 05:57:56 UTC
svn commit: r502489 - in /xmlgraphics/batik/trunk:
resources/org/apache/batik/apps/svgbrowser/resources/
sources/org/apache/batik/anim/ sources/org/apache/batik/bridge/
sources/org/apache/batik/bridge/svg12/ test-sources/org/apache/batik/swing/
test-so...
Author: cam
Date: Thu Feb 1 20:57:56 2007
New Revision: 502489
URL: http://svn.apache.org/viewvc?view=rev&rev=502489
Log:
1. Ensure the animation engine of an SVG 1.2 resource document does not
prevent the document from being GCed.
2. Fixed typo in Squiggle's Prefrences window.
Modified:
xmlgraphics/batik/trunk/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties
xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java
xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/BridgeContext.java
xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java
xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVG12BridgeContext.java
xmlgraphics/batik/trunk/test-sources/org/apache/batik/swing/JSVGMemoryLeakTest.java
xmlgraphics/batik/trunk/test-sources/org/apache/batik/test/MemoryLeakTest.java
Modified: xmlgraphics/batik/trunk/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties (original)
+++ xmlgraphics/batik/trunk/resources/org/apache/batik/apps/svgbrowser/resources/GUI.properties Thu Feb 1 20:57:56 2007
@@ -496,7 +496,7 @@
PreferenceDialog.label.selection.xor.mode = Display selection overlay using XOR mode
PreferenceDialog.label.animation.limit.cpu = Limit to percentage of CPU usage
PreferenceDialog.label.percent = %
-PreferenceDialog.label.animation.limit.fps = Limit to number of frmaes per second
+PreferenceDialog.label.animation.limit.fps = Limit to number of frames per second
PreferenceDialog.label.fps = fps
PreferenceDialog.label.animation.limit.unlimited = Unlimited
PreferenceDialog.label.show.debug.trace = Print debugging information to console
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?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/anim/AnimationEngine.java Thu Feb 1 20:57:56 2007
@@ -86,6 +86,43 @@
}
/**
+ * Disposes this animation engine.
+ */
+ public void dispose() {
+ // Remove any target listeners that are registered.
+ Iterator i = targets.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
+ AnimationTarget target = (AnimationTarget) e.getKey();
+ TargetInfo info = (TargetInfo) e.getValue();
+
+ Iterator j = info.xmlAnimations.iterator();
+ while (j.hasNext()) {
+ DoublyIndexedTable.Entry e2 =
+ (DoublyIndexedTable.Entry) j.next();
+ String namespaceURI = (String) e2.getKey1();
+ String localName = (String) e2.getKey2();
+ Sandwich sandwich = (Sandwich) e2.getValue();
+ if (sandwich.listenerRegistered) {
+ target.removeTargetListener(namespaceURI, localName, false,
+ targetListener);
+ }
+ }
+
+ j = info.cssAnimations.entrySet().iterator();
+ while (j.hasNext()) {
+ Map.Entry e2 = (Map.Entry) j.next();
+ String propertyName = (String) e2.getKey();
+ Sandwich sandwich = (Sandwich) e2.getValue();
+ if (sandwich.listenerRegistered) {
+ target.removeTargetListener(null, propertyName, true,
+ targetListener);
+ }
+ }
+ }
+ }
+
+ /**
* Pauses the animations.
*/
public void pause() {
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/BridgeContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/BridgeContext.java?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/BridgeContext.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/BridgeContext.java Thu Feb 1 20:57:56 2007
@@ -318,6 +318,15 @@
}
/**
+ * Calls dispose on this BridgeContext, if it is a child context.
+ */
+ protected void finalize() {
+ if (primaryContext != null) {
+ dispose();
+ }
+ }
+
+ /**
* This function creates a new 'sub' BridgeContext to associated
* with 'newDoc' if one currently doesn't exist, otherwise it
* returns the BridgeContext currently associated with the
@@ -325,11 +334,14 @@
* @param newDoc The document to get/create a BridgeContext for.
*/
public BridgeContext createSubBridgeContext(SVGOMDocument newDoc) {
+ BridgeContext subCtx;
+
CSSEngine eng = newDoc.getCSSEngine();
- if (eng != null)
- return (BridgeContext)newDoc.getCSSEngine().getCSSContext();
+ if (eng != null) {
+ subCtx = (BridgeContext) newDoc.getCSSEngine().getCSSContext();
+ return subCtx;
+ }
- BridgeContext subCtx;
subCtx = createBridgeContext(newDoc);
subCtx.primaryContext = primaryContext != null ? primaryContext : this;
subCtx.primaryContext.childContexts.add(new WeakReference(subCtx));
@@ -1383,10 +1395,19 @@
}
/**
+ * Clears the list of child BridgeContexts and disposes them if there are
+ * no more references to them.
+ */
+ protected void clearChildContexts() {
+ childContexts.clear();
+ }
+
+ /**
* Disposes this BridgeContext.
*/
public void dispose() {
- childContexts.clear();
+ clearChildContexts();
+
synchronized (eventListenerSet) {
// remove all listeners added by Bridges
Iterator iter = eventListenerSet.iterator();
@@ -1412,6 +1433,12 @@
if (document != null) {
removeDOMListeners();
}
+
+ if (animationEngine != null) {
+ animationEngine.dispose();
+ animationEngine = null;
+ }
+
Iterator iter = interpreterMap.values().iterator();
while (iter.hasNext()) {
Interpreter interpreter = (Interpreter)iter.next();
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?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/SVGAnimationEngine.java Thu Feb 1 20:57:56 2007
@@ -20,6 +20,7 @@
import java.awt.Color;
import java.awt.Paint;
+import java.lang.ref.WeakReference;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
@@ -277,6 +278,10 @@
* Disposes this animation engine.
*/
public void dispose() {
+ synchronized (this) {
+ pause();
+ super.dispose();
+ }
}
/**
@@ -437,7 +442,7 @@
UpdateManager um = ctx.getUpdateManager();
if (um != null) {
RunnableQueue q = um.getUpdateRunnableQueue();
- animationTickRunnable = new AnimationTickRunnable(q);
+ animationTickRunnable = new AnimationTickRunnable(q, this);
q.setIdleRunnable(animationTickRunnable);
}
} catch (AnimationException ex) {
@@ -657,12 +662,12 @@
/**
* Idle runnable to tick the animation, that reads times from System.in.
*/
- protected class DebugAnimationTickRunnable extends AnimationTickRunnable {
+ protected static class DebugAnimationTickRunnable extends AnimationTickRunnable {
float t = 0f;
- public DebugAnimationTickRunnable(RunnableQueue q) {
- super(q);
+ public DebugAnimationTickRunnable(RunnableQueue q, SVGAnimationEngine eng) {
+ super(q, eng);
waitTime = Long.MAX_VALUE;
new Thread() {
public void run() {
@@ -700,18 +705,22 @@
}
public void run() {
- try {
+ SVGAnimationEngine eng = getAnimationEngine();
+ synchronized (eng) {
try {
- tick(t, false);
- } catch (AnimationException ex) {
- throw new BridgeException(ctx, ex.getElement().getElement(),
- ex.getMessage());
- }
- } catch (BridgeException ex) {
- if (ctx.getUserAgent() == null) {
- ex.printStackTrace();
- } else {
- ctx.getUserAgent().displayError(ex);
+ try {
+ eng.tick(t, false);
+ } catch (AnimationException ex) {
+ throw new BridgeException
+ (eng.ctx, ex.getElement().getElement(),
+ ex.getMessage());
+ }
+ } catch (BridgeException ex) {
+ if (eng.ctx.getUserAgent() == null) {
+ ex.printStackTrace();
+ } else {
+ eng.ctx.getUserAgent().displayError(ex);
+ }
}
}
}
@@ -720,7 +729,7 @@
/**
* Idle runnable to tick the animation.
*/
- protected class AnimationTickRunnable
+ protected static class AnimationTickRunnable
implements RunnableQueue.IdleRunnable {
/**
@@ -773,12 +782,20 @@
protected int timeIndex;
/**
+ * A weak reference to the SVGAnimationEngine this AnimationTickRunnable
+ * is for. We makes this a WeakReference so that a ticking animation
+ * engine does not prevent from being GCed.
+ */
+ protected WeakReference engRef;
+
+ /**
* Creates a new AnimationTickRunnable.
*/
- public AnimationTickRunnable(RunnableQueue q) {
+ public AnimationTickRunnable(RunnableQueue q, SVGAnimationEngine eng) {
this.q = q;
+ this.engRef = new WeakReference(eng);
// Initialize the past times to 100ms.
- Arrays.fill( times, 100 );
+ Arrays.fill(times, 100);
sumTime = 100 * NUM_TIMES;
}
@@ -810,70 +827,83 @@
* Performs one tick of the animation.
*/
public void run() {
- try {
+ SVGAnimationEngine eng = getAnimationEngine();
+ synchronized (eng) {
+ int animationLimitingMode = eng.animationLimitingMode;
+ float animationLimitingAmount = eng.animationLimitingAmount;
try {
- long before = System.currentTimeMillis();
- time.setTime(new Date(before));
- float t = timedDocumentRoot.convertWallclockTime(time);
-// if (Math.floor(t) > second) {
-// second = Math.floor(t);
-// System.err.println("fps: " + frames);
-// frames = 0;
-// }
- float t2 = tick(t, false);
- long after = System.currentTimeMillis();
- long dur = after - before;
- if (dur == 0) {
- dur = 1;
- }
- sumTime -= times[timeIndex];
- sumTime += dur;
- times[timeIndex] = dur;
- timeIndex = (timeIndex + 1) % NUM_TIMES;
-
- if (t2 == Float.POSITIVE_INFINITY) {
- waitTime = Long.MAX_VALUE;
- } else {
- waitTime = before + (long) (t2 * 1000) - 1000;
- if (waitTime < after) {
- waitTime = after;
+ try {
+ long before = System.currentTimeMillis();
+ time.setTime(new Date(before));
+ float t = eng.timedDocumentRoot.convertWallclockTime(time);
+// if (Math.floor(t) > second) {
+// second = Math.floor(t);
+// System.err.println("fps: " + frames);
+// frames = 0;
+// }
+ float t2 = eng.tick(t, false);
+ long after = System.currentTimeMillis();
+ long dur = after - before;
+ if (dur == 0) {
+ dur = 1;
}
- if (animationLimitingMode != 0) {
- float ave = (float) sumTime / NUM_TIMES;
- float delay;
- if (animationLimitingMode == 1) {
- // %cpu
- delay = ave / animationLimitingAmount - ave;
- } else {
- // fps
- delay = 1000f / animationLimitingAmount - ave;
+ sumTime -= times[timeIndex];
+ sumTime += dur;
+ times[timeIndex] = dur;
+ timeIndex = (timeIndex + 1) % NUM_TIMES;
+
+ if (t2 == Float.POSITIVE_INFINITY) {
+ waitTime = Long.MAX_VALUE;
+ } else {
+ waitTime = before + (long) (t2 * 1000) - 1000;
+ if (waitTime < after) {
+ waitTime = after;
}
- long newWaitTime = after + (long) delay;
- if (newWaitTime > waitTime) {
- waitTime = newWaitTime;
+ if (animationLimitingMode != 0) {
+ float ave = (float) sumTime / NUM_TIMES;
+ float delay;
+ if (animationLimitingMode == 1) {
+ // %cpu
+ delay = ave / animationLimitingAmount - ave;
+ } else {
+ // fps
+ delay = 1000f / animationLimitingAmount - ave;
+ }
+ long newWaitTime = after + (long) delay;
+ if (newWaitTime > waitTime) {
+ waitTime = newWaitTime;
+ }
}
}
+// frames++;
+ } catch (AnimationException ex) {
+ throw new BridgeException
+ (eng.ctx, ex.getElement().getElement(),
+ ex.getMessage());
+ }
+ } catch (BridgeException ex) {
+ if (eng.ctx.getUserAgent() == null) {
+ ex.printStackTrace();
+ } else {
+ eng.ctx.getUserAgent().displayError(ex);
}
-// frames++;
- } catch (AnimationException ex) {
- throw new BridgeException(ctx, ex.getElement().getElement(),
- ex.getMessage());
- }
- } catch (BridgeException ex) {
- if (ctx.getUserAgent() == null) {
- ex.printStackTrace();
- } else {
- ctx.getUserAgent().displayError(ex);
}
- }
- if (animationLimitingMode == 0) {
- // so we don't steal too much time from the Swing thread
- try {
- Thread.sleep(1);
- } catch (InterruptedException ie) {
+ if (animationLimitingMode == 0) {
+ // so we don't steal too much time from the Swing thread
+ try {
+ Thread.sleep(1);
+ } catch (InterruptedException ie) {
+ }
}
}
+ }
+
+ /**
+ * Returns the SVGAnimationEngine this AnimationTickRunnable is for.
+ */
+ protected SVGAnimationEngine getAnimationEngine() {
+ return (SVGAnimationEngine) engRef.get();
}
}
Modified: xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVG12BridgeContext.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVG12BridgeContext.java?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVG12BridgeContext.java (original)
+++ xmlgraphics/batik/trunk/sources/org/apache/batik/bridge/svg12/SVG12BridgeContext.java Thu Feb 1 20:57:56 2007
@@ -132,8 +132,8 @@
* Disposes this BridgeContext.
*/
public void dispose() {
+ clearChildContexts();
- childContexts.clear();
synchronized (eventListenerSet) {
// remove all listeners added by Bridges
Iterator iter = eventListenerSet.iterator();
@@ -169,6 +169,12 @@
removeDOMListeners();
removeBindingListener();
}
+
+ if (animationEngine != null) {
+ animationEngine.dispose();
+ animationEngine = null;
+ }
+
Iterator iter = interpreterMap.values().iterator();
while (iter.hasNext()) {
Interpreter interpreter = (Interpreter)iter.next();
Modified: xmlgraphics/batik/trunk/test-sources/org/apache/batik/swing/JSVGMemoryLeakTest.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/test-sources/org/apache/batik/swing/JSVGMemoryLeakTest.java?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/test-sources/org/apache/batik/swing/JSVGMemoryLeakTest.java (original)
+++ xmlgraphics/batik/trunk/test-sources/org/apache/batik/swing/JSVGMemoryLeakTest.java Thu Feb 1 20:57:56 2007
@@ -186,7 +186,6 @@
if (subCtxs[i] != null) {
SVGOMDocument doc = (SVGOMDocument) subCtxs[i].getDocument();
registerObjectDesc(subCtxs[i], "BridgeContext_" + doc.getURL());
- System.err.println("found subctx for " + doc.getURL());
}
}
}
Modified: xmlgraphics/batik/trunk/test-sources/org/apache/batik/test/MemoryLeakTest.java
URL: http://svn.apache.org/viewvc/xmlgraphics/batik/trunk/test-sources/org/apache/batik/test/MemoryLeakTest.java?view=diff&rev=502489&r1=502488&r2=502489
==============================================================================
--- xmlgraphics/batik/trunk/test-sources/org/apache/batik/test/MemoryLeakTest.java (original)
+++ xmlgraphics/batik/trunk/test-sources/org/apache/batik/test/MemoryLeakTest.java Thu Feb 1 20:57:56 2007
@@ -147,8 +147,8 @@
if (objStr.length() > 40)
objStr = objStr.substring(0,40) + "..." ;
System.err.println(">>>>> Objects not cleared: " + objStr);
- // System.err.println("Waiting for heap dump...");
- // try { Thread.sleep(60000); } catch (InterruptedException ie) { }
+ // System.err.println("Waiting 5 second for heap dump...");
+ // try { Thread.sleep(5000); } catch (InterruptedException ie) { }
return false;
}
@@ -223,8 +223,8 @@
if (objStr.length() > 40)
objStr = objStr.substring(0,40) + "..." ;
System.err.println(">>>>> Objects not cleared: " + objStr);
- // System.err.println("Waiting for heap dump...");
- // try { Thread.sleep(60000); } catch (InterruptedException ie) { }
+ // System.err.println("Waiting for 5 seconds for heap dump...");
+ // try { Thread.sleep(5000); } catch (InterruptedException ie) { }
return false;
}