| /* Copyright (C) 2000, 2003, 2004 Free Software Foundation |
| |
| This file is part of libgcj. |
| |
| This software is copyrighted work licensed under the terms of the |
| Libgcj License. Please consult the file "LIBGCJ_LICENSE" for |
| details. */ |
| |
| package gnu.awt.xlib; |
| |
| import java.awt.*; |
| import java.awt.image.WritableRaster; |
| import java.awt.image.Raster; |
| import java.awt.image.DataBuffer; |
| import java.awt.image.ColorModel; |
| import java.awt.image.ImageObserver; |
| import java.awt.image.BufferedImage; |
| import gnu.gcj.xlib.GC; |
| import gnu.gcj.xlib.XImage; |
| import gnu.gcj.xlib.Drawable; |
| import gnu.gcj.xlib.Window; |
| import gnu.gcj.xlib.Drawable; |
| import gnu.gcj.xlib.Pixmap; |
| import gnu.gcj.xlib.Visual; |
| import gnu.awt.j2d.DirectRasterGraphics; |
| import gnu.awt.j2d.MappedRaster; |
| |
| public class XGraphics implements Cloneable, DirectRasterGraphics |
| { |
| static class XRaster extends MappedRaster |
| { |
| XImage ximage; |
| |
| public XRaster(WritableRaster raster, XImage ximage, ColorModel cm) |
| { |
| super(raster, cm); |
| this.ximage = ximage; |
| } |
| } |
| |
| GC context; |
| XGraphicsConfiguration config; |
| Rectangle clipBounds; |
| |
| XFontMetrics metrics; |
| |
| |
| public Object clone() |
| { |
| try |
| { |
| XGraphics gfxCopy = (XGraphics) super.clone(); |
| gfxCopy.context = context.create(); |
| |
| return gfxCopy; |
| } |
| catch (CloneNotSupportedException ex) |
| { |
| // This should never happen. |
| throw new InternalError (); |
| } |
| } |
| |
| public void dispose() |
| { |
| GC lContext = context; |
| context = null; |
| config = null; |
| clipBounds = null; |
| metrics = null; |
| |
| if (lContext != null) |
| { |
| lContext.dispose(); |
| } |
| } |
| |
| public XGraphics(Drawable drawable, XGraphicsConfiguration config) |
| { |
| context = GC.create(drawable); |
| this.config = config; |
| } |
| |
| public void setColor(Color color) |
| { |
| context.setForeground(config.getPixel(color)); |
| } |
| |
| public void setPaintMode() |
| { |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public void setXORMode(Color c1) |
| { |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public void setFont(Font font) |
| { |
| if (font == null) |
| return; |
| if ((metrics != null) && font.equals(metrics.getFont())) |
| return; |
| metrics = config.getXFontMetrics(font); |
| if (metrics != null) |
| context.setFont(metrics.xfont); |
| } |
| |
| public FontMetrics getFontMetrics(Font font) |
| { |
| if ((metrics != null) && font.equals(metrics.getFont())) |
| return metrics; |
| |
| return config.getXFontMetrics(font); |
| } |
| |
| public void setClip(int x, int y, int width, int height) |
| { |
| Rectangle[] rects = { new Rectangle(x, y, width, height) }; |
| context.setClipRectangles(rects); |
| } |
| |
| public void setClip(Shape clip) |
| { |
| /* TODO: create a special RectangleUnion shape that can be |
| used to draw advantage of the GCs ability to set multiple |
| rectangles. |
| */ |
| |
| /* FIXME: creating all these objects is wasteful and can be |
| costly in the long run, since this code is run at every |
| expose. */ |
| Rectangle newClipBounds = clip.getBounds(); |
| |
| /* FIXME: decide whether this test code is worth anything |
| * (as of 2004-01-29, it prints frequently) |
| if ((clipBounds != null) && !clipBounds.contains(newClipBounds)) |
| { |
| System.err.println("warning: old clip ("+ clipBounds +") does " + |
| "not fully contain new clip (" + |
| newClipBounds + ")"); |
| } |
| */ |
| clipBounds = newClipBounds; |
| Rectangle[] rects = { clipBounds }; |
| context.setClipRectangles(rects); |
| } |
| |
| public void copyArea(int x, int y, int width, int height, int |
| dx, int dy) |
| { |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public void drawLine(int x1, int y1, int x2, int y2) |
| { |
| context.drawLine(x1, y1, x2, y2); |
| } |
| |
| public void drawRect(int x, int y, int width, int height) |
| { |
| throw new UnsupportedOperationException("not implemented yet"); |
| } |
| |
| public void fillRect(int x, int y, int width, int height) |
| { |
| context.fillRectangle(x, y, width, height); |
| } |
| |
| public void drawArc(int x, int y, int width, int height, int |
| startAngle, int arcAngle) |
| { |
| context.drawArc (x, y, width, height, startAngle, arcAngle); |
| } |
| |
| public void fillArc(int x, int y, int width, int height, int |
| startAngle, int arcAngle) |
| { |
| context.fillArc (x, y, width, height, startAngle, arcAngle); |
| } |
| |
| public void drawPolyline(int[] xPoints, int[] yPoints, int |
| nPoints) |
| { |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public void drawPolygon(int[] xPoints, int[] yPoints, int |
| nPoints) |
| { |
| throw new UnsupportedOperationException("not implemented"); |
| } |
| |
| public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints, |
| int translateX, int translateY) |
| { |
| context.fillPolygon(xPoints, yPoints, nPoints, translateX, translateY); |
| } |
| |
| public void drawString(String str, int x, int y) |
| { |
| context.drawString(str, x, y); |
| } |
| |
| public boolean drawImage(Image img, int x, int y, |
| ImageObserver observer) |
| { |
| if (img instanceof XOffScreenImage) |
| { |
| // FIXME: have to enforce clip, or is it OK as-is? |
| XOffScreenImage offScreenImage = (XOffScreenImage) img; |
| Pixmap pixmap = offScreenImage.getPixmap (); |
| context.copyArea (pixmap, 0, 0, x, y, |
| offScreenImage.getWidth (), offScreenImage.getHeight ()); |
| return true; |
| } |
| if (clipBounds == null) |
| return false; // ***FIXME*** |
| |
| if (!(img instanceof BufferedImage)) |
| { |
| throw new AWTError("unknown image class"); |
| } |
| |
| BufferedImage bimg = (BufferedImage) img; |
| |
| XImage ximg = (XImage) bimg.getProperty("gnu.gcj.xlib.XImage"); |
| if (ximg == null) |
| { |
| System.err.println("FIXME: skipping null XImage, should " + |
| "really do on the spot conversion"); |
| return false; |
| } |
| |
| /* |
| +------------------ |
| | clip |
| | +---------+ |
| | img | | |
| | +--+-------+ | |
| | | | | | |
| | | | | | |
| | | +-------+-+ |
| | | | |
| | +----------+ |
| */ |
| |
| int iLeft = Math.max(x, clipBounds.x); |
| int iTop = Math.max(y, clipBounds.y); |
| int iRight = Math.min(x + bimg.getWidth(), |
| clipBounds.x + clipBounds.width); |
| int iBottom = Math.min(y + bimg.getHeight(), |
| clipBounds.y + clipBounds.height); |
| |
| int srcX = iLeft - x; |
| int srcY = iTop - y; |
| |
| int width = iRight - iLeft; |
| int height = iBottom - iTop; |
| |
| if ((width > 0) && (height > 0)) |
| context.putImage(ximg, srcX, srcY, iLeft, iTop, width, height); |
| |
| return true; |
| } |
| |
| public MappedRaster mapRaster(Rectangle bounds) |
| { |
| Visual visual = config.getVisual(); |
| XImage ximage = new XImage(visual, bounds.width, bounds.height, |
| false // do not auto allocate memory |
| ); |
| |
| WritableRaster raster = |
| config.createRasterForXImage(ximage, |
| new Point(bounds.x, bounds.y)); |
| |
| DataBuffer dataB = raster.getDataBuffer(); |
| XGraphicsConfiguration.attachData(ximage, dataB, 0); |
| |
| Drawable drawable = context.getDrawable(); |
| |
| // TODO: restrict to clipping |
| |
| Rectangle mBounds = drawable.copyIntoXImage(ximage, bounds, 0, 0); |
| |
| return new XRaster(raster, ximage, config.imageCM); |
| } |
| |
| |
| public void unmapRaster(MappedRaster mappedRaster) |
| { |
| XRaster xraster = (XRaster) mappedRaster; |
| XImage ximage = xraster.ximage; |
| Raster raster = xraster.getRaster(); |
| int x = raster.getMinX(); |
| int y = raster.getMinY(); |
| int width = raster.getWidth(); |
| int height = raster.getHeight(); |
| |
| context.putImage(ximage, 0, 0, x, y, width, height); |
| } |
| } |