summaryrefslogtreecommitdiff
path: root/gnu/java/awt/peer/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/java/awt/peer/gtk')
-rw-r--r--gnu/java/awt/peer/gtk/BufferedImageGraphics.java122
-rw-r--r--gnu/java/awt/peer/gtk/CairoGraphics2D.java295
-rw-r--r--gnu/java/awt/peer/gtk/CairoSurface.java5
-rw-r--r--gnu/java/awt/peer/gtk/ComponentGraphics.java51
-rw-r--r--gnu/java/awt/peer/gtk/FreetypeGlyphVector.java4
-rw-r--r--gnu/java/awt/peer/gtk/GdkFontMetrics.java157
-rw-r--r--gnu/java/awt/peer/gtk/GdkFontPeer.java217
-rw-r--r--gnu/java/awt/peer/gtk/GtkComponentPeer.java56
-rw-r--r--gnu/java/awt/peer/gtk/GtkToolkit.java51
9 files changed, 571 insertions, 387 deletions
diff --git a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
index 341fa2a4e..7de9c057e 100644
--- a/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
+++ b/gnu/java/awt/peer/gtk/BufferedImageGraphics.java
@@ -54,11 +54,11 @@ import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBufferInt;
-import java.awt.image.DirectColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
+import java.awt.image.SinglePixelPackedSampleModel;
import java.util.WeakHashMap;
/**
@@ -100,12 +100,6 @@ public class BufferedImageGraphics extends CairoGraphics2D
*/
private long cairo_t;
- /**
- * Colormodels we recognize for fast copying.
- */
- static ColorModel rgb32 = new DirectColorModel(24, 0xFF0000, 0xFF00, 0xFF);
- static ColorModel argb32 = new DirectColorModel(32, 0xFF0000, 0xFF00, 0xFF,
- 0xFF000000);
private boolean hasFastCM;
private boolean hasAlpha;
@@ -117,12 +111,14 @@ public class BufferedImageGraphics extends CairoGraphics2D
imageHeight = bi.getHeight();
locked = false;
- if(bi.getColorModel().equals(rgb32))
+ if (!(image.getSampleModel() instanceof SinglePixelPackedSampleModel))
+ hasFastCM = false;
+ else if(bi.getColorModel().equals(CairoSurface.cairoCM_opaque))
{
hasFastCM = true;
hasAlpha = false;
}
- else if(bi.getColorModel().equals(argb32))
+ else if(bi.getColorModel().equals(CairoSurface.cairoColorModel))
{
hasFastCM = true;
hasAlpha = true;
@@ -176,8 +172,11 @@ public class BufferedImageGraphics extends CairoGraphics2D
imageWidth = copyFrom.imageWidth;
imageHeight = copyFrom.imageHeight;
locked = false;
+
+ hasFastCM = copyFrom.hasFastCM;
+ hasAlpha = copyFrom.hasAlpha;
+
copy( copyFrom, cairo_t );
- setClip(0, 0, surface.width, surface.height);
}
/**
@@ -188,30 +187,79 @@ public class BufferedImageGraphics extends CairoGraphics2D
if (locked)
return;
+ double[] points = new double[]{x, y, width+x, height+y};
+ transform.transform(points, 0, points, 0, 2);
+ x = (int)points[0];
+ y = (int)points[1];
+ width = (int)Math.ceil(points[2] - points[0]);
+ height = (int)Math.ceil(points[3] - points[1]);
+
int[] pixels = surface.getPixels(imageWidth * imageHeight);
if( x > imageWidth || y > imageHeight )
return;
+
+ // Deal with negative width/height.
+ if (height < 0)
+ {
+ y += height;
+ height = -height;
+ }
+ if (width < 0)
+ {
+ x += width;
+ width = -width;
+ }
+
// Clip edges.
- if( x < 0 ){ width = width + x; x = 0; }
- if( y < 0 ){ height = height + y; y = 0; }
+ if( x < 0 )
+ x = 0;
+ if( y < 0 )
+ y = 0;
+
if( x + width > imageWidth )
width = imageWidth - x;
if( y + height > imageHeight )
height = imageHeight - y;
- // The setRGB method assumes (or should assume) that pixels are NOT
- // alpha-premultiplied, but Cairo stores data with premultiplication
- // (thus the pixels returned in getPixels are premultiplied).
- // This is ignored for consistency, however, since in
- // CairoGrahpics2D.drawImage we also use non-premultiplied data
if(!hasFastCM)
- image.setRGB(x, y, width, height, pixels,
- x + y * imageWidth, imageWidth);
+ {
+ image.setRGB(x, y, width, height, pixels,
+ x + y * imageWidth, imageWidth);
+ // The setRGB method assumes (or should assume) that pixels are NOT
+ // alpha-premultiplied, but Cairo stores data with premultiplication
+ // (thus the pixels returned in getPixels are premultiplied).
+ // This is ignored for consistency, however, since in
+ // CairoGrahpics2D.drawImage we also use non-premultiplied data
+
+ }
else
- System.arraycopy(pixels, y * imageWidth,
- ((DataBufferInt)image.getRaster().getDataBuffer()).
- getData(), y * imageWidth, height * imageWidth);
+ {
+ int[] db = ((DataBufferInt)image.getRaster().getDataBuffer()).
+ getData();
+
+ // This should not fail, as we check the image sample model when we
+ // set the hasFastCM flag
+ SinglePixelPackedSampleModel sm = (SinglePixelPackedSampleModel)image.getSampleModel() ;
+
+ int minX = image.getRaster().getSampleModelTranslateX();
+ int minY = image.getRaster().getSampleModelTranslateY();
+
+ if (sm.getScanlineStride() == imageWidth && minX == 0)
+ {
+ System.arraycopy(pixels, y * imageWidth,
+ db, y * imageWidth - minY,
+ height * imageWidth);
+ }
+ else
+ {
+ int scanline = sm.getScanlineStride();
+ for (int i = y; i < height; i++)
+ System.arraycopy(pixels, i * imageWidth + x, db,
+ (i - minY) * scanline + x - minX, width);
+
+ }
+ }
}
/**
@@ -244,15 +292,19 @@ public class BufferedImageGraphics extends CairoGraphics2D
*/
public void draw(Shape s)
{
+ // Find total bounds of shape
+ Rectangle r = findStrokedBounds(s);
+ if (shiftDrawCalls)
+ {
+ r.width++;
+ r.height++;
+ }
+
+ // Do the drawing
if (comp == null || comp instanceof AlphaComposite)
{
super.draw(s);
- Rectangle r = s.getBounds();
-
- if (shiftDrawCalls)
- updateBufferedImage(r.x, r.y, r.width+1, r.height+1);
- else
- updateBufferedImage(r.x, r.y, r.width, r.height);
+ updateBufferedImage(r.x, r.y, r.width, r.height);
}
else
{
@@ -263,7 +315,7 @@ public class BufferedImageGraphics extends CairoGraphics2D
g2d.setColor(this.getColor());
g2d.draw(s);
- drawComposite(s.getBounds2D(), null);
+ drawComposite(r.getBounds2D(), null);
}
}
@@ -356,10 +408,17 @@ public class BufferedImageGraphics extends CairoGraphics2D
public void drawGlyphVector(GlyphVector gv, float x, float y)
{
+ // Find absolute bounds, in user-space, of this glyph vector
+ Rectangle2D bounds = gv.getLogicalBounds();
+ bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
+ bounds.getWidth(), bounds.getHeight());
+
+ // Perform draw operation
if (comp == null || comp instanceof AlphaComposite)
{
super.drawGlyphVector(gv, x, y);
- updateBufferedImage(0, 0, imageWidth, imageHeight);
+ updateBufferedImage((int)bounds.getX(), (int)bounds.getY(),
+ (int)bounds.getWidth(), (int)bounds.getHeight());
}
else
{
@@ -370,9 +429,6 @@ public class BufferedImageGraphics extends CairoGraphics2D
g2d.setStroke(this.getStroke());
g2d.drawGlyphVector(gv, x, y);
- Rectangle2D bounds = gv.getLogicalBounds();
- bounds = new Rectangle2D.Double(x + bounds.getX(), y + bounds.getY(),
- bounds.getWidth(), bounds.getHeight());
drawComposite(bounds, null);
}
}
diff --git a/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
index ce3041d73..16de95185 100644
--- a/gnu/java/awt/peer/gtk/CairoGraphics2D.java
+++ b/gnu/java/awt/peer/gtk/CairoGraphics2D.java
@@ -71,6 +71,7 @@ import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
@@ -134,6 +135,7 @@ public abstract class CairoGraphics2D extends Graphics2D
* The current paint
*/
Paint paint;
+ boolean customPaint;
/**
* The current stroke
@@ -255,6 +257,8 @@ public abstract class CairoGraphics2D extends Graphics2D
bg = new Color(g.bg.getRGB());
}
+ firstClip = g.firstClip;
+ originalClip = g.originalClip;
clip = g.getClip();
if (g.transform == null)
@@ -311,6 +315,11 @@ public abstract class CairoGraphics2D extends Graphics2D
int width, int height, int dx, int dy);
+ /**
+ * Find the bounds of this graphics context, in device space.
+ *
+ * @return the bounds in device-space
+ */
protected abstract Rectangle2D getRealBounds();
////// Native Methods ////////////////////////////////////////////////////
@@ -336,7 +345,8 @@ public abstract class CairoGraphics2D extends Graphics2D
int g2, int b2, int a2, boolean cyclic);
private native void setPaintPixels(long pointer, int[] pixels, int w,
- int h, int stride, boolean repeat);
+ int h, int stride, boolean repeat,
+ int x, int y);
/**
* Set the current transform matrix
@@ -691,6 +701,7 @@ public abstract class CairoGraphics2D extends Graphics2D
if (paint instanceof Color)
{
setColor((Color) paint);
+ customPaint = false;
}
else if (paint instanceof TexturePaint)
{
@@ -708,7 +719,8 @@ public abstract class CairoGraphics2D extends Graphics2D
AffineTransformOp op = new AffineTransformOp(at, getRenderingHints());
BufferedImage texture = op.filter(img, null);
int[] pixels = texture.getRGB(0, 0, width, height, null, 0, width);
- setPaintPixels(nativePointer, pixels, width, height, width, true);
+ setPaintPixels(nativePointer, pixels, width, height, width, true, 0, 0);
+ customPaint = false;
}
else if (paint instanceof GradientPaint)
{
@@ -721,36 +733,90 @@ public abstract class CairoGraphics2D extends Graphics2D
c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(),
c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(),
gp.isCyclic());
+ customPaint = false;
}
else
{
- // Get bounds in device space
- int minX = 0;
- int minY = 0;
- int width = (int)getRealBounds().getWidth();
- int height = (int)getRealBounds().getHeight();
-
- Point2D origin = transform.transform(new Point2D.Double(minX, minY),
- null);
- Point2D extreme = transform.transform(new Point2D.Double(width + minX,
- height + minY),
- null);
- minX = (int)origin.getX();
- minY = (int)origin.getY();
- width = (int)extreme.getX() - minX;
- height = (int)extreme.getY() - minY;
-
- // Get raster of the paint background
- PaintContext pc = paint.createContext(ColorModel.getRGBdefault(),
- new Rectangle(minX, minY,
- width, height),
- getRealBounds(),
- transform, hints);
+ customPaint = true;
+ }
+ }
+
+ /**
+ * Sets a custom paint
+ *
+ * @param bounds the bounding box, in user space
+ */
+ protected void setCustomPaint(Rectangle bounds)
+ {
+ if (paint instanceof Color || paint instanceof TexturePaint
+ || paint instanceof GradientPaint)
+ return;
+
+ int userX = bounds.x;
+ int userY = bounds.y;
+ int userWidth = bounds.width;
+ int userHeight = bounds.height;
+
+ // Find bounds in device space
+ Point2D origin = transform.transform(new Point2D.Double(userX, userY),
+ null);
+ Point2D extreme = transform.transform(new Point2D.Double(userWidth + userX,
+ userHeight + userY),
+ null);
+ int deviceX = (int)origin.getX();
+ int deviceY = (int)origin.getY();
+ int deviceWidth = (int)Math.ceil(extreme.getX() - origin.getX());
+ int deviceHeight = (int)Math.ceil(extreme.getY() - origin.getY());
+
+ // Get raster of the paint background
+ PaintContext pc = paint.createContext(CairoSurface.cairoColorModel,
+ new Rectangle(deviceX, deviceY,
+ deviceWidth,
+ deviceHeight),
+ bounds,
+ transform, hints);
+
+ Raster raster = pc.getRaster(deviceX, deviceY, deviceWidth,
+ deviceHeight);
+
+ // Clear the transform matrix in Cairo, since the raster returned by the
+ // PaintContext is already in device-space
+ AffineTransform oldTx = new AffineTransform(transform);
+ setTransformImpl(new AffineTransform());
+
+ // Set pixels in cairo, aligning the top-left of the background image
+ // to the top-left corner in device space
+ if (pc.getColorModel().equals(CairoSurface.cairoColorModel)
+ && raster.getSampleModel().getTransferType() == DataBuffer.TYPE_INT)
+ {
+ // Use a fast copy if the paint context can uses a Cairo-compatible
+ // color model
+ setPaintPixels(nativePointer,
+ (int[])raster.getDataElements(0, 0, deviceWidth,
+ deviceHeight, null),
+ deviceWidth, deviceHeight, deviceWidth, false,
+ deviceX, deviceY);
+ }
+
+ else if (pc.getColorModel().equals(CairoSurface.cairoCM_opaque)
+ && raster.getSampleModel().getTransferType() == DataBuffer.TYPE_INT)
+ {
+ // We can also optimize if the context uses a similar color model
+ // but without an alpha channel; we just add the alpha
+ int[] pixels = (int[])raster.getDataElements(0, 0, deviceWidth,
+ deviceHeight, null);
- Raster raster = pc.getRaster(minX, minY, width, height);
+ for (int i = 0; i < pixels.length; i++)
+ pixels[i] = 0xff000000 | (pixels[i] & 0x00ffffff);
- // Work around colorspace issues, and force use of the
- // BufferedImage.getRGB method... this can be improved upon.
+ setPaintPixels(nativePointer, pixels, deviceWidth, deviceHeight,
+ deviceWidth, false, deviceX, deviceY);
+ }
+
+ else
+ {
+ // Fall back on wrapping the raster in a BufferedImage, and
+ // use BufferedImage.getRGB() to do color-model conversion
WritableRaster wr = Raster.createWritableRaster(raster.getSampleModel(),
new Point(raster.getMinX(),
raster.getMinY()));
@@ -760,15 +826,15 @@ public abstract class CairoGraphics2D extends Graphics2D
pc.getColorModel().isAlphaPremultiplied(),
null);
- // Set pixels in cairo
setPaintPixels(nativePointer,
- img2.getRGB(0, 0, width, height, null, 0, width),
- width, height, width, false);
- // setPaintPixels(nativePointer,
- // raster.getPixels(0, 0, width, height, (int[])null),
- // width, height, width, false);
- // doesn't work... but would be much more efficient!
+ img2.getRGB(0, 0, deviceWidth, deviceHeight, null, 0,
+ deviceWidth),
+ deviceWidth, deviceHeight, deviceWidth, false,
+ deviceX, deviceY);
}
+
+ // Restore transform
+ setTransformImpl(oldTx);
}
public Stroke getStroke()
@@ -799,6 +865,33 @@ public abstract class CairoGraphics2D extends Graphics2D
}
}
+ /**
+ * Utility method to find the bounds of a shape, including the stroke width.
+ *
+ * @param s the shape
+ * @return the bounds of the shape, including stroke width
+ */
+ protected Rectangle findStrokedBounds(Shape s)
+ {
+ Rectangle r = s.getBounds();
+
+ if (stroke instanceof BasicStroke)
+ {
+ int strokeWidth = (int)Math.ceil(((BasicStroke)stroke).getLineWidth());
+ r.x -= strokeWidth / 2;
+ r.y -= strokeWidth / 2;
+ r.height += strokeWidth;
+ r.width += strokeWidth;
+ }
+ else
+ {
+ Shape s2 = stroke.createStrokedShape(s);
+ r = s2.getBounds();
+ }
+
+ return r;
+ }
+
public void setPaintMode()
{
setComposite(AlphaComposite.SrcOver);
@@ -1023,6 +1116,12 @@ public abstract class CairoGraphics2D extends Graphics2D
return;
}
+ if (customPaint)
+ {
+ Rectangle r = findStrokedBounds(s);
+ setCustomPaint(r);
+ }
+
createPath(s, true);
cairoStroke(nativePointer);
}
@@ -1031,6 +1130,9 @@ public abstract class CairoGraphics2D extends Graphics2D
{
createPath(s, false);
+ if (customPaint)
+ setCustomPaint(s.getBounds());
+
double alpha = 1.0;
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
@@ -1045,9 +1147,25 @@ public abstract class CairoGraphics2D extends Graphics2D
if (s instanceof Rectangle2D)
{
Rectangle2D r = (Rectangle2D) s;
- cairoRectangle(nativePointer, shifted(r.getX(),shiftDrawCalls && isDraw),
- shifted(r.getY(), shiftDrawCalls && isDraw), r.getWidth(),
- r.getHeight());
+
+ // Pixels need to be shifted in draw operations to ensure that they
+ // light up entire pixels, but we also need to make sure the rectangle
+ // does not get distorted by this shifting operation
+ double x = shiftX(r.getX(),shiftDrawCalls && isDraw);
+ double y = shiftY(r.getY(), shiftDrawCalls && isDraw);
+ double w = shiftX(r.getWidth() + r.getX(), shiftDrawCalls && isDraw) - x;
+ double h = shiftY(r.getHeight() + r.getY(), shiftDrawCalls && isDraw) - y;
+ cairoRectangle(nativePointer, x, y, w, h);
+ }
+
+ // Lines are easy too
+ else if (s instanceof Line2D)
+ {
+ Line2D l = (Line2D) s;
+ cairoMoveTo(nativePointer, shiftX(l.getX1(), shiftDrawCalls && isDraw),
+ shiftY(l.getY1(), shiftDrawCalls && isDraw));
+ cairoLineTo(nativePointer, shiftX(l.getX2(), shiftDrawCalls && isDraw),
+ shiftY(l.getY2(), shiftDrawCalls && isDraw));
}
// We can optimize ellipses too; however we don't bother optimizing arcs:
@@ -1076,8 +1194,8 @@ public abstract class CairoGraphics2D extends Graphics2D
}
cairoArc(nativePointer,
- shifted(e.getCenterX() / xscale, shiftDrawCalls && isDraw),
- shifted(e.getCenterY() / yscale, shiftDrawCalls && isDraw),
+ shiftX(e.getCenterX() / xscale, shiftDrawCalls && isDraw),
+ shiftY(e.getCenterY() / yscale, shiftDrawCalls && isDraw),
radius, 0, Math.PI * 2);
if (xscale != 1 || yscale != 1)
@@ -1133,15 +1251,14 @@ public abstract class CairoGraphics2D extends Graphics2D
// to draw a single pixel. This is emulated by drawing
// a one pixel sized rectangle.
if (x1 == x2 && y1 == y2)
- cairoFillRect(nativePointer, x1, y1, 1, 1);
+ fill(new Rectangle(x1, y1, 1, 1));
else
- cairoDrawLine(nativePointer, x1 + 0.5, y1 + 0.5, x2 + 0.5, y2 + 0.5);
+ draw(new Line2D.Double(x1, y1, x2, y2));
}
public void drawRect(int x, int y, int width, int height)
{
- cairoDrawRect(nativePointer, shifted(x, shiftDrawCalls),
- shifted(y, shiftDrawCalls), width, height);
+ draw(new Rectangle(x, y, width, height));
}
public void fillArc(int x, int y, int width, int height, int startAngle,
@@ -1154,10 +1271,7 @@ public abstract class CairoGraphics2D extends Graphics2D
public void fillRect(int x, int y, int width, int height)
{
- fill(new Rectangle(x, y, width, height));
- // TODO: If we want to use the more efficient
- //cairoFillRect(nativePointer, x, y, width, height);
- // we need to override this method in subclasses
+ fill (new Rectangle(x, y, width, height));
}
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
@@ -1523,8 +1637,14 @@ public abstract class CairoGraphics2D extends Graphics2D
{
if (str == null || str.length() == 0)
return;
- (new TextLayout( str, getFont(), getFontRenderContext() )).
- draw(this, x, y);
+ GdkFontPeer fontPeer = (GdkFontPeer) font.getPeer();
+ TextLayout tl = (TextLayout) fontPeer.textLayoutCache.get(str);
+ if (tl == null)
+ {
+ tl = new TextLayout( str, getFont(), getFontRenderContext() );
+ fontPeer.textLayoutCache.put(str, tl);
+ }
+ tl.draw(this, x, y);
}
public void drawString(String str, int x, int y)
@@ -1544,6 +1664,9 @@ public abstract class CairoGraphics2D extends Graphics2D
if( gv.getNumGlyphs() <= 0 )
return;
+ if (customPaint)
+ setCustomPaint(gv.getOutline().getBounds());
+
if (comp instanceof AlphaComposite)
alpha = ((AlphaComposite) comp).getAlpha();
if (gv instanceof FreetypeGlyphVector && alpha == 1.0)
@@ -1553,9 +1676,10 @@ public abstract class CairoGraphics2D extends Graphics2D
float[] positions = gv.getGlyphPositions (0, n, null);
setFont (gv.getFont ());
- synchronized( this.font )
+ GdkFontPeer fontPeer = (GdkFontPeer) font.getPeer();
+ synchronized (fontPeer)
{
- cairoDrawGlyphVector(nativePointer, (GdkFontPeer)getFont().getPeer(),
+ cairoDrawGlyphVector(nativePointer, fontPeer,
x, y, n, codes, positions);
}
}
@@ -1593,9 +1717,7 @@ public abstract class CairoGraphics2D extends Graphics2D
public FontMetrics getFontMetrics(Font f)
{
- // the reason we go via the toolkit here is to try to get
- // a cached object. the toolkit keeps such a cache.
- return Toolkit.getDefaultToolkit().getFontMetrics(f);
+ return ((GdkFontPeer) f.getPeer()).getFontMetrics(f);
}
public void setFont(Font f)
@@ -1612,7 +1734,11 @@ public abstract class CairoGraphics2D extends Graphics2D
((ClasspathToolkit)(Toolkit.getDefaultToolkit()))
.getFont(f.getName(), f.getAttributes());
- cairoSetFont(nativePointer, (GdkFontPeer)getFont().getPeer());
+ GdkFontPeer fontpeer = (GdkFontPeer) getFont().getPeer();
+ synchronized (fontpeer)
+ {
+ cairoSetFont(nativePointer, fontpeer);
+ }
}
public Font getFont()
@@ -1732,12 +1858,33 @@ public abstract class CairoGraphics2D extends Graphics2D
}
/**
- * Shifts coordinates by 0.5.
+ * Shifts an x-coordinate by 0.5 in device space.
+ */
+ private double shiftX(double coord, boolean doShift)
+ {
+ if (doShift)
+ {
+ double shift = 0.5;
+ if (!transform.isIdentity())
+ shift /= transform.getScaleX();
+ return Math.round(coord) + shift;
+ }
+ else
+ return coord;
+ }
+
+ /**
+ * Shifts a y-coordinate by 0.5 in device space.
*/
- private double shifted(double coord, boolean doShift)
+ private double shiftY(double coord, boolean doShift)
{
if (doShift)
- return Math.floor(coord) + 0.5;
+ {
+ double shift = 0.5;
+ if (!transform.isIdentity())
+ shift /= transform.getScaleY();
+ return Math.round(coord) + shift;
+ }
else
return coord;
}
@@ -1758,35 +1905,35 @@ public abstract class CairoGraphics2D extends Graphics2D
switch (seg)
{
case PathIterator.SEG_MOVETO:
- x = shifted(coords[0], doShift);
- y = shifted(coords[1], doShift);
+ x = shiftX(coords[0], doShift);
+ y = shiftY(coords[1], doShift);
cairoMoveTo(nativePointer, x, y);
break;
case PathIterator.SEG_LINETO:
- x = shifted(coords[0], doShift);
- y = shifted(coords[1], doShift);
+ x = shiftX(coords[0], doShift);
+ y = shiftY(coords[1], doShift);
cairoLineTo(nativePointer, x, y);
break;
case PathIterator.SEG_QUADTO:
// splitting a quadratic bezier into a cubic:
// see: http://pfaedit.sourceforge.net/bezier.html
- double x1 = x + (2.0 / 3.0) * (shifted(coords[0], doShift) - x);
- double y1 = y + (2.0 / 3.0) * (shifted(coords[1], doShift) - y);
+ double x1 = x + (2.0 / 3.0) * (shiftX(coords[0], doShift) - x);
+ double y1 = y + (2.0 / 3.0) * (shiftY(coords[1], doShift) - y);
- double x2 = x1 + (1.0 / 3.0) * (shifted(coords[2], doShift) - x);
- double y2 = y1 + (1.0 / 3.0) * (shifted(coords[3], doShift) - y);
+ double x2 = x1 + (1.0 / 3.0) * (shiftX(coords[2], doShift) - x);
+ double y2 = y1 + (1.0 / 3.0) * (shiftY(coords[3], doShift) - y);
- x = shifted(coords[2], doShift);
- y = shifted(coords[3], doShift);
+ x = shiftX(coords[2], doShift);
+ y = shiftY(coords[3], doShift);
cairoCurveTo(nativePointer, x1, y1, x2, y2, x, y);
break;
case PathIterator.SEG_CUBICTO:
- x = shifted(coords[4], doShift);
- y = shifted(coords[5], doShift);
- cairoCurveTo(nativePointer, shifted(coords[0], doShift),
- shifted(coords[1], doShift),
- shifted(coords[2], doShift),
- shifted(coords[3], doShift), x, y);
+ x = shiftX(coords[4], doShift);
+ y = shiftY(coords[5], doShift);
+ cairoCurveTo(nativePointer, shiftX(coords[0], doShift),
+ shiftY(coords[1], doShift),
+ shiftX(coords[2], doShift),
+ shiftY(coords[3], doShift), x, y);
break;
case PathIterator.SEG_CLOSE:
cairoClosePath(nativePointer);
diff --git a/gnu/java/awt/peer/gtk/CairoSurface.java b/gnu/java/awt/peer/gtk/CairoSurface.java
index d3b3d4504..5b63e62e7 100644
--- a/gnu/java/awt/peer/gtk/CairoSurface.java
+++ b/gnu/java/awt/peer/gtk/CairoSurface.java
@@ -88,6 +88,11 @@ public class CairoSurface extends WritableRaster
0xFF000000,
true,
Buffers.smallestAppropriateTransferType(32));
+
+ // This CM corresponds to the CAIRO_FORMAT_RGB24 type in Cairo
+ static ColorModel cairoCM_opaque = new DirectColorModel(24, 0x00FF0000,
+ 0x0000FF00,
+ 0x000000FF);
/**
* Allocates and clears the buffer and creates the cairo surface.
* @param width, height - the image size
diff --git a/gnu/java/awt/peer/gtk/ComponentGraphics.java b/gnu/java/awt/peer/gtk/ComponentGraphics.java
index c8ec2c95e..612efd628 100644
--- a/gnu/java/awt/peer/gtk/ComponentGraphics.java
+++ b/gnu/java/awt/peer/gtk/ComponentGraphics.java
@@ -480,57 +480,6 @@ public class ComponentGraphics extends CairoGraphics2D
return super.drawImage(bimg, x, y, width, height, observer);
}
- public void drawLine(int x1, int y1, int x2, int y2)
- {
- lock();
- try
- {
- if (comp == null || comp instanceof AlphaComposite)
- super.drawLine(x1, y1, x2, y2);
-
- else
- draw(new Line2D.Double(x1, y1, x2, y2));
- }
- finally
- {
- unlock();
- }
- }
-
- public void drawRect(int x, int y, int width, int height)
- {
- lock();
- try
- {
- if (comp == null || comp instanceof AlphaComposite)
- super.drawRect(x, y, width, height);
-
- else
- draw(new Rectangle2D.Double(x, y, width, height));
- }
- finally
- {
- unlock();
- }
- }
-
- public void fillRect(int x, int y, int width, int height)
- {
- lock();
- try
- {
- if (comp == null || comp instanceof AlphaComposite)
- super.fillRect(x, y, width, height);
-
- else
- fill(new Rectangle2D.Double(x, y, width, height));
- }
- finally
- {
- unlock();
- }
- }
-
public void setClip(Shape s)
{
lock();
diff --git a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
index 98f1bd69b..4ad87a84b 100644
--- a/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
+++ b/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java
@@ -294,7 +294,7 @@ public class FreetypeGlyphVector extends GlyphVector
{
int[] rval;
- if( codeReturn == null )
+ if( codeReturn == null || codeReturn.length < numEntries)
rval = new int[ numEntries ];
else
rval = codeReturn;
@@ -395,7 +395,7 @@ public class FreetypeGlyphVector extends GlyphVector
public float[] getGlyphPositions(int beginGlyphIndex, int numEntries,
float[] positionReturn)
{
- if (positionReturn == null)
+ if (positionReturn == null || positionReturn.length < (numEntries * 2))
positionReturn = new float[numEntries*2];
System.arraycopy(glyphPositions, beginGlyphIndex*2, positionReturn, 0,
diff --git a/gnu/java/awt/peer/gtk/GdkFontMetrics.java b/gnu/java/awt/peer/gtk/GdkFontMetrics.java
deleted file mode 100644
index 30b1ff15e..000000000
--- a/gnu/java/awt/peer/gtk/GdkFontMetrics.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/* GdkFontMetrics.java
- Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package gnu.java.awt.peer.gtk;
-
-import gnu.java.awt.ClasspathToolkit;
-
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Toolkit;
-
-public class GdkFontMetrics extends FontMetrics
-{
-
- private int[] font_metrics;
- GdkFontPeer peer;
-
- static final int FONT_METRICS_ASCENT = 0;
- static final int FONT_METRICS_MAX_ASCENT = 1;
- static final int FONT_METRICS_DESCENT = 2;
- static final int FONT_METRICS_MAX_DESCENT = 3;
- static final int FONT_METRICS_MAX_ADVANCE = 4;
-
- static final int TEXT_METRICS_X_BEARING = 0;
- static final int TEXT_METRICS_Y_BEARING = 1;
- static final int TEXT_METRICS_WIDTH = 2;
- static final int TEXT_METRICS_HEIGHT = 3;
- static final int TEXT_METRICS_X_ADVANCE = 4;
- static final int TEXT_METRICS_Y_ADVANCE = 5;
-
- /**
- * Makes sure to return a Font based on the given Font that has as
- * peer a GdkFontPeer. Used in the initializer.
- */
- private static Font initFont(Font font)
- {
- if (font == null)
- return new Font("Dialog", Font.PLAIN, 12);
- else if (font.getPeer() instanceof GdkFontPeer)
- return font;
- else
- {
- ClasspathToolkit toolkit;
- toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
- return toolkit.getFont(font.getName(), font.getAttributes());
- }
- }
-
- public GdkFontMetrics (Font font)
- {
- super(initFont(font));
- peer = (GdkFontPeer) this.font.getPeer();
-
- font_metrics = new int[5];
- double [] hires = new double[5];
- peer.getFontMetrics (hires);
- for (int i = 0; i < 5; ++i)
- font_metrics[i] = (int) hires[i];
- }
-
- public int stringWidth (String str)
- {
-
-// TextLayout layout = new TextLayout(str, getFont(), null);
-// return (int) layout.getAdvance();
- // We need to filter control chars, because they are never displayed
- // in Java and thus also have no metrics.
- int len = str.length();
- StringBuilder b = new StringBuilder(len);
- for (int i = 0; i < len; i++)
- {
- char ch = str.charAt(i);
- if (! Character.isISOControl(ch))
- b.append(ch);
- }
- double [] hires = new double[6];
- String string = b.toString();
- peer.getTextMetrics(string, hires);
- return (int) hires [TEXT_METRICS_WIDTH];
- }
-
- public int charWidth (char ch)
- {
- return stringWidth (new String (new char[] { ch }));
- }
-
- public int charsWidth (char data[], int off, int len)
- {
- return stringWidth (new String (data, off, len));
- }
-
- public int getLeading ()
- {
- // Sun always returns 0.
- return 0;
- }
-
- public int getAscent ()
- {
- return font_metrics[FONT_METRICS_ASCENT];
- }
-
- public int getMaxAscent ()
- {
- return font_metrics[FONT_METRICS_MAX_ASCENT];
- }
-
- public int getDescent ()
- {
- return font_metrics[FONT_METRICS_DESCENT];
- }
-
- public int getMaxDescent ()
- {
- return font_metrics[FONT_METRICS_MAX_DESCENT];
- }
-
- public int getMaxAdvance ()
- {
- return font_metrics[FONT_METRICS_MAX_ADVANCE];
- }
-}
diff --git a/gnu/java/awt/peer/gtk/GdkFontPeer.java b/gnu/java/awt/peer/gtk/GdkFontPeer.java
index 40b234984..5f5126ac5 100644
--- a/gnu/java/awt/peer/gtk/GdkFontPeer.java
+++ b/gnu/java/awt/peer/gtk/GdkFontPeer.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.java.awt.peer.gtk;
+import gnu.java.awt.ClasspathToolkit;
import gnu.java.awt.peer.ClasspathFontPeer;
import gnu.java.awt.font.opentype.NameDecoder;
@@ -48,39 +49,125 @@ import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.GlyphMetrics;
import java.awt.font.LineMetrics;
+import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.text.CharacterIterator;
import java.util.Locale;
import java.util.Map;
-import java.util.ResourceBundle;
import java.nio.ByteBuffer;
import java.util.HashMap;
public class GdkFontPeer extends ClasspathFontPeer
{
+ static final FontRenderContext DEFAULT_CTX =
+ new FontRenderContext(null, false, false);
+
+ /**
+ * Caches TextLayout instances for use in charsWidth() and drawString().
+ * The size of the cache has been chosen so that relativly large GUIs with
+ * text documents are still efficient.
+ */
+ HashMap textLayoutCache = new GtkToolkit.LRUCache(500);
+
+ private class GdkFontMetrics extends FontMetrics
+ {
+
+ public GdkFontMetrics (Font font)
+ {
+ super(initFont(font));
+ }
+
+ public int stringWidth (String str)
+ {
+ TextLayout tl = (TextLayout) textLayoutCache.get(str);
+ if (tl == null)
+ {
+ tl = new TextLayout(str, font, DEFAULT_CTX);
+ textLayoutCache.put(str, tl);
+ }
+ return (int) tl.getAdvance();
+ }
+
+ public int charWidth (char ch)
+ {
+ return stringWidth (new String (new char[] { ch }));
+ }
+
+ public int charsWidth (char data[], int off, int len)
+ {
+ return stringWidth (new String (data, off, len));
+ }
+
+ public int getHeight()
+ {
+ return (int) height;
+ }
+
+ public int getLeading ()
+ {
+ return (int) (height - (ascent + descent));
+ }
+
+ public int getAscent ()
+ {
+ return (int) ascent;
+ }
+
+ public int getMaxAscent ()
+ {
+ return (int) ascent;
+ }
+
+ public int getDescent ()
+ {
+ return (int) descent;
+ }
+
+ public int getMaxDescent ()
+ {
+ return (int) maxDescent;
+ }
+
+ public int getMaxAdvance ()
+ {
+ return (int) maxAdvance;
+ }
+ }
+
static native void initStaticState();
private final int native_state = GtkGenericPeer.getUniqueInteger ();
- private static ResourceBundle bundle;
/**
* Cache GlyphMetrics objects.
*/
private HashMap metricsCache;
-
+
+ private static final int FONT_METRICS_ASCENT = 0;
+ private static final int FONT_METRICS_MAX_ASCENT = 1;
+ private static final int FONT_METRICS_DESCENT = 2;
+ private static final int FONT_METRICS_MAX_DESCENT = 3;
+ private static final int FONT_METRICS_MAX_ADVANCE = 4;
+ private static final int FONT_METRICS_HEIGHT = 5;
+ private static final int FONT_METRICS_UNDERLINE_OFFSET = 6;
+ private static final int FONT_METRICS_UNDERLINE_THICKNESS = 7;
+
+ float ascent;
+ float descent;
+ float maxAscent;
+ float maxDescent;
+ float maxAdvance;
+ float height;
+ float underlineOffset;
+ float underlineThickness;
+
+ GdkFontMetrics metrics;
+
static
{
System.loadLibrary("gtkpeer");
initStaticState ();
- try
- {
- bundle = ResourceBundle.getBundle ("gnu.java.awt.peer.gtk.font");
- }
- catch (Throwable ignored)
- {
- bundle = null;
- }
}
private ByteBuffer nameTable = null;
@@ -89,8 +176,8 @@ public class GdkFontPeer extends ClasspathFontPeer
private native void dispose ();
private native void setFont (String family, int style, int size);
- native void getFontMetrics(double [] metrics);
- native void getTextMetrics(String str, double [] metrics);
+ native synchronized void getFontMetrics(double [] metrics);
+ native synchronized void getTextMetrics(String str, double [] metrics);
native void releasePeerGraphicsResource();
@@ -149,6 +236,7 @@ public class GdkFontPeer extends ClasspathFontPeer
initState ();
setFont (this.familyName, this.style, (int)this.size);
metricsCache = new HashMap();
+ setupMetrics();
}
public GdkFontPeer (String name, Map attributes)
@@ -157,6 +245,40 @@ public class GdkFontPeer extends ClasspathFontPeer
initState ();
setFont (this.familyName, this.style, (int)this.size);
metricsCache = new HashMap();
+ setupMetrics();
+ }
+
+
+ /**
+ * Makes sure to return a Font based on the given Font that has as
+ * peer a GdkFontPeer. Used in the initializer.
+ */
+ static Font initFont(Font font)
+ {
+ if (font == null)
+ return new Font("Dialog", Font.PLAIN, 12);
+ else if (font.getPeer() instanceof GdkFontPeer)
+ return font;
+ else
+ {
+ ClasspathToolkit toolkit;
+ toolkit = (ClasspathToolkit) Toolkit.getDefaultToolkit();
+ return toolkit.getFont(font.getName(), font.getAttributes());
+ }
+ }
+
+ private void setupMetrics()
+ {
+ double [] hires = new double[8];
+ getFontMetrics(hires);
+ ascent = (float) hires[FONT_METRICS_ASCENT];
+ maxAscent = (float) hires[FONT_METRICS_MAX_ASCENT];
+ descent = (float) hires[FONT_METRICS_DESCENT];
+ maxDescent = (float) hires[FONT_METRICS_MAX_DESCENT];
+ maxAdvance = (float) hires[FONT_METRICS_MAX_ADVANCE];
+ height = (float) hires[FONT_METRICS_HEIGHT];
+ underlineOffset = (float) hires[FONT_METRICS_UNDERLINE_OFFSET];
+ underlineThickness = (float) hires[FONT_METRICS_UNDERLINE_THICKNESS];
}
/**
@@ -261,26 +383,17 @@ public class GdkFontPeer extends ClasspathFontPeer
return Font.ROMAN_BASELINE;
}
- private static class GdkFontLineMetrics extends LineMetrics
+ private class GdkFontLineMetrics extends LineMetrics
{
- private FontMetrics fm;
- private int nchars;
- private float strikethroughOffset, strikethroughThickness,
- underlineOffset, underlineThickness;
-
- public GdkFontLineMetrics (GdkFontPeer fp, FontMetrics m, int n)
+ private int nchars;
+ public GdkFontLineMetrics (GdkFontPeer fp, int n)
{
- fm = m;
nchars = n;
- strikethroughOffset = 0f;
- underlineOffset = 0f;
- strikethroughThickness = ((float)fp.getSize(null)) / 12f;
- underlineThickness = strikethroughThickness;
}
public float getAscent()
{
- return (float) fm.getAscent ();
+ return ascent;
}
public int getBaselineIndex()
@@ -296,27 +409,52 @@ public class GdkFontPeer extends ClasspathFontPeer
public float getDescent()
{
- return (float) fm.getDescent ();
+ return descent;
}
public float getHeight()
{
- return (float) fm.getHeight ();
+ return height;
}
- public float getLeading() { return 0.f; }
- public int getNumChars() { return nchars; }
- public float getStrikethroughOffset() { return 0.f; }
- public float getStrikethroughThickness() { return 0.f; }
- public float getUnderlineOffset() { return 0.f; }
- public float getUnderlineThickness() { return 0.f; }
+ public float getLeading()
+ {
+ return height - (ascent + descent);
+ }
+
+ public int getNumChars()
+ {
+ return nchars;
+ }
+
+ public float getStrikethroughOffset()
+ {
+ // FreeType doesn't seem to provide a value here.
+ return ascent / 2;
+ }
+
+ public float getStrikethroughThickness()
+ {
+ // FreeType doesn't seem to provide a value here.
+ return 1.f;
+ }
+
+ public float getUnderlineOffset()
+ {
+ return underlineOffset;
+ }
+
+ public float getUnderlineThickness()
+ {
+ return underlineThickness;
+ }
}
public LineMetrics getLineMetrics (Font font, CharacterIterator ci,
int begin, int limit, FontRenderContext rc)
{
- return new GdkFontLineMetrics (this, getFontMetrics (font), limit - begin);
+ return new GdkFontLineMetrics (this, limit - begin);
}
public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
@@ -361,14 +499,14 @@ public class GdkFontPeer extends ClasspathFontPeer
public LineMetrics getLineMetrics (Font font, String str,
FontRenderContext frc)
{
- return new GdkFontLineMetrics (this, getFontMetrics (font), str.length ());
+ return new GdkFontLineMetrics (this, str.length ());
}
public FontMetrics getFontMetrics (Font font)
{
- // Get the font metrics through GtkToolkit to take advantage of
- // the metrics cache.
- return Toolkit.getDefaultToolkit().getFontMetrics (font);
+ if (metrics == null)
+ metrics = new GdkFontMetrics(font);
+ return metrics;
}
/**
@@ -387,4 +525,5 @@ public class GdkFontPeer extends ClasspathFontPeer
{
metricsCache.put( new Integer( glyphCode ), metrics );
}
+
}
diff --git a/gnu/java/awt/peer/gtk/GtkComponentPeer.java b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
index f96033e56..f6bf588e9 100644
--- a/gnu/java/awt/peer/gtk/GtkComponentPeer.java
+++ b/gnu/java/awt/peer/gtk/GtkComponentPeer.java
@@ -90,6 +90,11 @@ public class GtkComponentPeer extends GtkGenericPeer
Insets insets;
+ /**
+ * The current repaint area.
+ */
+ protected Rectangle paintArea;
+
/* this isEnabled differs from Component.isEnabled, in that it
knows if a parent is disabled. In that case Component.isEnabled
may return true, but our isEnabled will always return false */
@@ -308,13 +313,20 @@ public class GtkComponentPeer extends GtkGenericPeer
// seems expensive. However, the graphics state does not carry
// over between calls to paint, and resetting the graphics object
// may even be more costly than simply creating a new one.
- Graphics g = getGraphics();
-
- g.setClip(event.getUpdateRect());
-
- awtComponent.paint(g);
-
- g.dispose();
+ synchronized (paintArea)
+ {
+ Graphics g = getGraphics();
+ try
+ {
+ g.setClip(paintArea);
+ awtComponent.paint(g);
+ }
+ finally
+ {
+ g.dispose();
+ paintArea = null;
+ }
+ }
}
// This method and its overrides are the only methods in the peers
@@ -327,13 +339,20 @@ public class GtkComponentPeer extends GtkGenericPeer
|| (awtComponent.getWidth() < 1 || awtComponent.getHeight() < 1))
return;
- Graphics g = getGraphics();
-
- g.setClip(event.getUpdateRect());
-
- awtComponent.update(g);
-
- g.dispose();
+ synchronized (paintArea)
+ {
+ Graphics g = getGraphics();
+ try
+ {
+ g.setClip(paintArea);
+ awtComponent.update(g);
+ }
+ finally
+ {
+ g.dispose();
+ paintArea = null;
+ }
+ }
}
public boolean isFocusTraversable ()
@@ -754,7 +773,14 @@ public class GtkComponentPeer extends GtkGenericPeer
public void coalescePaintEvent (PaintEvent e)
{
-
+ synchronized (this)
+ {
+ Rectangle newRect = e.getUpdateRect();
+ if (paintArea == null)
+ paintArea = newRect;
+ else
+ Rectangle.union(paintArea, newRect, paintArea);
+ }
}
public void updateCursorImmediately ()
diff --git a/gnu/java/awt/peer/gtk/GtkToolkit.java b/gnu/java/awt/peer/gtk/GtkToolkit.java
index d2721b43f..26724206d 100644
--- a/gnu/java/awt/peer/gtk/GtkToolkit.java
+++ b/gnu/java/awt/peer/gtk/GtkToolkit.java
@@ -62,6 +62,7 @@ import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Label;
import java.awt.List;
@@ -83,6 +84,7 @@ import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
+import java.awt.dnd.InvalidDnDOperationException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.im.InputMethodHighlight;
import java.awt.image.ColorModel;
@@ -115,7 +117,6 @@ import java.awt.peer.WindowPeer;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
@@ -295,7 +296,7 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
"SansSerif" });
}
- private class LRUCache extends LinkedHashMap
+ static class LRUCache extends LinkedHashMap
{
int max_entries;
public LRUCache(int max)
@@ -310,23 +311,11 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
}
private LRUCache fontCache = new LRUCache(50);
- private LRUCache metricsCache = new LRUCache(50);
private LRUCache imageCache = new LRUCache(50);
public FontMetrics getFontMetrics (Font font)
{
- synchronized (metricsCache)
- {
- if (metricsCache.containsKey(font))
- return (FontMetrics) metricsCache.get(font);
- }
-
- FontMetrics m = new GdkFontMetrics (font);
- synchronized (metricsCache)
- {
- metricsCache.put(font, m);
- }
- return m;
+ return ((GdkFontPeer) font.getPeer()).getFontMetrics(font);
}
public Image getImage (String filename)
@@ -431,109 +420,130 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
protected ButtonPeer createButton (Button b)
{
+ checkHeadless();
return new GtkButtonPeer (b);
}
protected CanvasPeer createCanvas (Canvas c)
{
+ checkHeadless();
return new GtkCanvasPeer (c);
}
protected CheckboxPeer createCheckbox (Checkbox cb)
{
+ checkHeadless();
return new GtkCheckboxPeer (cb);
}
protected CheckboxMenuItemPeer createCheckboxMenuItem (CheckboxMenuItem cmi)
{
+ checkHeadless();
return new GtkCheckboxMenuItemPeer (cmi);
}
protected ChoicePeer createChoice (Choice c)
{
+ checkHeadless();
return new GtkChoicePeer (c);
}
protected DialogPeer createDialog (Dialog d)
{
+ checkHeadless();
GtkMainThread.createWindow();
return new GtkDialogPeer (d);
}
protected FileDialogPeer createFileDialog (FileDialog fd)
{
+ checkHeadless();
return new GtkFileDialogPeer (fd);
}
protected FramePeer createFrame (Frame f)
{
+ checkHeadless();
GtkMainThread.createWindow();
return new GtkFramePeer (f);
}
protected LabelPeer createLabel (Label label)
{
+ checkHeadless();
return new GtkLabelPeer (label);
}
protected ListPeer createList (List list)
{
+ checkHeadless();
return new GtkListPeer (list);
}
protected MenuPeer createMenu (Menu m)
{
+ checkHeadless();
return new GtkMenuPeer (m);
}
protected MenuBarPeer createMenuBar (MenuBar mb)
{
+ checkHeadless();
return new GtkMenuBarPeer (mb);
}
protected MenuItemPeer createMenuItem (MenuItem mi)
{
+ checkHeadless();
return new GtkMenuItemPeer (mi);
}
protected PanelPeer createPanel (Panel p)
{
+ checkHeadless();
return new GtkPanelPeer (p);
}
protected PopupMenuPeer createPopupMenu (PopupMenu target)
{
+ checkHeadless();
return new GtkPopupMenuPeer (target);
}
protected ScrollPanePeer createScrollPane (ScrollPane sp)
{
+ checkHeadless();
return new GtkScrollPanePeer (sp);
}
protected ScrollbarPeer createScrollbar (Scrollbar sb)
{
+ checkHeadless();
return new GtkScrollbarPeer (sb);
}
protected TextAreaPeer createTextArea (TextArea ta)
{
+ checkHeadless();
return new GtkTextAreaPeer (ta);
}
protected TextFieldPeer createTextField (TextField tf)
{
+ checkHeadless();
return new GtkTextFieldPeer (tf);
}
protected WindowPeer createWindow (Window w)
{
+ checkHeadless();
GtkMainThread.createWindow();
return new GtkWindowPeer (w);
}
public EmbeddedWindowPeer createEmbeddedWindow (EmbeddedWindow w)
{
+ checkHeadless();
GtkMainThread.createWindow();
return new GtkEmbeddedWindowPeer (w);
}
@@ -603,6 +613,8 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent e)
{
+ if (GraphicsEnvironment.isHeadless())
+ throw new InvalidDnDOperationException();
return new GtkDragSourceContextPeer(e);
}
@@ -612,7 +624,8 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
int actions,
DragGestureListener l)
{
- if (recognizer.getName().equals("java.awt.dnd.MouseDragGestureRecognizer"))
+ if (recognizer.getName().equals("java.awt.dnd.MouseDragGestureRecognizer")
+ && ! GraphicsEnvironment.isHeadless())
{
GtkMouseDragGestureRecognizer gestureRecognizer
= new GtkMouseDragGestureRecognizer(ds, comp, actions, l);
@@ -672,6 +685,12 @@ public class GtkToolkit extends gnu.java.awt.ClasspathToolkit
|| state == Frame.MAXIMIZED_BOTH;
}
+ private void checkHeadless()
+ {
+ if (GraphicsEnvironment.isHeadless())
+ throw new HeadlessException();
+ }
+
public native int getMouseNumberOfButtons();
} // class GtkToolkit