001: /*
002: * @(#)Surface.java 1.51 04/07/26
003: *
004: * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: *
009: * -Redistribution of source code must retain the above copyright notice, this
010: * list of conditions and the following disclaimer.
011: *
012: * -Redistribution in binary form must reproduce the above copyright notice,
013: * this list of conditions and the following disclaimer in the documentation
014: * and/or other materials provided with the distribution.
015: *
016: * Neither the name of Sun Microsystems, Inc. or the names of contributors may
017: * be used to endorse or promote products derived from this software without
018: * specific prior written permission.
019: *
020: * This software is provided "AS IS," without a warranty of any kind. ALL
021: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
022: * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
023: * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
024: * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
025: * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
026: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
027: * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
028: * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
029: * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
030: * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
031: *
032: * You acknowledge that this software is not designed, licensed or intended
033: * for use in the design, construction, operation or maintenance of any
034: * nuclear facility.
035: */
036:
037: /*
038: * @(#)Surface.java 1.48 03/01/23
039: */
040:
041: package org.cougaar.core.qos.frame.visualizer;
042:
043: import java.awt.AlphaComposite;
044: import java.awt.Color;
045: import java.awt.Dimension;
046: import java.awt.GradientPaint;
047: import java.awt.Graphics;
048: import java.awt.Graphics2D;
049: import java.awt.Paint;
050: import java.awt.RenderingHints;
051: import java.awt.Toolkit;
052: import java.awt.image.BufferedImage;
053: import java.awt.image.DataBuffer;
054: import java.awt.image.DataBufferByte;
055: import java.awt.image.DataBufferInt;
056: import java.awt.image.DataBufferUShort;
057: import java.awt.image.DirectColorModel;
058: import java.awt.image.IndexColorModel;
059: import java.awt.image.Raster;
060: import java.awt.image.WritableRaster;
061: import java.awt.print.PageFormat;
062: import java.awt.print.Printable;
063: import java.awt.print.PrinterException;
064:
065: import javax.swing.JPanel;
066: import javax.swing.RepaintManager;
067:
068: /**
069: * Surface is the base class for the 2d rendering demos. Demos must
070: * implement the render() method. Subclasses for Surface are
071: * AnimatingSurface, ControlsSurface and AnimatingControlsSurface.
072: */
073: public abstract class Surface extends JPanel implements Printable {
074:
075: public Object AntiAlias = RenderingHints.VALUE_ANTIALIAS_ON;
076: public Object Rendering = RenderingHints.VALUE_RENDER_SPEED;
077: public AlphaComposite composite;
078: public Paint texture;
079: public String perfStr; // PerformanceMonitor
080: public BufferedImage bimg;
081: public int imageType;
082: public String name;
083: public boolean clearSurface = true;
084: // Demos using animated gif's that implement ImageObserver set dontThread.
085: public boolean dontThread;
086: public AnimatingSurface animating;
087:
088: protected long sleepAmount = 50;
089:
090: private long orig, start, frame;
091: private Toolkit toolkit;
092: private boolean perfMonitor;
093: private int biw, bih;
094: private boolean clearOnce;
095: private boolean toBeInitialized = true;
096:
097: public Surface() {
098: setDoubleBuffered(this instanceof AnimatingSurface);
099: toolkit = getToolkit();
100: name = this .getClass().getName();
101: name = name.substring(name.indexOf(".", 7) + 1);
102: setImageType(0);
103:
104: // To launch an individual demo with the performance str output :
105: // java -Djava2demo.perf= -cp Java2Demo.jar demos.Clipping.ClipAnim
106: try {
107: if (System.getProperty("java2demo.perf") != null) {
108: perfMonitor = true;
109: }
110: } catch (Exception ex) {
111: }
112: if (this instanceof AnimatingSurface) {
113: animating = (AnimatingSurface) this ;
114: }
115: }
116:
117: /*
118: protected Image getImage(String name) {
119: return DemoImages.getImage(name, this);
120: }
121:
122:
123: protected Font getFont(String name) {
124: return DemoFonts.getFont(name);
125: }
126: */
127:
128: public int getImageType() {
129: return imageType;
130: }
131:
132: public void setImageType(int imgType) {
133: if (imgType == 0) {
134: imageType = 1;
135: } else {
136: imageType = imgType;
137: }
138: bimg = null;
139: }
140:
141: public void setAntiAlias(boolean aa) {
142: AntiAlias = aa ? RenderingHints.VALUE_ANTIALIAS_ON
143: : RenderingHints.VALUE_ANTIALIAS_OFF;
144: }
145:
146: public void setRendering(boolean rd) {
147: Rendering = rd ? RenderingHints.VALUE_RENDER_QUALITY
148: : RenderingHints.VALUE_RENDER_SPEED;
149: }
150:
151: public void setTexture(Object obj) {
152: if (obj instanceof GradientPaint) {
153: texture = new GradientPaint(0, 0, Color.white,
154: getSize().width * 2, 0, Color.green);
155: } else {
156: texture = (Paint) obj;
157: }
158: }
159:
160: public void setComposite(boolean cp) {
161: composite = cp ? AlphaComposite.getInstance(
162: AlphaComposite.SRC_OVER, 0.5f) : null;
163: }
164:
165: public void setMonitor(boolean pm) {
166: perfMonitor = pm;
167: }
168:
169: public void setSleepAmount(long amount) {
170: sleepAmount = amount;
171: }
172:
173: public long getSleepAmount() {
174: return sleepAmount;
175: }
176:
177: public BufferedImage createBufferedImage(Graphics2D g2, int w,
178: int h, 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: biw = w;
195: bih = h;
196: return bi;
197: }
198:
199: // Lookup tables for BYTE_BINARY 1, 2 and 4 bits.
200: static byte[] lut1Arr = new byte[] { 0, (byte) 255 };
201: static byte[] lut2Arr = new byte[] { 0, (byte) 85, (byte) 170,
202: (byte) 255 };
203: static byte[] lut4Arr = new byte[] { 0, (byte) 17, (byte) 34,
204: (byte) 51, (byte) 68, (byte) 85, (byte) 102, (byte) 119,
205: (byte) 136, (byte) 153, (byte) 170, (byte) 187, (byte) 204,
206: (byte) 221, (byte) 238, (byte) 255 };
207:
208: private BufferedImage createBinaryImage(int w, int h, int pixelBits) {
209: int bytesPerRow = w * pixelBits / 8;
210: if (w * pixelBits % 8 != 0) {
211: bytesPerRow++;
212: }
213: byte[] imageData = new byte[h * bytesPerRow];
214: IndexColorModel cm = null;
215: switch (pixelBits) {
216: case 1:
217: cm = new IndexColorModel(pixelBits, lut1Arr.length,
218: lut1Arr, lut1Arr, lut1Arr);
219: break;
220: case 2:
221: cm = new IndexColorModel(pixelBits, lut2Arr.length,
222: lut2Arr, lut2Arr, lut2Arr);
223: break;
224: case 4:
225: cm = new IndexColorModel(pixelBits, lut4Arr.length,
226: lut4Arr, lut4Arr, lut4Arr);
227: break;
228: default: {
229: new Exception("Invalid # of bit per pixel")
230: .printStackTrace();
231: }
232: }
233:
234: DataBuffer db = new DataBufferByte(imageData, imageData.length);
235: WritableRaster r = Raster.createPackedRaster(db, w, h,
236: pixelBits, null);
237: return new BufferedImage(cm, r, false, null);
238: }
239:
240: private BufferedImage createSGISurface(int w, int h, int pixelBits) {
241: int rMask32 = 0xFF000000;
242: int rMask16 = 0xF800;
243: int gMask32 = 0x00FF0000;
244: int gMask16 = 0x07C0;
245: int bMask32 = 0x0000FF00;
246: int bMask16 = 0x003E;
247:
248: DirectColorModel dcm = null;
249: DataBuffer db = null;
250: WritableRaster wr = null;
251: switch (pixelBits) {
252: case 16:
253: short[] imageDataUShort = new short[w * h];
254: dcm = new DirectColorModel(16, rMask16, gMask16, bMask16);
255: db = new DataBufferUShort(imageDataUShort,
256: imageDataUShort.length);
257: wr = Raster.createPackedRaster(db, w, h, w, new int[] {
258: rMask16, gMask16, bMask16 }, null);
259: break;
260: case 32:
261: int[] imageDataInt = new int[w * h];
262: dcm = new DirectColorModel(32, rMask32, gMask32, bMask32);
263: db = new DataBufferInt(imageDataInt, imageDataInt.length);
264: wr = Raster.createPackedRaster(db, w, h, w, new int[] {
265: rMask32, gMask32, bMask32 }, null);
266: break;
267: default: {
268: new Exception("Invalid # of bit per pixel")
269: .printStackTrace();
270: }
271: }
272:
273: return new BufferedImage(dcm, wr, false, null);
274: }
275:
276: public Graphics2D createGraphics2D(int width, int height,
277: BufferedImage bi, Graphics g) {
278:
279: Graphics2D g2 = null;
280:
281: if (bi != null) {
282: g2 = bi.createGraphics();
283: } else {
284: g2 = (Graphics2D) g;
285: }
286:
287: g2.setBackground(getBackground());
288: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, AntiAlias);
289: g2.setRenderingHint(RenderingHints.KEY_RENDERING, Rendering);
290:
291: if (clearSurface || clearOnce) {
292: g2.clearRect(0, 0, width, height);
293: clearOnce = false;
294: }
295:
296: if (texture != null) {
297: // set composite to opaque for texture fills
298: g2.setComposite(AlphaComposite.SrcOver);
299: g2.setPaint(texture);
300: g2.fillRect(0, 0, width, height);
301: }
302:
303: if (composite != null) {
304: g2.setComposite(composite);
305: }
306:
307: return g2;
308: }
309:
310: // ...demos that extend Surface must implement this routine...
311: public abstract void render(int w, int h, Graphics2D g2);
312:
313: /**
314: * It's possible to turn off double-buffering for just the repaint
315: * calls invoked directly on the non double buffered component.
316: * This can be done by overriding paintImmediately() (which is called
317: * as a result of repaint) and getting the current RepaintManager and
318: * turning off double buffering in the RepaintManager before calling
319: * super.paintImmediately(g).
320: */
321: public void paintImmediately(int x, int y, int w, int h) {
322: RepaintManager repaintManager = null;
323: boolean save = true;
324: if (!isDoubleBuffered()) {
325: repaintManager = RepaintManager.currentManager(this );
326: save = repaintManager.isDoubleBufferingEnabled();
327: repaintManager.setDoubleBufferingEnabled(false);
328: }
329: super .paintImmediately(x, y, w, h);
330:
331: if (repaintManager != null) {
332: repaintManager.setDoubleBufferingEnabled(save);
333: }
334: }
335:
336: public void paint(Graphics g) {
337:
338: Dimension d = getSize();
339:
340: if (imageType == 1)
341: bimg = null;
342: else if (bimg == null || biw != d.width || bih != d.height) {
343: bimg = createBufferedImage((Graphics2D) g, d.width,
344: d.height, imageType - 2);
345: clearOnce = true;
346: toBeInitialized = true;
347: }
348:
349: if (toBeInitialized) {
350: if (animating != null)
351: animating.reset(d.width, d.height);
352: toBeInitialized = false;
353: startClock();
354: }
355:
356: if (animating != null && animating.thread != null) {
357: animating.step(d.width, d.height);
358: }
359: Graphics2D g2 = createGraphics2D(d.width, d.height, bimg, g);
360: render(d.width, d.height, g2);
361: g2.dispose();
362:
363: if (bimg != null) {
364: g.drawImage(bimg, 0, 0, null);
365: toolkit.sync();
366: }
367:
368: if (perfMonitor) {
369: LogPerformance();
370: }
371: }
372:
373: public int print(Graphics g, PageFormat pf, int pi)
374: throws PrinterException {
375: if (pi >= 1) {
376: return Printable.NO_SUCH_PAGE;
377: }
378:
379: Graphics2D g2d = (Graphics2D) g;
380: g2d.translate(pf.getImageableX(), pf.getImageableY());
381: g2d.translate(pf.getImageableWidth() / 2, pf
382: .getImageableHeight() / 2);
383:
384: Dimension d = getSize();
385:
386: double scale = Math.min(pf.getImageableWidth() / d.width, pf
387: .getImageableHeight()
388: / 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,
397: g2d);
398: render(d.width, d.height, g2);
399: g2.dispose();
400: } else {
401: g2d.drawImage(bimg, 0, 0, this );
402: }
403:
404: return Printable.PAGE_EXISTS;
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: if (frame == 0) {
420: perfStr = name + " " + rel + " ms";
421: if (animating == null || animating.thread == null) {
422: frame = -1;
423: }
424: } else {
425: String s1 = Float
426: .toString((REPORTFRAMES / (rel / 1000.0f)));
427: s1 = (s1.length() < 4) ? s1.substring(0, s1.length())
428: : s1.substring(0, 4);
429: perfStr = name + " " + s1 + " fps";
430: }
431: //if (outputPerf) {
432: // System.out.println(perfStr);
433: //}
434: start = end;
435: }
436: ++frame;
437: }
438:
439: /*
440: // System.out graphics state information.
441: public void verbose() {
442: String 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 = AntiAlias == RenderingHints.VALUE_ANTIALIAS_ON
452: ? str.concat(" ANTIALIAS_ON ")
453: : str.concat(" ANTIALIAS_OFF ");
454:
455: str = Rendering == RenderingHints.VALUE_RENDER_QUALITY
456: ? str.concat("RENDER_QUALITY ")
457: : str.concat("RENDER_SPEED ");
458:
459: if (texture != null) {
460: str = str.concat("Texture ");
461: }
462:
463: if (composite != null) {
464: str = str.concat("Composite=" + composite.getAlpha() + " ");
465: }
466:
467: Runtime r = Runtime.getRuntime();
468: r.gc();
469: float freeMemory = (float) r.freeMemory();
470: float totalMemory = (float) r.totalMemory();
471: str = str.concat(((totalMemory - freeMemory)/1024) + "K used");
472: System.out.println(str);
473: }
474: */
475: /*
476: public static void createDemoFrame(Surface surface) {
477: final DemoPanel dp = new DemoPanel(surface);
478: Frame f = new Frame("Java2D Demo - " + surface.name);
479: f.addWindowListener(new WindowAdapter() {
480: public void windowClosing(WindowEvent e) {System.exit(0);}
481: public void windowDeiconified(WindowEvent e) { dp.start(); }
482: public void windowIconified(WindowEvent e) { dp.stop(); }
483: });
484: f.add("Center", dp);
485: f.pack();
486: f.setSize(new Dimension(500,300));
487: f.setVisible(true);
488: if (surface.animating != null) {
489: surface.animating.start();
490: }
491: }
492: */
493: }
|