1 /* Copyright (C) 1999, 2000  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.gcj.xlib;
10 
11 import java.awt.Rectangle;
12 
13 /** An X11 drawable.
14  *
15  * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
16  */
17 public class Drawable extends XID
18 {
19   private GC[] gcCache = new GC[10];
20   private int gcCachedCount = 0;
21 
Drawable(Display display, int xid)22   public Drawable(Display display, int xid)
23   {
24     super(display, xid);
25   }
26 
27   /**
28    * Gets as much as possible of the image data within the requested
29    * region. Data from obscured parts of windows may not be
30    * retrievable.
31    *
32    * @param dest where to place the image data.
33    *
34    * @return the actual region of image data that was retrieved.
35    */
copyIntoXImage(XImage dest, Rectangle bounds, int destX, int destY)36   public Rectangle copyIntoXImage(XImage dest, Rectangle bounds,
37 				  int destX, int destY)
38   {
39     Rectangle newBounds = null;
40     int tries = 5;
41     while (!bounds.isEmpty())
42       {
43 	if (copyIntoXImageImpl(dest, bounds.x, bounds.y,
44 			       bounds.width, bounds.height,
45 			       destX, destY))
46 	  return bounds;
47 
48 	// failed, likely due to wrong bounds...
49 
50 	newBounds = getBounds(newBounds);
51 
52 	bounds = newBounds.intersection(bounds);
53 
54 	tries--;
55 
56 	if (tries < 0)
57 	throw new RuntimeException("copyIntoXImage is buggy");
58 
59       }
60 
61     return bounds; // always empty
62   }
63 
64 
65 
66   /**
67    * Performs an XGetSubImage. This method will fail if the X server
68    * does not possess the requested image data. This might occur when
69    * requesting the image date of a window that is partially obscured.
70    *
71    * @param desitantionImage where to place the image data
72    *
73    * @return false if method was unable to read the requested region.
74    */
copyIntoXImageImpl(XImage destinationImage, int x, int y, int width, int height, int destX, int destY)75   private native boolean copyIntoXImageImpl(XImage destinationImage,
76 					    int x, int y,
77 					    int width, int height,
78 					    int destX, int destY);
79 
getBounds(Rectangle rv)80   public native Rectangle getBounds(Rectangle rv);
81 
getDepth()82   public native int getDepth ();
83 
84   private static final String MSG_XGETSUBIMAGE_FAILED =
85     "XGetSubImage() failed.";
86 
finalize()87   protected void finalize() throws Throwable
88   {
89     // Dispose all the cached GCs, to reduce X server resource usage
90     for (int i=0; i<gcCachedCount; i++)
91       gcCache[i].disposeImpl ();
92     gcCachedCount = 0;
93     super.finalize();
94   }
95 
96   /** Put a GC in the cache for this drawable, so it can be retrieved later.
97    * @param gc The GC to put
98    */
putGCInCache(GC gc)99   void putGCInCache (GC gc)
100   {
101     if (gcCachedCount >= gcCache.length)
102     {
103       // List full - extend it to double its present size
104       GC[] oldList = gcCache;
105       gcCache = new GC[oldList.length*2];
106       System.arraycopy (oldList,0,gcCache,0,oldList.length);
107     }
108     gcCache[gcCachedCount++] = gc;
109   }
110 
111   /** Get a GC from the cache, if available
112    * @return A GC from the cache, or null if the cache is empty
113    */
getGCFromCache()114   GC getGCFromCache ()
115   {
116     return (gcCachedCount>0) ? gcCache[--gcCachedCount] : null;
117   }
118 }
119