KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java2d > Surface


1 /*
2  * @(#)Surface.java 1.55 06/08/09
3  *
4  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * -Redistribution of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * -Redistribution in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17  * be used to endorse or promote products derived from this software without
18  * specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
24  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  * You acknowledge that this software is not designed, licensed or intended
33  * for use in the design, construction, operation or maintenance of any
34  * nuclear facility.
35  */

36
37 /*
38  * @(#)Surface.java 1.55 06/08/09
39  */

40
41 package java2d;
42
43 import java.awt.*;
44 import java.awt.image.*;
45 import java.awt.print.*;
46 import java.awt.event.*;
47 import javax.swing.JPanel JavaDoc;
48 import javax.swing.RepaintManager JavaDoc;
49
50 import static java.awt.RenderingHints JavaDoc.*;
51
52
53 /**
54  * Surface is the base class for the 2d rendering demos. Demos must
55  * implement the render() method. Subclasses for Surface are
56  * AnimatingSurface, ControlsSurface and AnimatingControlsSurface.
57  */

58 public abstract class Surface extends JPanel JavaDoc implements Printable {
59
60
61     public Object JavaDoc AntiAlias = VALUE_ANTIALIAS_ON;
62     public Object JavaDoc Rendering = VALUE_RENDER_SPEED;
63     public AlphaComposite composite;
64     public Paint texture;
65     public String JavaDoc perfStr; // PerformanceMonitor
66
public BufferedImage bimg;
67     public int imageType;
68     public String JavaDoc name;
69     public boolean clearSurface = true;
70     // Demos using animated gif's that implement ImageObserver set dontThread.
71
public boolean dontThread;
72     public AnimatingSurface animating;
73
74     protected long sleepAmount = 50;
75
76     private long orig, start, frame;
77     private Toolkit toolkit;
78     private boolean perfMonitor, outputPerf;
79     private int biw, bih;
80     private boolean clearOnce;
81     private boolean toBeInitialized = true;
82
83
84     public Surface() {
85         setDoubleBuffered(this instanceof AnimatingSurface);
86         toolkit = getToolkit();
87         name = this.getClass().getSimpleName();
88         setImageType(0);
89
90         // To launch an individual demo with the performance str output :
91
// java -Djava2demo.perf= -cp Java2Demo.jar demos.Clipping.ClipAnim
92
try {
93             if (System.getProperty("java2demo.perf") != null) {
94                 perfMonitor = outputPerf = true;
95             }
96         } catch (Exception JavaDoc ex) { }
97         if (this instanceof AnimatingSurface) {
98             animating = (AnimatingSurface) this;
99         }
100     }
101
102
103     protected Image getImage(String JavaDoc name) {
104         return DemoImages.getImage(name, this);
105     }
106
107
108     protected Font getFont(String JavaDoc name) {
109         return DemoFonts.getFont(name);
110     }
111
112
113     public int getImageType() {
114         return imageType;
115     }
116
117
118     public void setImageType(int imgType) {
119         if (imgType == 0) {
120             imageType = 1;
121         } else {
122             imageType = imgType;
123         }
124         bimg = null;
125     }
126
127
128     public void setAntiAlias(boolean aa) {
129         AntiAlias = aa ? VALUE_ANTIALIAS_ON : VALUE_ANTIALIAS_OFF;
130     }
131
132
133     public void setRendering(boolean rd) {
134         Rendering = rd ? VALUE_RENDER_QUALITY : VALUE_RENDER_SPEED;
135     }
136
137
138     public void setTexture(Object JavaDoc obj) {
139         if (obj instanceof GradientPaint) {
140             texture = new GradientPaint(0, 0, Color.white,
141                                         getSize().width*2, 0, Color.green);
142         } else {
143             texture = (Paint) obj;
144         }
145     }
146
147
148     public void setComposite(boolean cp) {
149         composite = cp
150             ? AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f)
151             : null;
152     }
153
154
155     public void setMonitor(boolean pm) {
156         perfMonitor = pm;
157     }
158
159
160     public void setSleepAmount(long amount) {
161         sleepAmount = amount;
162     }
163
164
165     public long getSleepAmount() {
166         return sleepAmount;
167     }
168
169
170     public BufferedImage createBufferedImage(Graphics2D g2,
171                                              int w,
172                                              int h,
173                                              int imgType) {
174         BufferedImage bi = null;
175         if (imgType == 0) {
176             bi = (BufferedImage) g2.getDeviceConfiguration().
177                                     createCompatibleImage(w, h);
178         } else if (imgType > 0 && imgType < 14) {
179             bi = new BufferedImage(w, h, imgType);
180         } else if (imgType == 14) {
181             bi = createBinaryImage(w, h, 2);
182         } else if (imgType == 15) {
183             bi = createBinaryImage(w, h, 4);
184         } else if (imgType == 16) {
185             bi = createSGISurface(w, h, 32);
186         } else if (imgType == 17) {
187             bi = createSGISurface(w, h, 16);
188         }
189         return bi;
190     }
191
192
193     // Lookup tables for BYTE_BINARY 1, 2 and 4 bits.
194
static byte[] lut1Arr = new byte[] {0, (byte)255 };
195     static byte[] lut2Arr = new byte[] {0, (byte)85, (byte)170, (byte)255};
196     static byte[] lut4Arr = new byte[] {0, (byte)17, (byte)34, (byte)51,
197                                   (byte)68, (byte)85,(byte) 102, (byte)119,
198                                   (byte)136, (byte)153, (byte)170, (byte)187,
199                                   (byte)204, (byte)221, (byte)238, (byte)255};
200
201
202     private BufferedImage createBinaryImage(int w, int h, int pixelBits) {
203        int bytesPerRow = w * pixelBits / 8;
204        if (w * pixelBits % 8 != 0) {
205            bytesPerRow++;
206        }
207        byte[] imageData = new byte[h * bytesPerRow];
208        IndexColorModel cm = null;
209        switch (pixelBits) {
210        case 1:
211            cm = new IndexColorModel(pixelBits, lut1Arr.length,
212                                     lut1Arr, lut1Arr, lut1Arr);
213            break;
214        case 2:
215            cm = new IndexColorModel(pixelBits, lut2Arr.length,
216                                     lut2Arr, lut2Arr, lut2Arr);
217            break;
218        case 4:
219            cm = new IndexColorModel(pixelBits, lut4Arr.length,
220                                     lut4Arr, lut4Arr, lut4Arr);
221            break;
222        default:
223            {new Exception JavaDoc("Invalid # of bit per pixel").printStackTrace();}
224        }
225        
226        DataBuffer db = new DataBufferByte(imageData, imageData.length);
227        WritableRaster r = Raster.createPackedRaster(db, w, h, pixelBits, null);
228        return new BufferedImage(cm, r, false, null);
229     }
230
231     private BufferedImage createSGISurface(int w, int h, int pixelBits) {
232        int rMask32 = 0xFF000000;
233        int rMask16 = 0xF800;
234        int gMask32 = 0x00FF0000;
235        int gMask16 = 0x07C0;
236        int bMask32 = 0x0000FF00;
237        int bMask16 = 0x003E;
238
239        DirectColorModel dcm = null;
240        DataBuffer db = null;
241        WritableRaster wr = null;
242        switch (pixelBits) {
243        case 16:
244        short[] imageDataUShort = new short[w * h];
245        dcm = new DirectColorModel(16, rMask16, gMask16, bMask16);
246        db = new DataBufferUShort(imageDataUShort, imageDataUShort.length);
247        wr = Raster.createPackedRaster(db, w, h, w,
248                       new int[] {rMask16, gMask16, bMask16},
249                       null);
250        break;
251        case 32:
252        int[] imageDataInt = new int[w * h];
253        dcm = new DirectColorModel(32, rMask32, gMask32, bMask32);
254        db = new DataBufferInt(imageDataInt, imageDataInt.length);
255        wr = Raster.createPackedRaster(db, w, h, w,
256                       new int[] {rMask32, gMask32, bMask32},
257                       null);
258        break;
259        default:
260        {new Exception JavaDoc("Invalid # of bit per pixel").printStackTrace();}
261        }
262        
263        return new BufferedImage(dcm, wr, false, null);
264     }
265
266     public Graphics2D createGraphics2D(int width,
267                                        int height,
268                                        BufferedImage bi,
269                                        Graphics g) {
270
271         Graphics2D g2 = null;
272
273         if (bi != null) {
274             g2 = bi.createGraphics();
275         } else {
276             g2 = (Graphics2D) g;
277         }
278
279         g2.setBackground(getBackground());
280         g2.setRenderingHint(KEY_ANTIALIASING, AntiAlias);
281         g2.setRenderingHint(KEY_RENDERING, Rendering);
282
283         if (clearSurface || clearOnce) {
284             g2.clearRect(0, 0, width, height);
285             clearOnce = false;
286         }
287
288         if (texture != null) {
289             // set composite to opaque for texture fills
290
g2.setComposite(AlphaComposite.SrcOver);
291             g2.setPaint(texture);
292             g2.fillRect(0, 0, width, height);
293         }
294
295         if (composite != null) {
296             g2.setComposite(composite);
297         }
298
299         return g2;
300     }
301
302     // ...demos that extend Surface must implement this routine...
303
public abstract void render(int w, int h, Graphics2D g2);
304
305
306     /**
307      * It's possible to turn off double-buffering for just the repaint
308      * calls invoked directly on the non double buffered component.
309      * This can be done by overriding paintImmediately() (which is called
310      * as a result of repaint) and getting the current RepaintManager and
311      * turning off double buffering in the RepaintManager before calling
312      * super.paintImmediately(g).
313      */

314     public void paintImmediately(int x,int y,int w, int h) {
315         RepaintManager JavaDoc repaintManager = null;
316         boolean save = true;
317         if (!isDoubleBuffered()) {
318              repaintManager = RepaintManager.currentManager(this);
319              save = repaintManager.isDoubleBufferingEnabled();
320              repaintManager.setDoubleBufferingEnabled(false);
321         }
322         super.paintImmediately(x, y, w, h);
323
324         if (repaintManager != null) {
325             repaintManager.setDoubleBufferingEnabled(save);
326         }
327     }
328
329
330     public void paint(Graphics g) {
331
332         super.paint(g);
333
334         Dimension d = getSize();
335
336         if(biw != d.width || bih != d.height) {
337             toBeInitialized = true;
338             biw = d.width;
339             bih = d.height;
340         }
341
342         if (imageType == 1)
343             bimg = null;
344         else if(bimg == null || toBeInitialized) {
345             bimg = createBufferedImage((Graphics2D)g,
346                                        d.width, d.height, imageType-2);
347             clearOnce = true;
348         }
349
350         if (toBeInitialized) {
351             if (animating != null)
352               animating.reset(d.width, d.height);
353             toBeInitialized = false;
354             startClock();
355         }
356
357         if (animating != null && animating.thread != null) {
358             animating.step(d.width, d.height);
359         }
360         Graphics2D g2 = createGraphics2D(d.width, d.height, bimg, g);
361         render(d.width, d.height, g2);
362         g2.dispose();
363
364         if (bimg != null) {
365             g.drawImage(bimg, 0, 0, null);
366             toolkit.sync();
367         }
368
369         if (perfMonitor) {
370             LogPerformance();
371         }
372     }
373
374
375     public int print(Graphics g, PageFormat pf, int pi) throws PrinterException {
376         if (pi >= 1) {
377             return Printable.NO_SUCH_PAGE;
378         }
379
380         Graphics2D g2d = (Graphics2D) g;
381         g2d.translate(pf.getImageableX(), pf.getImageableY());
382         g2d.translate(pf.getImageableWidth() / 2,
383                       pf.getImageableHeight() / 2);
384         
385         Dimension d = getSize();
386
387         double scale = Math.min(pf.getImageableWidth() / d.width,
388                                 pf.getImageableHeight() / d.height);
389         if (scale < 1.0) {
390             g2d.scale(scale, scale);
391         }
392
393         g2d.translate(-d.width / 2.0, -d.height / 2.0);
394
395         if (bimg == null) {
396             Graphics2D g2 = createGraphics2D(d.width, d.height, null, g2d);
397             render(d.width, d.height, g2);
398             g2.dispose();
399         } else {
400             g2d.drawImage(bimg, 0, 0, this);
401         }
402
403         return Printable.PAGE_EXISTS;
404     }
405
406
407     public void startClock() {
408         orig = System.currentTimeMillis();
409         start = orig;
410     frame = 0;
411     }
412
413     private static final int REPORTFRAMES = 30;
414
415     private void LogPerformance() {
416         if ((frame % REPORTFRAMES) == 0) {
417             long end = System.currentTimeMillis();
418             long rel = (end - start);
419             long tot = (end - orig);
420             if (frame == 0) {
421                 perfStr = name + " " + rel+" ms";
422                 if (animating == null || animating.thread == null) {
423                     frame = -1;
424                 }
425             } else {
426                 String JavaDoc s1 = Float.toString((REPORTFRAMES/(rel/1000.0f)));
427                 s1 = (s1.length() < 4) ? s1.substring(0,s1.length()) : s1.substring(0,4);
428                 perfStr = name + " " + s1 + " fps";
429             }
430             if (outputPerf) {
431                 System.out.println(perfStr);
432             }
433             start = end;
434         }
435         ++frame;
436     }
437
438
439
440     // System.out graphics state information.
441
public void verbose() {
442         String JavaDoc str = " " + name + " ";
443         if (animating != null && animating.thread != null) {
444             str = str.concat(" Running");
445         } else if (this instanceof AnimatingSurface) {
446             str = str.concat(" Stopped");
447         }
448
449         str = str.concat(" " + GlobalControls.screenCombo.getSelectedItem());
450
451         str.concat((AntiAlias == VALUE_ANTIALIAS_ON ) ? " ANTIALIAS_ON "
452                                                        : " ANTIALIAS_OFF ");
453         str.concat((Rendering == VALUE_RENDER_QUALITY) ? "RENDER_QUALITY "
454                                                        : "RENDER_SPEED ");
455
456         if (texture != null) {
457             str = str.concat("Texture ");
458         }
459
460         if (composite != null) {
461             str = str.concat("Composite=" + composite.getAlpha() + " ");
462         }
463
464         Runtime JavaDoc r = Runtime.getRuntime();
465         r.gc();
466         float freeMemory = (float) r.freeMemory();
467         float totalMemory = (float) r.totalMemory();
468         str = str.concat(((totalMemory - freeMemory)/1024) + "K used");
469         System.out.println(str);
470     }
471
472
473     public static void createDemoFrame(Surface surface) {
474         final DemoPanel dp = new DemoPanel(surface);
475         Frame f = new Frame("Java2D Demo - " + surface.name);
476         f.addWindowListener(new WindowAdapter() {
477             public void windowClosing (WindowEvent e) { System.exit(0); }
478             public void windowDeiconified(WindowEvent e) { dp.start(); }
479             public void windowIconified (WindowEvent e) { dp.stop(); }
480         });
481         f.add("Center", dp);
482         f.pack();
483         f.setSize(new Dimension(500,300));
484         f.setVisible(true);
485         if (surface.animating != null) {
486             surface.animating.start();
487         }
488     }
489 }
490
Popular Tags