/*
* @(#)X11Image.java 1.25 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package java.awt;
import java.util.Hashtable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;
import java.awt.image.ImageProducer;
import java.awt.image.ImageObserver;
import java.awt.image.ImageConsumer;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.DirectColorModel;
/** @version 1.16, 12/05/01
*/
class X11Image extends java.awt.image.BufferedImage implements ImageConsumer {
static final int REDRAW_COUNT = 20;
int Xpixmap; /* X Drawable pixmap, so you can use the XDraw funcs with image */
int Xclipmask; /* XImage, clientside XBitmap of clipmask, no need for draw func functionality */
int width, height;
int status;
private Hashtable myProperties;
private HashSet observers = new HashSet();
private ColorModel colorModel;
private int scanlineCount;
private ImageProducer myProducer;
private Vector XpixmapList; /* Was going to be used with multiple frame images */
/* create the offscreen image source */
private native int pCreatePixmap(int width, int height, Color bg);
private native int pCreatePixmapImg(int Ximage, int width, int height); /* This will destroy the image */
private native int pCreateClipmask(int width, int height); /* needed for transparency */
private native int pGetSubPixmapImage(int Ximage, int x, int y, int width, int height);
private native int pGetSubImage(int Ximage, int x, int y, int width, int height);
static private native void initIDs();
static {
Toolkit.getDefaultToolkit();
initIDs();
}
X11Image(int w, int h, Color background) {
width = w;
height = h;
if ((width > 0) && (height > 0)) {
Xpixmap = pCreatePixmap(w, h, background);
Xclipmask = pCreateClipmask(w, h);
/* status |= ImageObserver.WIDTH|ImageObserver.HEIGHT; */
}
colorModel = Toolkit.getDefaultToolkit().getColorModel();
}
X11Image(ImageProducer imageProd) {
width = -1;
height = -1;
myProducer = imageProd;
myProducer.startProduction(this);
}
X11Image(int Ximage, int Xclipmask, int w, int h) {
Xpixmap = pCreatePixmapImg(Ximage, w, h);
this.Xclipmask = Xclipmask;
width = w;
height = h;
colorModel = Toolkit.getDefaultToolkit().getColorModel();
}
public Graphics getGraphics() {
return new X11Graphics(this);
}
public int getWidth() {
return width;
}
public int getWidth(ImageObserver observer) {
if (width == -1) addObserver(observer);
return width;
}
public int getHeight() {
return height;
}
public int getHeight(ImageObserver observer) {
if (height == -1) addObserver(observer);
return height;
}
public Object getProperty(String name, ImageObserver observer) {
if (myProperties == null) {
addObserver(observer);
return UndefinedProperty;
}
return myProperties.get(name);
}
public String[] getPropertyNames() {
Object[] names = myProperties.keySet().toArray();
String[] newNames = new String[names.length];
System.arraycopy(names, 0, newNames, 0, newNames.length);
return newNames;
}
int getStatus(ImageObserver observer) {
addObserver(observer);
return status;
}
public java.awt.image.BufferedImage getSubImage(int x, int y, int w, int h) {
int Ximage = pGetSubPixmapImage(Xpixmap, x, y, w, h);
int newXclipmask = pGetSubImage(Xclipmask, x, y, w, h);
return new X11Image(Ximage, newXclipmask, w, h);
}
boolean prepareImage(int width, int height, ImageObserver observer) {
addObserver(observer);
if ((width > 0) && (height > 0)) {
setDimensions(width, height);
return true;
}
return false;
}
void addObserver(ImageObserver observer) {
if (observer != null)
observers.add(observer);
}
public void flush() {}
public ImageProducer getSource() {
return myProducer;
}
/***** --- Consumer Stuff --- *****/
public void imageComplete(int stat) {
int obsStat = 0;
if (stat == STATICIMAGEDONE)
obsStat = ImageObserver.ALLBITS;
else if (stat == SINGLEFRAMEDONE)
obsStat = ImageObserver.FRAMEBITS;
else if (stat == IMAGEERROR)
obsStat = ImageObserver.ERROR;
else if (stat == IMAGEABORTED)
obsStat = ImageObserver.ABORT;
status |= obsStat;
if ((obsStat != 0) && (observers != null)) {
Iterator obs = observers.iterator();
synchronized (observers) {
while (obs.hasNext()) {
ImageObserver iobs = (ImageObserver) obs.next();
iobs.imageUpdate(this, obsStat, 0, 0, width, height);
}
}
}
if ((obsStat & (ImageObserver.ALLBITS | ImageObserver.ERROR | ImageObserver.ABORT)) != 0)
myProducer.removeConsumer(this);
}
public void setColorModel(ColorModel cm) {
colorModel = cm;
}
public void setDimensions(int width, int height) {
if (Xpixmap != 0) Thread.dumpStack();
this.width = width;
this.height = height;
if ((this.width > 0) && (this.height > 0)) {
Xpixmap = pCreatePixmap(this.width, this.height, null);
Xclipmask = pCreateClipmask(this.width, this.height);
}
/*
if(this.width>0) status|=ImageObserver.WIDTH;
if(this.height>0) status|=ImageObserver.HEIGHT;
*/
Iterator obs = observers.iterator();
synchronized (observers) {
while (obs.hasNext()) {
ImageObserver iobs = (ImageObserver) obs.next();
iobs.imageUpdate(this, ImageObserver.WIDTH, 0, 0, width, 0);
iobs.imageUpdate(this, ImageObserver.HEIGHT, 0, 0, 0, height);
}
}
}
public void setProperties(Hashtable props) {
myProperties = props;
}
public void setHints(int hints) {/*
System.out.println("ImageHints:");
if((hints&RANDOMPIXELORDER) != 0)
System.out.println("Hints: random order");
if((hints&TOPDOWNLEFTRIGHT) != 0)
System.out.println("Hints: top down");
if((hints&COMPLETESCANLINES) != 0)
System.out.println("Hints: complete scan lines");
if((hints&SINGLEPASS) != 0)
System.out.println("Hints: single pass");
if((hints&SINGLEFRAME) != 0)
System.out.println("Hints: single frame");
*/}
private native void pSetPixels(int src, int clipmask, int[] pixels, int x, int y, int w, int h, int scansize);
private native int[] pGetPixels(int src, int clipmask, int[] pixels, int x, int y, int w, int h, int scansize, int offset);
private native int[] XIndexColorCvt(ColorModel cm, byte[] pixels, int off);
private native int[] XIndexColorCvt(ColorModel cm, int[] pixels, int off);
private native int[] XDirectColorCvt(ColorModel cm, int[] pixels, int off);
private int[] XDefaultColorCvt(ColorModel cm, byte[] pixels, int off) {
int[] p = new int[pixels.length - off];
for (int i = off; i < pixels.length; i++)
p[i - off] = cm.getRGB(pixels[i] & 0xFF);
return p;
}
private int[] XDefaultColorCvt(ColorModel cm, int[] pixels, int off) {
int[] p = new int[pixels.length - off];
for (int i = off; i < pixels.length; i++)
p[i - off] = cm.getRGB(pixels[i]);
return p;
}
public void setPixels(int x, int y, int w, int h, ColorModel cm, byte[] pixels, int off, int scansize) {
int[] p;
if (cm instanceof IndexColorModel)
p = XIndexColorCvt(cm, pixels, off);
else p = XDefaultColorCvt(cm, pixels, off);
if (scansize == 0) scansize = p.length;
pSetPixels(Xpixmap, Xclipmask, p, x, y, w, h, scansize);
scanlineCount++;
if (scanlineCount % REDRAW_COUNT == 0) {
Iterator obs = observers.iterator();
synchronized (observers) {
while (obs.hasNext()) {
ImageObserver iobs = (ImageObserver) obs.next();
iobs.imageUpdate(this, ImageObserver.SOMEBITS, x, y, w, h);
}
}
}
}
public void setPixels(int x, int y, int w, int h, ColorModel cm, int[] pixels, int off, int scansize) {
int[] p;
if (cm instanceof DirectColorModel)
p = XDirectColorCvt(cm, pixels, off);
else if (cm instanceof IndexColorModel)
p = XIndexColorCvt(cm, pixels, off);
else p = XDefaultColorCvt(cm, pixels, off);
if (scansize == 0) scansize = p.length;
pSetPixels(Xpixmap, Xclipmask, p, x, y, w, h, scansize);
scanlineCount++;
status |= ImageObserver.SOMEBITS;
if (scanlineCount % REDRAW_COUNT == 0) {
Iterator obs = observers.iterator();
synchronized (observers) {
while (obs.hasNext()) {
ImageObserver iobs = (ImageObserver) obs.next();
iobs.imageUpdate(this, ImageObserver.SOMEBITS, x, y, w, h);
}
}
}
}
public void setRGB(int startX, int startY, int w, int h,
int[] rgbArray, int offset, int scansize) {
System.out.println("setRGB...." + colorModel);
int[] p = XDirectColorCvt(colorModel, rgbArray, offset);
if (scansize == 0) scansize = p.length;
pSetPixels(Xpixmap, Xclipmask, p, startX, startY, w, h, scansize);
}
public int[] getRGB(int startX, int startY, int w, int h,
int[] rgbArray, int offset, int scansize) {
return null;
}
}