📄 image.java
字号:
/* * Copyright (c) 1998 * Transvirtual Technologies, Inc. All rights reserved. * * Copyright (c) 2004 * The Kaffe.org's developers. See ChangeLog for details. * * See the file "license.terms" for information on usage and redistribution * of this file. * * @author P.C.Mehlitz */package java.awt;import java.awt.image.ImageObserver;import java.awt.image.ImageProducer;import java.awt.image.MemoryImageSource;import java.io.File;import java.net.URL;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import gnu.classpath.Pointer;import org.kaffe.util.VectorSnapshot;public class Image{ Pointer nativeData; int width = -1; int height = -1; ImageProducer producer; Object observers; int flags; Hashtable props; Image next; final public static int SCALE_DEFAULT = 1; final public static int SCALE_FAST = 2; final public static int SCALE_SMOOTH = 4; final public static int SCALE_REPLICATE = 8; final public static int SCALE_AREA_AVERAGING = 16; final static int MASK = ImageObserver.WIDTH|ImageObserver.HEIGHT| ImageObserver.PROPERTIES|ImageObserver.SOMEBITS| ImageObserver.FRAMEBITS|ImageObserver.ALLBITS| ImageObserver.ERROR|ImageObserver.ABORT; final static int PRODUCING = 1 << 8; final static int READY = ImageObserver.WIDTH | ImageObserver.HEIGHT | ImageObserver.ALLBITS | PRODUCING; final static int SCREEN = 1 << 10; final static int BLOCK_FRAMELOADER = 1 << 11; final static int IS_ANIMATION = 1 << 12; final public static Object UndefinedProperty = ImageLoader.class; static Image unknownImage;public Image() {}Image ( File file ) { producer = new ImageNativeProducer( this, file);}Image ( Image img, int w, int h ) { nativeData = Toolkit.imgCreateScaledImage(img.nativeData, w, h); width = w; height = h; flags = READY;}Image ( ImageProducer ip ) { producer = ip; // there currently is no way to check the size of a MemoryImageSource, // so everything != 0 causes async production if ( (Defaults.MemImageSrcThreshold == 0) && (producer instanceof MemoryImageSource) ) { flags |= PRODUCING; synchronized ( ImageLoader.syncLoader ) { ImageLoader.syncLoader.img = this; ip.startProduction( ImageLoader.syncLoader); } }}Image ( URL url ) { producer = new ImageNativeProducer( url);}Image ( byte[] data, int offs, int len) { producer = new ImageNativeProducer( this, data, offs, len);}Image ( int w, int h ) { nativeData = Toolkit.imgCreateScreenImage( w, h ); width = w; height = h; flags = READY | SCREEN;}synchronized void activateFrameLoader () { // activate waiting FrameLoader if ( (flags & BLOCK_FRAMELOADER) != 0 ){ flags &= ~BLOCK_FRAMELOADER; notify(); }}// -------------------------------------------------------------------------void addObserver ( ImageObserver observer ) { if ( observer == null ) { return; } if ( observers == null ) { observers = observer; } else if ( observers instanceof Vector ) { Vector v = (Vector) observers; if ( !v.contains(observer) ) v.addElement(observer); } else { if ( observer != observers ) { Vector v = new Vector( 3); v.addElement( observers); v.addElement( observer); observers = v; } }}synchronized int checkImage ( int w, int h, ImageObserver obs, boolean load ){ if ( (flags & (ImageObserver.ALLBITS | ImageObserver.FRAMEBITS)) != 0 ) { if ( ((w > 0) || (h > 0)) && (w != width) && (h != height) ){ scale( w, h); } if ( load && (flags & ImageObserver.FRAMEBITS) != 0 ) addObserver( obs); } else if ( load && ((flags & PRODUCING) == 0) ) { loadImage( this, w, h, obs); } return (flags & MASK);}protected void finalize () throws Throwable { flush(); super.finalize();}public void flush () { // This is the bad guy - the spec demands that it reverts us into a "not-yet-loaded" // state, "to be recreated or fetched again from its source" when a subsequent // rendering takes place. Since "its source" doesn't mean the *original* source // (see getSource() - "an object that *produces* the image"), we could stay with the // native representation (probably the most efficient storage and prod environment), // but apps explicitly using flush most probably use it because the original // image source has changed, i.e. they use flush() as a way to in-situ modify // otherwise constant images (by means of changed sources). Only heaven knows why // they don't replace the image (this is like a Graphics that can be brought back // to life after a dispose()). That means we have to keep a ref of byte[] data, and // we can't produce on-screen images if ( nativeData != null && (flags & ImageObserver.ALLBITS) != 0){ Toolkit.imgFreeImage( nativeData); nativeData = null; flags = 0; width = -1; height = -1; }}public Graphics getGraphics () { if ((flags & SCREEN) == 0 || nativeData == null) { return null; } else { return NativeGraphics.getGraphics( this, nativeData, NativeGraphics.TGT_TYPE_IMAGE, 0, 0, 0, 0, width, height, Color.black, Color.white, Defaults.WndFont, false); }}public synchronized int getHeight ( ImageObserver observer ) { if ( (flags & ImageObserver.HEIGHT) != 0 ) { return height; } else { loadImage( this, -1, -1, observer); return (-1); }}public Object getProperty ( String name, ImageObserver observer ) { if ( props == null ) { if ( (flags & (ImageObserver.FRAMEBITS | ImageObserver.ALLBITS)) != 0 ) return UndefinedProperty; else if ( (flags & PRODUCING) == 0 ) loadImage( this, -1, -1, observer); return null; } else { Object val = props.get( name); if ( val == null ) return UndefinedProperty; return val; }}public Image getScaledInstance (int width, int height, int hints) { if ( (flags & (ImageObserver.ERROR|ImageObserver.FRAMEBITS)) == 0 ){ MediaTracker mt = new MediaTracker( null); mt.addImage( this, 0); try { mt.waitForID( 0); } catch ( InterruptedException x ){ return null; } } if ( (flags & (ImageObserver.ERROR|ImageObserver.ABORT)) != 0 ){ return null; } if ( (width < 0) && (height < 0) ){ throw new AWTError( "illegal image scaling request: , w: " + width + ", h: " + height); } // a negative value is computed from the other dimension and // a constant aspect ratio if ( width < 0 ){ width = (int) (((float)height / this.height) * this.width); } else if ( height < 0 ){ height = (int) (((float)width / this.width) * this.height); } return (new Image(this, width, height));}public ImageProducer getSource () { if ( producer == null ) producer = new ImageNativeProducer( this); return producer;}static Image getUnknownImage (){ if ( unknownImage == null ){ int d = Toolkit.screenSize.height / 64; unknownImage = new Image( d, d); Graphics g = unknownImage.getGraphics(); if ( g != null ){ g.setColor( Color.white); g.fillRect( 0, 0, d, d); g.setColor( Color.red); g.draw3DRect( 0, 0, d, d, false); g.dispose(); } } return unknownImage;}public synchronized int getWidth ( ImageObserver observer ) { if ( (flags & ImageObserver.WIDTH) != 0 ) { return (width); } else { loadImage( this, -1, -1, observer); return (-1); }}static boolean loadImage ( Image img, int w, int h, ImageObserver obs ) { // a last safeguard against careless apps which don't handle // failed image loads if ( img != null ){ synchronized ( img ) { // it's (partly?) loaded already if ( (img.flags & (ImageObserver.FRAMEBITS|ImageObserver.ALLBITS)) != 0 ){ if ( ((w > 0) || (h > 0)) && (w != img.width) && (h != img.height) ) { // but do we have to scale it? img.scale( w, h); } if ( (img.flags & ImageObserver.FRAMEBITS) != 0 ) { img.addObserver( obs); } return (true); } // we ultimately failed else if ( (img.flags & ImageObserver.ABORT) != 0 ) { return (false); } // there's work ahead, kick it off else if ( (img.flags & PRODUCING) == 0 ) { img.flags |= PRODUCING; if ( obs != null ) { img.addObserver( obs); } /* * We now load the image data synchronously - it's not clear * that's what you should actually do but it fixes a problem * with the Citrix ICA client. (Tim 1/18/99) */ ImageLoader.loadSync( img); return (true); } } } return (false);}void removeObserver ( ImageObserver observer ) { if ( (observers == null) || (observer == null) ) return; if ( observers == observer ){ observers = null; } else if ( observers instanceof Vector ) { Vector v = (Vector)observers; v.removeElement( observer); if ( v.size() == 1 ) observers = v.firstElement(); }}private boolean scale (int w, int h) { if ((flags & SCREEN) != 0 || (flags & ImageObserver.ALLBITS) == 0 || nativeData == null) { return (false); } if (w != width || h != height) { Pointer oldNativeData = nativeData; nativeData = Toolkit.imgCreateScaledImage( nativeData, w, h ); Toolkit.imgFreeImage( oldNativeData); width = w; height = h; } return (true);}synchronized void stateChange(int flags, int x, int y, int w, int h) { ImageObserver obs; this.flags |= flags; if (observers == null) { return; } // We get false if they're no longer interested in updates. This is *NOT* what is said in the // Addison-Wesley documentation, but is what is says in the JDK javadoc documentation. if ( observers instanceof ImageObserver ){ obs = (ImageObserver) observers; if ( !obs.imageUpdate( this, flags, x, y, w, h)) { observers = null; } } else if ( observers instanceof Vector ){ // we can't use a (index-based) standard Vector enumerator because we have // to notify *all* elements regardless of any removals for ( Enumeration e=VectorSnapshot.getCached( (Vector)observers); e.hasMoreElements(); ) { obs = (ImageObserver) e.nextElement(); if ( !obs.imageUpdate( this, flags, x, y, w, h)) removeObserver( obs); } }}public String toString() { String s = getClass().getName() + " [" + width + ',' + height + ((nativeData != null) ? ", native" : ", non-native") + ", flags: " + Integer.toHexString( flags); if ( (flags & PRODUCING) != 0 ) s += " producing"; if ( (flags & ImageObserver.ALLBITS) != 0 ) s += " allbits"; else if ( (flags & ImageObserver.FRAMEBITS) != 0 ) s += " framebits"; else if ( (flags & ImageObserver.ERROR) != 0 ) s += " error"; s += "]"; return s; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -