280 lines
6.8 KiB
Java
280 lines
6.8 KiB
Java
|
/* Copyright (C) 2000 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.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()
|
||
|
{
|
||
|
XGraphics gfxCopy = (XGraphics) super.clone();
|
||
|
gfxCopy.context = context.create();
|
||
|
|
||
|
return gfxCopy;
|
||
|
}
|
||
|
|
||
|
public void dispose()
|
||
|
{
|
||
|
GC lContext = context;
|
||
|
context = null;
|
||
|
config = null;
|
||
|
clipBounds = null;
|
||
|
|
||
|
if (lContext != null)
|
||
|
{
|
||
|
lContext.dispose();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public XGraphics(Drawable drawable, XGraphicsConfiguration config)
|
||
|
{
|
||
|
context = new GC(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 ((metrics != null) && font.equals(metrics.getFont())) return;
|
||
|
|
||
|
metrics = config.getXFontMetrics(font);
|
||
|
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();
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
throw new UnsupportedOperationException("not implemented");
|
||
|
}
|
||
|
|
||
|
public void fillArc(int x, int y, int width, int height, int
|
||
|
startAngle, int arcAngle)
|
||
|
{
|
||
|
throw new UnsupportedOperationException("not implemented");
|
||
|
}
|
||
|
|
||
|
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)
|
||
|
{
|
||
|
throw new UnsupportedOperationException("not implemented");
|
||
|
}
|
||
|
|
||
|
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 (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);
|
||
|
}
|
||
|
}
|