2003-12-26 Guilhem Lavaux <guilhem@kaffe.org>
[official-gcc.git] / libjava / gnu / awt / xlib / XGraphicsConfiguration.java
blobbdbf3e18a74dfd064047f6c8fdc3559eba0778ff
1 /* Copyright (C) 2000, 2003 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7 details. */
9 package gnu.awt.xlib;
11 import java.awt.GraphicsConfiguration;
12 import java.awt.Rectangle;
13 import java.awt.Graphics2D;
14 import java.awt.Graphics;
15 import java.awt.GraphicsDevice;
16 import java.awt.Point;
17 import java.awt.Color;
18 import java.awt.color.ColorSpace;
19 import java.awt.Font;
20 import java.awt.image.*;
21 import java.awt.geom.AffineTransform;
22 import gnu.gcj.xlib.GC;
23 import gnu.gcj.xlib.Drawable;
24 import gnu.gcj.xlib.Window;
25 import gnu.gcj.xlib.XImage;
26 import gnu.gcj.xlib.Visual;
27 import gnu.gcj.xlib.Colormap;
28 import gnu.gcj.xlib.XColor;
29 import gnu.gcj.xlib.Screen;
30 import gnu.gcj.xlib.Display;
31 import gnu.gcj.xlib.XException;
32 import gnu.java.awt.Buffers;
33 import java.util.Enumeration;
34 import java.util.Hashtable;
36 public class XGraphicsConfiguration extends GraphicsConfiguration
38 //public abstract GraphicsDevice getDevice();
40 Visual visual;
41 int format;
42 Colormap colormap;
43 ColorModel imageCM;
44 ColorModel pixelCM;
45 private static final int CACHE_SIZE_PER_DISPLAY = 10;
46 static FontMetricsCache fontMetricsCache = new FontMetricsCache ();
48 /** Font metrics cache class. Caches at most CACHE_SIZE_PER_DISPLAY
49 * XFontMetrics objects for each display device. When a display's cache
50 * gets full, the least-recently used entry is overwritten.
51 * XXX: lruOrder rolls over after a few billion operations, so it might
52 * on very rare occasions misinterpret which is the oldest entry
54 static class FontMetricsCache
56 private java.util.Hashtable displays = new java.util.Hashtable ();
58 /** Font metrics cache for a display device
60 class PerDisplayCache
62 private int lruCount = 0;
63 private java.util.Hashtable entries = new java.util.Hashtable ();
65 class CacheEntry
67 int lruOrder;
68 XFontMetrics fm;
69 Font font;
72 /** Get an entry (null if not there) and update LRU ordering
74 XFontMetrics get (Font font)
76 CacheEntry entry = (CacheEntry)entries.get (font);
77 if (entry != null)
79 entry.lruOrder = lruCount++;
81 return (entry==null) ? null : entry.fm;
84 /** Put an entry in the cache, eliminating the oldest entry if
85 * the cache is at capacity.
87 void put (Font font, XFontMetrics fontMetrics)
89 if (entries.size () >= CACHE_SIZE_PER_DISPLAY)
91 // cache is full -- eliminate the oldest entry
92 // slow operation, but shouldn't happen very often
93 int maxAge = 0;
94 CacheEntry oldestEntry = null;
95 int referenceCount = lruCount;
96 for (Enumeration e = entries.elements (); e.hasMoreElements ();)
98 CacheEntry entry = (CacheEntry)e.nextElement ();
99 if ((referenceCount-entry.lruOrder) > maxAge)
101 maxAge = referenceCount-entry.lruOrder;
102 oldestEntry = entry;
105 if (oldestEntry != null)
106 entries.remove (oldestEntry.font);
108 CacheEntry newEntry = new CacheEntry ();
109 newEntry.lruOrder = lruCount++;
110 newEntry.fm = fontMetrics;
111 newEntry.font = font;
112 entries.put (font,newEntry);
116 /** Get the font metrics for a font, if it is present in the cache.
117 * @param font The AWT font for which to find the font metrics
118 * @param display The display, to select the cached entries for that display
119 * @return The font metrics, or null if not cached
121 XFontMetrics get (Font font, Display display)
123 PerDisplayCache cache = (PerDisplayCache)displays.get (display);
124 return (cache==null) ? null : cache.get (font);
127 /** Put a font in the cache
128 * @param font The font
129 * @param display The display
130 * @param fontMetrics The font metrics
132 void put (Font font, Display display, XFontMetrics fontMetrics)
134 PerDisplayCache cache = (PerDisplayCache)displays.get (display);
135 if (cache == null)
137 cache = new PerDisplayCache ();
138 displays.put (display,cache);
140 cache.put (font,fontMetrics);
144 public XGraphicsConfiguration(Visual visual)
146 this.visual = visual;
149 public BufferedImage createCompatibleImage(int width, int height)
151 XImage ximg = new XImage(visual, width, height,
152 false // do not auto allocate memory
155 Point origin = new Point(0, 0);
156 WritableRaster raster = createRasterForXImage(ximg, origin);
158 /* This is not a good way of doing this. Multiple toolkits may
159 want to share the BufferedImage. */
160 Hashtable props = new Hashtable();
161 props.put("gnu.gcj.xlib.XImage", ximg);
162 props.put("java.awt.GraphicsConfiguration", this);
164 BufferedImage bimg = new BufferedImage(imageCM,raster, false, props);
166 DataBuffer dataB = raster.getDataBuffer();
167 attachData(ximg, dataB, 0);
168 return bimg;
171 WritableRaster createRasterForXImage(XImage ximage, Point origin)
173 if (imageCM == null) prepareColorModel(ximage);
176 This will not work, since it creates a sample model that
177 does not necessarily match the format of the XImage.
179 WritableRaster raster =
180 imageCM.createCompatibleWritableRaster(width, height); */
182 // Create a sample model matching the XImage:
184 SampleModel imageSM = null;
186 int width = ximage.getWidth();
187 int height = ximage.getHeight();
188 int bitsPerPixel = ximage.getBitsPerPixel();
189 int dataType =
190 Buffers.smallestAppropriateTransferType(bitsPerPixel);
191 int bitsPerDataElement = DataBuffer.getDataTypeSize(dataType);
192 int scanlineStride = ximage.getBytesPerLine()*8/bitsPerDataElement;
194 if (imageCM instanceof IndexColorModel)
196 int[] bandOffsets = {0};
197 imageSM = new ComponentSampleModel(dataType,
198 width, height,
199 1, // pixel stride
200 scanlineStride,
201 bandOffsets);
203 else if (imageCM instanceof PackedColorModel)
205 PackedColorModel pcm = (PackedColorModel) imageCM;
206 int[] masks = pcm.getMasks();
208 imageSM = new SinglePixelPackedSampleModel(dataType,
209 width, height,
210 scanlineStride,
211 masks);
214 if (imageSM == null)
216 throw new UnsupportedOperationException("creating sample model " +
217 "for " + imageCM +
218 " not implemented");
221 WritableRaster raster = Raster.createWritableRaster(imageSM, origin);
222 return raster;
228 * Attach a the memory of a data buffer to an XImage
229 * structure. [This method is not gnu.awt.xlib specific, and should
230 * maybe be moved to a different location.]
232 * @param offset Offset to data. The given offset does not include
233 * data buffer offset, which will also be added.
235 static void attachData(XImage ximage, DataBuffer dataB, int offset)
237 offset += dataB.getOffset();
238 switch (dataB.getDataType())
240 case DataBuffer.TYPE_BYTE:
241 ximage.setData(((DataBufferByte) dataB).getData(), offset);
242 break;
243 case DataBuffer.TYPE_USHORT:
244 ximage.setData(((DataBufferUShort) dataB).getData(), offset);
245 break;
246 case DataBuffer.TYPE_INT:
247 ximage.setData(((DataBufferInt) dataB).getData(), offset);
248 break;
249 default:
250 throw
251 new UnsupportedOperationException("Do not know how to " +
252 "set data for data " +
253 "type " +
254 dataB.getDataType());
258 void prepareColorModel(XImage ximage)
260 format = ximage.getFormat();
261 int bitsPerPixel = ximage.getBitsPerPixel();
262 switch (format) {
263 case XImage.ZPIXMAP_FORMAT:
264 calcZPixmapModels(bitsPerPixel);
265 break;
267 default:
268 throw new UnsupportedOperationException("unimplemented format");
272 void calcZPixmapModels(int bitsPerPixel)
274 switch (visual.getVisualClass())
276 case Visual.VC_TRUE_COLOR:
277 calcDecomposedRGBModels(bitsPerPixel);
278 break;
279 case Visual.VC_PSEUDO_COLOR:
280 calcPseudoColorModels(bitsPerPixel);
281 break;
282 default:
283 String msg = "unimplemented visual class";
284 throw new UnsupportedOperationException(msg);
288 void calcDecomposedRGBModels(int bitsPerPixel)
290 int dataType = Buffers.smallestAppropriateTransferType(bitsPerPixel);
293 if (DataBuffer.getDataTypeSize(dataType) == bitsPerPixel)
295 ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
297 imageCM = new DirectColorModel(cs,
298 visual.getDepth(),
299 visual.getRedMask(),
300 visual.getGreenMask(),
301 visual.getBlueMask(),
302 0, // no alpha
303 false,
304 dataType);
306 else
308 throw new
309 UnsupportedOperationException("unimplemented bits per pixel");
313 void calcPseudoColorModels(int bitsPerPixel)
315 if (colormap == null)
316 colormap = visual.getScreen().getDefaultColormap();
318 XColor[] colArray = colormap.getXColors();
320 int numCol = colArray.length;
321 byte[] rmap = new byte[numCol];
322 byte[] gmap = new byte[numCol];
323 byte[] bmap = new byte[numCol];
324 byte[] amap = new byte[numCol];
326 for (int i=0; i < numCol; i++)
328 XColor color = colArray[i];
329 if (color.getFlags() == Colormap.FLAG_SHARED)
331 rmap[i] = (byte) (color.getRed() >> 8);
332 gmap[i] = (byte) (color.getGreen() >> 8);
333 bmap[i] = (byte) (color.getBlue() >> 8);
334 amap[i] = (byte) 0xff;
335 } // else, leave default zero values...
338 imageCM = new IndexColorModel(visual.getDepth(), numCol,
339 rmap, gmap, bmap, amap);
343 * Gets the associated device that this configuration describes.
345 * @return the device
347 public GraphicsDevice getDevice()
349 throw new UnsupportedOperationException("not implemented");
353 * Returns a buffered image optimized to this device, so that blitting can
354 * be supported in the buffered image.
356 * @param w the width of the buffer
357 * @param h the height of the buffer
358 * @return the buffered image, or null if none is supported
360 public BufferedImage createCompatibleImage(int width,
361 int height,
362 int transparency)
364 throw new UnsupportedOperationException("not implemented");
368 * Returns a buffered volatile image optimized to this device, so that
369 * blitting can be supported in the buffered image. Because the buffer is
370 * volatile, it can be optimized by native graphics accelerators.
372 * @param w the width of the buffer
373 * @param h the height of the buffer
374 * @return the buffered image, or null if none is supported
375 * @see Component#createVolatileImage(int, int)
376 * @since 1.4
378 public VolatileImage createCompatibleVolatileImage(int w, int h)
380 throw new UnsupportedOperationException("not implemented");
384 * FIXME: I'm not sure which color model that should be returned here.
386 public ColorModel getColorModel()
388 if (pixelCM == null)
389 preparePixelCM();
390 return pixelCM;
393 void preparePixelCM()
395 switch (visual.getVisualClass())
397 case Visual.VC_TRUE_COLOR:
398 pixelCM = new DirectColorModel(visual.getDepth(),
399 visual.getRedMask(),
400 visual.getGreenMask(),
401 visual.getBlueMask());
402 break;
403 case Visual.VC_PSEUDO_COLOR:
405 if (colormap == null)
406 colormap = visual.getScreen().getDefaultColormap();
408 XColor[] colArray = colormap.getXColors();
410 int numCol = colArray.length;
411 byte[] rmap = new byte[numCol];
412 byte[] gmap = new byte[numCol];
413 byte[] bmap = new byte[numCol];
414 byte[] amap = new byte[numCol];
416 for (int i=0; i < numCol; i++)
418 XColor color = colArray[i];
419 if (color.getFlags() == Colormap.FLAG_SHARED) {
420 rmap[i] = (byte) (color.getRed() >> 8);
421 gmap[i] = (byte) (color.getGreen() >> 8);
422 bmap[i] = (byte) (color.getBlue() >> 8);
423 amap[i] = (byte) 0xff;
424 } // else, leave default zero values...
428 pixelCM = new IndexColorModel(visual.getDepth(), numCol,
429 rmap, gmap, bmap, amap);
430 break;
431 default:
432 throw new UnsupportedOperationException("not implemented");
436 public ColorModel getColorModel(int transparency)
438 throw new UnsupportedOperationException("not implemented");
441 public AffineTransform getDefaultTransform()
443 throw new UnsupportedOperationException("not implemented");
446 public AffineTransform getNormalizingTransform()
448 throw new UnsupportedOperationException("not implemented");
451 public Rectangle getBounds()
453 throw new UnsupportedOperationException("not implemented");
456 Visual getVisual()
458 return visual;
461 /* FIXME: This should be moved to XGraphicsDevice... */
462 XFontMetrics getXFontMetrics (java.awt.Font awtFont)
464 // If the metrics object for this font is already cached, use it.
465 // Otherwise create and cache it.
466 Display display = visual.getScreen ().getDisplay ();
467 XFontMetrics fm = fontMetricsCache.get (awtFont,display);
468 if (fm == null)
470 String foundry = "*";
471 String family = awtFont.getName ();
472 String weight = awtFont.isBold () ? "bold" : "medium";
473 String slant = awtFont.isItalic () ? "i" : "r";
474 String sWidth = "*";
475 String addStyle = "";
476 String pixelSize = "*";
477 String pointSize = awtFont.getSize () + "0";
478 String xres = "*";
479 String yres = "*";
480 String spacing = "*";
481 String averageWidth = "*";
482 String charset = "iso10646-1"; // because we use functions like XDrawString16
484 String logicalFontDescription =
485 "-" + // FontNameRegistry prefix
486 foundry + "-" + family + "-" + weight + "-" +
487 slant + "-" + sWidth + "-" + addStyle + "-" +
488 pixelSize + "-" + pointSize + "-" + xres + "-" +
489 yres + "-" + spacing + "-" + averageWidth + "-";
491 // Try to load a Unicode font. If that doesn't work, try again, without
492 // specifying the character set.
495 gnu.gcj.xlib.Font xfont = new gnu.gcj.xlib.Font (display, logicalFontDescription + charset);
496 fm = new XFontMetrics (xfont, awtFont);
498 catch (XException e)
500 gnu.gcj.xlib.Font xfont = new gnu.gcj.xlib.Font (display, logicalFontDescription + "*-*");
501 fm = new XFontMetrics (xfont, awtFont);
503 fontMetricsCache.put (awtFont,display,fm);
505 return fm;
508 int getPixel(Color color)
510 /* FIXME: consider an integer technique whenever
511 * the ColorModel is 8 bits per color.
512 * The problem with using integers is that it doesn't work unless
513 * the colors are 8 bits each (as in the array), since ColorModel.getDataElement(int[],int)
514 * expects non-normalized values. For example, in a 16-bit display mode, you
515 * would typically have 5 bits each for red and blue, and 6 bits for green.
516 int[] components =
518 color.getRed (),
519 color.getGreen (),
520 color.getBlue (),
521 0xff
525 float[] normalizedComponents =
527 ((float)color.getRed ()) / 255F,
528 ((float)color.getGreen ()) / 255F,
529 ((float)color.getBlue ()) / 255F,
532 int[] unnormalizedComponents = { 0, 0, 0, 0xff };
533 ColorModel cm = getColorModel ();
534 cm.getUnnormalizedComponents(normalizedComponents, 0,
535 unnormalizedComponents, 0);
536 return cm.getDataElement (unnormalizedComponents, 0);