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.j2d;
10 
11 import java.awt.Color;
12 import java.awt.Image;
13 import java.awt.Shape;
14 import java.awt.Rectangle;
15 import java.awt.Graphics;
16 import java.awt.Graphics2D;
17 import java.awt.GraphicsConfiguration;
18 import java.awt.Font;
19 import java.awt.FontMetrics;
20 import java.awt.image.BufferedImage;
21 import java.awt.image.ImageObserver;
22 import java.awt.image.Raster;
23 import java.awt.image.WritableRaster;
24 import java.awt.image.ColorModel;
25 
26 /**
27  * IntegerGraphicsState is one of several graphics state
28  * implementations.  This graphics state is used when the graphics
29  * object has simple properties, (coordinate translation only, no
30  * transform) and the backend supports integer coordinates (pixel
31  * based). For primitive paint operations, this object translates the
32  * coordinates and forwards the request to the backend. For requests
33  * to draw arbitrary shapes and paths, this object translates the
34  * requests to primitive drawing operations supported by the
35  * backend. IntegerGraphicsState is meant to support the most common
36  * state of an graphics object. The degree of functionality is roughly
37  * equivalent with the old java.awt.Graphics API.
38  */
39 public class IntegerGraphicsState extends AbstractGraphicsState
40 {
41   int tx;
42   int ty;
43 
44   DirectRasterGraphics directGfx;
45   Shape clip;
46 
47   /** Interface for images which are coupled to a GraphicsConfiguration,
48    * as is typically the case for an off-screen buffer used in
49    * double-buffering.  Any image which implements this interface is
50    * rendered directly by DirectRasterGraphics (i.e. by directGfx.drawImage)
51    */
52   public interface ScreenCoupledImage
53   {
54     /** Get the GraphicsConfiguration to which this image is coupled
55      * @return the GraphicsConfiguration
56      */
getGraphicsConfiguration()57     GraphicsConfiguration getGraphicsConfiguration ();
58   }
59 
IntegerGraphicsState(DirectRasterGraphics directGfx)60   public IntegerGraphicsState(DirectRasterGraphics directGfx)
61   {
62     this.directGfx = directGfx;
63   }
64 
clone()65   public Object clone()
66   {
67     IntegerGraphicsState clone = (IntegerGraphicsState) super.clone();
68     clone.directGfx = (DirectRasterGraphics) directGfx.clone();
69 
70     return clone;
71   }
72 
dispose()73   public void dispose()
74   {
75     DirectRasterGraphics lDeviceGfx = directGfx;
76 
77     directGfx = null;
78 
79     if (lDeviceGfx != null)
80       lDeviceGfx.dispose();
81 
82     super.dispose();
83   }
84 
85   // -------- Graphics methods:
86 
setColor(Color color)87   public void setColor(Color color)
88   {
89     directGfx.setColor(color);
90   }
91 
setPaintMode()92   public void setPaintMode()
93   {
94     directGfx.setPaintMode();
95   }
96 
setXORMode(Color altColor)97   public void setXORMode(Color altColor)
98   {
99     directGfx.setXORMode(altColor);
100   }
101 
setFont(Font font)102   public void setFont(Font font)
103   {
104     directGfx.setFont(font);
105   }
106 
getFontMetrics(Font font)107   public FontMetrics getFontMetrics(Font font)
108   {
109     return directGfx.getFontMetrics(font);
110   }
111 
setClip(Shape clip)112   public void setClip(Shape clip)
113   {
114     if (clip instanceof Rectangle)
115       {
116 	Rectangle clipRect = (Rectangle) ((Rectangle) clip).clone();
117 	clipRect.x += tx;
118 	clipRect.y += ty;
119 
120 	this.clip = clipRect;
121 
122 	directGfx.setClip(clipRect);
123 	return;
124       }
125 
126     String msg =
127       "translating clip shape " + clip + " into device " +
128       "coordinate space has not been implemented yet";
129 
130     throw new UnsupportedOperationException(msg);
131   }
132 
getClip()133   public Shape getClip()
134   {
135     if (clip instanceof Rectangle)
136       {
137 	Rectangle clipRect = (Rectangle) clip;
138 	clipRect.x -= tx;
139 	clipRect.y -= ty;
140 	return clipRect;
141       }
142 
143     String msg =
144       "translating clip shape " + clip + " into user " +
145       "coordinate space has not been implemented yet";
146 
147     throw new UnsupportedOperationException(msg);
148   }
149 
getClipBounds()150   public Rectangle getClipBounds()
151   {
152     Rectangle clipRect = clip.getBounds();
153 
154     clipRect.x -= tx;
155     clipRect.y -= ty;
156     return clipRect;
157   }
158 
copyArea(int x, int y, int width, int height, int dx, int dy)159   public void copyArea(int x, int y,
160 		       int width, int height,
161 		       int dx, int dy)
162   {
163     directGfx.copyArea(x+tx, y+ty, width, height, dx, dy);
164   }
165 
drawLine(int x1, int y1, int x2, int y2)166   public void drawLine(int x1, int y1,
167 		       int x2, int y2)
168   {
169     directGfx.drawLine(x1+tx, y1+ty, x2+tx, y2+ty);
170   }
171 
fillRect(int x, int y, int width, int height)172   public void fillRect(int x, int y,
173 		       int width, int height)
174   {
175     directGfx.fillRect(x+tx, y+ty, width, height);
176   }
177 
clearRect(int x, int y, int width, int height)178   public void clearRect(int x, int y,
179 			int width, int height)
180   {
181     directGfx.setColor(frontend.getBackground());
182     directGfx.fillRect(x+tx, y+ty, width, height);
183     directGfx.setColor(frontend.getColor());
184   }
185 
drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)186   public void drawRoundRect(int x, int y,
187 			    int width, int height,
188 			    int arcWidth, int arcHeight)
189   {
190     throw new UnsupportedOperationException("not implemented yet");
191   }
192 
fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)193   public void fillRoundRect(int x, int y,
194 			    int width, int height,
195 			    int arcWidth, int arcHeight)
196   {
197     throw new UnsupportedOperationException("not implemented yet");
198   }
199 
drawOval(int x, int y, int width, int height)200   public void drawOval(int x, int y,
201 		       int width, int height)
202   {
203     drawArc (x, y, width, height, 0, 360);
204   }
205 
fillOval(int x, int y, int width, int height)206   public void fillOval(int x, int y,
207 		       int width, int height)
208   {
209     fillArc (x, y, width, height, 0, 360);
210   }
211 
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)212   public void drawArc(int x, int y,
213 		      int width, int height,
214 		      int startAngle, int arcAngle)
215   {
216     directGfx.drawArc(x+tx, y+ty, width, height, startAngle, arcAngle);
217   }
218 
fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)219   public void fillArc(int x, int y,
220 		      int width, int height,
221 		      int startAngle, int arcAngle)
222   {
223     directGfx.fillArc(x+tx, y+ty, width, height, startAngle, arcAngle);
224   }
225 
drawPolyline(int[] xPoints, int[] yPoints, int nPoints)226   public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
227   {
228     if ((tx == 0) && (ty == 0))
229       {
230 	directGfx.drawPolyline(xPoints, yPoints, nPoints);
231 	return;
232       }
233 
234     throw new UnsupportedOperationException("translate not implemented");
235   }
236 
drawPolygon(int[] xPoints, int[] yPoints, int nPoints)237   public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
238   {
239     if ((tx == 0) && (ty == 0))
240       {
241 	directGfx.drawPolygon(xPoints, yPoints, nPoints);
242 	return;
243       }
244 
245     throw new UnsupportedOperationException("translate not implemented");
246   }
247 
fillPolygon(int[] xPoints, int[] yPoints, int nPoints)248   public void fillPolygon (int[] xPoints, int[] yPoints, int nPoints)
249   {
250     // FIXME: remove tx & ty args once translation via AffineTransform
251     // is implemented.
252     directGfx.fillPolygon (xPoints, yPoints, nPoints, tx, ty);
253   }
254 
drawImage(Image image, int x, int y, ImageObserver observer)255   public boolean drawImage(Image image, int x, int y,
256 			   ImageObserver observer)
257   {
258     x += tx;
259     y += ty;
260 
261     if (image instanceof ScreenCoupledImage)
262     {
263       GraphicsConfiguration config
264         = ((ScreenCoupledImage)image).getGraphicsConfiguration ();
265       if (config == frontend.config)
266         return directGfx.drawImage (image, x, y, observer);
267     }
268     if (image instanceof BufferedImage)
269     {
270       BufferedImage bImage = (BufferedImage) image;
271       // FIXME: eliminate? ScreenCoupledImage is probably more efficient
272       Object config = bImage.getProperty ("java.awt.GraphicsConfiguration");
273       if (config == frontend.config)
274         return directGfx.drawImage (image, x, y, observer);
275 
276       int width = image.getWidth (null);
277       int height = image.getHeight (null);
278 
279       Rectangle bounds = new Rectangle (x, y, width, height);
280 
281       MappedRaster mr = directGfx.mapRaster (bounds);
282 
283       // manipulate raster here...
284       ColorModel colorModel = mr.getColorModel ();
285       WritableRaster raster = mr.getRaster ();
286 
287       int xEnd = x + width;
288       int yEnd = y + height;
289 
290       // FIXME: Use the following code only as a fallback. It's SLOW!
291 
292       Object rgbElem = null;
293       for (int yy=0; yy<height; yy++)
294       {
295         for (int xx=0; xx<width; xx++)
296         {
297           int srgb = bImage.getRGB (xx, yy);
298           int sa = ((srgb >>> 24) & 0xff) + 1;
299           int sr = ((srgb >>> 16) & 0xff) + 1;
300           int sg = ((srgb >>> 8) & 0xff) + 1;
301           int sb = (srgb & 0xff) + 1;
302 
303           rgbElem = raster.getDataElements (xx+x, yy+y, rgbElem);
304           int drgb = colorModel.getRGB (rgbElem);
305           int dr = ((drgb >>> 16) & 0xff) + 1;
306           int dg = ((drgb >>> 8) & 0xff) + 1;
307           int db = (drgb & 0xff) + 1;
308           int da = 256 - sa;
309 
310           dr = ((sr*sa + dr*da) >>> 8) - 1;
311           dg = ((sg*sa + dg*da) >>> 8) - 1;
312           db = ((sb*sa + db*da) >>> 8) - 1;
313 
314           drgb = (dr<<16) | (dg<<8) | db;
315 
316           rgbElem = colorModel.getDataElements (drgb, rgbElem);
317 
318           raster.setDataElements (xx+x, yy+y, rgbElem);
319         }
320       }
321       directGfx.unmapRaster (mr);
322       return true;
323 
324     }
325     throw new UnsupportedOperationException ("drawing image " + image +
326     "not implemented");
327   }
328 
329 
330   // -------- Graphics2D methods:
331 
draw(Shape shape)332   public void draw(Shape shape)
333   {
334     if (shape instanceof Rectangle)
335       {
336 	Rectangle rect = (Rectangle) shape;
337 	directGfx.drawRect(rect.x+tx, rect.y+ty, rect.width, rect.height);
338 	return;
339       }
340 
341     throw new UnsupportedOperationException("shape not implemented");
342   }
343 
fill(Shape shape)344   public void fill(Shape shape)
345   {
346     if (shape instanceof Rectangle)
347       {
348 	Rectangle rect = (Rectangle) shape;
349 	directGfx.fillRect(rect.x+tx, rect.y+ty, rect.width, rect.height);
350 	return;
351       }
352 
353     throw new UnsupportedOperationException("not implemented");
354   }
355 
hit(Rectangle rect, Shape text, boolean onStroke)356   public boolean hit(Rectangle rect, Shape text,
357 		     boolean onStroke)
358   {
359     throw new UnsupportedOperationException("not implemented");
360   }
361 
drawString(String text, int x, int y)362   public void drawString(String text, int x, int y)
363   {
364     directGfx.drawString(text, x+tx, y+ty);
365   }
366 
drawString(String text, float x, float y)367   public void drawString(String text, float x, float y)
368   {
369     drawString(text, (int) x, (int) y);
370   }
371 
translate(int x, int y)372   public void translate(int x, int y)
373   {
374     tx += x;
375     ty += y;
376   }
377 
translate(double tx, double ty)378   public void translate(double tx, double ty)
379   {
380     if ((tx == 0) && (ty == 0))
381       return;
382 
383     needAffineTransform();
384   }
385 
rotate(double theta)386   public void rotate(double theta)
387   {
388     if (theta == 0)
389       return;
390 
391     needAffineTransform();
392   }
393 
rotate(double theta, double x, double y)394   public void rotate(double theta, double x, double y)
395   {
396     if (theta == 0)
397       return;
398 
399     needAffineTransform();
400   }
401 
scale(double scaleX, double scaleY)402   public void scale(double scaleX, double scaleY)
403   {
404     if ((scaleX == 1) && (scaleY == 1))
405       return;
406 
407     needAffineTransform();
408   }
409 
shear(double shearX, double shearY)410   public void shear(double shearX, double shearY)
411   {
412     if ((shearX == 0) && (shearY == 0))
413       return;
414 
415     needAffineTransform();
416   }
417 
needAffineTransform()418   private void needAffineTransform()
419   {
420     throw new UnsupportedOperationException("state with affine " +
421 					    "transform not implemented");
422   }
423 }
424