| /* |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| package org.apache.batik.apps.slideshow; |
| |
| import java.awt.Color; |
| import java.awt.Cursor; |
| import java.awt.Dimension; |
| import java.awt.Graphics; |
| import java.awt.Graphics2D; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.Toolkit; |
| import java.awt.event.MouseAdapter; |
| import java.awt.event.MouseEvent; |
| import java.awt.image.BufferedImage; |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.util.List; |
| import java.util.ArrayList; |
| |
| import javax.swing.JComponent; |
| import javax.swing.JWindow; |
| |
| import org.apache.batik.bridge.BridgeContext; |
| import org.apache.batik.bridge.DocumentLoader; |
| import org.apache.batik.bridge.GVTBuilder; |
| import org.apache.batik.bridge.UserAgent; |
| import org.apache.batik.bridge.UserAgentAdapter; |
| import org.apache.batik.bridge.ViewBox; |
| import org.apache.batik.gvt.GraphicsNode; |
| import org.apache.batik.gvt.renderer.StaticRenderer; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.svg.SVGDocument; |
| |
| /** |
| * |
| * @version $Id$ |
| */ |
| public class Main extends JComponent { |
| |
| StaticRenderer renderer; |
| UserAgent userAgent; |
| DocumentLoader loader; |
| BridgeContext ctx; |
| |
| BufferedImage image; |
| BufferedImage display; |
| File [] files; |
| |
| static int duration = 3000; |
| static int frameDelay = duration+7000; |
| |
| volatile boolean done = false; |
| |
| public Main(File []files, Dimension size) { |
| setBackground(Color.black); |
| this.files = files; |
| UserAgentAdapter ua = new UserAgentAdapter(); |
| renderer = new StaticRenderer(); |
| userAgent = ua; |
| loader = new DocumentLoader(userAgent); |
| ctx = new BridgeContext(userAgent, loader); |
| ua.setBridgeContext(ctx); |
| |
| if (size == null) { |
| size = Toolkit.getDefaultToolkit().getScreenSize(); |
| } |
| |
| setPreferredSize(size); |
| setDoubleBuffered(false); |
| addMouseListener(new MouseAdapter() { |
| public void mouseClicked(MouseEvent me) { |
| if (done) |
| System.exit(0); |
| else |
| togglePause(); |
| } |
| }); |
| |
| size.width += 2; |
| size.height += 2; |
| display = new BufferedImage(size.width, size.height, |
| BufferedImage.TYPE_INT_BGR); |
| |
| Thread t = new RenderThread(); |
| t.start(); |
| |
| JWindow w = new JWindow(); |
| w.setBackground(Color.black); |
| w.getContentPane().setBackground(Color.black); |
| w.getContentPane().add(this); |
| w.pack(); |
| w.setLocation(new Point(-1, -1)); |
| w.setVisible(true); |
| } |
| |
| class RenderThread extends Thread { |
| RenderThread(){ |
| super("RenderThread"); |
| setDaemon( true ); |
| } |
| |
| public void run() { |
| renderer.setDoubleBuffered(true); |
| for (int i=0; i<files.length; i++) { |
| GraphicsNode gvtRoot = null; |
| GVTBuilder builder = new GVTBuilder(); |
| |
| try { |
| String fileName = files[ i ].toURI().toURL().toString(); |
| System.out.println("Reading: " + fileName ); |
| Document svgDoc = loader.loadDocument( fileName ); |
| System.out.println("Building: " + fileName ); |
| gvtRoot = builder.build(ctx, svgDoc); |
| System.out.println("Rendering: " + fileName ); |
| renderer.setTree(gvtRoot); |
| |
| Element elt = ((SVGDocument)svgDoc).getRootElement(); |
| renderer.setTransform |
| (ViewBox.getViewTransform |
| (null, elt, display.getWidth(), display.getHeight(), |
| ctx)); |
| |
| renderer.updateOffScreen(display.getWidth(), |
| display.getHeight()); |
| |
| Rectangle r = new Rectangle(0, 0, |
| display.getWidth(), |
| display.getHeight()); |
| renderer.repaint(r); |
| System.out.println("Painting: " + fileName ); |
| image = renderer.getOffScreen(); |
| setTransition(image); |
| |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| if (transitionThread != null) { |
| try { |
| transitionThread.join(); |
| } catch (InterruptedException ie) { } |
| done = true; |
| setCursor(new Cursor(Cursor.WAIT_CURSOR)); |
| } |
| |
| } |
| } |
| |
| volatile Thread transitionThread = null; |
| |
| public void setTransition(BufferedImage newImg) { |
| synchronized (this) { |
| while (transitionThread != null) { |
| try { |
| wait(); |
| } catch (InterruptedException ie) { } |
| } |
| transitionThread = new TransitionThread(newImg); |
| transitionThread.start(); |
| } |
| } |
| |
| |
| long startLastTransition=0; |
| |
| volatile boolean paused = false; |
| |
| public void togglePause() { |
| synchronized(this) { |
| paused = !paused; |
| Cursor c; |
| if (paused) { |
| c = new Cursor(Cursor.WAIT_CURSOR); |
| } else { |
| c = new Cursor(Cursor.DEFAULT_CURSOR); |
| if (transitionThread != null) { |
| synchronized (transitionThread) { |
| transitionThread.notifyAll(); |
| } |
| } |
| } |
| setCursor(c); |
| } |
| } |
| |
| class TransitionThread extends Thread { |
| BufferedImage src; |
| int blockw = 75; |
| int blockh = 75; |
| |
| public TransitionThread(BufferedImage bi) { |
| super( "TransitionThread"); |
| setDaemon( true ); |
| src = bi; |
| } |
| |
| public void run() { |
| int xblocks = (display.getWidth()+blockw-1)/blockw; |
| int yblocks = (display.getHeight()+blockh-1)/blockh; |
| int nblocks = xblocks*yblocks; |
| |
| int tblock = duration/nblocks; |
| |
| Point [] rects = new Point[nblocks]; |
| for (int y=0; y<yblocks; y++) |
| for (int x=0; x<xblocks; x++) |
| rects[y*xblocks+x] = new Point(x, y); |
| |
| Graphics2D g2d = display.createGraphics(); |
| g2d.setColor( Color.black ); |
| |
| long currTrans = System.currentTimeMillis(); |
| while ((currTrans-startLastTransition) < frameDelay) { |
| try { |
| long stime = frameDelay-(currTrans-startLastTransition); |
| if (stime > 500) { |
| System.gc(); |
| currTrans = System.currentTimeMillis(); |
| stime = frameDelay-(currTrans-startLastTransition); |
| } |
| if (stime > 0) sleep(stime); |
| } catch (InterruptedException ie) { } |
| currTrans = System.currentTimeMillis(); |
| } |
| |
| synchronized(this) { |
| while (paused) { |
| try { |
| wait(); |
| } catch (InterruptedException ie) { } |
| } |
| } |
| |
| long last = startLastTransition = System.currentTimeMillis(); |
| |
| for (int i=0; i<rects.length; i++) { |
| int idx = (int)(Math.random()*(rects.length-i)); |
| Point pt = rects[idx]; |
| System.arraycopy( rects, idx + 1, rects, idx + 1 - 1, rects.length - i - idx -1 ); // +1?? |
| int x=pt.x*blockw, y=pt.y*blockh; |
| int w=blockw, h = blockh; |
| if (x+w > src.getWidth()) w = src.getWidth()-x; |
| if (y+h > src.getHeight()) h = src.getHeight()-y; |
| |
| synchronized (display) { |
| g2d.fillRect(x, y, w, h); |
| BufferedImage sub; |
| |
| sub = src.getSubimage(x, y, w, h); |
| g2d.drawImage(sub, null, x, y); |
| } |
| |
| repaint(x, y, w, h); |
| long current = System.currentTimeMillis(); |
| try { |
| long dt = current-last; |
| if (dt < tblock) |
| sleep(tblock-dt); |
| } catch (InterruptedException ie) { } |
| last = current; |
| } |
| |
| synchronized (Main.this) { |
| transitionThread = null; |
| Main.this.notifyAll(); |
| } |
| } |
| |
| } |
| |
| public void paint(Graphics g) { |
| Graphics2D g2d = (Graphics2D)g; |
| if (display == null) return; |
| // System.out.println("Drawing Image: " + display); |
| g2d.drawImage(display, null, 0, 0); |
| } |
| |
| public static void readFileList(String file, List fileVec) { |
| BufferedReader br; |
| try { |
| br = new BufferedReader(new FileReader(file)); |
| } catch(FileNotFoundException fnfe) { |
| System.err.println("Unable to open file-list: " + file); |
| return; |
| } |
| try { |
| URL flURL = new File(file).toURI().toURL(); |
| String line; |
| while ((line = br.readLine()) != null) { |
| String str = line; |
| int idx = str.indexOf('#'); |
| if (idx != -1) |
| str = str.substring(0, idx); |
| str = str.trim(); |
| if (str.length() == 0) |
| continue; |
| try { |
| URL imgURL = new URL(flURL, str); |
| fileVec.add(imgURL.getFile()); |
| } catch (MalformedURLException mue) { |
| System.err.println("Can't make sense of line:\n " + line); |
| } |
| } |
| } catch (IOException ioe) { |
| System.err.println("Error while reading file-list: " + file); |
| } finally { |
| try { br.close(); } catch (IOException ioe) { } |
| } |
| } |
| |
| public static void main(String []args) { |
| |
| List fileVec = new ArrayList(); |
| |
| Dimension d = null; |
| |
| if (args.length == 0) { |
| showUsage(); |
| return; |
| } |
| |
| for (int i=0; i<args.length; i++) { |
| if ((args[i].equals("-h")) || |
| (args[i].equals("-help")) || |
| (args[i].equals("--help"))){ |
| showUsage(); |
| return; |
| } else if (args[i].equals("--")) { |
| i++; |
| while(i < args.length) { |
| fileVec.add(args[i++]); |
| } |
| break; |
| } else if ((args[i].equals("-fl"))|| |
| (args[i].equals("--file-list"))) { |
| if (i+1 == args.length) { |
| System.err.println |
| ("Must provide name of file list file after " + |
| args[i]); |
| break; |
| } |
| readFileList(args[i+1], fileVec); |
| i++; |
| } else if ((args[i].equals("-ft"))|| |
| (args[i].equals("--frame-time"))) { |
| if (i+1 == args.length) { |
| System.err.println |
| ("Must provide time in millis after " + args[i]); |
| break; |
| } |
| try { |
| frameDelay = Integer.decode(args[i + 1]); |
| i++; |
| } catch (NumberFormatException nfe) { |
| System.err.println |
| ("Can't parse frame time: " + args[i+1]); |
| } |
| } else if ((args[i].equals("-tt"))|| |
| (args[i].equals("--transition-time"))) { |
| if (i+1 == args.length) { |
| System.err.println |
| ("Must provide time in millis after " + args[i]); |
| break; |
| } |
| try { |
| duration = Integer.decode(args[i + 1]); |
| i++; |
| } catch (NumberFormatException nfe) { |
| System.err.println |
| ("Can't parse transition time: " + args[i+1]); |
| } |
| } else if ((args[i].equals("-ws"))|| |
| (args[i].equals("--window-size"))) { |
| |
| if (i+1 == args.length) { |
| System.err.println |
| ("Must provide window size [w,h] after " + args[i]); |
| break; |
| } |
| try { |
| int idx = args[i+1].indexOf(','); |
| int w, h; |
| if (idx == -1) |
| w = h = Integer.decode(args[i + 1]); |
| else { |
| String wStr = args[i+1].substring(0,idx); |
| String hStr = args[i+1].substring(idx+1); |
| w = Integer.decode(wStr); |
| h = Integer.decode(hStr); |
| } |
| d = new Dimension(w, h); |
| i++; |
| } catch (NumberFormatException nfe) { |
| System.err.println |
| ("Can't parse window size: " + args[i+1]); |
| } |
| } else |
| fileVec.add(args[i]); |
| } |
| |
| File [] files = new File[fileVec.size()]; |
| |
| |
| for (int i=0; i<fileVec.size(); i++) { |
| try { |
| files[i] = new File((String)fileVec.get(i)); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| new Main(files, d); |
| } |
| |
| public static void showUsage() { |
| System.out.println |
| ("Options:\n" + |
| " -- : Remaining args are file names\n" + |
| " -fl <file>\n" + |
| " --file-list <file> : file contains list of images to\n" + |
| " show one per line\n" + |
| " -ws <width>[,<height>]\n" + |
| " -window-size <width>[,<height>] : Set the size of slideshow window\n" + |
| " defaults to full screen\n" + |
| " -ft <int>\n" + |
| " --frame-time <int> : Amount of time in millisecs to\n" + |
| " show each frame.\n" + |
| " Includes transition time.\n" + |
| " -tt <int>\n" + |
| " --transition-time <int> : Amount of time in millisecs to\n" + |
| " transition between frames.\n" + |
| " <file> : SVG file to display"); |
| } |
| |
| } |