Source for gnu.awt.xlib.XGraphics

   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:     
  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: 
  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: 
  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: 
  78:   public XGraphics(Drawable drawable, XGraphicsConfiguration config)
  79:   {
  80:     context = GC.create(drawable);
  81:     this.config = config;
  82:   }  
  83:   
  84:   public void setColor(Color color)
  85:   {
  86:     if (color != null)
  87:       context.setForeground(config.getPixel(color));
  88:   }
  89: 
  90:   public void setPaintMode()
  91:   {
  92:     throw new UnsupportedOperationException("not implemented");
  93:   }
  94: 
  95:   public void setXORMode(Color c1)
  96:   {
  97:     throw new UnsupportedOperationException("not implemented");
  98:   }
  99:     
 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:     
 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:     
 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:     
 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:     
 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:     
 157:   public void drawLine(int x1, int y1, int x2, int y2)
 158:   {
 159:     context.drawLine(x1, y1, x2, y2);
 160:   }
 161:     
 162:   public void drawRect(int x, int y, int width, int height)
 163:   {
 164:     throw new UnsupportedOperationException("not implemented yet");
 165:   }
 166:     
 167:   public void fillRect(int x, int y, int width, int height)
 168:   {
 169:     context.fillRectangle(x, y, width, height);
 170:   }
 171:     
 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:     
 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:     
 184:   public void drawPolyline(int[] xPoints, int[] yPoints, int
 185:                nPoints)
 186:   {
 187:     throw new UnsupportedOperationException("not implemented");
 188:   }
 189:     
 190:   public void drawPolygon(int[] xPoints, int[] yPoints, int
 191:               nPoints)
 192:   {
 193:     throw new UnsupportedOperationException("not implemented");
 194:   }
 195:     
 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: 
 202:   public void drawString(String str, int x, int y)
 203:   {
 204:     context.drawString(str, x, y);
 205:   }
 206: 
 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: 
 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:     
 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: }