Source for gnu.java.awt.peer.gtk.GdkGraphics

   1: /* GdkGraphics.java
   2:    Copyright (C) 1998, 1999, 2002, 2005  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: 
  39: package gnu.java.awt.peer.gtk;
  40: 
  41: import gnu.classpath.Configuration;
  42: 
  43: import java.awt.Color;
  44: import java.awt.Dimension;
  45: import java.awt.Font;
  46: import java.awt.FontMetrics;
  47: import java.awt.Graphics;
  48: import java.awt.Image;
  49: import java.awt.Rectangle;
  50: import java.awt.Shape;
  51: import java.awt.image.ImageObserver;
  52: import java.text.AttributedCharacterIterator;
  53: 
  54: public class GdkGraphics extends Graphics
  55: {
  56:   static 
  57:   {
  58:     if (Configuration.INIT_LOAD_LIBRARY)
  59:       {
  60:         System.loadLibrary("gtkpeer");
  61:       }
  62:     initStaticState ();
  63:   }
  64:   
  65:   static native void initStaticState();
  66:   private final int native_state = GtkGenericPeer.getUniqueInteger ();
  67: 
  68:   Color color, xorColor;
  69:   GtkComponentPeer component;
  70:   Font font = new Font ("Dialog", Font.PLAIN, 12);
  71:   Rectangle clip;
  72:   GtkImage image; 
  73: 
  74:   int xOffset = 0;
  75:   int yOffset = 0;
  76: 
  77:   static final int GDK_COPY = 0, GDK_XOR = 2;
  78: 
  79:   native void initState (GtkComponentPeer component);
  80:   native void initStateUnlocked (GtkComponentPeer component);
  81:   native void initState (int width, int height);
  82:   native void initFromImage (GtkImage image);
  83:   native void nativeCopyState (GdkGraphics g);
  84: 
  85:   /**
  86:    * A cached instance that is used by {@link #create} in order to avoid
  87:    * massive allocation of graphics contexts.
  88:    */
  89:   GdkGraphics cached = null;
  90: 
  91:   /**
  92:    * A link to the parent context. This is used in {@link #dispose} to put
  93:    * this graphics context into the cache.
  94:    */
  95:   GdkGraphics parent = null;
  96: 
  97:   GdkGraphics (GdkGraphics g)
  98:   {
  99:     parent = g;
 100:     copyState (g);
 101:   }
 102: 
 103:   GdkGraphics (int width, int height)
 104:   {
 105:     initState (width, height);
 106:     color = Color.black;
 107:     clip = new Rectangle (0, 0, width, height);
 108:     font = new Font ("Dialog", Font.PLAIN, 12);
 109:   }
 110: 
 111:   GdkGraphics (GtkImage image)
 112:   {
 113:     this.image = image;
 114:     initFromImage (image);
 115:     color = Color.black;
 116:     clip = new Rectangle (0, 0, 
 117:               image.getWidth(null), image.getHeight(null));
 118:     font = new Font ("Dialog", Font.PLAIN, 12);
 119:   }
 120: 
 121:   GdkGraphics (GtkComponentPeer component)
 122:   {
 123:     this.component = component;
 124:     color = Color.black;
 125: 
 126:     if (component.isRealized ())
 127:       initComponentGraphics ();
 128:     else
 129:       connectSignals (component);
 130:   }
 131: 
 132:   void initComponentGraphics ()
 133:   {
 134:     initState (component);
 135:     color = component.awtComponent.getForeground ();
 136:     if (color == null)
 137:       color = Color.BLACK;
 138:     Dimension d = component.awtComponent.getSize ();
 139:     clip = new Rectangle (0, 0, d.width, d.height);
 140:   }
 141: 
 142:   // called back by native side: realize_cb
 143:   void initComponentGraphicsUnlocked ()
 144:   {
 145:     initStateUnlocked (component);
 146:     color = component.awtComponent.getForeground ();
 147:     if (color == null)
 148:       color = Color.BLACK;
 149:     Dimension d = component.awtComponent.getSize ();
 150:     clip = new Rectangle (0, 0, d.width, d.height);
 151:   }
 152: 
 153:   native void connectSignals (GtkComponentPeer component);
 154: 
 155:   public native void clearRect(int x, int y, int width, int height);
 156: 
 157:   public void clipRect (int x, int y, int width, int height)
 158:   {
 159:     if (component != null && ! component.isRealized ())
 160:       return;
 161: 
 162:     clip = clip.intersection (new Rectangle (x, y, width, height));
 163:     setClipRectangle (clip.x, clip.y, clip.width, clip.height);
 164:   }
 165: 
 166:   public native void copyArea(int x, int y, int width, int height, 
 167:                   int dx, int dy);
 168: 
 169:   /**
 170:    * Creates a copy of this GdkGraphics instance. This implementation can
 171:    * reuse a cached instance to avoid massive instantiation of Graphics objects
 172:    * during painting.
 173:    *
 174:    * @return a copy of this graphics context
 175:    */
 176:   public Graphics create()
 177:   {
 178:     GdkGraphics copy = cached;
 179:     if (copy == null)
 180:       copy = new GdkGraphics(this);
 181:     else
 182:       {
 183:         copy.copyState(this);
 184:         cached = null;
 185:       }
 186:     return copy;
 187:   }
 188: 
 189:   public native void nativeDispose();
 190: 
 191:   /**
 192:    * Disposes this graphics object. This puts this graphics context into the
 193:    * cache of its parent graphics if there is one.
 194:    */
 195:   public void dispose()
 196:   {
 197:     if (parent != null)
 198:       {
 199:         parent.cached = this;
 200:         parent = null;
 201:       }
 202:     else
 203:       nativeDispose();
 204:   }
 205: 
 206:   /**
 207:    * This is called when this object gets finalized by the garbage collector.
 208:    * In addition to {@link Graphics#finalize()} this calls nativeDispose() to
 209:    * make sure the native resources are freed before the graphics context is
 210:    * thrown away.
 211:    */
 212:   public void finalize()
 213:   {
 214:     super.finalize();
 215:     nativeDispose();
 216:   }
 217: 
 218:   public boolean drawImage (Image img, int x, int y, 
 219:                 Color bgcolor, ImageObserver observer)
 220:   {
 221:     return drawImage(img, x, y, img.getWidth(null), img.getHeight(null),
 222:              bgcolor, observer);
 223:   }
 224: 
 225:   public boolean drawImage (Image img, int x, int y, ImageObserver observer)
 226:   {
 227:     return drawImage (img, x, y, null, observer);
 228:   }
 229: 
 230:   public boolean drawImage (Image img, int x, int y, int width, int height, 
 231:                 Color bgcolor, ImageObserver observer)
 232:   {
 233:     if (img instanceof GtkImage)
 234:       return ((GtkImage)img).drawImage (this, x, y, width, height, 
 235:                     bgcolor, observer);
 236:     else
 237:       return (new GtkImage(img.getSource())).drawImage (this, x, y, 
 238:                             width, height, 
 239:                             bgcolor, observer);
 240:   }
 241: 
 242:   public boolean drawImage (Image img, int x, int y, int width, int height, 
 243:                 ImageObserver observer)
 244:   {
 245:     return drawImage (img, x, y, width, height,  null, observer);
 246:   }
 247: 
 248:   public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, 
 249:                 int sx1, int sy1, int sx2, int sy2, 
 250:                 Color bgcolor, ImageObserver observer)
 251:   {
 252:     if (img instanceof GtkImage)
 253:       return ((GtkImage)img).drawImage(this, dx1, dy1, dx2, dy2, 
 254:                        sx1, sy1, sx2, sy2, bgcolor, observer);
 255:     else
 256:       return (new GtkImage(img.getSource())).drawImage(this, dx1, dy1, 
 257:                                dx2, dy2, 
 258:                                sx1, sy1, sx2, sy2, 
 259:                                bgcolor, observer);
 260:   }
 261: 
 262:   public boolean drawImage (Image img, int dx1, int dy1, int dx2, int dy2, 
 263:                 int sx1, int sy1, int sx2, int sy2, 
 264:                 ImageObserver observer) 
 265:   {
 266:     return drawImage (img, dx1, dy1, dx2, dy2, 
 267:               sx1, sy1, sx2, sy2, 
 268:               null, observer);
 269:   }
 270: 
 271:   public native void drawLine(int x1, int y1, int x2, int y2);
 272: 
 273:   public native void drawArc(int x, int y, int width, int height,
 274:                  int startAngle, int arcAngle);
 275:   public native void fillArc(int x, int y, int width, int height, 
 276:                  int startAngle, int arcAngle);
 277:   public native void drawOval(int x, int y, int width, int height);
 278:   public native void fillOval(int x, int y, int width, int height);
 279: 
 280:   public native void drawPolygon(int[] xPoints, int[] yPoints, int nPoints);
 281:   public native void fillPolygon(int[] xPoints, int[] yPoints, int nPoints);
 282: 
 283:   public native void drawPolyline(int[] xPoints, int[] yPoints, int nPoints);
 284: 
 285:   public native void drawRect(int x, int y, int width, int height);
 286:   public native void fillRect(int x, int y, int width, int height);
 287: 
 288:   GdkFontPeer getFontPeer() 
 289:   {
 290:     return (GdkFontPeer) getFont().getPeer(); 
 291:   }
 292: 
 293:   native void drawString (GdkFontPeer f, String str, int x, int y);
 294:   public void drawString (String str, int x, int y)
 295:   {
 296:     drawString(getFontPeer(), str, x, y);
 297:   }  
 298:   
 299:   public void drawString (AttributedCharacterIterator ci, int x, int y)
 300:   {
 301:     throw new Error ("not implemented");
 302:   }
 303: 
 304:   public void drawRoundRect(int x, int y, int width, int height, 
 305:                 int arcWidth, int arcHeight)
 306:   {
 307:     if (arcWidth > width)
 308:       arcWidth = width;
 309:     if (arcHeight > height)
 310:       arcHeight = height;
 311: 
 312:     int xx = x + width - arcWidth;
 313:     int yy = y + height - arcHeight;
 314: 
 315:     drawArc (x, y, arcWidth, arcHeight, 90, 90);
 316:     drawArc (xx, y, arcWidth, arcHeight, 0, 90);
 317:     drawArc (xx, yy, arcWidth, arcHeight, 270, 90);
 318:     drawArc (x, yy, arcWidth, arcHeight, 180, 90);
 319: 
 320:     int y1 = y + arcHeight / 2;
 321:     int y2 = y + height - arcHeight / 2;
 322:     drawLine (x, y1, x, y2);
 323:     drawLine (x + width, y1, x + width, y2);
 324: 
 325:     int x1 = x + arcWidth / 2;
 326:     int x2 = x + width - arcWidth / 2;
 327:     drawLine (x1, y, x2, y);
 328:     drawLine (x1, y + height, x2, y + height);
 329:   }
 330: 
 331:   public void fillRoundRect (int x, int y, int width, int height, 
 332:                  int arcWidth, int arcHeight)
 333:   {
 334:     if (arcWidth > width)
 335:       arcWidth = width;
 336:     if (arcHeight > height)
 337:       arcHeight = height;
 338: 
 339:     int xx = x + width - arcWidth;
 340:     int yy = y + height - arcHeight;
 341: 
 342:     fillArc (x, y, arcWidth, arcHeight, 90, 90);
 343:     fillArc (xx, y, arcWidth, arcHeight, 0, 90);
 344:     fillArc (xx, yy, arcWidth, arcHeight, 270, 90);
 345:     fillArc (x, yy, arcWidth, arcHeight, 180, 90);
 346: 
 347:     fillRect (x, y + arcHeight / 2, width, height - arcHeight + 1);
 348:     fillRect (x + arcWidth / 2, y, width - arcWidth + 1, height);
 349:   }
 350: 
 351:   public Shape getClip ()
 352:   {
 353:     return getClipBounds ();
 354:   }
 355: 
 356:   public Rectangle getClipBounds ()
 357:   {
 358:     if (clip == null)
 359:       return null;
 360:     else
 361:       return clip.getBounds();
 362:   }
 363: 
 364:   public Color getColor ()
 365:   {
 366:     return color;
 367:   }
 368: 
 369:   public Font getFont ()
 370:   {
 371:     return font;
 372:   }
 373: 
 374:   public FontMetrics getFontMetrics (Font font)
 375:   {
 376:     return new GdkFontMetrics (font);
 377:   }
 378: 
 379:   native void setClipRectangle (int x, int y, int width, int height);
 380: 
 381:   public void setClip (int x, int y, int width, int height)
 382:   {
 383:     if ((component != null && ! component.isRealized ())
 384:         || clip == null)
 385:       return;
 386: 
 387:     clip.x = x;
 388:     clip.y = y;
 389:     clip.width = width;
 390:     clip.height = height;
 391:     
 392:     setClipRectangle (x, y, width, height);
 393:   }
 394: 
 395:   public void setClip (Rectangle clip)
 396:   {
 397:     setClip (clip.x, clip.y, clip.width, clip.height);
 398:   }
 399: 
 400:   public void setClip (Shape clip)
 401:   {
 402:     if (clip == null)
 403:       {
 404:     // Reset clipping.
 405:     Dimension d = component.awtComponent.getSize();
 406:     setClip(new Rectangle (0, 0, d.width, d.height));
 407:       }
 408:     else
 409:       setClip(clip.getBounds());
 410:   }
 411: 
 412:   private native void setFGColor(int red, int green, int blue);
 413: 
 414:   public void setColor (Color c)
 415:   {
 416:     if (c == null)
 417:       color = Color.BLACK;
 418:     else
 419:       color = c;
 420: 
 421:     if (xorColor == null) /* paint mode */
 422:       setFGColor (color.getRed (), color.getGreen (), color.getBlue ());
 423:     else          /* xor mode */
 424:       setFGColor (color.getRed   () ^ xorColor.getRed (),
 425:           color.getGreen () ^ xorColor.getGreen (),
 426:           color.getBlue  () ^ xorColor.getBlue ());
 427:   }
 428:   
 429:   public void setFont (Font font)
 430:   {
 431:     if (font != null)
 432:       this.font = font;
 433:   }
 434: 
 435:   native void setFunction (int gdk_func);
 436: 
 437:   public void setPaintMode ()
 438:   {
 439:     xorColor = null;
 440: 
 441:     setFunction (GDK_COPY);
 442:     setFGColor (color.getRed (), color.getGreen (), color.getBlue ());
 443:   }
 444: 
 445:   public void setXORMode (Color c)
 446:   {
 447:     xorColor = c;
 448: 
 449:     setFunction (GDK_XOR);
 450:     setFGColor (color.getRed   () ^ xorColor.getRed (),
 451:         color.getGreen () ^ xorColor.getGreen (),
 452:         color.getBlue  () ^ xorColor.getBlue ());
 453:   }
 454: 
 455:   public native void translateNative(int x, int y);
 456: 
 457:   public void translate (int x, int y)
 458:   {
 459:     if (component != null && ! component.isRealized ())
 460:       return;
 461: 
 462:     clip.x -= x;
 463:     clip.y -= y;
 464: 
 465:     translateNative (x, y);
 466:   }
 467: 
 468:   /**
 469:    * Copies over the state of another GdkGraphics to this instance. This is
 470:    * used by the {@link #GdkGraphics(GdkGraphics)} constructor and the
 471:    * {@link #create()} method.
 472:    *
 473:    * @param g the GdkGraphics object to copy the state from
 474:    */
 475:   private void copyState(GdkGraphics g)
 476:   {
 477:     color = g.color;
 478:     xorColor = g.xorColor;
 479:     font = g.font;
 480:     if (font == null)
 481:       font = new Font ("Dialog", Font.PLAIN, 12);
 482:     clip = new Rectangle (g.clip);
 483:     component = g.component;
 484:     nativeCopyState(g);
 485:   }
 486: }