Source for gnu.awt.j2d.IntegerGraphicsState

   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:      */
  57:     GraphicsConfiguration getGraphicsConfiguration ();
  58:   }
  59:   
  60:   public IntegerGraphicsState(DirectRasterGraphics directGfx)
  61:   {
  62:     this.directGfx = directGfx;
  63:   }
  64:   
  65:   public Object clone()
  66:   {
  67:     IntegerGraphicsState clone = (IntegerGraphicsState) super.clone();
  68:     clone.directGfx = (DirectRasterGraphics) directGfx.clone();
  69:     
  70:     return clone;
  71:   }
  72: 
  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:   
  87:   public void setColor(Color color)
  88:   {
  89:     directGfx.setColor(color);
  90:   }
  91:   
  92:   public void setPaintMode()
  93:   {
  94:     directGfx.setPaintMode();
  95:   }
  96: 
  97:   public void setXORMode(Color altColor)
  98:   {
  99:     directGfx.setXORMode(altColor);
 100:   }
 101:   
 102:   public void setFont(Font font)
 103:   {
 104:     directGfx.setFont(font);
 105:   }
 106:   
 107:   public FontMetrics getFontMetrics(Font font)
 108:   {
 109:     return directGfx.getFontMetrics(font);
 110:   }
 111: 
 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: 
 133:   public Shape getClip()
 134:   {
 135:     if (clip == null)
 136:       return null;
 137:     if (clip instanceof Rectangle)
 138:       {
 139:     Rectangle clipRect = (Rectangle) ((Rectangle) clip).clone();
 140:     clipRect.x -= tx;
 141:     clipRect.y -= ty;
 142:     return clipRect;
 143:       }
 144: 
 145:     String msg =
 146:       "translating clip shape " + clip + " into user " +
 147:       "coordinate space has not been implemented yet";
 148:     
 149:     throw new UnsupportedOperationException(msg);
 150:   }
 151: 
 152:   public Rectangle getClipBounds()
 153:   {
 154:     if (clip == null)
 155:       return null;
 156:     Rectangle clipRect = clip.getBounds();
 157:     
 158:     clipRect.x -= tx;
 159:     clipRect.y -= ty;
 160:     return clipRect;
 161:   }
 162: 
 163:   public void copyArea(int x, int y, 
 164:                int width, int height,
 165:                int dx, int dy)
 166:   {
 167:     directGfx.copyArea(x+tx, y+ty, width, height, dx, dy);
 168:   }
 169: 
 170:   public void drawLine(int x1, int y1,
 171:                int x2, int y2)
 172:   {
 173:     directGfx.drawLine(x1+tx, y1+ty, x2+tx, y2+ty);
 174:   }
 175:     
 176:   public void fillRect(int x, int y,
 177:                int width, int height)
 178:   {
 179:     directGfx.fillRect(x+tx, y+ty, width, height);
 180:   }
 181:     
 182:   public void clearRect(int x, int y,
 183:             int width, int height)
 184:   {
 185:     directGfx.setColor(frontend.getBackground());
 186:     directGfx.fillRect(x+tx, y+ty, width, height);
 187:     directGfx.setColor(frontend.getColor());
 188:   }
 189: 
 190:   public void drawRoundRect(int x, int y,
 191:                 int width, int height,
 192:                 int arcWidth, int arcHeight)
 193:   {
 194:     throw new UnsupportedOperationException("not implemented yet");
 195:   }
 196:   
 197:   public void fillRoundRect(int x, int y,
 198:                 int width, int height,
 199:                 int arcWidth, int arcHeight)
 200:   {
 201:     throw new UnsupportedOperationException("not implemented yet");
 202:   }
 203: 
 204:   public void drawOval(int x, int y,
 205:                int width, int height)
 206:   {
 207:     drawArc (x, y, width, height, 0, 360);
 208:   }
 209:   
 210:   public void fillOval(int x, int y,
 211:                int width, int height)
 212:   {
 213:     fillArc (x, y, width, height, 0, 360);
 214:   }
 215: 
 216:   public void drawArc(int x, int y,
 217:               int width, int height,
 218:               int startAngle, int arcAngle)
 219:   {
 220:     directGfx.drawArc(x+tx, y+ty, width, height, startAngle, arcAngle);
 221:   }    
 222: 
 223:   public void fillArc(int x, int y,
 224:               int width, int height,
 225:               int startAngle, int arcAngle)
 226:   {
 227:     directGfx.fillArc(x+tx, y+ty, width, height, startAngle, arcAngle);
 228:   }
 229:   
 230:   public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
 231:   {
 232:     if ((tx == 0) && (ty == 0))
 233:       {
 234:     directGfx.drawPolyline(xPoints, yPoints, nPoints);
 235:     return;
 236:       }
 237:         
 238:     throw new UnsupportedOperationException("translate not implemented");
 239:   }
 240: 
 241:   public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
 242:   {
 243:     if ((tx == 0) && (ty == 0))
 244:       {
 245:     directGfx.drawPolygon(xPoints, yPoints, nPoints);
 246:     return;
 247:       }
 248: 
 249:     throw new UnsupportedOperationException("translate not implemented");
 250:   }
 251:   
 252:   public void fillPolygon (int[] xPoints, int[] yPoints, int nPoints)
 253:   {
 254:     // FIXME: remove tx & ty args once translation via AffineTransform
 255:     // is implemented.
 256:     directGfx.fillPolygon (xPoints, yPoints, nPoints, tx, ty);
 257:   }
 258: 
 259:   public boolean drawImage(Image image, int x, int y,
 260:                ImageObserver observer)
 261:   {
 262:     x += tx;
 263:     y += ty;
 264:     
 265:     if (image instanceof ScreenCoupledImage)
 266:     {
 267:       GraphicsConfiguration config
 268:         = ((ScreenCoupledImage)image).getGraphicsConfiguration ();
 269:       if (config == frontend.config)
 270:         return directGfx.drawImage (image, x, y, observer);
 271:     }
 272:     if (image instanceof BufferedImage)
 273:     {
 274:       BufferedImage bImage = (BufferedImage) image;
 275:       // FIXME: eliminate? ScreenCoupledImage is probably more efficient
 276:       Object config = bImage.getProperty ("java.awt.GraphicsConfiguration");
 277:       if (config == frontend.config)
 278:         return directGfx.drawImage (image, x, y, observer);
 279:       
 280:       int width = image.getWidth (null);
 281:       int height = image.getHeight (null);
 282:       
 283:       Rectangle bounds = new Rectangle (x, y, width, height);
 284:       
 285:       MappedRaster mr = directGfx.mapRaster (bounds);
 286:       
 287:       // manipulate raster here...
 288:       ColorModel colorModel = mr.getColorModel ();
 289:       WritableRaster raster = mr.getRaster ();
 290:       
 291:       int xEnd = x + width;
 292:       int yEnd = y + height;
 293:       
 294:       // FIXME: Use the following code only as a fallback. It's SLOW!
 295:       
 296:       Object rgbElem = null;
 297:       for (int yy=0; yy<height; yy++)
 298:       {
 299:         for (int xx=0; xx<width; xx++)
 300:         {
 301:           int srgb = bImage.getRGB (xx, yy);
 302:           int sa = ((srgb >>> 24) & 0xff) + 1;
 303:           int sr = ((srgb >>> 16) & 0xff) + 1;
 304:           int sg = ((srgb >>> 8) & 0xff) + 1;
 305:           int sb = (srgb & 0xff) + 1;
 306:           
 307:           rgbElem = raster.getDataElements (xx+x, yy+y, rgbElem);
 308:           int drgb = colorModel.getRGB (rgbElem);
 309:           int dr = ((drgb >>> 16) & 0xff) + 1;
 310:           int dg = ((drgb >>> 8) & 0xff) + 1;
 311:           int db = (drgb & 0xff) + 1;
 312:           int da = 256 - sa;
 313:           
 314:           dr = ((sr*sa + dr*da) >>> 8) - 1;
 315:           dg = ((sg*sa + dg*da) >>> 8) - 1;
 316:           db = ((sb*sa + db*da) >>> 8) - 1;
 317:           
 318:           drgb = (dr<<16) | (dg<<8) | db;
 319:           
 320:           rgbElem = colorModel.getDataElements (drgb, rgbElem);
 321:           
 322:           raster.setDataElements (xx+x, yy+y, rgbElem);
 323:         }
 324:       }
 325:       directGfx.unmapRaster (mr);
 326:       return true;
 327:       
 328:     }
 329:     throw new UnsupportedOperationException ("drawing image " + image +
 330:     "not implemented");
 331:   }
 332:   
 333: 
 334:   // -------- Graphics2D methods:
 335:   
 336:   public void draw(Shape shape)
 337:   {
 338:     if (shape instanceof Rectangle)
 339:       {
 340:     Rectangle rect = (Rectangle) shape;
 341:     directGfx.drawRect(rect.x+tx, rect.y+ty, rect.width, rect.height);
 342:     return;
 343:       } 
 344:     
 345:     throw new UnsupportedOperationException("shape not implemented");
 346:   }
 347: 
 348:   public void fill(Shape shape)
 349:   {
 350:     if (shape instanceof Rectangle)
 351:       {
 352:     Rectangle rect = (Rectangle) shape;
 353:     directGfx.fillRect(rect.x+tx, rect.y+ty, rect.width, rect.height);
 354:     return;
 355:       }
 356:     
 357:     throw new UnsupportedOperationException("not implemented");
 358:   }
 359:     
 360:   public boolean hit(Rectangle rect, Shape text,
 361:              boolean onStroke)
 362:   {
 363:     throw new UnsupportedOperationException("not implemented");
 364:   }
 365: 
 366:   public void drawString(String text, int x, int y)
 367:   {
 368:     directGfx.drawString(text, x+tx, y+ty);
 369:   }
 370: 
 371:   public void drawString(String text, float x, float y)
 372:   {
 373:     drawString(text, (int) x, (int) y);
 374:   }
 375:   
 376:   public void translate(int x, int y)
 377:   {
 378:     tx += x;
 379:     ty += y;
 380:   }
 381:     
 382:   public void translate(double tx, double ty)
 383:   {
 384:     if ((tx == 0) && (ty == 0))
 385:       return;
 386:     
 387:     needAffineTransform();
 388:   }
 389: 
 390:   public void rotate(double theta)
 391:   {
 392:     if (theta == 0)
 393:       return;
 394:     
 395:     needAffineTransform();
 396:   }
 397: 
 398:   public void rotate(double theta, double x, double y)
 399:   {
 400:     if (theta == 0)
 401:       return;
 402:     
 403:     needAffineTransform();
 404:   }
 405: 
 406:   public void scale(double scaleX, double scaleY)
 407:   {
 408:     if ((scaleX == 1) && (scaleY == 1))
 409:       return;
 410: 
 411:     needAffineTransform();
 412:   }
 413:   
 414:   public void shear(double shearX, double shearY)
 415:   {
 416:     if ((shearX == 0) && (shearY == 0))
 417:       return;
 418:     
 419:     needAffineTransform();
 420:   }   
 421:   
 422:   private void needAffineTransform()
 423:   {
 424:     throw new UnsupportedOperationException("state with affine " +
 425:                         "transform not implemented");
 426:   }
 427: }