/* Copyright (C) 2000 Free Software Foundation This file is part of libgcj. This software is copyrighted work licensed under the terms of the Libgcj License. Please consult the file "LIBGCJ_LICENSE" for details. */ package gnu.awt.xlib; import java.awt.GraphicsConfiguration; import java.awt.Rectangle; import java.awt.Graphics2D; import java.awt.Graphics; import java.awt.Point; import java.awt.Color; import java.awt.color.ColorSpace; import java.awt.image.*; import java.awt.geom.AffineTransform; import gnu.gcj.xlib.GC; import gnu.gcj.xlib.Drawable; import gnu.gcj.xlib.Window; import gnu.gcj.xlib.XImage; import gnu.gcj.xlib.Visual; import gnu.gcj.xlib.Colormap; import gnu.gcj.xlib.XColor; import gnu.gcj.xlib.Screen; import gnu.gcj.xlib.Display; import gnu.gcj.awt.Buffers; import java.util.Hashtable; public class XGraphicsConfiguration extends GraphicsConfiguration { //public abstract GraphicsDevice getDevice(); Visual visual; int format; Colormap colormap; ColorModel imageCM; ColorModel pixelCM; public XGraphicsConfiguration(Visual visual) { this.visual = visual; } public BufferedImage createCompatibleImage(int width, int height) { XImage ximg = new XImage(visual, width, height, false // do not auto allocate memory ); Point origin = new Point(0, 0); WritableRaster raster = createRasterForXImage(ximg, origin); /* This is not a good way of doing this. Multiple toolkits may want to share the BufferedImage. */ Hashtable props = new Hashtable(); props.put("gnu.gcj.xlib.XImage", ximg); props.put("java.awt.GraphicsConfiguration", this); BufferedImage bimg = new BufferedImage(imageCM,raster, false, props); DataBuffer dataB = raster.getDataBuffer(); attachData(ximg, dataB, 0); return bimg; } WritableRaster createRasterForXImage(XImage ximage, Point origin) { if (imageCM == null) prepareColorModel(ximage); /* This will not work, since it creates a sample model that does not necessarily match the format of the XImage. WritableRaster raster = imageCM.createCompatibleWritableRaster(width, height); */ // Create a sample model matching the XImage: SampleModel imageSM = null; int width = ximage.getWidth(); int height = ximage.getHeight(); int bitsPerPixel = ximage.getBitsPerPixel(); int dataType = Buffers.smallestAppropriateTransferType(bitsPerPixel); int bitsPerDataElement = DataBuffer.getDataTypeSize(dataType); int scanlineStride = ximage.getBytesPerLine()*8/bitsPerDataElement; if (imageCM instanceof IndexColorModel) { int[] bandOffsets = {0}; imageSM = new ComponentSampleModel(dataType, width, height, 1, // pixel stride scanlineStride, bandOffsets); } else if (imageCM instanceof PackedColorModel) { PackedColorModel pcm = (PackedColorModel) imageCM; int[] masks = pcm.getMasks(); imageSM = new SinglePixelPackedSampleModel(dataType, width, height, scanlineStride, masks); } if (imageSM == null) { throw new UnsupportedOperationException("creating sample model " + "for " + imageCM + " not implemented"); } WritableRaster raster = Raster.createWritableRaster(imageSM, origin); return raster; } /** * Attach a the memory of a data buffer to an XImage * structure. [This method is not gnu.awt.xlib specific, and should * maybe be moved to a different location.] * * @param offset Offset to data. The given offset does not include * data buffer offset, which will also be added. */ static void attachData(XImage ximage, DataBuffer dataB, int offset) { offset += dataB.getOffset(); switch (dataB.getDataType()) { case DataBuffer.TYPE_BYTE: ximage.setData(((DataBufferByte) dataB).getData(), offset); break; case DataBuffer.TYPE_USHORT: ximage.setData(((DataBufferUShort) dataB).getData(), offset); break; case DataBuffer.TYPE_INT: ximage.setData(((DataBufferInt) dataB).getData(), offset); break; default: throw new UnsupportedOperationException("Do not know how to " + "set data for data " + "type " + dataB.getDataType()); } } void prepareColorModel(XImage ximage) { format = ximage.getFormat(); int bitsPerPixel = ximage.getBitsPerPixel(); switch (format) { case XImage.ZPIXMAP_FORMAT: calcZPixmapModels(bitsPerPixel); break; default: throw new UnsupportedOperationException("unimplemented format"); } } void calcZPixmapModels(int bitsPerPixel) { switch (visual.getVisualClass()) { case Visual.VC_TRUE_COLOR: calcDecomposedRGBModels(bitsPerPixel); break; case Visual.VC_PSEUDO_COLOR: calcPseudoColorModels(bitsPerPixel); break; default: String msg = "unimplemented visual class"; throw new UnsupportedOperationException(msg); } } void calcDecomposedRGBModels(int bitsPerPixel) { int dataType = Buffers.smallestAppropriateTransferType(bitsPerPixel); if (DataBuffer.getDataTypeSize(dataType) == bitsPerPixel) { ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); imageCM = new DirectColorModel(cs, visual.getDepth(), visual.getRedMask(), visual.getGreenMask(), visual.getBlueMask(), 0, // no alpha false, dataType); } else { throw new UnsupportedOperationException("unimplemented bits per pixel"); } } void calcPseudoColorModels(int bitsPerPixel) { if (colormap == null) colormap = visual.getScreen().getDefaultColormap(); XColor[] colArray = colormap.getXColors(); int numCol = colArray.length; byte[] rmap = new byte[numCol]; byte[] gmap = new byte[numCol]; byte[] bmap = new byte[numCol]; byte[] amap = new byte[numCol]; for (int i=0; i < numCol; i++) { XColor color = colArray[i]; if (color.getFlags() == Colormap.FLAG_SHARED) { rmap[i] = (byte) (color.getRed() >> 8); gmap[i] = (byte) (color.getGreen() >> 8); bmap[i] = (byte) (color.getBlue() >> 8); amap[i] = (byte) 0xff; } // else, leave default zero values... } imageCM = new IndexColorModel(visual.getDepth(), numCol, rmap, gmap, bmap, amap); } public BufferedImage createCompatibleImage(int width, int height, int transparency) { throw new UnsupportedOperationException("not implemented"); } /** * FIXME: I'm not sure which color model that should be returned here. */ public ColorModel getColorModel() { if (pixelCM == null) preparePixelCM(); return pixelCM; } void preparePixelCM() { switch (visual.getVisualClass()) { case Visual.VC_TRUE_COLOR: pixelCM = new DirectColorModel(visual.getDepth(), visual.getRedMask(), visual.getGreenMask(), visual.getBlueMask()); break; case Visual.VC_PSEUDO_COLOR: if (colormap == null) colormap = visual.getScreen().getDefaultColormap(); XColor[] colArray = colormap.getXColors(); int numCol = colArray.length; byte[] rmap = new byte[numCol]; byte[] gmap = new byte[numCol]; byte[] bmap = new byte[numCol]; byte[] amap = new byte[numCol]; for (int i=0; i < numCol; i++) { XColor color = colArray[i]; if (color.getFlags() == Colormap.FLAG_SHARED) { rmap[i] = (byte) (color.getRed() >> 8); gmap[i] = (byte) (color.getGreen() >> 8); bmap[i] = (byte) (color.getBlue() >> 8); amap[i] = (byte) 0xff; } // else, leave default zero values... } pixelCM = new IndexColorModel(visual.getDepth(), numCol, rmap, gmap, bmap, amap); break; default: throw new UnsupportedOperationException("not implemented"); } } public ColorModel getColorModel(int transparency) { throw new UnsupportedOperationException("not implemented"); } public AffineTransform getDefaultTransform() { throw new UnsupportedOperationException("not implemented"); } public AffineTransform getNormalizingTransform() { throw new UnsupportedOperationException("not implemented"); } public Rectangle getBounds() { throw new UnsupportedOperationException("not implemented"); } Visual getVisual() { return visual; } /* FIXME: This should be moved to XGraphicsDevice... */ XFontMetrics getXFontMetrics(java.awt.Font awtFont) { // FIXME: do caching... String family = "*"; String name = awtFont.getName(); String weight = awtFont.isBold() ? "bold" : "medium"; String slant = awtFont.isItalic() ? "i" : "r"; String addStyle = "*"; String pixelSize = "*"; String pointSize = awtFont.getSize() + "0"; String xres = "*"; String yres = "*"; String spacing = "*"; String averageWidth = "*"; String charset = "*"; String logicalFontDescription = family + "-" + name + "-" + weight + "-" + slant + "-" + addStyle + "-" + pixelSize + "-" + pointSize + "-" + xres + "-" + yres + "-" + spacing + "-" + averageWidth + "-" + charset; Display display = visual.getScreen().getDisplay(); gnu.gcj.xlib.Font xfont = new gnu.gcj.xlib.Font(display, logicalFontDescription); return new XFontMetrics(xfont, awtFont); } int getPixel(Color color) { int[] components = { color.getRed(), color.getGreen(), color.getBlue(), 0xff }; ColorModel cm = getColorModel(); return cm.getDataElement(components, 0); } }