diff options
Diffstat (limited to 'gnu/java/awt/peer/gtk')
-rw-r--r-- | gnu/java/awt/peer/gtk/BufferedImageGraphics.java | 122 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/CairoGraphics2D.java | 295 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/CairoSurface.java | 5 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/ComponentGraphics.java | 51 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/FreetypeGlyphVector.java | 4 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GdkFontMetrics.java | 157 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GdkFontPeer.java | 217 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkComponentPeer.java | 56 | ||||
-rw-r--r-- | gnu/java/awt/peer/gtk/GtkToolkit.java | 51 |
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 |