import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.swing.*;

import Acme.JPM.Encoders.GifEncoder;


/**
 * A Servlet for displaying swing components
 */

public class SwingServlet extends HttpServlet
{
	public void doGet(HttpServletRequest req, HttpServletResponse res)
		throws ServletException, IOException 
	{
		JComponent c = createComponent(req);
		ImageProducer image = convertToGIF(c,req.getParameter("transparent")!=null);
		sendAsGIF(req,res,image);
	}
	/**
	 * Override me!
	 */
	protected JComponent createComponent(HttpServletRequest req) 
		throws ServletException,IOException
	{
		return new JButton("Swing Servlet");
	}
	/**
	 * Paints the swing component to an Image
	 * @return The image containing the painted component
	 */
	protected ImageProducer convertToGIF(final JComponent comp, boolean transparent)
	{
		comp.setDoubleBuffered(false);
		JFrame frame = new JFrame();
		frame.setContentPane(comp);
		frame.pack();
	  
		// Get a graphics region, using the Frame
		Dimension size = comp.getSize();
		Image image = comp.createImage(size.width,size.height);
		final Graphics g = image.getGraphics();
		// Workaround for JDK 1.2.2 bug (Linux)
		g.setClip(0,0,size.width,size.height);

		try 
		{
			// Paint the Swing component into the image, being careful to comply
			// with Swing's single thread requirements.
			
			SwingUtilities.invokeAndWait(new Runnable()
			{
				public void run()
				{
					comp.paint(g);
				}
			});
		}
		catch (Exception x) { x.printStackTrace(); }
		finally 
		{ 
			g.dispose();
			frame.dispose();
		}

		ImageProducer prod = image.getSource();
		
		// Add a filter to make the background transparent
		
		if (transparent)
		{
			Color bg = comp.getBackground();
			ImageFilter f = new TransparentFilter(bg);			
			prod = new FilteredImageSource(prod,f);
		}
	  
		return prod;
	}
	protected void sendAsGIF(HttpServletRequest req, HttpServletResponse res, 
							 ImageProducer image) throws IOException
	{
		ServletOutputStream out = res.getOutputStream();  // binary output!
		
		// Encode the off screen image into a GIF and send it to the client
		res.setContentType("image/gif");
		GifEncoder encoder = new GifEncoder(image, out);
		encoder.encode();
		out.close();
	}
}
class TransparentFilter extends RGBImageFilter
{
	TransparentFilter(Color trans)
	{
		transparent = trans.getRGB() & 0xffffff;
		rt = transparent & 0xff;
		gt = transparent>>8 & 0xff;
		bt = transparent>>16 & 0xff;
		clear = 0;
	}
	public int filterRGB(int x, int y, int rgb) 
	{
		int deltar = (rgb     & 0xff) - rt;
		int deltag = (rgb>>8  & 0xff) - gt;
		int deltab = (rgb>>16 & 0xff) - bt;
		return Math.abs(deltar)+Math.abs(deltag)+Math.abs(deltab) < 25 ? clear : rgb;
	}
	private int transparent;
	private int clear;
	private int rt, gt, bt;
}
