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