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. |