summaryrefslogtreecommitdiff
path: root/gnu/java/awt/peer/x/XGraphics.java
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/java/awt/peer/x/XGraphics.java')
-rw-r--r--gnu/java/awt/peer/x/XGraphics.java489
1 files changed, 213 insertions, 276 deletions
diff --git a/gnu/java/awt/peer/x/XGraphics.java b/gnu/java/awt/peer/x/XGraphics.java
index 81168797c..134d7d330 100644
--- a/gnu/java/awt/peer/x/XGraphics.java
+++ b/gnu/java/awt/peer/x/XGraphics.java
@@ -38,40 +38,33 @@ exception statement from your version. */
package gnu.java.awt.peer.x;
+import gnu.x11.Colormap;
+import gnu.x11.Data;
+import gnu.x11.Display;
import gnu.x11.Drawable;
import gnu.x11.GC;
import gnu.x11.Pixmap;
import gnu.x11.Point;
+import gnu.x11.image.ZPixmap;
import java.awt.AWTError;
import java.awt.Color;
-import java.awt.Composite;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.GraphicsConfiguration;
import java.awt.Image;
-import java.awt.Paint;
import java.awt.Rectangle;
-import java.awt.RenderingHints;
import java.awt.Shape;
-import java.awt.Stroke;
-import java.awt.RenderingHints.Key;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.geom.AffineTransform;
+import java.awt.Toolkit;
+import java.awt.Transparency;
import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
-import java.awt.image.RenderedImage;
-import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
-import java.util.Map;
+import java.util.HashMap;
public class XGraphics
- extends Graphics2D
+ extends Graphics
implements Cloneable
{
@@ -111,6 +104,11 @@ public class XGraphics
*/
private boolean disposed = false;
+ // TODO: Workaround for limitation in current Escher.
+ private Pixmap.Format pixmapFormat;
+ private int imageByteOrder;
+ private int pixelByteCount;
+
/**
* Creates a new XGraphics on the specified X Drawable.
*
@@ -123,6 +121,11 @@ public class XGraphics
translateX = 0;
translateY = 0;
clip = new Rectangle(0, 0, d.width, d.height);
+
+ Display display = xdrawable.display;
+ pixmapFormat = display.default_pixmap_format;
+ imageByteOrder = display.image_byte_order;
+ pixelByteCount = pixmapFormat.bits_per_pixel () / 8;
}
/**
@@ -147,7 +150,6 @@ public class XGraphics
{
clip.x -= x;
clip.y -= y;
- setClip(clip);
}
}
@@ -171,7 +173,18 @@ public class XGraphics
{
if (c != null)
{
- xgc.set_foreground(c.getRGB());
+ XToolkit tk = (XToolkit) Toolkit.getDefaultToolkit();
+ HashMap colorMap = tk.colorMap;
+ gnu.x11.Color col = (gnu.x11.Color) colorMap.get(c);
+ if (col == null)
+ {
+ Colormap map = xdrawable.display.default_colormap;
+ col = map.alloc_color (c.getRed() * 256,
+ c.getGreen() * 256,
+ c.getBlue() * 256);
+ colorMap.put(c, col);
+ }
+ xgc.set_foreground(col);
foreground = c;
}
}
@@ -257,7 +270,7 @@ public class XGraphics
computeIntersection(x, y, width, height, clip);
}
// Update the X clip setting.
- setClip(clip.x, clip.y, clip.width, clip.height);
+ setXClip(clip.x, clip.y, clip.width, clip.height);
}
/**
@@ -282,9 +295,19 @@ public class XGraphics
}
else
{
- hit = clip.intersects(x, y, w, h);
+ // It's easier to determine if the rectangle lies outside the clip,
+ // so we determine that and reverse the result (if it's not completely
+ // outside, it most likely hits the clip rectangle).
+ int x2 = x + w;
+ int y2 = y + h;
+ int clipX2 = clip.x + clip.width;
+ int clipY2 = clip.y + clip.height;
+ boolean outside = (x < clip.x && x2 < clip.x) // Left.
+ || (x > clipX2 && x2 > clipX2) // Right.
+ || (y < clip.y && y2 < clip.y) // Top.
+ || (y > clipY2 && y2 > clipY2); // Bottom.
+ hit = ! outside;
}
- //System.err.println("hitClip: " + hit);
return hit;
}
@@ -294,10 +317,23 @@ public class XGraphics
clip.setBounds(x, y, width, height);
else
clip = new Rectangle(x, y, width, height);
+ setXClip(clip.x, clip.y, clip.width, clip.height);
+ }
+ /**
+ * Sets the clip on the X server GC. The coordinates are not yet translated,
+ * this will be performed by the X server.
+ *
+ * @param x the clip, X coordinate
+ * @param y the clip, Y coordinate
+ * @param w the clip, width
+ * @param h the clip, height
+ */
+ private void setXClip(int x, int y, int w, int h)
+ {
gnu.x11.Rectangle[] clipRects = new gnu.x11.Rectangle[] {
- new gnu.x11.Rectangle(x, y, width, height) };
- xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.UN_SORTED);
+ new gnu.x11.Rectangle(x, y, w, h) };
+ xgc.set_clip_rectangles(translateX, translateY, clipRects, GC.YX_BANDED);
}
public Shape getClip()
@@ -309,33 +345,44 @@ public class XGraphics
/**
* Sets the current clip.
*
- * @param clip the clip to set
+ * @param c the clip to set
*/
- public void setClip(Shape clip)
+ public void setClip(Shape c)
{
- if (clip != null)
+ if (c != null)
{
Rectangle b;
- if (clip instanceof Rectangle)
+ if (c instanceof Rectangle)
{
- b = (Rectangle) clip;
+ b = (Rectangle) c;
}
else
{
- b = clip.getBounds();
+ b = c.getBounds();
}
- setClip(b.x, b.y, b.width, b.height);
+ clip.setBounds(b);
+ setXClip(b.x, b.y, b.width, b.height);
}
else
{
- setClip(0, 0, xdrawable.width, xdrawable.height);
+ clip.setBounds(0, 0, xdrawable.width, xdrawable.height);
+ setXClip(0, 0, xdrawable.width, xdrawable.height);
}
}
public void copyArea(int x, int y, int width, int height, int dx, int dy)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+ // Clip and translate src rectangle.
+ int srcX = Math.min(Math.max(x, clip.x), clip.x + clip.width)
+ + translateX;
+ int srcY = Math.min(Math.max(y, clip.y), clip.y + clip.height)
+ + translateY;
+ int srcWidth = Math.min(Math.max(x + width, clip.x),
+ clip.x + clip.width) - x;
+ int srcHeight = Math.min(Math.max(y + height, clip.y),
+ clip.y + clip.height) - y;
+ xdrawable.copy_area(xdrawable, xgc, srcX, srcY, srcWidth, srcHeight,
+ srcX + dx, srcY + dy);
}
/**
@@ -498,32 +545,51 @@ public class XGraphics
xdrawable.copy_area(pm, xgc, 0, 0, pm.width, pm.height,
x + translateX, y + translateY);
}
-// else if (image instanceof BufferedImage)
-// {
-// BufferedImage bufferedImage = (BufferedImage) image;
-// Raster raster = bufferedImage.getData();
-// int w = bufferedImage.getWidth();
-// int h = bufferedImage.getHeight();
-// // Push data to X server.
-// ZPixmap zPixmap = new ZPixmap(xdrawable.display, w, h,
-// xdrawable.display.default_pixmap_format);
-// System.err.println("data buffer length: " + zPixmap.data.length);
-// int[] pixel = new int[4];
-// for (int tx = 0; tx < w; tx++)
-// {
-// for (int ty = 0; ty < h; ty++)
-// {
-// pixel = raster.getPixel(tx, ty, pixel);
-//// System.err.print("r: " + pixel[0]);
-//// System.err.print(", g: " + pixel[1]);
-//// System.err.println(", b: " + pixel[2]);
-// zPixmap.set_red(tx, ty, pixel[0]);
-// zPixmap.set_green(tx, ty, pixel[1]);
-// zPixmap.set_blue(tx, ty, pixel[2]);
-// }
-// }
-// xdrawable.put_image(xgc, zPixmap, x, y);
-// }
+ else if (image instanceof BufferedImage
+ && ((BufferedImage) image).getTransparency() != Transparency.OPAQUE)
+ {
+ BufferedImage bi = (BufferedImage) image;
+ int width = bi.getWidth();
+ int height = bi.getHeight();
+ Data img = xdrawable.image(x + translateX, y + translateY,
+ width, height, 0xFFFFFFFF, 2);
+
+ // Compute line byte count.
+ int lineBitCount = width * pixmapFormat.bits_per_pixel ();
+ int rem = lineBitCount % pixmapFormat.scanline_pad ();
+ int linePadCount = lineBitCount / pixmapFormat.scanline_pad ()
+ + (rem == 0 ? 0 : 1);
+ int lineByteCount = linePadCount * pixmapFormat.scanline_pad () / 8;
+
+ // Composite source and destination pixel data.
+ int[] trgb = new int[3]; // The device rgb pixels.
+ for (int yy = 0; yy < height; yy++)
+ {
+ for (int xx = 0; xx < width; xx++)
+ {
+ getRGB(xx, yy, img, trgb, lineByteCount);
+ int srgb = bi.getRGB(xx, yy);
+ float alpha = ((srgb >> 24) & 0xff) / 256F;
+ float tAlpha = 1.F - alpha;
+ int red = (srgb >> 16) & 0xFF;
+ int green = (srgb >> 8) & 0xFF;
+ int blue = (srgb) & 0xFF;
+ trgb[0] = (int) (trgb[0] * tAlpha + red * alpha);
+ trgb[1] = (int) (trgb[1] * tAlpha + green * alpha);
+ trgb[2] = (int) (trgb[2] * tAlpha + blue * alpha);
+ setRGB(xx, yy, img, trgb, lineByteCount);
+ }
+ }
+
+ // Now we have the transparent image composited onto the target
+ // Image, now we only must copy it to the Drawable.
+ ZPixmap pm = new ZPixmap(xdrawable.display);
+ pm.width = width;
+ pm.height = height;
+ pm.init();
+ System.arraycopy(img.data, 32, pm.data, 0, img.data.length - 32);
+ xdrawable.put_image(xgc, pm, x + translateX, y + translateY);
+ }
else
{
// Pre-render the image into an XImage.
@@ -538,6 +604,59 @@ public class XGraphics
return true;
}
+ /**
+ * Helper method to work around limitation in the current Escher impl.
+ *
+ * @param x the x position
+ * @param y the y position
+ * @param img the image data
+ * @param rgb an 3-size array that holds the rgb values on method exit
+ */
+ private void getRGB(int x, int y, Data img, int[] rgb, int lineByteCount)
+ {
+ // TODO: Does this also work on non-RGB devices?
+ int i = y * lineByteCount + pixelByteCount * x;
+ if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST)
+ {//if (i >= 5716-33) System.err.println("lbc: " + lineByteCount + ", " + pixelByteCount);
+ rgb[2] = img.data[32 + i];
+ rgb[1] = img.data[32 + i + 1];
+ rgb[0] = img.data[32 + i + 2];
+ }
+ else
+ { // MSB_FIRST
+ rgb[0] = img.data[32 + i];
+ rgb[1] = img.data[32 + i + 1];
+ rgb[2] = img.data[32 + i + 2];
+ }
+
+ }
+
+ /**
+ * Helper method to work around limitation in the current Escher impl.
+ *
+ * @param x the x position
+ * @param y the y position
+ * @param img the image data
+ * @param rgb an 3-size array that holds the rgb values on method exit
+ */
+ private void setRGB(int x, int y, Data img, int[] rgb, int lineByteCount)
+ {
+ // TODO: Does this also work on non-RGB devices?
+ int i = y * lineByteCount + pixelByteCount * x;
+ if (imageByteOrder == gnu.x11.image.Image.LSB_FIRST)
+ {
+ img.data[32 + i] = (byte) rgb[2];
+ img.data[32 + i + 1] = (byte) rgb[1];
+ img.data[32 + i + 2] = (byte) rgb[0];
+ }
+ else
+ { // MSB_FIRST
+ img.data[32 + i] = (byte) rgb[0];
+ img.data[32 + i + 1] = (byte) rgb[1];
+ img.data[32 + i + 2] = (byte) rgb[2];
+ }
+ }
+
public boolean drawImage(Image image, int x, int y, int width, int height,
ImageObserver observer)
{
@@ -563,16 +682,41 @@ public class XGraphics
int sx1, int sy1, int sx2, int sy2,
ImageObserver observer)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+ return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null,
+ observer);
}
public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
int sx1, int sy1, int sx2, int sy2, Color bgcolor,
ImageObserver observer)
{
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
+
+ // FIXME: What to do with bgcolor?
+
+ // Scale the image.
+ int sw = image.getWidth(observer);
+ int sh = image.getHeight(observer);
+ double scaleX = Math.abs(dx2 - dx1) / (double) Math.abs(sx2 - sx1);
+ double scaleY = Math.abs(dy2 - dy1) / (double) Math.abs(sy2 - sy1);
+ Image scaled = image.getScaledInstance((int) (scaleX * sw),
+ (int) (scaleY * sh),
+ Image.SCALE_FAST);
+
+ // Scaled source coordinates.
+ int sx1s = (int) (scaleX * Math.min(sx1, sx2));
+ int sx2s = (int) (scaleX * Math.max(sx1, sx2));
+
+ // Temporarily clip to the target rectangle.
+ Rectangle old = clip;
+ clipRect(dx1, dy1, dx2 - dx1, dy2 - dy1);
+
+ // Draw scaled image.
+ boolean res = drawImage(scaled, dx1 - sx1s, dy1 - sx2s, observer);
+
+ // Reset clip.
+ setClip(old);
+
+ return res;
}
/**
@@ -580,221 +724,14 @@ public class XGraphics
*/
public void dispose()
{
- xdrawable.display.flush();
if (! disposed)
{
xgc.free();
+ xdrawable.display.flush();
disposed = true;
}
}
- // Additional Graphics2D methods.
-
- public void draw(Shape shape)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public boolean drawImage(Image image, AffineTransform xform, ImageObserver obs)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawImage(BufferedImage image, BufferedImageOp op, int x, int y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawRenderedImage(RenderedImage image, AffineTransform xform)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawRenderableImage(RenderableImage image, AffineTransform xform)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawString(String text, float x, float y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawString(AttributedCharacterIterator iterator, float x, float y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void fill(Shape shape)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public boolean hit(Rectangle rect, Shape text, boolean onStroke)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public GraphicsConfiguration getDeviceConfiguration()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setComposite(Composite comp)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setPaint(Paint paint)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setStroke(Stroke stroke)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setRenderingHint(Key hintKey, Object hintValue)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Object getRenderingHint(Key hintKey)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setRenderingHints(Map hints)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void addRenderingHints(Map hints)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public RenderingHints getRenderingHints()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void translate(double tx, double ty)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void rotate(double theta)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void rotate(double theta, double x, double y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void scale(double scaleX, double scaleY)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void shear(double shearX, double shearY)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void transform(AffineTransform Tx)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setTransform(AffineTransform Tx)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public AffineTransform getTransform()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Paint getPaint()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Composite getComposite()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void setBackground(Color color)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Color getBackground()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public Stroke getStroke()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void clip(Shape s)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public FontRenderContext getFontRenderContext()
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void drawGlyphVector(GlyphVector g, float x, float y)
- {
- // FIXME: Implement this.
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
-
// Additional helper methods.
/**
@@ -806,18 +743,18 @@ public class XGraphics
{
XGraphics copy = (XGraphics) super.clone();
copy.xgc = xgc.copy();
-
- // Save the original clip.
if (clip != null)
- copy.clip = new Rectangle(clip);
+ {
+ copy.clip = new Rectangle(clip);
+ copy.setXClip(clip.x, clip.y, clip.width, clip.height);
+ }
return copy;
}
catch (CloneNotSupportedException ex)
{
- AWTError err = new AWTError("Error while cloning XGraphics");
- err.initCause(ex);
- throw err;
+ assert false;
}
+ return null;
}
/**