Source for gnu.java.awt.peer.x.XGraphics2D

   1: /* XGraphics2D.java -- A Java based Graphics2D impl for X
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.java.awt.peer.x;
  39: 
  40: import java.awt.Color;
  41: import java.awt.Graphics;
  42: import java.awt.GraphicsConfiguration;
  43: import java.awt.Image;
  44: import java.awt.Paint;
  45: import java.awt.Rectangle;
  46: import java.awt.Shape;
  47: import java.awt.Toolkit;
  48: import java.awt.geom.AffineTransform;
  49: import java.awt.image.ColorModel;
  50: import java.awt.image.ImageObserver;
  51: import java.awt.image.Raster;
  52: import java.util.HashMap;
  53: 
  54: import gnu.java.awt.java2d.AbstractGraphics2D;
  55: import gnu.java.awt.java2d.ScanlineCoverage;
  56: import gnu.x11.Colormap;
  57: import gnu.x11.Drawable;
  58: import gnu.x11.GC;
  59: import gnu.x11.image.ZPixmap;
  60: 
  61: public class XGraphics2D
  62:   extends AbstractGraphics2D
  63: {
  64: 
  65:   /**
  66:    * The X Drawable to draw on.
  67:    */
  68:   private Drawable xdrawable;
  69: 
  70:   /**
  71:    * The X graphics context (GC).
  72:    */
  73:   private GC xgc;
  74: 
  75:   /**
  76:    * Indicates if this graphics has already been disposed.
  77:    */
  78:   private boolean disposed;
  79: 
  80:   /**
  81:    * The current foreground color, possibly null.
  82:    */
  83:   private Color foreground;
  84: 
  85:   XGraphics2D(Drawable d)
  86:   {
  87:     super();
  88:     xdrawable = d;
  89:     xgc = new GC(d);
  90:     init();
  91:     disposed = false;
  92:     //setClip(new Rectangle(0, 0, xdrawable.width, xdrawable.height));
  93:   }
  94: 
  95:   protected void rawDrawLine(int x0, int y0, int x1, int y1)
  96:   {
  97:     xdrawable.segment(xgc, x0, y0, x1, y1);
  98:   }
  99: 
 100:   protected void rawFillRect(int x, int y, int w, int h)
 101:   {
 102:     xdrawable.rectangle(xgc, x, y, w, h, true);
 103:   }
 104: 
 105:   /**
 106:    * Returns the color model of this Graphics object.
 107:    *
 108:    * @return the color model of this Graphics object
 109:    */
 110:   protected ColorModel getColorModel()
 111:   {
 112:     return Toolkit.getDefaultToolkit().getColorModel();
 113:   }
 114: 
 115:   /**
 116:    * Returns the color model of the target device.
 117:    *
 118:    * @return the color model of the target device
 119:    */
 120:   protected ColorModel getDestinationColorModel()
 121:   {
 122:     return Toolkit.getDefaultToolkit().getColorModel();
 123:   }
 124: 
 125:   /**
 126:    * Returns the bounds of the target.
 127:    *
 128:    * @return the bounds of the target
 129:    */
 130:   protected Rectangle getDeviceBounds()
 131:   {
 132:     return new Rectangle(0, 0, xdrawable.width, xdrawable.height);
 133:   }
 134: 
 135:   public GraphicsConfiguration getDeviceConfiguration()
 136:   {
 137:     // FIXME: Implement this.
 138:     throw new UnsupportedOperationException("Not yet implemented");
 139:   }
 140: 
 141:   public void dispose()
 142:   {
 143:     if (!disposed)
 144:       {
 145:         xgc.free();
 146:         xdrawable.display.flush();
 147:         disposed = true;
 148:       }
 149:   }
 150: 
 151:   public Graphics create()
 152:   {
 153:     // super.create() returns a copy created by clone(), so it should
 154:     // be a XGraphics2D.
 155:     XGraphics2D copy = (XGraphics2D) super.create();
 156:     copy.xgc = xgc.copy();
 157:     return copy;
 158:   }
 159: 
 160:   public void setClip(Shape c)
 161:   {
 162:     super.setClip(c);
 163:     if (c instanceof Rectangle)
 164:       {
 165:         Rectangle r = (Rectangle) c;
 166:         AffineTransform t = getTransform();
 167:         int translateX = (int) t.getTranslateX();
 168:         //System.err.println("translateX: " + translateX);
 169:         int translateY = (int) t.getTranslateY();
 170:         //System.err.println("translateY: " + translateY);
 171:         //System.err.println("clip: " + c);
 172:         gnu.x11.Rectangle clip = new gnu.x11.Rectangle(r.x, r.y, r.width,
 173:                                                        r.height);
 174:         xgc.set_clip_rectangles(translateX, translateY,
 175:                                 new gnu.x11.Rectangle[]{clip}, GC.UN_SORTED);
 176:       }
 177:   }
 178: 
 179:   /**
 180:    * Notifies the backend that the raster has changed in the specified
 181:    * rectangular area. The raster that is provided in this method is always
 182:    * the same as the one returned in {@link #getDestinationRaster}.
 183:    * Backends that reflect changes to this raster directly don't need to do
 184:    * anything here.
 185:    *
 186:    * @param raster the updated raster, identical to the raster returned
 187:    *        by {@link #getDestinationRaster()}
 188:    * @param x the upper left corner of the updated region, X coordinate
 189:    * @param y the upper lef corner of the updated region, Y coordinate
 190:    * @param w the width of the updated region
 191:    * @param h the height of the updated region
 192:    */
 193:   protected void updateRaster(Raster raster, int x, int y, int w, int h)
 194:   {
 195:     if (w > 0 && h > 0)
 196:       {
 197:         ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
 198:                                       xdrawable.display.default_pixmap_format);
 199:         int[] pixel = null;
 200:         int x1 = x + w;
 201:         int y1 = y + h;
 202:         for (int tx = x; tx < x1; tx++)
 203:           {
 204:             for (int ty = y; ty < y1; ty++)
 205:               {
 206:                 pixel = raster.getPixel(tx, ty, pixel);
 207:                 //System.err.println("tx: " + tx + ", ty: " + ty + ", pixel: " + pixel[0] + ", " + pixel[1] + ", " + pixel[2]);
 208: //              System.err.print("r: " + pixel[0]);
 209: //              System.err.print(", g: " + pixel[1]);
 210: //              System.err.println(", b: " + pixel[2]);
 211:                 zPixmap.set_red(tx - x, ty - y, pixel[0]);
 212:                 zPixmap.set_green(tx - x, ty - y, pixel[1]);
 213:                 zPixmap.set_blue(tx - x, ty - y, pixel[2]);
 214:               }
 215:           }
 216:         xdrawable.put_image(xgc, zPixmap, x, y);
 217:       }
 218:   }
 219: 
 220:   public void renderScanline(int y, ScanlineCoverage c)
 221:   {
 222:     ScanlineCoverage.Iterator iter = c.iterate();
 223:     float coverageAlpha = 0;
 224:     int maxCoverage = c.getMaxCoverage();
 225:     Color old = getColor();
 226:     Color col = getColor();
 227:     if (col == null)
 228:       col = Color.BLACK;
 229:     while (iter.hasNext())
 230:       {
 231:         ScanlineCoverage.Range range = iter.next();
 232:         // TODO: Dumb implementation for testing.
 233:         coverageAlpha = range.getCoverage();
 234:         if (coverageAlpha > 0)
 235:           {
 236:             int red = col.getRed();
 237:             int green = col.getGreen();
 238:             int blue = col.getBlue();
 239:             if (coverageAlpha < c.getMaxCoverage())
 240:               {
 241:                 float alpha = coverageAlpha / maxCoverage;
 242:                 red = 255 - (int) ((255 - red) * alpha);
 243:                 green = 255 - (int) ((255 - green) * alpha);
 244:                 blue = 255 - (int) ((255 - blue) * alpha);
 245:               }
 246:             xgc.set_foreground(red << 16 | green << 8 | blue);
 247:             int x0 = range.getXPos();
 248:             int l = range.getLength();
 249:             xdrawable.fill_rectangle(xgc, x0, y, l, 1);
 250:           }
 251:       }
 252:     if (old != null)
 253:       xgc.set_foreground(old.getRGB());
 254:   }
 255: 
 256:   protected void fillScanline(int x0, int x1, int y)
 257:   {
 258:     xdrawable.segment(xgc, x0, y, x1, y);
 259:   }
 260: 
 261:   protected void fillScanlineAA(int x0, int x1, int y, int alpha)
 262:   {
 263:     //System.err.println("fillScanlineAA: " + x0 + ", " + x1 + ", " + y + ", " + alpha);
 264:     // FIXME: This is for testing only.
 265:     Color c = getColor();
 266:     setColor(new Color(255-alpha, 255-alpha, 255-alpha));
 267:     xdrawable.segment(xgc, x0, y, x1, y);
 268:     setColor(c);
 269:   }
 270: 
 271:   protected void init()
 272:   {
 273:     super.init();
 274:   }
 275: 
 276:   public void setPaint(Paint p)
 277:   {
 278:     super.setPaint(p);
 279:     if (p instanceof Color)
 280:       {
 281:         Color c = (Color) p;
 282:         XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
 283:         HashMap colorMap = tk.colorMap;
 284:         gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c);
 285:         if (col == null)
 286:           {
 287:             Colormap map = xdrawable.display.default_colormap;
 288:             col = map.alloc_color (c.getRed() * 256,
 289:                                    c.getGreen() * 256,
 290:                                    c.getBlue() * 256);
 291:             colorMap.put(c, col);
 292:           }
 293:         xgc.set_foreground(col);
 294:         foreground = c;
 295:       }
 296:   }
 297: 
 298:   protected void fillShape(Shape s, boolean isFont)
 299:   {
 300:     synchronized (xdrawable.display) {
 301:       super.fillShape(s, isFont);
 302:     }
 303:   }
 304: 
 305:   protected boolean rawDrawImage(Image image, int x, int y, ImageObserver obs)
 306:   {
 307:     boolean ret;
 308:     if (image instanceof XImage)
 309:       {
 310:         XImage xImage = (XImage) image;
 311:         xdrawable.copy_area(xImage.pixmap, xgc, 0, 0, xImage.getWidth(obs),
 312:                             xImage.getHeight(obs), x, y);
 313:         ret = true;
 314:       }
 315:     else if (image instanceof PixmapVolatileImage)
 316:       {
 317:         PixmapVolatileImage pvi = (PixmapVolatileImage) image;
 318:         xdrawable.copy_area(pvi.getPixmap(), xgc, 0, 0, pvi.getWidth(obs),
 319:                             pvi.getHeight(obs), x, y);
 320:         ret = true;
 321:       }
 322:     else
 323:       {
 324:         ret = super.rawDrawImage(image, x, y, obs);
 325:       }
 326:     return ret;
 327:   }
 328: 
 329: 
 330: }