summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/kitfox/salamander/renderer/SurfaceManager.java
diff options
context:
space:
mode:
authorkitfox2007-04-12 22:35:16 +0200
committerkitfox2007-04-12 22:35:16 +0200
commit23ebe96d580929d66b7c8efc1b61226db0c7dcf9 (patch)
treef218607e111344462350292ac2a64ec05a464504 /src/main/java/com/kitfox/salamander/renderer/SurfaceManager.java
parentPseudocode for main rendering logic. Roughing in SVG structure. (diff)
downloadsvg-salamander-core-23ebe96d580929d66b7c8efc1b61226db0c7dcf9.tar.gz
svg-salamander-core-23ebe96d580929d66b7c8efc1b61226db0c7dcf9.tar.xz
svg-salamander-core-23ebe96d580929d66b7c8efc1b61226db0c7dcf9.zip
Pseudocode for main rendering logic. Roughing in SVG structure.
git-svn-id: https://svn.java.net/svn/svgsalamander~svn/trunk/svg-core@11 7dc7fa77-23fb-e6ad-8e2e-c86bd48ed22b
Diffstat (limited to 'src/main/java/com/kitfox/salamander/renderer/SurfaceManager.java')
-rwxr-xr-xsrc/main/java/com/kitfox/salamander/renderer/SurfaceManager.java236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/main/java/com/kitfox/salamander/renderer/SurfaceManager.java b/src/main/java/com/kitfox/salamander/renderer/SurfaceManager.java
new file mode 100755
index 0000000..83cd227
--- /dev/null
+++ b/src/main/java/com/kitfox/salamander/renderer/SurfaceManager.java
@@ -0,0 +1,236 @@
+/*
+ * SurfaceManager.java
+ *
+ * Created on April 12, 2007, 8:37 AM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package com.kitfox.salamander.renderer;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.image.BufferedImage;
+import java.lang.ref.WeakReference;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+
+/**
+ *
+ * @author kitfox
+ */
+public class SurfaceManager implements Runnable
+{
+ public class SurfaceInfo
+ {
+ private BufferedImage image;
+ private BufImgInfo info;
+
+ SurfaceInfo(BufferedImage image, BufImgInfo info)
+ {
+ this.image = image;
+ this.info = info;
+ }
+
+ public BufferedImage getBuffer()
+ {
+ return image;
+ }
+
+ /**
+ * Release resources to be recycled. Do not use the image after calling this.
+ */
+ public void dispose()
+ {
+ image = null;
+ allocatedSurfs.remove(info);
+ pooledSurfs.add(info);
+ info.touch();
+ info = null;
+ }
+ }
+
+ static class BufImgInfo implements Comparable<BufImgInfo>
+ {
+ final int width;
+ final int height;
+ final int area;
+ WeakReference<SurfaceInfo> surfRef;
+ final BufferedImage image;
+ long touchTime;
+
+ BufImgInfo(BufferedImage image)
+ {
+ this.width = image.getWidth();
+ this.height = image.getHeight();
+ this.area = width * height;
+// ref = new SoftReference(img);
+ this.image = image;
+// this.surfRef = new WeakReference<SurfaceInfo>(null);
+ }
+
+ public void attach(SurfaceInfo surf)
+ {
+ surfRef = new WeakReference(surf);
+// touch();
+ }
+
+ public int compareTo(SurfaceManager.BufImgInfo obj)
+ {
+ return area < obj.area ? -1 : (area > obj.area ? 1 : 0);
+ }
+
+ void touch()
+ {
+ touchTime = System.currentTimeMillis();
+ }
+ }
+
+ private static final SurfaceManager singleton = new SurfaceManager();
+ TreeSet<BufImgInfo> pooledSurfs = new TreeSet<BufImgInfo>();
+ HashSet<BufImgInfo> allocatedSurfs = new HashSet<BufImgInfo>();
+// WeakHashMap<SurfaceInfo, BufImgInfo> surfaces = new WeakHashMap<SurfaceInfo, BufImgInfo>();
+
+ int SWEEP_DELAY = 10000; //Every 10 seconds
+
+ /** Creates a new instance of SurfaceManager */
+ private SurfaceManager()
+ {
+ Thread thread = new Thread(this);
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ public static SurfaceManager getDefault()
+ {
+ return singleton;
+ }
+
+ /**
+ * @return a new, cleared temporary surface to render upon. Remember to call
+ * dispose() on the SurfaceInfo when you're finished with it.
+ */
+ public SurfaceInfo getSurface(int width, int height, GraphicsConfiguration gc)
+ {
+ SurfaceInfo surfInfo;
+ BufImgInfo bufInfo = null;
+ int targetArea = width * height;
+
+ //Search for exising surface
+ Iterator<BufImgInfo> it = pooledSurfs.iterator();
+ for (; it.hasNext();)
+ {
+ BufImgInfo info = it.next();
+ if (info.area >= targetArea)
+ {
+ if (info.width >= width && info.height >= height)
+ {
+ bufInfo = info;
+ }
+ break;
+ }
+ }
+
+ if (bufInfo == null)
+ {
+ for (; it.hasNext();)
+ {
+ BufImgInfo info = it.next();
+ if (info.area / 2 <= targetArea)
+ {
+ //Do not use exceptionally poorly fit buffers
+ break;
+ }
+ if (info.width >= width && info.height >= height)
+ {
+ bufInfo = info;
+ break;
+ }
+ }
+ }
+
+ if (bufInfo != null)
+ {
+ //Refurbish
+// BufferedImage img = bufInfo.ref.get();
+ BufferedImage img = bufInfo.image;
+
+ Graphics2D g = img.createGraphics();
+
+ g.setComposite(AlphaComposite.Clear);
+ g.fillRect(0, 0, width, height);
+
+ g.dispose();
+
+ surfInfo = new SurfaceInfo(img.getSubimage(0, 0, width, height), bufInfo);
+// surfaces.put(surfInfo, bufInfo);
+ allocatedSurfs.add(bufInfo);
+ pooledSurfs.remove(bufInfo);
+ }
+ else
+ {
+ //Create a new surface
+ BufferedImage img;
+ if (gc.getColorModel().hasAlpha())
+ {
+ img = gc.createCompatibleImage(width, height);
+ }
+ else
+ {
+ img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ bufInfo = new BufImgInfo(img);
+ surfInfo = new SurfaceInfo(img, bufInfo);
+// surfaces.put(surfInfo, bufInfo);
+ allocatedSurfs.add(bufInfo);
+ }
+
+ bufInfo.attach(surfInfo);
+ return surfInfo;
+ }
+
+ public void run()
+ {
+ while (true)
+ {
+ /*
+ //Clean up memory leaked images
+ for (Iterator<BufImgInfo> it = allocatedSurfs.iterator(); it.hasNext();)
+ {
+ BufImgInfo info = it.next();
+ if (info.surfRef.get() == null)
+ {
+ it.remove();
+ pooledSurfs.add(info);
+ info.touch();
+ }
+ }
+ */
+
+ //Kill out of date pooled surfaces
+ long curTime = System.currentTimeMillis();
+ for (Iterator<BufImgInfo> it = pooledSurfs.iterator(); it.hasNext();)
+ {
+ BufImgInfo info = it.next();
+ if ((curTime - info.touchTime) > SWEEP_DELAY)
+ {
+ it.remove();
+ }
+ }
+
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+}