1 /* Copyright (C) 2000, 2003, 2004 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.*; 12 import java.awt.image.WritableRaster; 13 import java.awt.image.Raster; 14 import java.awt.image.DataBuffer; 15 import java.awt.image.ColorModel; 16 import java.awt.image.ImageObserver; 17 import java.awt.image.BufferedImage; 18 import gnu.gcj.xlib.GC; 19 import gnu.gcj.xlib.XImage; 20 import gnu.gcj.xlib.Drawable; 21 import gnu.gcj.xlib.Window; 22 import gnu.gcj.xlib.Drawable; 23 import gnu.gcj.xlib.Pixmap; 24 import gnu.gcj.xlib.Visual; 25 import gnu.awt.j2d.DirectRasterGraphics; 26 import gnu.awt.j2d.MappedRaster; 27 28 public class XGraphics implements Cloneable, DirectRasterGraphics 29 { 30 static class XRaster extends MappedRaster 31 { 32 XImage ximage; 33 XRaster(WritableRaster raster, XImage ximage, ColorModel cm)34 public XRaster(WritableRaster raster, XImage ximage, ColorModel cm) 35 { 36 super(raster, cm); 37 this.ximage = ximage; 38 } 39 } 40 41 GC context; 42 XGraphicsConfiguration config; 43 Rectangle clipBounds; 44 45 XFontMetrics metrics; 46 47 clone()48 public Object clone() 49 { 50 try 51 { 52 XGraphics gfxCopy = (XGraphics) super.clone(); 53 gfxCopy.context = context.create(); 54 55 return gfxCopy; 56 } 57 catch (CloneNotSupportedException ex) 58 { 59 // This should never happen. 60 throw new InternalError (); 61 } 62 } 63 dispose()64 public void dispose() 65 { 66 GC lContext = context; 67 context = null; 68 config = null; 69 clipBounds = null; 70 metrics = null; 71 72 if (lContext != null) 73 { 74 lContext.dispose(); 75 } 76 } 77 XGraphics(Drawable drawable, XGraphicsConfiguration config)78 public XGraphics(Drawable drawable, XGraphicsConfiguration config) 79 { 80 context = GC.create(drawable); 81 this.config = config; 82 } 83 setColor(Color color)84 public void setColor(Color color) 85 { 86 if (color != null) 87 context.setForeground(config.getPixel(color)); 88 } 89 setPaintMode()90 public void setPaintMode() 91 { 92 throw new UnsupportedOperationException("not implemented"); 93 } 94 setXORMode(Color c1)95 public void setXORMode(Color c1) 96 { 97 throw new UnsupportedOperationException("not implemented"); 98 } 99 setFont(Font font)100 public void setFont(Font font) 101 { 102 if (font == null) 103 return; 104 if ((metrics != null) && font.equals(metrics.getFont())) 105 return; 106 metrics = config.getXFontMetrics(font); 107 if (metrics != null) 108 context.setFont(metrics.xfont); 109 } 110 getFontMetrics(Font font)111 public FontMetrics getFontMetrics(Font font) 112 { 113 if ((metrics != null) && font.equals(metrics.getFont())) 114 return metrics; 115 116 return config.getXFontMetrics(font); 117 } 118 setClip(int x, int y, int width, int height)119 public void setClip(int x, int y, int width, int height) 120 { 121 Rectangle[] rects = { new Rectangle(x, y, width, height) }; 122 context.setClipRectangles(rects); 123 } 124 setClip(Shape clip)125 public void setClip(Shape clip) 126 { 127 /* TODO: create a special RectangleUnion shape that can be 128 used to draw advantage of the GCs ability to set multiple 129 rectangles. 130 */ 131 132 /* FIXME: creating all these objects is wasteful and can be 133 costly in the long run, since this code is run at every 134 expose. */ 135 Rectangle newClipBounds = clip.getBounds(); 136 137 /* FIXME: decide whether this test code is worth anything 138 * (as of 2004-01-29, it prints frequently) 139 if ((clipBounds != null) && !clipBounds.contains(newClipBounds)) 140 { 141 System.err.println("warning: old clip ("+ clipBounds +") does " + 142 "not fully contain new clip (" + 143 newClipBounds + ")"); 144 } 145 */ 146 clipBounds = newClipBounds; 147 Rectangle[] rects = { clipBounds }; 148 context.setClipRectangles(rects); 149 } 150 copyArea(int x, int y, int width, int height, int dx, int dy)151 public void copyArea(int x, int y, int width, int height, int 152 dx, int dy) 153 { 154 throw new UnsupportedOperationException("not implemented"); 155 } 156 drawLine(int x1, int y1, int x2, int y2)157 public void drawLine(int x1, int y1, int x2, int y2) 158 { 159 context.drawLine(x1, y1, x2, y2); 160 } 161 drawRect(int x, int y, int width, int height)162 public void drawRect(int x, int y, int width, int height) 163 { 164 throw new UnsupportedOperationException("not implemented yet"); 165 } 166 fillRect(int x, int y, int width, int height)167 public void fillRect(int x, int y, int width, int height) 168 { 169 context.fillRectangle(x, y, width, height); 170 } 171 drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)172 public void drawArc(int x, int y, int width, int height, int 173 startAngle, int arcAngle) 174 { 175 context.drawArc (x, y, width, height, startAngle, arcAngle); 176 } 177 fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)178 public void fillArc(int x, int y, int width, int height, int 179 startAngle, int arcAngle) 180 { 181 context.fillArc (x, y, width, height, startAngle, arcAngle); 182 } 183 drawPolyline(int[] xPoints, int[] yPoints, int nPoints)184 public void drawPolyline(int[] xPoints, int[] yPoints, int 185 nPoints) 186 { 187 throw new UnsupportedOperationException("not implemented"); 188 } 189 drawPolygon(int[] xPoints, int[] yPoints, int nPoints)190 public void drawPolygon(int[] xPoints, int[] yPoints, int 191 nPoints) 192 { 193 throw new UnsupportedOperationException("not implemented"); 194 } 195 fillPolygon(int[] xPoints, int[] yPoints, int nPoints, int translateX, int translateY)196 public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints, 197 int translateX, int translateY) 198 { 199 context.fillPolygon(xPoints, yPoints, nPoints, translateX, translateY); 200 } 201 drawString(String str, int x, int y)202 public void drawString(String str, int x, int y) 203 { 204 context.drawString(str, x, y); 205 } 206 drawImage(Image img, int x, int y, ImageObserver observer)207 public boolean drawImage(Image img, int x, int y, 208 ImageObserver observer) 209 { 210 if (img instanceof XOffScreenImage) 211 { 212 // FIXME: have to enforce clip, or is it OK as-is? 213 XOffScreenImage offScreenImage = (XOffScreenImage) img; 214 Pixmap pixmap = offScreenImage.getPixmap (); 215 context.copyArea (pixmap, 0, 0, x, y, 216 offScreenImage.getWidth (), offScreenImage.getHeight ()); 217 return true; 218 } 219 if (clipBounds == null) 220 return false; // ***FIXME*** 221 222 if (!(img instanceof BufferedImage)) 223 { 224 throw new AWTError("unknown image class"); 225 } 226 227 BufferedImage bimg = (BufferedImage) img; 228 229 XImage ximg = (XImage) bimg.getProperty("gnu.gcj.xlib.XImage"); 230 if (ximg == null) 231 { 232 System.err.println("FIXME: skipping null XImage, should " + 233 "really do on the spot conversion"); 234 return false; 235 } 236 237 /* 238 +------------------ 239 | clip 240 | +---------+ 241 | img | | 242 | +--+-------+ | 243 | | | | | 244 | | | | | 245 | | +-------+-+ 246 | | | 247 | +----------+ 248 */ 249 250 int iLeft = Math.max(x, clipBounds.x); 251 int iTop = Math.max(y, clipBounds.y); 252 int iRight = Math.min(x + bimg.getWidth(), 253 clipBounds.x + clipBounds.width); 254 int iBottom = Math.min(y + bimg.getHeight(), 255 clipBounds.y + clipBounds.height); 256 257 int srcX = iLeft - x; 258 int srcY = iTop - y; 259 260 int width = iRight - iLeft; 261 int height = iBottom - iTop; 262 263 if ((width > 0) && (height > 0)) 264 context.putImage(ximg, srcX, srcY, iLeft, iTop, width, height); 265 266 return true; 267 } 268 mapRaster(Rectangle bounds)269 public MappedRaster mapRaster(Rectangle bounds) 270 { 271 Visual visual = config.getVisual(); 272 XImage ximage = new XImage(visual, bounds.width, bounds.height, 273 false // do not auto allocate memory 274 ); 275 276 WritableRaster raster = 277 config.createRasterForXImage(ximage, 278 new Point(bounds.x, bounds.y)); 279 280 DataBuffer dataB = raster.getDataBuffer(); 281 XGraphicsConfiguration.attachData(ximage, dataB, 0); 282 283 Drawable drawable = context.getDrawable(); 284 285 // TODO: restrict to clipping 286 287 Rectangle mBounds = drawable.copyIntoXImage(ximage, bounds, 0, 0); 288 289 return new XRaster(raster, ximage, config.imageCM); 290 } 291 292 unmapRaster(MappedRaster mappedRaster)293 public void unmapRaster(MappedRaster mappedRaster) 294 { 295 XRaster xraster = (XRaster) mappedRaster; 296 XImage ximage = xraster.ximage; 297 Raster raster = xraster.getRaster(); 298 int x = raster.getMinX(); 299 int y = raster.getMinY(); 300 int width = raster.getWidth(); 301 int height = raster.getHeight(); 302 303 context.putImage(ximage, 0, 0, x, y, width, height); 304 } 305 } 306