|
From: <ka...@us...> - 2010-07-10 11:57:01
|
Revision: 3371
http://java-game-lib.svn.sourceforge.net/java-game-lib/?rev=3371&view=rev
Author: kappa1
Date: 2010-07-10 11:56:55 +0000 (Sat, 10 Jul 2010)
Log Message:
-----------
AppletLoader: fixed flicker on animated gifs using ImageObserver. When image is ready to be drawn it is copied into a buffer image ready to be drawn. Also now supports variable time animated gifs and not limited to drawing only every 100ms.
Modified Paths:
--------------
trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
Modified: trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java
===================================================================
--- trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2010-07-09 21:46:27 UTC (rev 3370)
+++ trunk/LWJGL/src/java/org/lwjgl/util/applet/AppletLoader.java 2010-07-10 11:56:55 UTC (rev 3371)
@@ -39,6 +39,7 @@
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
+import java.awt.image.ImageObserver;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -172,14 +173,17 @@
protected int totalSizeExtract;
/** logo to be shown while loading */
- protected Image logo;
+ protected Image logo, logoBuffer;
/** progressbar to render while loading */
- protected Image progressbar;
+ protected Image progressbar, progressbarBuffer;
/** offscreen image used */
protected Image offscreen;
+ /** set to true while painting is done */
+ protected boolean painting;
+
/** background color of applet */
protected Color bgColor = Color.white;
@@ -357,6 +361,9 @@
progressbar = null;
logo = null;
+
+ logoBuffer = null;
+ progressbarBuffer = null;
}
/**
@@ -393,6 +400,18 @@
// create offscreen if missing
if (offscreen == null) {
offscreen = createImage(getWidth(), getHeight());
+
+ // create buffers for animated gifs
+ logoBuffer = createImage(logo.getWidth(null), logo.getHeight(null));
+ progressbarBuffer = createImage(logo.getWidth(null), logo.getHeight(null));
+
+ // add image observer, it will notify when next animated gif frame is ready
+ offscreen.getGraphics().drawImage(logo, 0, 0, this);
+ offscreen.getGraphics().drawImage(progressbar, 0, 0, this);
+
+ // in case image is not animated fill image buffers once
+ imageUpdate(logo, ImageObserver.FRAMEBITS, 0, 0, 0, 0);
+ imageUpdate(progressbar, ImageObserver.FRAMEBITS, 0, 0, 0, 0);
}
// draw everything onto an image before drawing to avoid flicker
@@ -407,8 +426,8 @@
int x = 0, y = 0;
if(logo != null && !fatalError) {
- x = (offscreen.getWidth(null) - logo.getWidth(this)) / 2;
- y = (offscreen.getHeight(null) - logo.getHeight(this)) / 2;
+ x = (offscreen.getWidth(null) - logo.getWidth(null)) / 2;
+ y = (offscreen.getHeight(null) - logo.getHeight(null)) / 2;
}
og.setColor(fgColor);
@@ -433,13 +452,15 @@
}
} else {
og.setColor(fgColor);
-
+
+ painting = true;
+
// draw logo
- og.drawImage(logo, x, y, null);
+ og.drawImage(logoBuffer, x, y, this);
// draw message
int messageX = (offscreen.getWidth(null) - fm.stringWidth(message)) / 2;
- int messageY = y + logo.getHeight(null) + 20;
+ int messageY = y + logoBuffer.getHeight(null) + 20;
og.drawString(message, messageX, messageY);
// draw subtaskmessage, if any
@@ -449,16 +470,53 @@
}
// draw loading bar, clipping it depending on percentage done
- int barSize = (progressbar.getWidth(this) * percentage) / 100;
+ int barSize = (progressbarBuffer.getWidth(null) * percentage) / 100;
og.clipRect(0, 0, x + barSize, offscreen.getHeight(null));
- og.drawImage(progressbar, x, y, null);
+ og.drawImage(progressbarBuffer, x, y, this);
+
+ painting = false;
}
og.dispose();
-
- // finally draw it all centred
+
+ // finally draw it all
g.drawImage(offscreen, (getWidth() - offscreen.getWidth(null))/2, (getHeight() - offscreen.getHeight(null))/2, null);
}
+
+ /**
+ * When an animated gif frame is ready to be drawn the ImageObserver
+ * will call this method.
+ *
+ * The Image frame is copied into a buffer, which is then drawn.
+ * This is done to prevent image tearing on gif animations.
+ */
+ public boolean imageUpdate(Image img, int flag, int x, int y, int width, int height) {
+
+ // if image frame is ready to be drawn and is currently not being painted
+ if (flag == ImageObserver.FRAMEBITS && !painting) {
+ Image buffer;
+
+ // select which buffer to fill
+ if (img == logo) buffer = logoBuffer;
+ else buffer = progressbarBuffer;
+
+ Graphics g = buffer.getGraphics();
+
+ // clear background on buffer
+ g.setColor(bgColor);
+ g.fillRect(0, 0, buffer.getWidth(null), buffer.getHeight(null));
+
+ // buffer background is cleared, so draw logo under progressbar
+ if (img == progressbar) g.drawImage(logoBuffer, 0, 0, null);
+
+ g.drawImage(img, 0, 0, this);
+ g.dispose();
+
+ repaint();
+ }
+
+ return true;
+ }
/**
* @return string describing the state of the loader
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|