1 /* Copyright (C) 2000, 2003  Free Software Foundation
2 
3    This file is part of libgcj.
4 
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
7 details.  */
8 
9 package gnu.awt.xlib;
10 
11 import java.awt.Image;
12 import java.awt.Graphics;
13 import java.awt.Graphics2D;
14 import java.awt.GraphicsConfiguration;
15 import java.awt.image.ColorModel;
16 import java.awt.image.ImageObserver;
17 import java.awt.image.ImageProducer;
18 import java.awt.image.ImageConsumer;
19 import java.util.Hashtable;
20 import gnu.awt.j2d.DirectRasterGraphics;
21 import gnu.awt.j2d.Graphics2DImpl;
22 import gnu.awt.j2d.IntegerGraphicsState;
23 import gnu.gcj.xlib.Drawable;
24 import gnu.gcj.xlib.Pixmap;
25 import gnu.gcj.xlib.Screen;
26 import gnu.gcj.xlib.Visual;
27 import gnu.gcj.xlib.GC;
28 
29 /** Image class for xlib off-screen buffers.
30  * The image is stored in a server-side pixmap for best performance.
31  * This class supports getGraphics, so you can draw on the pixmap, and is
32  * specially handled when doing drawImage, so that the image copy is done
33  * entirely in the X server.
34  * This class does not support rasterization, for which you'd need an XImage.
35  *
36  * @author  scott gilbertson <scottg@mantatest.com> <sgilbertson@cogeco.ca>
37  */
38 public class XOffScreenImage extends Image
39                              implements IntegerGraphicsState.ScreenCoupledImage,
40                              ImageConsumer
41 {
42   private Pixmap pixmap;
43   private XGraphicsConfiguration config;
44   private int width;
45   private int height;
46   private Drawable drawable;
47   private ImageProducer prod;
48   private GC gc;
49   private ColorModel pixmapColorModel;
50 
51   /** Create a new XOffScreenImage
52    * @param config Graphics configuration, to compare against on-screen
53    *               components and to create the appropriate Graphics
54    * @param drawable The drawable with which the image is compatible
55    * @param width The width of the image
56    * @param height The height of the image
57    * @param cm The ColorModel associated with drawable
58    */
XOffScreenImage(XGraphicsConfiguration config, Drawable drawable, int width, int height, ColorModel cm)59   XOffScreenImage (XGraphicsConfiguration config, Drawable drawable, int width, int height, ColorModel cm)
60   {
61     this.config = config;
62     this.width = width;
63     this.height = height;
64     this.drawable = drawable;
65     pixmapColorModel = cm;
66     pixmap = new Pixmap (drawable, width, height, drawable.getDepth ());
67     gc = GC.create (pixmap);
68   }
69 
70   /** Create a new XOffScreenImage and obtain image data from an ImageProducer
71    * @param config Graphics configuration, to compare against on-screen
72    *               components and to create the appropriate Graphics
73    * @param drawable The drawable with which the image is compatible
74    * @param prod The source of image data for this image
75    * @param cm The ColorModel associated with drawable
76    */
XOffScreenImage(XGraphicsConfiguration config, Drawable drawable, ImageProducer prod, ColorModel cm)77   XOffScreenImage (XGraphicsConfiguration config, Drawable drawable, ImageProducer prod, ColorModel cm)
78   {
79     this.config = config;
80     this.width = 0;  // size will be overridden in a moment
81     this.height = 0;
82     this.drawable = drawable;
83     this.prod = prod;
84     pixmapColorModel = cm;
85     prod.startProduction (this);
86   }
87 
88   /** Get the pixmap which contains this image
89    * @return The pixmap
90    */
getPixmap()91   public Pixmap getPixmap ()
92   {
93     return pixmap;
94   }
95 
96   /** Flushes (that is, destroys) any resources used for this image.  This
97    * includes the actual image data.
98    */
flush()99   public void flush ()
100   {
101     // FIXME: should dispose pixmap
102     pixmap = null;
103   }
104 
105   /** Returns a graphics context object for drawing an off-screen object.
106    * This method is only valid for off-screen objects.
107    *
108    * @return a graphics context object for an off-screen object
109    * @see Graphics#createImage(int, int)
110    */
getGraphics()111   public Graphics getGraphics ()
112   {
113     DirectRasterGraphics gfxDevice = new XGraphics (pixmap, config);
114     IntegerGraphicsState igState = new IntegerGraphicsState (gfxDevice);
115     Graphics2DImpl gfx2d = new Graphics2DImpl (config);
116     gfx2d.setState (igState);
117     return gfx2d;
118   }
119 
120   /** Returns the height of the image, or -1 if it is unknown.  If the
121    * image height is unknown, the observer object will be notified when
122    * the value is known.
123    *
124    * @param observer the image observer for this object
125    * @return the height in pixels
126    * @see #getWidth(ImageObserver)
127    */
getHeight(ImageObserver observer)128   public int getHeight (ImageObserver observer)
129   {
130     return height;
131   }
132 
133   /** Returns the height of the image, or -1 if it is unknown.  If the
134    * image height is unknown, the observer object will be notified when
135    * the value is known.
136    *
137    * @return the height in pixels
138    * @see #getWidth()
139    */
getHeight()140   public int getHeight ()
141   {
142     return height;
143   }
144 
145   /** Returns the image producer object for this object. The producer is the
146    * object which generates pixels for this image.
147    *
148    * @return the image producer for this object
149    */
getSource()150   public ImageProducer getSource ()
151   {
152     if (prod == null)
153       throw new UnsupportedOperationException ("getSource not supported");
154     else
155       return prod;
156   }
157 
158   /** Returns the width of the image, or -1 if it is unknown.  If the
159    * image width is unknown, the observer object will be notified when
160    * the value is known.
161    *
162    * @param observer the image observer for this object
163    * @return the width in pixels
164    * @see #getHeight(ImageObserver)
165    */
getWidth(ImageObserver observer)166   public int getWidth (ImageObserver observer)
167   {
168     return width;
169   }
170 
171   /** Returns the width of the image, or -1 if it is unknown.  If the
172    * image width is unknown, the observer object will be notified when
173    * the value is known.
174    *
175    * @return the width in pixels
176    * @see #getHeight()
177    */
getWidth()178   public int getWidth ()
179   {
180     return width;
181   }
182 
183   /** This method requests a named property for an object.  The value of the
184    * property is returned. The value <code>UndefinedProperty</code> is
185    * returned if there is no property with the specified name.  The value
186    * <code>null</code> is returned if the properties for the object are
187    * not yet known.  In this case, the specified image observer is notified
188    * when the properties are known.
189    *
190    * @param name the requested property name
191    * @param observer the image observer for this object
192    * @return the named property, if available
193    * @see #UndefinedProperty
194    */
getProperty(String name, ImageObserver observer)195   public Object getProperty (String name, ImageObserver observer)
196   {
197     return null;
198   }
199 
200   /** Get the GraphicsConfiguration to which this image is coupled
201    * @return the GraphicsConfiguration
202    */
getGraphicsConfiguration()203   public GraphicsConfiguration getGraphicsConfiguration ()
204   {
205     return config;
206   }
207 
imageComplete(int status)208   public void imageComplete (int status)
209   {
210   }
211 
setColorModel(ColorModel model)212   public void setColorModel (ColorModel model)
213   {
214   }
215 
setDimensions(int width, int height)216   public void setDimensions (int width, int height)
217   {
218     this.width = width;
219     this.height = height;
220     pixmap = new Pixmap (drawable, width, height, drawable.getDepth ());
221     gc = GC.create (pixmap);
222   }
223 
setHints(int flags)224   public void setHints (int flags)
225   {
226   }
227 
setPixels(int x, int y, int w, int h, ColorModel model, int[] pixels, int offset, int scansize)228   public void setPixels (int x, int y, int w, int h, ColorModel model, int[] pixels, int offset, int scansize)
229   {
230     int idx = 0;
231     float[] normalizedComponents = new float [4];
232     int[] unnormalizedComponents = { 0, 0, 0, 0xff };
233     normalizedComponents[3] = 1;
234     for (int yp=y; yp < (y + h); yp++)
235     {
236       for (int xp=x; xp < (x + w); xp++)
237       {
238         int p = (yp - y) * scansize + (xp - x) + offset;
239         // FIXME: there HAS to be a more efficient mechanism for color mapping
240         normalizedComponents[0] = (float)model.getRed (pixels[p]) / 255F;
241         normalizedComponents[1] = (float)model.getGreen (pixels[p]) / 255F;
242         normalizedComponents[2] = (float)model.getBlue (pixels[p]) / 255F;
243         pixmapColorModel.getUnnormalizedComponents (normalizedComponents, 0,
244           unnormalizedComponents, 0);
245         int pixelColor = pixmapColorModel.getDataElement (unnormalizedComponents, 0);
246         gc.setForeground (pixelColor);
247         gc.drawPoint (xp, yp);
248       }
249     }
250   }
251 
setPixels(int x, int y, int w, int h, ColorModel model, byte[] pixels, int offset, int scansize)252   public void setPixels (int x, int y, int w, int h, ColorModel model, byte[] pixels, int offset, int scansize)
253   {
254     int idx = 0;
255     float[] normalizedComponents = new float [4];
256     int[] unnormalizedComponents = { 0, 0, 0, 0xff };
257     normalizedComponents[3] = 1;
258     for (int yp=y; yp < (y + h); yp++)
259     {
260       for (int xp=x; xp < (x + w); xp++)
261       {
262         // FIXME: there HAS to be a more efficient mechanism for color mapping
263         int p = (yp - y) * scansize + (xp - x) + offset;
264         normalizedComponents[0] = (float)model.getRed (pixels[p]) / 255F;
265         normalizedComponents[1] = (float)model.getGreen (pixels[p]) / 255F;
266         normalizedComponents[2] = (float)model.getBlue (pixels[p]) / 255F;
267         pixmapColorModel.getUnnormalizedComponents (normalizedComponents, 0,
268           unnormalizedComponents, 0);
269         int pixelColor = pixmapColorModel.getDataElement (unnormalizedComponents, 0);
270         gc.setForeground (pixelColor);
271         gc.drawPoint (xp, yp);
272       }
273     }
274   }
275 
setProperties(Hashtable props)276   public void setProperties (Hashtable props)
277   {
278   }
279 
280 }
281