home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / JBuilder8.iso / Solaris / resource / jre / demo / jfc / Java2D / src / java2d / Surface.java < prev    next >
Encoding:
Java Source  |  2002-09-06  |  15.4 KB  |  489 lines

  1. /*
  2.  * Copyright (c) 2002 Sun Microsystems, Inc. All  Rights Reserved.
  3.  * 
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 
  8.  * -Redistributions of source code must retain the above copyright
  9.  *  notice, this list of conditions and the following disclaimer.
  10.  * 
  11.  * -Redistribution in binary form must reproduct the above copyright
  12.  *  notice, this list of conditions and the following disclaimer in
  13.  *  the documentation and/or other materials provided with the distribution.
  14.  * 
  15.  * Neither the name of Sun Microsystems, Inc. or the names of contributors
  16.  * may be used to endorse or promote products derived from this software
  17.  * without specific prior written permission.
  18.  * 
  19.  * This software is provided "AS IS," without a warranty of any kind. ALL
  20.  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
  21.  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
  22.  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT
  23.  * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
  24.  * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
  25.  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
  26.  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
  27.  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
  28.  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
  29.  * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
  30.  * 
  31.  * You acknowledge that Software is not designed, licensed or intended for
  32.  * use in the design, construction, operation or maintenance of any nuclear
  33.  * facility.
  34.  */
  35.  
  36. /*
  37.  * @(#)Surface.java    1.46 02/06/13
  38.  */
  39.  
  40. package java2d;
  41.  
  42. import java.awt.*;
  43. import java.awt.image.*;
  44. import java.awt.print.*;
  45. import java.awt.event.*;
  46. import javax.swing.JPanel;
  47. import javax.swing.RepaintManager;
  48.  
  49.  
  50. /**
  51.  * Surface is the base class for the 2d rendering demos.  Demos must
  52.  * implement the render() method. Subclasses for Surface are 
  53.  * AnimatingSurface, ControlsSurface and AnimatingControlsSurface.
  54.  */
  55. public abstract class Surface extends JPanel implements Printable {
  56.  
  57.  
  58.     public Object AntiAlias = RenderingHints.VALUE_ANTIALIAS_ON;
  59.     public Object Rendering = RenderingHints.VALUE_RENDER_SPEED;
  60.     public AlphaComposite composite;
  61.     public Paint texture;
  62.     public String perfStr;            // PerformanceMonitor
  63.     public BufferedImage bimg;
  64.     public int imageType;
  65.     public String name;         
  66.     public boolean clearSurface = true;
  67.     // Demos using animated gif's that implement ImageObserver set dontThread.
  68.     public boolean dontThread;       
  69.     public AnimatingSurface animating;
  70.  
  71.     protected long sleepAmount = 50;
  72.  
  73.     private long orig, start, frame;
  74.     private Toolkit toolkit;
  75.     private boolean perfMonitor, outputPerf;
  76.     private int biw, bih;
  77.     private boolean clearOnce;
  78.     private boolean toBeInitialized = true;
  79.  
  80.  
  81.     public Surface() {
  82.         setDoubleBuffered(this instanceof AnimatingSurface);
  83.         toolkit = getToolkit();
  84.         name = this.getClass().getName();
  85.         name = name.substring(name.indexOf(".", 7)+1);
  86.         setImageType(0);
  87.  
  88.         // To launch an individual demo with the performance str output  :
  89.         //    java -Djava2demo.perf= -cp Java2Demo.jar demos.Clipping.ClipAnim
  90.         try {
  91.             if (System.getProperty("java2demo.perf") != null) {
  92.                 perfMonitor = outputPerf = true;
  93.             }
  94.         } catch (Exception ex) { }
  95.         if (this instanceof AnimatingSurface) {
  96.             animating = (AnimatingSurface) this;
  97.         }
  98.     }
  99.  
  100.  
  101.     protected Image getImage(String name) {
  102.         return DemoImages.getImage(name, this);
  103.     }
  104.  
  105.  
  106.     protected Font getFont(String name) {
  107.         return DemoFonts.getFont(name);
  108.     }
  109.  
  110.  
  111.     public int getImageType() {
  112.         return imageType;
  113.     }
  114.  
  115.  
  116.     public void setImageType(int imgType) {
  117.         if (imgType == 0) {
  118.             if (this instanceof AnimatingSurface) {
  119.                 imageType = 2;
  120.             } else {
  121.                 imageType = 1;
  122.             }
  123.         } else {
  124.             imageType = imgType;
  125.         }
  126.         bimg = null;
  127.     }
  128.  
  129.  
  130.     public void setAntiAlias(boolean aa) {
  131.         AntiAlias = aa 
  132.             ? RenderingHints.VALUE_ANTIALIAS_ON
  133.             : RenderingHints.VALUE_ANTIALIAS_OFF;
  134.     }
  135.  
  136.  
  137.     public void setRendering(boolean rd) {
  138.         Rendering = rd
  139.             ? RenderingHints.VALUE_RENDER_QUALITY
  140.             : RenderingHints.VALUE_RENDER_SPEED;
  141.     }
  142.  
  143.  
  144.     public void setTexture(Object obj) {
  145.         if (obj instanceof GradientPaint) {
  146.             texture = new GradientPaint(0, 0, Color.white,
  147.                                         getSize().width*2, 0, Color.green);
  148.         } else {
  149.             texture = (Paint) obj;
  150.         }
  151.     }
  152.  
  153.  
  154.     public void setComposite(boolean cp) {
  155.         composite = cp 
  156.             ? AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f) 
  157.             : null;
  158.     }
  159.  
  160.  
  161.     public void setMonitor(boolean pm) {
  162.         perfMonitor = pm;
  163.     }
  164.  
  165.  
  166.     public void setSleepAmount(long amount) {
  167.         sleepAmount = amount;
  168.     }
  169.  
  170.  
  171.     public long getSleepAmount() {
  172.         return sleepAmount;
  173.     }
  174.  
  175.  
  176.     public BufferedImage createBufferedImage(int w, int h, int imgType) {
  177.         BufferedImage bi = null;
  178.         if (imgType == 0) {
  179.             bi = (BufferedImage) getGraphicsConfiguration().createCompatibleImage(w, h);  
  180.         } else if (imgType > 0 && imgType < 14) {
  181.             bi = new BufferedImage(w, h, imgType);
  182.         } else if (imgType == 14) {
  183.             bi = createBinaryImage(w, h, 2);
  184.         } else if (imgType == 15) {
  185.             bi = createBinaryImage(w, h, 4);
  186.         } else if (imgType == 16) {
  187.             bi = createSGISurface(w, h, 32);
  188.         } else if (imgType == 17) {
  189.             bi = createSGISurface(w, h, 16);
  190.         }
  191.         biw = w;
  192.         bih = h;
  193.         return bi;
  194.     }
  195.  
  196.  
  197.     // Lookup tables for BYTE_BINARY 1, 2 and 4 bits.
  198.     static byte[] lut1Arr = new byte[] {0, (byte)255 };
  199.     static byte[] lut2Arr = new byte[] {0, (byte)85, (byte)170, (byte)255};
  200.     static byte[] lut4Arr = new byte[] {0, (byte)17, (byte)34, (byte)51,
  201.                                   (byte)68, (byte)85,(byte) 102, (byte)119,
  202.                                   (byte)136, (byte)153, (byte)170, (byte)187,
  203.                                   (byte)204, (byte)221, (byte)238, (byte)255};
  204.  
  205.  
  206.     private BufferedImage createBinaryImage(int w, int h, int pixelBits) {
  207.        int bytesPerRow = w * pixelBits / 8;
  208.        if (w * pixelBits % 8 != 0) {
  209.            bytesPerRow++;
  210.        }
  211.        byte[] imageData = new byte[h * bytesPerRow];
  212.        IndexColorModel cm = null;
  213.        switch (pixelBits) {
  214.        case 1:
  215.            cm = new IndexColorModel(pixelBits, lut1Arr.length,
  216.                                     lut1Arr, lut1Arr, lut1Arr);
  217.            break;
  218.        case 2:
  219.            cm = new IndexColorModel(pixelBits, lut2Arr.length,
  220.                                     lut2Arr, lut2Arr, lut2Arr);
  221.            break;
  222.        case 4:
  223.            cm = new IndexColorModel(pixelBits, lut4Arr.length,
  224.                                     lut4Arr, lut4Arr, lut4Arr);
  225.            break;
  226.        default:
  227.            {new Exception("Invalid # of bit per pixel").printStackTrace();}
  228.        }
  229.        
  230.        DataBuffer db = new DataBufferByte(imageData, imageData.length);
  231.        WritableRaster r = Raster.createPackedRaster(db, w, h, pixelBits, null);
  232.        return new BufferedImage(cm, r, false, null);
  233.     }
  234.  
  235.     private BufferedImage createSGISurface(int w, int h, int pixelBits) {
  236.        int rMask32 = 0xFF000000;
  237.        int rMask16 = 0xF800;
  238.        int gMask32 = 0x00FF0000;
  239.        int gMask16 = 0x07C0;
  240.        int bMask32 = 0x0000FF00;
  241.        int bMask16 = 0x003E;
  242.  
  243.        DirectColorModel dcm = null;
  244.        DataBuffer db = null;
  245.        WritableRaster wr = null;
  246.        switch (pixelBits) {
  247.        case 16:
  248.        short[] imageDataUShort = new short[w * h];
  249.        dcm = new DirectColorModel(16, rMask16, gMask16, bMask16);
  250.        db = new DataBufferUShort(imageDataUShort, imageDataUShort.length);
  251.        wr = Raster.createPackedRaster(db, w, h, w, 
  252.                       new int[] {rMask16, gMask16, bMask16},
  253.                       null);
  254.        break;
  255.        case 32:
  256.        int[] imageDataInt = new int[w * h];
  257.        dcm = new DirectColorModel(32, rMask32, gMask32, bMask32);
  258.        db = new DataBufferInt(imageDataInt, imageDataInt.length);
  259.        wr = Raster.createPackedRaster(db, w, h, w, 
  260.                       new int[] {rMask32, gMask32, bMask32},
  261.                       null);
  262.        break;
  263.        default:
  264.        {new Exception("Invalid # of bit per pixel").printStackTrace();}
  265.        }
  266.        
  267.        return new BufferedImage(dcm, wr, false, null);
  268.     }
  269.  
  270.     public Graphics2D createGraphics2D(int width, 
  271.                                        int height, 
  272.                                        BufferedImage bi, 
  273.                                        Graphics g) {
  274.  
  275.         Graphics2D g2 = null;
  276.  
  277.         if (bi != null) {
  278.             g2 = bi.createGraphics();
  279.         } else {
  280.             g2 = (Graphics2D) g;
  281.         }
  282.  
  283.         g2.setBackground(getBackground());
  284.         g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias);
  285.         g2.setRenderingHint(RenderingHints.KEY_RENDERING, Rendering);
  286.  
  287.         if (clearSurface || clearOnce) {
  288.             g2.clearRect(0, 0, width, height);
  289.             clearOnce = false;
  290.         }
  291.  
  292.         if (texture != null) {
  293.             // set composite to opaque for texture fills
  294.             g2.setComposite(AlphaComposite.SrcOver);
  295.             g2.setPaint(texture);
  296.             g2.fillRect(0, 0, width, height);
  297.         }
  298.  
  299.         if (composite != null) {
  300.             g2.setComposite(composite);
  301.         }
  302.  
  303.         return g2;
  304.     }
  305.  
  306.     // ...demos that extend Surface must implement this routine...
  307.     public abstract void render(int w, int h, Graphics2D g2);
  308.  
  309.  
  310.     /**
  311.      * It's possible to turn off double-buffering for just the repaint 
  312.      * calls invoked directly on the non double buffered component.  
  313.      * This can be done by overriding paintImmediately() (which is called 
  314.      * as a result of repaint) and getting the current RepaintManager and 
  315.      * turning off double buffering in the RepaintManager before calling 
  316.      * super.paintImmediately(g).
  317.      */
  318.     public void paintImmediately(int x,int y,int w, int h) {
  319.         RepaintManager repaintManager = null;
  320.         boolean save = true;
  321.         if (!isDoubleBuffered()) {
  322.              repaintManager = RepaintManager.currentManager(this);
  323.              save = repaintManager.isDoubleBufferingEnabled();
  324.              repaintManager.setDoubleBufferingEnabled(false);
  325.         }
  326.         super.paintImmediately(x, y, w, h);
  327.  
  328.         if (repaintManager != null) {
  329.             repaintManager.setDoubleBufferingEnabled(save);
  330.         }
  331.     }
  332.  
  333.  
  334.     public void paint(Graphics g) {
  335.  
  336.         Dimension d = getSize();
  337.  
  338.         if (imageType == 1)
  339.             bimg = null;
  340.         else if (bimg == null || biw != d.width || bih != d.height) {
  341.             bimg = createBufferedImage(d.width, d.height, imageType-2);
  342.             clearOnce = true;
  343.             toBeInitialized = true;
  344.         }
  345.  
  346.         if (toBeInitialized) {
  347.             if (animating != null)
  348.               animating.reset(d.width, d.height);
  349.             toBeInitialized = false;
  350.             startClock();
  351.         }
  352.  
  353.         if (animating != null && animating.thread != null) {
  354.             animating.step(d.width, d.height);
  355.         }
  356.         Graphics2D g2 = createGraphics2D(d.width, d.height, bimg, g);
  357.         render(d.width, d.height, g2);
  358.         g2.dispose();
  359.  
  360.         if (bimg != null)  {
  361.             g.drawImage(bimg, 0, 0, null);
  362.             toolkit.sync();
  363.         }
  364.  
  365.         if (perfMonitor) {
  366.             LogPerformance();
  367.         }
  368.     }
  369.  
  370.  
  371.     public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
  372.         if (pi >= 1) {
  373.             return Printable.NO_SUCH_PAGE;
  374.         }
  375.  
  376.         Graphics2D g2d = (Graphics2D) g;
  377.         g2d.translate(pf.getImageableX(), pf.getImageableY());
  378.         g2d.translate(pf.getImageableWidth() / 2,
  379.                       pf.getImageableHeight() / 2);
  380.         
  381.         Dimension d = getSize();
  382.  
  383.         double scale = Math.min(pf.getImageableWidth() / d.width,
  384.                                 pf.getImageableHeight() / d.height);
  385.         if (scale < 1.0) {
  386.             g2d.scale(scale, scale);
  387.         }
  388.  
  389.         g2d.translate(-d.width / 2.0, -d.height / 2.0);
  390.  
  391.         if (bimg == null) {
  392.             Graphics2D g2 = createGraphics2D(d.width, d.height, null, g2d);
  393.             render(d.width, d.height, g2);
  394.             g2.dispose();
  395.         } else {
  396.             g2d.drawImage(bimg, 0, 0, this);
  397.         }
  398.  
  399.         return Printable.PAGE_EXISTS;
  400.     }
  401.  
  402.  
  403.     public void startClock() {
  404.         orig = System.currentTimeMillis();
  405.         start = orig;
  406.     frame = 0;
  407.     }
  408.  
  409.     private static final int REPORTFRAMES = 30;
  410.  
  411.     private void LogPerformance() {
  412.         if ((frame % REPORTFRAMES) == 0) {
  413.             long end = System.currentTimeMillis();
  414.             long rel = (end - start);
  415.             long tot = (end - orig);
  416.             if (frame == 0) {
  417.                 perfStr = name + " " + rel+" ms";
  418.                 if (animating == null || animating.thread == null) {
  419.                     frame = -1;     
  420.                 }
  421.             } else {
  422.                 String s1 = Float.toString((REPORTFRAMES/(rel/1000.0f)));
  423.                 s1 = (s1.length() < 4) ? s1.substring(0,s1.length()) : s1.substring(0,4);
  424.                 perfStr = name + " " + s1 + " fps";
  425.             }
  426.             if (outputPerf) {
  427.                 System.out.println(perfStr);
  428.             }
  429.             start = end;
  430.         }
  431.         ++frame;
  432.     }
  433.  
  434.  
  435.  
  436.     // System.out graphics state information.
  437.     public void verbose() {
  438.         String str = "  " + name + " ";
  439.         if (animating != null && animating.thread != null) {
  440.             str = str.concat(" Running");
  441.         } else if (this instanceof AnimatingSurface) {
  442.             str = str.concat(" Stopped");
  443.         }
  444.  
  445.         str = str.concat(" " + GlobalControls.screenCombo.getSelectedItem());
  446.  
  447.         str = AntiAlias == RenderingHints.VALUE_ANTIALIAS_ON
  448.             ? str.concat(" ANTIALIAS_ON ") 
  449.             : str.concat(" ANTIALIAS_OFF ");
  450.  
  451.         str = Rendering == RenderingHints.VALUE_RENDER_QUALITY
  452.             ? str.concat("RENDER_QUALITY ") 
  453.             : str.concat("RENDER_SPEED ");
  454.  
  455.         if (texture != null) {
  456.             str = str.concat("Texture ");
  457.         }
  458.  
  459.         if (composite != null) {
  460.             str = str.concat("Composite=" + composite.getAlpha() + " ");
  461.         }
  462.  
  463.         Runtime r = Runtime.getRuntime();
  464.         r.gc();
  465.         float freeMemory = (float) r.freeMemory();
  466.         float totalMemory = (float) r.totalMemory();
  467.         str = str.concat(((totalMemory - freeMemory)/1024) + "K used");
  468.         System.out.println(str);
  469.     }
  470.  
  471.  
  472.     public static void createDemoFrame(Surface surface) {
  473.         final DemoPanel dp = new DemoPanel(surface);
  474.         Frame f = new Frame("Java2D Demo - " + surface.name);
  475.         f.addWindowListener(new WindowAdapter() {
  476.             public void windowClosing(WindowEvent e) {System.exit(0);}
  477.             public void windowDeiconified(WindowEvent e) {  dp.start(); }
  478.             public void windowIconified(WindowEvent e) { dp.stop(); }
  479.         });
  480.         f.add("Center", dp);
  481.         f.pack();
  482.         f.setSize(new Dimension(500,300));
  483.         f.setVisible(true);
  484.         if (surface.animating != null) {
  485.             surface.animating.start();
  486.         }
  487.     }
  488. }
  489.