diff options
author | Thomas Fitzsimmons <fitzsim@redhat.com> | 2006-06-14 03:38:34 +0000 |
---|---|---|
committer | Thomas Fitzsimmons <fitzsim@gcc.gnu.org> | 2006-06-14 03:38:34 +0000 |
commit | 648e8d6dd39f9bb1a61b7886007088e1064f7dae (patch) | |
tree | 4ead311615cefc89deebca761f0deb7edf23dcb8 /libjava/classpath/gnu/java/awt/peer | |
parent | e3d437c0561389c39a8232327982baba7e9dfe46 (diff) | |
download | gcc-648e8d6dd39f9bb1a61b7886007088e1064f7dae.zip gcc-648e8d6dd39f9bb1a61b7886007088e1064f7dae.tar.gz gcc-648e8d6dd39f9bb1a61b7886007088e1064f7dae.tar.bz2 |
configure: Regenerate.
2006-06-13 Thomas Fitzsimmons <fitzsim@redhat.com>
* configure: Regenerate.
* Makefile.in: Regenerate.
* configure.ac (--enable-plugin): New option.
(ac_configure_args): Add --enable-tool-wrappers.
(ac_configure_args): Add --disable-plugin unless --enable-plugin
was specified.
* gcj/Makefile.in: Regenerate.
* sources.am (gnu_java_net_source_files): Add
classpath/gnu/java/net/IndexListParser.java.
(property_files): Remove
classpath/resource/gnu/classpath/tools/jarsigner/MessageBundle.properties,
classpath/resource/gnu/classpath/tools/keytool/MessageBundle.properties.
Add
classpath/resource/gnu/classpath/tools/appletviewer/MessagesBundle.properties,
classpath/resource/gnu/classpath/tools/appletviewer/MessagesBundle_de.properties,
classpath/resource/gnu/classpath/tools/getopt/Messages.properties,
classpath/resource/gnu/classpath/tools/jar/messages.properties,
classpath/resource/gnu/classpath/tools/jarsigner/messages.properties,
classpath/resource/gnu/classpath/tools/keytool/messages.properties,
classpath/resource/gnu/classpath/tools/native2ascii/messages.properties,
classpath/resource/gnu/classpath/tools/serialver/messages.properties.
* classpath/Makefile.in: Regenerate.
* classpath/native/jni/gtk-peer/cairographics2d.h,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoGraphics2D.c,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_ComponentGraphics.c,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkVolatileImage.c,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_CairoSurface.c,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkTextLayout.c:
Merge from GNU Classpath.
* classpath/native/Makefile.in: Regenerate.
* classpath/native/jawt/Makefile.in: Regenerate.
* classpath/native/jawt/Makefile.am: Install libjawt.so in GCJ's
versioned library directory.
* classpath/native/Makefile.am: Add plugin directory if
--enable-plugin was specified.
* classpath/native/plugin/Makefile.in: Regenerate. *
classpath/native/plugin/Makefile.am: Install libgcjwebplugin.so in
GCJ's versioned library directory.
* classpath/resource/gnu/classpath/tools/native2ascii/messages.properties:
New file.
* classpath/resource/gnu/classpath/tools/getopt/Messages.properties:
Likewise.
* classpath/resource/gnu/classpath/tools/jarsigner/messages.properties:
Likewise.
* classpath/resource/gnu/classpath/tools/jarsigner/MessageBundle.properties:
Remove file.
* classpath/resource/gnu/classpath/tools/keytool/messages.properties:
New file.
* classpath/resource/gnu/classpath/tools/keytool/MessageBundle.properties:
Remove file.
* classpath/resource/gnu/classpath/tools/appletviewer/MessagesBundle_de.properties:
New file.
* classpath/resource/gnu/classpath/tools/appletviewer/MessagesBundle.properties:
Likewise.
* classpath/resource/gnu/classpath/tools/jar/messages.properties:
Likewise.
* classpath/resource/gnu/classpath/tools/serialver/messages.properties:
Likewise.
* classpath/gnu/java/net/IndexListParser.java:
Likewise.
* classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java,
classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,
classpath/gnu/java/awt/peer/gtk/CairoSurface.java,
classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java,
classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java,
classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java,
classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java,
classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java,
classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java,
classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java,
classpath/gnu/java/awt/font/opentype/truetype/VirtualMachine.java,
classpath/gnu/java/awt/java2d/PolyEdge.java,
classpath/gnu/java/awt/java2d/AbstractGraphics2D.java: Merge from
GNU Classpath.
* classpath/tools/toolwrapper.c: Replace tools.zip reference with
libgcj-tools-4.2.0.jar.
* classpath/tools/Makefile.in: Regenerate.
* classpath/tools/Makefile.am: Rename tools.zip to
libgcj-tools-4.2.0.jar. Install libgcj-tools-4.2.0.jar in
$(datadir)/java.
* classpath/javax/swing/JTabbedPane.java,
classpath/javax/swing/text/DefaultStyledDocument.java,
classpath/javax/swing/text/html/HTMLDocument.java,
classpath/javax/swing/text/GapContent.java,
classpath/javax/swing/JComponent.java,
classpath/javax/swing/RepaintManager.java,
classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java,
classpath/javax/swing/plaf/basic/BasicScrollBarUI.java,
classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java,
classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java,
classpath/javax/swing/plaf/basic/BasicLookAndFeel.java,
classpath/javax/swing/plaf/metal/MetalButtonUI.java,
classpath/java/text/Bidi.java,
classpath/java/awt/image/BufferedImage.java,
classpath/java/awt/datatransfer/DataFlavor.java,
classpath/java/awt/geom/AffineTransform.java,
classpath/java/awt/dnd/DropTargetDropEvent.java,
classpath/java/awt/dnd/DropTargetContext.java,
classpath/java/awt/font/TextLayout.java,
classpath/include/gnu_java_awt_peer_gtk_ComponentGraphics.h,
classpath/include/gnu_java_awt_peer_gtk_CairoGraphics2D.h,
classpath/include/gnu_java_awt_peer_gtk_FreetypeGlyphVector.h,
classpath/include/gnu_java_awt_peer_gtk_GdkTextLayout.h,
classpath/include/gnu_java_awt_peer_gtk_GtkVolatileImage.h,
classpath/include/gnu_java_awt_peer_gtk_CairoSurface.h: Merge from
GNU Classpath.
* classpath/include/gnu_java_awt_peer_gtk_GdkGraphics.h,
classpath/include/gnu_java_awt_peer_gtk_GdkGraphics2D.h,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c,
classpath/native/jni/gtk-peer/gtkcairopeer.h,
classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c:
Remove files.
* classpath/Makefile.am (SUBDIRS, DIST_SUBDIRS): Include tools
directory.
* include/Makefile.in: Regenerate.
* testsuite/Makefile.in: Regenerate.
From-SVN: r114633
Diffstat (limited to 'libjava/classpath/gnu/java/awt/peer')
10 files changed, 744 insertions, 248 deletions
diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java index 3179d33..9f8f494 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java @@ -38,14 +38,12 @@ exception statement from your version. */ package gnu.java.awt.peer.gtk; -import gnu.classpath.Configuration; import gnu.java.awt.ClasspathToolkit; import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; -import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; @@ -63,11 +61,12 @@ import java.awt.TexturePaint; import java.awt.Toolkit; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; +import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Area; -import java.awt.geom.Line2D; 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; @@ -77,12 +76,11 @@ import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ColorModel; -import java.awt.image.CropImageFilter; import java.awt.image.DataBuffer; import java.awt.image.DataBufferInt; import java.awt.image.DirectColorModel; -import java.awt.image.FilteredImageSource; import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; import java.awt.image.ImagingOpException; import java.awt.image.MultiPixelPackedSampleModel; import java.awt.image.Raster; @@ -94,7 +92,6 @@ import java.awt.image.renderable.RenderableImage; import java.text.AttributedCharacterIterator; import java.util.HashMap; import java.util.Map; -import java.util.Stack; /** * This is an abstract implementation of Graphics2D on Cairo. @@ -241,13 +238,10 @@ public abstract class CairoGraphics2D extends Graphics2D bg = new Color(g.bg.getRGB()); } - if (g.clip == null) - clip = null; - else - clip = new Rectangle(g.getClipBounds()); + clip = g.getClip(); if (g.transform == null) - transform = new AffineTransform(); + transform = null; else transform = new AffineTransform(g.transform); @@ -257,7 +251,8 @@ public abstract class CairoGraphics2D extends Graphics2D setBackground(bg); setPaint(paint); setStroke(stroke); - setTransform(transform); + setTransformImpl(transform); + setClip(clip); } /** @@ -275,8 +270,8 @@ public abstract class CairoGraphics2D extends Graphics2D * they have additional native structures. */ public void dispose() - { - disposeNative(); + { + disposeNative(nativePointer); nativePointer = 0; } @@ -304,7 +299,7 @@ public abstract class CairoGraphics2D extends Graphics2D /** * Dispose of allocate native resouces. */ - public native void disposeNative(); + public native void disposeNative(long pointer); /** * Draw pixels as an RGBA int matrix @@ -312,119 +307,125 @@ public abstract class CairoGraphics2D extends Graphics2D * @param stride - stride of the array width * @param i2u - affine transform array */ - private native void drawPixels(int[] pixels, int w, int h, int stride, - double[] i2u); + private native void drawPixels(long pointer, int[] pixels, int w, int h, + int stride, double[] i2u, double alpha); - private native void setGradient(double x1, double y1, double x2, double y2, + private native void setGradient(long pointer, double x1, double y1, + double x2, double y2, int r1, int g1, int b1, int a1, int r2, int g2, int b2, int a2, boolean cyclic); - private native void setTexturePixels(int[] pixels, int w, int h, int stride); + private native void setTexturePixels(long pointer, int[] pixels, int w, + int h, int stride); /** * Set the current transform matrix */ - private native void cairoSetMatrix(double[] m); + private native void cairoSetMatrix(long pointer, double[] m); /** * Set the compositing operator */ - private native void cairoSetOperator(int cairoOperator); + private native void cairoSetOperator(long pointer, int cairoOperator); /** * Sets the current color in RGBA as a 0.0-1.0 double */ - private native void cairoSetRGBAColor(double red, double green, + private native void cairoSetRGBAColor(long pointer, double red, double green, double blue, double alpha); /** * Sets the current winding rule in Cairo */ - private native void cairoSetFillRule(int cairoFillRule); + private native void cairoSetFillRule(long pointer, int cairoFillRule); /** * Set the line style, cap, join and miter limit. * Cap and join parameters are in the BasicStroke enumerations. */ - private native void cairoSetLine(double width, int cap, int join, double miterLimit); + private native void cairoSetLine(long pointer, double width, int cap, + int join, double miterLimit); /** * Set the dash style */ - private native void cairoSetDash(double[] dashes, int ndash, double offset); + private native void cairoSetDash(long pointer, double[] dashes, int ndash, + double offset); /* * Draws a Glyph Vector */ - native void cairoDrawGlyphVector(GdkFontPeer font, + native void cairoDrawGlyphVector(long pointer, GdkFontPeer font, float x, float y, int n, int[] codes, float[] positions); - private native void cairoRelCurveTo(double dx1, double dy1, double dx2, - double dy2, double dx3, double dy3); + private native void cairoRelCurveTo(long pointer, double dx1, double dy1, + double dx2, double dy2, double dx3, + double dy3); /** * Appends a rectangle to the current path */ - private native void cairoRectangle(double x, double y, double width, - double height); + private native void cairoRectangle(long pointer, double x, double y, + double width, double height); /** * New current path */ - private native void cairoNewPath(); + private native void cairoNewPath(long pointer); /** * Close current path */ - private native void cairoClosePath(); + private native void cairoClosePath(long pointer); /** moveTo */ - private native void cairoMoveTo(double x, double y); + private native void cairoMoveTo(long pointer, double x, double y); /** relative moveTo */ - private native void cairoRelMoveTo(double dx, double dy); + private native void cairoRelMoveTo(long pointer, double dx, double dy); /** lineTo */ - private native void cairoLineTo(double x, double y); + private native void cairoLineTo(long pointer, double x, double y); /** relative lineTo */ - private native void cairoRelLineTo(double dx, double dy); + private native void cairoRelLineTo(long pointer, double dx, double dy); /** Cubic curve-to */ - private native void cairoCurveTo(double x1, double y1, double x2, double y2, + private native void cairoCurveTo(long pointer, double x1, double y1, + double x2, double y2, double x3, double y3); /** * Stroke current path */ - private native void cairoStroke(); + private native void cairoStroke(long pointer); /** * Fill current path */ - private native void cairoFill(); + private native void cairoFill(long pointer, double alpha); /** * Clip current path */ - private native void cairoClip(); + private native void cairoClip(long pointer); /** * Save clip */ - private native void cairoPreserveClip(); + private native void cairoPreserveClip(long pointer); /** * Save clip */ - private native void cairoResetClip(); + private native void cairoResetClip(long pointer); /** * Set interpolation types */ - private native void cairoSurfaceSetFilter(int filter); + private native void cairoSurfaceSetFilter(long pointer, int filter); ///////////////////////// TRANSFORMS /////////////////////////////////// /** @@ -432,43 +433,60 @@ public abstract class CairoGraphics2D extends Graphics2D */ public void setTransform(AffineTransform tx) { + // Transform clip into target space using the old transform. + updateClip(transform); + + // Update the native transform. + setTransformImpl(tx); + + // Transform the clip back into user space using the inverse new transform. + try + { + updateClip(transform.createInverse()); + } + catch (NoninvertibleTransformException ex) + { + // TODO: How can we deal properly with this? + ex.printStackTrace(); + } + + if (clip != null) + setClip(clip); + } + + private void setTransformImpl(AffineTransform tx) + { transform = tx; if (transform != null) { - double[] m = new double[6]; - transform.getMatrix(m); - cairoSetMatrix(m); + double[] m = new double[6]; + transform.getMatrix(m); + cairoSetMatrix(nativePointer, m); } } - + public void transform(AffineTransform tx) { if (transform == null) transform = new AffineTransform(tx); else transform.concatenate(tx); - setTransform(transform); + if (clip != null) { - // FIXME: this should actuall try to transform the shape - // rather than degrade to bounds. - Rectangle2D r = clip.getBounds2D(); - double[] coords = new double[] - { - r.getX(), r.getY(), r.getX() + r.getWidth(), - r.getY() + r.getHeight() - }; - try - { - tx.createInverse().transform(coords, 0, coords, 0, 2); - r.setRect(coords[0], coords[1], coords[2] - coords[0], - coords[3] - coords[1]); - clip = r; - } - catch (java.awt.geom.NoninvertibleTransformException e) - { - } + try + { + AffineTransform clipTransform = tx.createInverse(); + updateClip(clipTransform); + } + catch (NoninvertibleTransformException ex) + { + // TODO: How can we deal properly with this? + ex.printStackTrace(); + } } + + setTransformImpl(transform); } public void rotate(double theta) @@ -501,18 +519,21 @@ public abstract class CairoGraphics2D extends Graphics2D { // FIXME: this should actuall try to transform the shape // rather than degrade to bounds. - Rectangle2D r; - if (clip instanceof Rectangle2D) - r = (Rectangle2D) clip; + { + Rectangle2D r = (Rectangle2D) clip; + r.setRect(r.getX() - tx, r.getY() - ty, r.getWidth(), + r.getHeight()); + } else - r = clip.getBounds2D(); - - r.setRect(r.getX() - tx, r.getY() - ty, r.getWidth(), r.getHeight()); - clip = r; + { + AffineTransform clipTransform = + AffineTransform.getTranslateInstance(-tx, -ty); + updateClip(clipTransform); + } } - setTransform(transform); + setTransformImpl(transform); } public void translate(int x, int y) @@ -531,19 +552,27 @@ public abstract class CairoGraphics2D extends Graphics2D { // Do not touch clip when s == null. if (s == null) - return; + { + // The spec says this should clear the clip. The reference + // implementation throws a NullPointerException instead. I think, + // in this case we should conform to the specs, as it shouldn't + // affect compatibility. + setClip(null); + return; + } // If the current clip is still null, initialize it. if (clip == null) - clip = originalClip; - - // This is so common, let's optimize this. - else if (clip instanceof Rectangle2D && s instanceof Rectangle2D) + { + clip = getRealBounds(); + } + + // This is so common, let's optimize this. + if (clip instanceof Rectangle2D && s instanceof Rectangle2D) { Rectangle2D clipRect = (Rectangle2D) clip; Rectangle2D r = (Rectangle2D) s; Rectangle2D.intersect(clipRect, r, clipRect); - // Call setClip so that subclasses get notified. setClip(clipRect); } else @@ -603,7 +632,7 @@ 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); - setTexturePixels(pixels, width, height, width); + setTexturePixels(nativePointer, pixels, width, height, width); } else if (paint instanceof GradientPaint) { @@ -612,9 +641,10 @@ public abstract class CairoGraphics2D extends Graphics2D Point2D p2 = gp.getPoint2(); Color c1 = gp.getColor1(); Color c2 = gp.getColor2(); - setGradient(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c1.getRed(), - c1.getGreen(), c1.getBlue(), c1.getAlpha(), c2.getRed(), - c2.getGreen(), c2.getBlue(), c2.getAlpha(), gp.isCyclic()); + setGradient(nativePointer, p1.getX(), p1.getY(), p2.getX(), p2.getY(), + c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha(), + c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha(), + gp.isCyclic()); } else throw new java.lang.UnsupportedOperationException(); @@ -631,7 +661,7 @@ public abstract class CairoGraphics2D extends Graphics2D if (stroke instanceof BasicStroke) { BasicStroke bs = (BasicStroke) stroke; - cairoSetLine(bs.getLineWidth(), bs.getEndCap(), + cairoSetLine(nativePointer, bs.getLineWidth(), bs.getEndCap(), bs.getLineJoin(), bs.getMiterLimit()); float[] dashes = bs.getDashArray(); @@ -640,11 +670,11 @@ public abstract class CairoGraphics2D extends Graphics2D double[] double_dashes = new double[dashes.length]; for (int i = 0; i < dashes.length; i++) double_dashes[i] = dashes[i]; - cairoSetDash(double_dashes, double_dashes.length, + cairoSetDash(nativePointer, double_dashes, double_dashes.length, (double) bs.getDashPhase()); } else - cairoSetDash(new double[0], 0, 0.0); + cairoSetDash(nativePointer, new double[0], 0, 0.0); } } @@ -675,8 +705,9 @@ public abstract class CairoGraphics2D extends Graphics2D { if (fg == null) fg = Color.BLACK; - cairoSetRGBAColor(fg.getRed() / 255.0, fg.getGreen() / 255.0, - fg.getBlue() / 255.0, fg.getAlpha() / 255.0); + cairoSetRGBAColor(nativePointer, fg.getRed() / 255.0, + fg.getGreen() / 255.0,fg.getBlue() / 255.0, + fg.getAlpha() / 255.0); } public Color getColor() @@ -686,15 +717,30 @@ public abstract class CairoGraphics2D extends Graphics2D public void clipRect(int x, int y, int width, int height) { - clip(new Rectangle(x, y, width, height)); + if (clip == null) + setClip(new Rectangle(x, y, width, height)); + else if (clip instanceof Rectangle) + { + computeIntersection(x, y, width, height, (Rectangle) clip); + setClip(clip); + } + else + clip(new Rectangle(x, y, width, height)); } public Shape getClip() { if (clip == null) return null; - else + else if (clip instanceof Rectangle2D) return clip.getBounds2D(); //getClipInDevSpace(); + else + { + GeneralPath p = new GeneralPath(); + PathIterator pi = clip.getPathIterator(new AffineTransform()); + p.append(pi, false); + return p; + } } public Rectangle getClipBounds() @@ -734,7 +780,7 @@ public abstract class CairoGraphics2D extends Graphics2D } public void setClip(Shape s) - { + { // The first time the clip is set, save it as the original clip // to reset to on s == null. We can rely on this being non-null // because the constructor in subclasses is expected to set the @@ -745,23 +791,23 @@ public abstract class CairoGraphics2D extends Graphics2D firstClip = false; } - if (s == null) - clip = originalClip; - else - clip = s; - - cairoResetClip(); + clip = s; + cairoResetClip(nativePointer); - cairoNewPath(); - if (clip instanceof Rectangle2D) + if (clip != null) { - Rectangle2D r = (Rectangle2D) clip; - cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + cairoNewPath(nativePointer); + if (clip instanceof Rectangle2D) + { + Rectangle2D r = (Rectangle2D) clip; + cairoRectangle(nativePointer, r.getX(), r.getY(), r.getWidth(), + r.getHeight()); + } + else + walkPath(clip.getPathIterator(null), false); + + cairoClip(nativePointer); } - else - walkPath(clip.getPathIterator(null), false); - - cairoClip(); } public void setBackground(Color c) @@ -797,10 +843,7 @@ public abstract class CairoGraphics2D extends Graphics2D if (comp instanceof AlphaComposite) { AlphaComposite a = (AlphaComposite) comp; - cairoSetOperator(a.getRule()); - Color c = getColor(); - setColor(new Color(c.getRed(), c.getGreen(), c.getBlue(), - (int) (a.getAlpha() * ((float) c.getAlpha())))); + cairoSetOperator(nativePointer, a.getRule()); } else { @@ -813,38 +856,55 @@ public abstract class CairoGraphics2D extends Graphics2D public void draw(Shape s) { - if (stroke != null && ! (stroke instanceof BasicStroke)) + if ((stroke != null && ! (stroke instanceof BasicStroke)) + || (comp instanceof AlphaComposite + && ((AlphaComposite) comp).getAlpha() != 1.0)) { + // FIXME: This is a hack to work around BasicStrokes's current + // limitations wrt cubic curves. + // See CubicSegment.getDisplacedSegments(). + if (stroke instanceof BasicStroke) + { + PathIterator flatten = s.getPathIterator(new AffineTransform(), + 1.0); + GeneralPath p = new GeneralPath(); + p.append(flatten, false); + s = p; + } fill(stroke.createStrokedShape(s)); return; } - cairoNewPath(); + cairoNewPath(nativePointer); if (s instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D) s; - cairoRectangle(shifted(r.getX(), shiftDrawCalls), + cairoRectangle(nativePointer, shifted(r.getX(), shiftDrawCalls), shifted(r.getY(), shiftDrawCalls), r.getWidth(), r.getHeight()); } else walkPath(s.getPathIterator(null), shiftDrawCalls); - cairoStroke(); + cairoStroke(nativePointer); } public void fill(Shape s) { - cairoNewPath(); + cairoNewPath(nativePointer); if (s instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D) s; - cairoRectangle(r.getX(), r.getY(), r.getWidth(), r.getHeight()); + cairoRectangle(nativePointer, r.getX(), r.getY(), r.getWidth(), + r.getHeight()); } else walkPath(s.getPathIterator(null), false); - cairoFill(); + double alpha = 1.0; + if (comp instanceof AlphaComposite) + alpha = ((AlphaComposite) comp).getAlpha(); + cairoFill(nativePointer, alpha); } /** @@ -856,8 +916,8 @@ public abstract class CairoGraphics2D extends Graphics2D public void clearRect(int x, int y, int width, int height) { if (bg != null) - cairoSetRGBAColor(bg.getRed() / 255.0, bg.getGreen() / 255.0, - bg.getBlue() / 255.0, 1.0); + cairoSetRGBAColor(nativePointer, bg.getRed() / 255.0, + bg.getGreen() / 255.0, bg.getBlue() / 255.0, 1.0); fillRect(x, y, width, height); updateColor(); } @@ -1005,19 +1065,19 @@ public abstract class CairoGraphics2D extends Graphics2D || hintKey.equals(RenderingHints.KEY_ALPHA_INTERPOLATION)) { if (hintValue.equals(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) - cairoSurfaceSetFilter(0); + cairoSurfaceSetFilter(nativePointer, 0); else if (hintValue.equals(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) - cairoSurfaceSetFilter(1); + cairoSurfaceSetFilter(nativePointer, 1); else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) - cairoSurfaceSetFilter(2); + cairoSurfaceSetFilter(nativePointer, 2); else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) - cairoSurfaceSetFilter(3); + cairoSurfaceSetFilter(nativePointer, 3); else if (hintValue.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) - cairoSurfaceSetFilter(4); + cairoSurfaceSetFilter(nativePointer, 4); } shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) @@ -1037,22 +1097,22 @@ public abstract class CairoGraphics2D extends Graphics2D if (hints.containsKey(RenderingHints.KEY_INTERPOLATION)) { if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) - cairoSurfaceSetFilter(0); + cairoSurfaceSetFilter(nativePointer, 0); else if (hints.containsValue(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) - cairoSurfaceSetFilter(1); + cairoSurfaceSetFilter(nativePointer, 1); } if (hints.containsKey(RenderingHints.KEY_ALPHA_INTERPOLATION)) { if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) - cairoSurfaceSetFilter(2); + cairoSurfaceSetFilter(nativePointer, 2); else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) - cairoSurfaceSetFilter(3); + cairoSurfaceSetFilter(nativePointer, 3); else if (hints.containsValue(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) - cairoSurfaceSetFilter(4); + cairoSurfaceSetFilter(nativePointer, 4); } shiftDrawCalls = hints.containsValue(RenderingHints.VALUE_STROKE_NORMALIZE) @@ -1084,7 +1144,7 @@ public abstract class CairoGraphics2D extends Graphics2D // other way around. Therefore to get the "user -> pixel" transform // that cairo wants from "image -> user" transform that we currently // have, we will need to invert the transformation matrix. - AffineTransform invertedXform = new AffineTransform(); + AffineTransform invertedXform; try { @@ -1096,11 +1156,17 @@ public abstract class CairoGraphics2D extends Graphics2D + xform.toString()); } - // Unrecognized image - convert to a BufferedImage and come back. + // Unrecognized image - convert to a BufferedImage + // Note - this can get us in trouble when the gdk lock is re-acquired. + // for example by VolatileImage. See ComponentGraphics for how we work + // around this. if( !(img instanceof BufferedImage) ) - return this.drawImage(Toolkit.getDefaultToolkit(). - createImage(img.getSource()), - xform, bgcolor, obs); + { + ImageProducer source = img.getSource(); + if (source == null) + return false; + img = Toolkit.getDefaultToolkit().createImage(source); + } BufferedImage b = (BufferedImage) img; DataBuffer db; @@ -1117,9 +1183,13 @@ public abstract class CairoGraphics2D extends Graphics2D invertedXform.getMatrix(i2u); + double alpha = 1.0; + if (comp instanceof AlphaComposite) + alpha = ((AlphaComposite) comp).getAlpha(); + if(db instanceof CairoSurface) { - ((CairoSurface)db).drawSurface(this, i2u); + ((CairoSurface)db).drawSurface(nativePointer, i2u, alpha); return true; } @@ -1155,7 +1225,7 @@ public abstract class CairoGraphics2D extends Graphics2D null, 0, width); } - drawPixels(pixels, width, height, width, i2u); + drawPixels(nativePointer, pixels, width, height, width, i2u, alpha); // Cairo seems to lose the current color which must be restored. updateColor(); @@ -1271,8 +1341,8 @@ public abstract class CairoGraphics2D extends Graphics2D { if (str == null || str.length() == 0) return; - - drawGlyphVector(getFont().createGlyphVector(null, str), x, y); + (new TextLayout( str, getFont(), getFontRenderContext() )). + draw(this, x, y); } public void drawString(String str, int x, int y) @@ -1287,12 +1357,25 @@ public abstract class CairoGraphics2D extends Graphics2D public void drawGlyphVector(GlyphVector gv, float x, float y) { - int n = gv.getNumGlyphs (); - int[] codes = gv.getGlyphCodes (0, n, null); - float[] positions = gv.getGlyphPositions (0, n, null); - - setFont (gv.getFont ()); - cairoDrawGlyphVector( (GdkFontPeer)getFont().getPeer(), x, y, n, codes, positions); + double alpha = 1.0; + if (comp instanceof AlphaComposite) + alpha = ((AlphaComposite) comp).getAlpha(); + if (gv instanceof FreetypeGlyphVector && alpha == 1.0) + { + int n = gv.getNumGlyphs (); + int[] codes = gv.getGlyphCodes (0, n, null); + float[] positions = gv.getGlyphPositions (0, n, null); + + setFont (gv.getFont ()); + cairoDrawGlyphVector(nativePointer, (GdkFontPeer)getFont().getPeer(), + x, y, n, codes, positions); + } + else + { + translate(x, y); + fill(gv.getOutline()); + translate(-x, -y); + } } public void drawString(AttributedCharacterIterator ci, float x, float y) @@ -1445,7 +1528,11 @@ public abstract class CairoGraphics2D extends Graphics2D for (int i = 0; i < pixels.length; i++) pixels[i] |= 0xFF000000; - drawPixels(pixels, r.getWidth(), r.getHeight(), r.getWidth(), i2u); + double alpha = 1.0; + if (comp instanceof AlphaComposite) + alpha = ((AlphaComposite) comp).getAlpha(); + drawPixels(nativePointer, pixels, r.getWidth(), r.getHeight(), + r.getWidth(), i2u, alpha); // Cairo seems to lose the current color which must be restored. updateColor(); @@ -1473,7 +1560,7 @@ public abstract class CairoGraphics2D extends Graphics2D double y = 0; double[] coords = new double[6]; - cairoSetFillRule(p.getWindingRule()); + cairoSetFillRule(nativePointer, p.getWindingRule()); for (; ! p.isDone(); p.next()) { int seg = p.currentSegment(coords); @@ -1482,12 +1569,12 @@ public abstract class CairoGraphics2D extends Graphics2D case PathIterator.SEG_MOVETO: x = shifted(coords[0], doShift); y = shifted(coords[1], doShift); - cairoMoveTo(x, y); + cairoMoveTo(nativePointer, x, y); break; case PathIterator.SEG_LINETO: x = shifted(coords[0], doShift); y = shifted(coords[1], doShift); - cairoLineTo(x, y); + cairoLineTo(nativePointer, x, y); break; case PathIterator.SEG_QUADTO: // splitting a quadratic bezier into a cubic: @@ -1500,18 +1587,18 @@ public abstract class CairoGraphics2D extends Graphics2D x = shifted(coords[2], doShift); y = shifted(coords[3], doShift); - cairoCurveTo(x1, y1, x2, y2, x, y); + cairoCurveTo(nativePointer, x1, y1, x2, y2, x, y); break; case PathIterator.SEG_CUBICTO: x = shifted(coords[4], doShift); y = shifted(coords[5], doShift); - cairoCurveTo(shifted(coords[0], doShift), + cairoCurveTo(nativePointer, shifted(coords[0], doShift), shifted(coords[1], doShift), shifted(coords[2], doShift), shifted(coords[3], doShift), x, y); break; case PathIterator.SEG_CLOSE: - cairoClosePath(); + cairoClosePath(nativePointer); break; } } @@ -1583,4 +1670,47 @@ public abstract class CairoGraphics2D extends Graphics2D return db.getData(); } + + /** + * Helper method to transform the clip. This is called by the various + * transformation-manipulation methods to update the clip (which is in + * userspace) accordingly. + * + * The transform usually is the inverse transform that was applied to the + * graphics object. + * + * @param t the transform to apply to the clip + */ + private void updateClip(AffineTransform t) + { + if (clip == null) + return; + + if (! (clip instanceof GeneralPath)) + clip = new GeneralPath(clip); + + GeneralPath p = (GeneralPath) clip; + p.transform(t); + } + + private static Rectangle computeIntersection(int x, int y, int w, int h, + Rectangle rect) + { + int x2 = (int) rect.x; + int y2 = (int) rect.y; + int w2 = (int) rect.width; + int h2 = (int) rect.height; + + int dx = (x > x2) ? x : x2; + int dy = (y > y2) ? y : y2; + int dw = (x + w < x2 + w2) ? (x + w - dx) : (x2 + w2 - dx); + int dh = (y + h < y2 + h2) ? (y + h - dy) : (y2 + h2 - dy); + + if (dw >= 0 && dh >= 0) + rect.setBounds(dx, dy, dw, dh); + else + rect.setBounds(0, 0, 0, 0); + + return rect; + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java index e19c9b9..5ccd2e1 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurface.java @@ -88,49 +88,65 @@ public class CairoSurface extends DataBuffer /** * Allocates and clears the buffer and creates the cairo surface. * @param width, height - the image size - * @param stride - the buffer row stride. + * @param stride - the buffer row stride. (in ints) */ private native void create(int width, int height, int stride); /** * Destroys the cairo surface and frees the buffer. */ - private native void destroy(); + private native void destroy(long surfacePointer, long bufferPointer); /** * Gets buffer elements */ - private native int nativeGetElem(int i); + private native int nativeGetElem(long bufferPointer, int i); /** * Sets buffer elements. */ - private native void nativeSetElem(int i, int val); + private native void nativeSetElem(long bufferPointer, int i, int val); /** * Draws this image to a given CairoGraphics context, * with an affine transform given by i2u. */ - public native void drawSurface(CairoGraphics2D context, double[] i2u); + public native void nativeDrawSurface(long surfacePointer, long contextPointer, + double[] i2u, double alpha); + + public void drawSurface(long contextPointer, double[] i2u, double alpha) + { + nativeDrawSurface(surfacePointer, contextPointer, i2u, alpha); + } /** * getPixels -return the pixels as a java array. */ - native int[] getPixels(int size); + native int[] nativeGetPixels(long bufferPointer, int size); + + public int[] getPixels(int size) + { + return nativeGetPixels(bufferPointer, size); + } /** * getPixels -return the pixels as a java array. */ - native void setPixels(int[] pixels); + native void nativeSetPixels(long bufferPointer, int[] pixels); + + public void setPixels(int[] pixels) + { + nativeSetPixels(bufferPointer, pixels); + } - native long getFlippedBuffer(int size); + native long getFlippedBuffer(long bufferPointer, int size); /** * Create a cairo_surface_t with specified width and height. * The format will be ARGB32 with premultiplied alpha and native bit * and word ordering. */ - CairoSurface(int width, int height) + public CairoSurface(int width, int height) { super(DataBuffer.TYPE_INT, width * height); @@ -140,7 +156,7 @@ public class CairoSurface extends DataBuffer this.width = width; this.height = height; - create(width, height, width * 4); + create(width, height, width); if(surfacePointer == 0 || bufferPointer == 0) throw new Error("Could not allocate bitmap."); @@ -160,7 +176,7 @@ public class CairoSurface extends DataBuffer width = image.width; height = image.height; - create(width, height, width * 4); + create(width, height, width); if(surfacePointer == 0 || bufferPointer == 0) throw new Error("Could not allocate bitmap."); @@ -195,7 +211,7 @@ public class CairoSurface extends DataBuffer public void dispose() { if(surfacePointer != 0) - destroy(); + destroy(surfacePointer, bufferPointer); } /** @@ -211,7 +227,8 @@ public class CairoSurface extends DataBuffer */ public GtkImage getGtkImage() { - return new GtkImage( width, height, getFlippedBuffer( width * height )); + return new GtkImage( width, height, + getFlippedBuffer(bufferPointer, width * height )); } /** @@ -251,7 +268,7 @@ public class CairoSurface extends DataBuffer { if(bank != 0 || i < 0 || i >= width*height) throw new IndexOutOfBoundsException(i+" size: "+width*height); - return nativeGetElem(i); + return nativeGetElem(bufferPointer, i); } /** @@ -261,7 +278,7 @@ public class CairoSurface extends DataBuffer { if(bank != 0 || i < 0 || i >= width*height) throw new IndexOutOfBoundsException(i+" size: "+width*height); - nativeSetElem(i, val); + nativeSetElem(bufferPointer, i, val); } /** @@ -277,12 +294,22 @@ public class CairoSurface extends DataBuffer * Creates a cairo_t drawing context, returns the pointer as a long. * Used by CairoSurfaceGraphics. */ - native long newCairoContext(); + native long nativeNewCairoContext(long surfacePointer); + + public long newCairoContext() + { + return nativeNewCairoContext(surfacePointer); + } /** * Copy an area of the surface. Expects parameters must be within bounds. * Count on a segfault otherwise. */ - native void copyAreaNative(int x, int y, int width, int height, - int dx, int dy, int stride); + native void copyAreaNative2(long bufferPointer, int x, int y, int width, + int height, int dx, int dy, int stride); + public void copyAreaNative(int x, int y, int width, + int height, int dx, int dy, int stride) + { + copyAreaNative2(bufferPointer, x, y, width, height, dx, dy, stride); + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java index 38c549d..91f0b49 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/CairoSurfaceGraphics.java @@ -40,6 +40,7 @@ package gnu.java.awt.peer.gtk; import java.awt.Graphics; import java.awt.Color; +import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.Point; import java.awt.Graphics2D; @@ -63,7 +64,6 @@ public class CairoSurfaceGraphics extends CairoGraphics2D this.surface = surface; cairo_t = surface.newCairoContext(); setup( cairo_t ); - setClip(0, 0, surface.width, surface.height); } /** @@ -75,7 +75,6 @@ public class CairoSurfaceGraphics extends CairoGraphics2D surface = copyFrom.surface; cairo_t = surface.newCairoContext(); copy( copyFrom, cairo_t ); - setClip(0, 0, surface.width, surface.height); } public Graphics create() @@ -85,7 +84,7 @@ public class CairoSurfaceGraphics extends CairoGraphics2D public GraphicsConfiguration getDeviceConfiguration() { - throw new UnsupportedOperationException(); + return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); } protected Rectangle2D getRealBounds() diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java index c6cf494..d1d3c28 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java @@ -46,6 +46,7 @@ import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Rectangle; import java.awt.Shape; +import java.awt.Toolkit; import java.awt.Point; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; @@ -53,6 +54,7 @@ import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; import java.awt.image.ImagingOpException; import java.awt.image.RenderedImage; @@ -67,6 +69,35 @@ public class ComponentGraphics extends CairoGraphics2D private GtkComponentPeer component; protected long cairo_t; + private static ThreadLocal hasLock = new ThreadLocal(); + private static Integer ONE = Integer.valueOf(1); + + private void lock() + { + Integer i = (Integer) hasLock.get(); + if (i == null) + { + start_gdk_drawing(); + hasLock.set(ONE); + } + else + hasLock.set(Integer.valueOf(i.intValue() + 1)); + } + + private void unlock() + { + Integer i = (Integer) hasLock.get(); + if (i == null) + throw new IllegalStateException(); + if (i == ONE) + { + hasLock.set(null); + end_gdk_drawing(); + } + else + hasLock.set(Integer.valueOf(i.intValue() - 1)); + } + ComponentGraphics() { } @@ -104,8 +135,8 @@ public class ComponentGraphics extends CairoGraphics2D */ public void dispose() { - disposeSurface(nativePointer); super.dispose(); + disposeSurface(nativePointer); } /** @@ -138,7 +169,7 @@ public class ComponentGraphics extends CairoGraphics2D int width, int height, int dx, int dy); private native void drawVolatile(GtkComponentPeer component, - Image vimg, int x, int y, + long vimg, int x, int y, int width, int height); /** @@ -180,63 +211,152 @@ public class ComponentGraphics extends CairoGraphics2D */ public void draw(Shape s) { - start_gdk_drawing(); - super.draw(s); - end_gdk_drawing(); + lock(); + try + { + super.draw(s); + } + finally + { + unlock(); + } } public void fill(Shape s) { - start_gdk_drawing(); - super.fill(s); - end_gdk_drawing(); + lock(); + try + { + super.fill(s); + } + finally + { + unlock(); + } } public void drawRenderedImage(RenderedImage image, AffineTransform xform) { - start_gdk_drawing(); - super.drawRenderedImage(image, xform); - end_gdk_drawing(); + lock(); + try + { + super.drawRenderedImage(image, xform); + } + finally + { + unlock(); + } } protected boolean drawImage(Image img, AffineTransform xform, Color bgcolor, ImageObserver obs) { - start_gdk_drawing(); - boolean rv = super.drawImage(img, xform, bgcolor, obs); - end_gdk_drawing(); + boolean rv; + lock(); + try + { + rv = super.drawImage(img, xform, bgcolor, obs); + } + finally + { + unlock(); + } return rv; } public void drawGlyphVector(GlyphVector gv, float x, float y) { - start_gdk_drawing(); - super.drawGlyphVector(gv, x, y); - end_gdk_drawing(); + lock(); + try + { + super.drawGlyphVector(gv, x, y); + } + finally + { + unlock(); + } } public boolean drawImage(Image img, int x, int y, ImageObserver observer) { - if( img instanceof GtkVolatileImage ) + // If it is a GtkVolatileImage with an "easy" transform then + // draw directly. Always pass a BufferedImage to super to avoid + // deadlock (see Note in CairoGraphics.drawImage()). + if (img instanceof GtkVolatileImage) { - drawVolatile( component, img, x, y - 20, - ((GtkVolatileImage)img).width, - ((GtkVolatileImage)img).height ); - return true; - } - return super.drawImage( img, x, y, observer ); + GtkVolatileImage vimg = (GtkVolatileImage) img; + int type = transform.getType(); + if (type == AffineTransform.TYPE_IDENTITY) + { + drawVolatile(component, vimg.nativePointer, + x, y, vimg.width, vimg.height); + return true; + } + else if (type == AffineTransform.TYPE_TRANSLATION) + { + x += transform.getTranslateX(); + y += transform.getTranslateY(); + drawVolatile(component, vimg.nativePointer, + x, y, vimg.width, vimg.height); + return true; + } + else + return super.drawImage(vimg.getSnapshot(), x, y, observer); + } + + BufferedImage bimg; + if (img instanceof BufferedImage) + bimg = (BufferedImage) img; + else + { + ImageProducer source = img.getSource(); + if (source == null) + return false; + bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source); + } + return super.drawImage(bimg, x, y, observer); } public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { - if( img instanceof GtkVolatileImage ) + // If it is a GtkVolatileImage with an "easy" transform then + // draw directly. Always pass a BufferedImage to super to avoid + // deadlock (see Note in CairoGraphics.drawImage()). + if (img instanceof GtkVolatileImage) + { + GtkVolatileImage vimg = (GtkVolatileImage) img; + int type = transform.getType(); + if (type == AffineTransform.TYPE_IDENTITY) + { + drawVolatile(component, vimg.nativePointer, + x, y, width, height); + return true; + } + else if (type == AffineTransform.TYPE_TRANSLATION) + { + x += transform.getTranslateX(); + y += transform.getTranslateY(); + drawVolatile(component, vimg.nativePointer, + x, y, width, height); + return true; + } + else + return super.drawImage(vimg.getSnapshot(), x, y, + width, height, observer); + } + + BufferedImage bimg; + if (img instanceof BufferedImage) + bimg = (BufferedImage) img; + else { - drawVolatile( component, img, x, y - 20, - width, height ); - return true; - } - return super.drawImage( img, x, y, width, height, observer ); + ImageProducer source = img.getSource(); + if (source == null) + return false; + bimg = (BufferedImage) Toolkit.getDefaultToolkit().createImage(source); + } + return super.drawImage(bimg, x, y, width, height, observer); } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java index 0f8ce6d..4978c6a 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/FreetypeGlyphVector.java @@ -56,6 +56,9 @@ public class FreetypeGlyphVector extends GlyphVector private Font font; private GdkFontPeer peer; // ATTN: Accessed from native code. + private Rectangle2D logicalBounds; + + private float[] glyphPositions; /** * The string represented by this GlyphVector. */ @@ -81,11 +84,22 @@ public class FreetypeGlyphVector extends GlyphVector */ private AffineTransform[] glyphTransforms; + private GlyphMetrics[] metricsCache; + /** * Create a glyphvector from a given (Freetype) font and a String. */ public FreetypeGlyphVector(Font f, String s, FontRenderContext frc) { + this(f, s, frc, Font.LAYOUT_LEFT_TO_RIGHT); + } + + /** + * Create a glyphvector from a given (Freetype) font and a String. + */ + public FreetypeGlyphVector(Font f, String s, FontRenderContext frc, + int flags) + { this.s = s; this.font = f; this.frc = frc; @@ -94,6 +108,14 @@ public class FreetypeGlyphVector extends GlyphVector peer = (GdkFontPeer)font.getPeer(); getGlyphs(); + if( flags == Font.LAYOUT_RIGHT_TO_LEFT ) + { + // reverse the glyph ordering. + int[] temp = new int[ nGlyphs ]; + for(int i = 0; i < nGlyphs; i++) + temp[ i ] = glyphCodes[ nGlyphs - i - 1]; + glyphCodes = temp; + } performDefaultLayout(); } @@ -121,21 +143,25 @@ public class FreetypeGlyphVector extends GlyphVector { nGlyphs = s.codePointCount( 0, s.length() ); glyphCodes = new int[ nGlyphs ]; + int[] codePoints = new int[ nGlyphs ]; int stringIndex = 0; + for(int i = 0; i < nGlyphs; i++) { - glyphCodes[i] = getGlyph( s.codePointAt(stringIndex) ); + codePoints[i] = s.codePointAt( stringIndex ); // UTF32 surrogate handling - if( s.codePointAt( stringIndex ) != (int)s.charAt( stringIndex ) ) + if( codePoints[i] != (int)s.charAt( stringIndex ) ) stringIndex ++; stringIndex ++; } + + glyphCodes = getGlyphs( codePoints ); } /** * Returns the glyph code within the font for a given character */ - public native int getGlyph(int codepoint); + public native int[] getGlyphs(int[] codepoints); /** * Returns the kerning of a glyph pair @@ -180,12 +206,15 @@ public class FreetypeGlyphVector extends GlyphVector */ public void performDefaultLayout() { + logicalBounds = null; // invalidate caches. + glyphPositions = null; + glyphTransforms = new AffineTransform[ nGlyphs ]; double x = 0; + for(int i = 0; i < nGlyphs; i++) { GlyphMetrics gm = getGlyphMetrics( i ); - Rectangle2D r = gm.getBounds2D(); glyphTransforms[ i ] = AffineTransform.getTranslateInstance(x, 0); x += gm.getAdvanceX(); if( i > 0 ) @@ -235,19 +264,48 @@ public class FreetypeGlyphVector extends GlyphVector gm.getAdvanceX(), r.getHeight() ); } + /* + * FIXME: Not all glyph types are supported. + * (The JDK doesn't really seem to do so either) + */ + public void setupGlyphMetrics() + { + metricsCache = new GlyphMetrics[ nGlyphs ]; + + for(int i = 0; i < nGlyphs; i++) + { + GlyphMetrics gm = (GlyphMetrics) + peer.getGlyphMetrics( glyphCodes[ i ] ); + if( gm == null ) + { + double[] val = getMetricsNative( glyphCodes[ i ] ); + if( val == null ) + gm = null; + else + { + gm = new GlyphMetrics( true, + (float)val[1], + (float)val[2], + new Rectangle2D.Double + ( val[3], val[4], + val[5], val[6] ), + GlyphMetrics.STANDARD ); + peer.putGlyphMetrics( glyphCodes[ i ], gm ); + } + } + metricsCache[ i ] = gm; + } + } + /** * Returns the metrics of a single glyph. */ public GlyphMetrics getGlyphMetrics(int glyphIndex) { - double[] val = getMetricsNative( glyphCodes[ glyphIndex ] ); - if( val == null ) - return null; - - return new GlyphMetrics( true, (float)val[1], (float)val[2], - new Rectangle2D.Double( val[3], val[4], - val[5], val[6] ), - GlyphMetrics.STANDARD ); + if( metricsCache == null ) + setupGlyphMetrics(); + + return metricsCache[ glyphIndex ]; } /** @@ -275,6 +333,9 @@ public class FreetypeGlyphVector extends GlyphVector public float[] getGlyphPositions(int beginGlyphIndex, int numEntries, float[] positionReturn) { + if( glyphPositions != null ) + return glyphPositions; + float[] rval; if( positionReturn == null ) @@ -289,6 +350,7 @@ public class FreetypeGlyphVector extends GlyphVector rval[i * 2 + 1] = (float)p.getY(); } + glyphPositions = rval; return rval; } @@ -316,11 +378,19 @@ public class FreetypeGlyphVector extends GlyphVector { if( nGlyphs == 0 ) return new Rectangle2D.Double(0, 0, 0, 0); + if( logicalBounds != null ) + return logicalBounds; Rectangle2D rect = (Rectangle2D)getGlyphLogicalBounds( 0 ); for( int i = 1; i < nGlyphs; i++ ) - rect = rect.createUnion( (Rectangle2D)getGlyphLogicalBounds( i ) ); + { + Rectangle2D r2 = (Rectangle2D)getGlyphLogicalBounds( i ); + Point2D p = getGlyphPosition( i ); + r2.setRect( p.getX(), p.getY(), r2.getWidth(), r2.getHeight() ); + rect = rect.createUnion( r2 ); + } + logicalBounds = rect; return rect; } @@ -360,7 +430,9 @@ public class FreetypeGlyphVector extends GlyphVector public Shape getOutline(float x, float y) { AffineTransform tx = AffineTransform.getTranslateInstance( x, y ); - return tx.createTransformedShape( getOutline() ); + GeneralPath gp = (GeneralPath)getOutline(); + gp.transform( tx ); + return gp; } /** @@ -380,6 +452,8 @@ public class FreetypeGlyphVector extends GlyphVector // FIXME: Scaling, etc.? glyphTransforms[ glyphIndex ].setToTranslation( newPos.getX(), newPos.getY() ); + logicalBounds = null; + glyphPositions = null; } /** @@ -388,5 +462,7 @@ public class FreetypeGlyphVector extends GlyphVector public void setGlyphTransform(int glyphIndex, AffineTransform newTX) { glyphTransforms[ glyphIndex ].setTransform( newTX ); + logicalBounds = null; + glyphPositions = null; } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java index 7aa5e7a..f5ed8a7 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkFontPeer.java @@ -57,12 +57,18 @@ 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 native void initStaticState(); private final int native_state = GtkGenericPeer.getUniqueInteger (); private static ResourceBundle bundle; + + /** + * Cache GlyphMetrics objects. + */ + private HashMap metricsCache; static { @@ -145,6 +151,7 @@ public class GdkFontPeer extends ClasspathFontPeer super(name, style, size); initState (); setFont (this.familyName, this.style, (int)this.size); + metricsCache = new HashMap(); } public GdkFontPeer (String name, Map attributes) @@ -152,6 +159,7 @@ public class GdkFontPeer extends ClasspathFontPeer super(name, attributes); initState (); setFont (this.familyName, this.style, (int)this.size); + metricsCache = new HashMap(); } /** @@ -252,18 +260,25 @@ public class GdkFontPeer extends ClasspathFontPeer public byte getBaselineFor (Font font, char c) { - throw new UnsupportedOperationException (); + // FIXME: Actually check. + return Font.ROMAN_BASELINE; } - protected class GdkFontLineMetrics extends LineMetrics + private static class GdkFontLineMetrics extends LineMetrics { - FontMetrics fm; - int nchars; + private FontMetrics fm; + private int nchars; + private float strikethroughOffset, strikethroughThickness, + underlineOffset, underlineThickness; - public GdkFontLineMetrics (FontMetrics m, int n) + public GdkFontLineMetrics (GdkFontPeer fp, FontMetrics m, int n) { fm = m; nchars = n; + strikethroughOffset = 0f; + underlineOffset = 0f; + strikethroughThickness = ((float)fp.getSize(null)) / 12f; + underlineThickness = strikethroughThickness; } public float getAscent() @@ -272,7 +287,8 @@ public class GdkFontPeer extends ClasspathFontPeer } public int getBaselineIndex() - { + { + // FIXME return Font.ROMAN_BASELINE; } @@ -303,7 +319,7 @@ public class GdkFontPeer extends ClasspathFontPeer public LineMetrics getLineMetrics (Font font, CharacterIterator ci, int begin, int limit, FontRenderContext rc) { - return new GdkFontLineMetrics (getFontMetrics (font), limit - begin); + return new GdkFontLineMetrics (this, getFontMetrics (font), limit - begin); } public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc) @@ -350,20 +366,15 @@ public class GdkFontPeer extends ClasspathFontPeer char[] chars, int start, int limit, int flags) { - int nchars = (limit - start) + 1; - char[] nc = new char[nchars]; - - for (int i = 0; i < nchars; ++i) - nc[i] = chars[start + i]; - - return createGlyphVector (font, frc, - new StringCharacterIterator (new String (nc))); + return new FreetypeGlyphVector( font, new String( chars, start, + limit - start), + frc, flags); } public LineMetrics getLineMetrics (Font font, String str, FontRenderContext frc) { - return new GdkFontLineMetrics (getFontMetrics (font), str.length ()); + return new GdkFontLineMetrics (this, getFontMetrics (font), str.length ()); } public FontMetrics getFontMetrics (Font font) @@ -372,4 +383,21 @@ public class GdkFontPeer extends ClasspathFontPeer // the metrics cache. return Toolkit.getDefaultToolkit().getFontMetrics (font); } + + /** + * Returns a cached GlyphMetrics object for a given glyphcode, + * or null if it doesn't exist in the cache. + */ + GlyphMetrics getGlyphMetrics( int glyphCode ) + { + return (GlyphMetrics)metricsCache.get( new Integer( glyphCode ) ); + } + + /** + * Put a GlyphMetrics object in the cache. + */ + void putGlyphMetrics( int glyphCode, Object metrics ) + { + metricsCache.put( new Integer( glyphCode ), metrics ); + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index 4e6181f..cd047f2 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -103,8 +103,15 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder native void pumpBytes (byte[] bytes, int len) throws IOException; native void pumpDone () throws IOException; native void finish (boolean needsClose); - static native void streamImage(int[] bytes, String format, int width, int height, boolean hasAlpha, DataOutput sink); - + + /** + * Converts given image to bytes. + * Will call the GdkPixbufWriter for each chunk. + */ + static native void streamImage(int[] bytes, String format, + int width, int height, + boolean hasAlpha, GdkPixbufWriter writer); + // gdk-pixbuf provids data in RGBA format static final ColorModel cm = new DirectColorModel (32, 0xff000000, 0x00ff0000, @@ -461,7 +468,7 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder } private static class GdkPixbufWriter - extends ImageWriter + extends ImageWriter implements Runnable { String ext; public GdkPixbufWriter(GdkPixbufWriterSpi ownerSpi, Object ext) @@ -519,14 +526,106 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder model = img.getColorModel(); } + Thread workerThread = new Thread(this, "GdkPixbufWriter"); + workerThread.start(); processImageStarted(1); synchronized(pixbufLock) { streamImage(pixels, this.ext, width, height, model.hasAlpha(), - (DataOutput) this.getOutput()); + this); } + synchronized(data) + { + data.add(DATADONE); + data.notifyAll(); + } + + while (workerThread.isAlive()) + { + try + { + workerThread.join(); + } + catch (InterruptedException ioe) + { + // Ignored. + } + } + + if (exception != null) + throw exception; + processImageComplete(); } + + /** + * Object marking end of data from native streamImage code. + */ + private static final Object DATADONE = new Object(); + + /** + * Holds the data gotten from the native streamImage code. + * A worker thread will pull data out. + * Needs to be synchronized for access. + * The special object DATADONE is added when all data has been delivered. + */ + private ArrayList data = new ArrayList(); + + /** + * Holds any IOException thrown by the run method that needs + * to be rethrown by the write method. + */ + private IOException exception; + + /** Callback for streamImage native code. **/ + private void write(byte[] bs) + { + synchronized(data) + { + data.add(bs); + data.notifyAll(); + } + } + + public void run() + { + boolean done = false; + while (!done) + { + synchronized(data) + { + while (data.isEmpty()) + { + try + { + data.wait(); + } + catch (InterruptedException ie) + { + /* ignore */ + } + } + + Object o = data.remove(0); + if (o == DATADONE) + done = true; + else + { + DataOutput out = (DataOutput) getOutput(); + try + { + out.write((byte[]) o); + } + catch (IOException ioe) + { + // We are only interested in the first exception. + if (exception == null) + exception = ioe; + } + } + } + } + } } private static class GdkPixbufReader diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java index d6b3de8..a876522 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkTextLayout.java @@ -1,5 +1,5 @@ /* GdkTextLayout.java - Copyright (C) 2003, 2005 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -84,7 +84,7 @@ public class GdkTextLayout private native void dispose (); - private native void cairoDrawGdkTextLayout(CairoGraphics2D g, float x, float y); + private native void cairoDrawGdkTextLayout(long cg2d, float x, float y); static native void initStaticState(); @@ -216,7 +216,7 @@ public class GdkTextLayout public void draw (Graphics2D g2, float x, float y) { - cairoDrawGdkTextLayout((CairoGraphics2D)g2, x, y); + cairoDrawGdkTextLayout(((CairoGraphics2D) g2).nativePointer, x, y); } public TextHitInfo getStrongCaret (TextHitInfo hit1, diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java b/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java index 53bcd73..f38007f 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GtkVolatileImage.java @@ -57,14 +57,28 @@ public class GtkVolatileImage extends VolatileImage native long init(GtkComponentPeer component, int width, int height); - native void destroy(); + native void destroy(long pointer); - native int[] getPixels(); + native int[] nativeGetPixels(long pointer); + public int[] getPixels() + { + return nativeGetPixels(nativePointer); + } + + native void nativeCopyArea(long pointer, int x, int y, int w, int h, int dx, + int dy ); + public void copyArea(int x, int y, int w, int h, int dx, int dy) + { + nativeCopyArea(nativePointer, x, y, w, h, dx, dy); + } - native void copyArea( int x, int y, int w, int h, int dx, int dy ); + native void nativeDrawVolatile(long pointer, long srcPtr, int x, int y, + int w, int h ); + public void drawVolatile(long srcPtr, int x, int y, int w, int h ) + { + nativeDrawVolatile(nativePointer, srcPtr, x, y, w, h); + } - native void drawVolatile( long ptr, int x, int y, int w, int h ); - public GtkVolatileImage(GtkComponentPeer component, int width, int height, ImageCapabilities caps) { @@ -91,7 +105,7 @@ public class GtkVolatileImage extends VolatileImage public void dispose() { - destroy(); + destroy(nativePointer); } public BufferedImage getSnapshot() diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java index d5adfcf..fa84ea0 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/VolatileImageGraphics.java @@ -67,14 +67,12 @@ public class VolatileImageGraphics extends ComponentGraphics this.owner = img; cairo_t = initFromVolatile( owner.nativePointer, img.width, img.height ); setup( cairo_t ); - setClip( new Rectangle( 0, 0, img.width, img.height) ); } private VolatileImageGraphics(VolatileImageGraphics copy) { this.owner = copy.owner; - initFromVolatile( owner.nativePointer, owner.width, owner.height ); - setClip( new Rectangle( 0, 0, owner.width, owner.height) ); + cairo_t = initFromVolatile(owner.nativePointer, owner.width, owner.height); copy( copy, cairo_t ); } @@ -118,5 +116,10 @@ public class VolatileImageGraphics extends ComponentGraphics } return super.drawImage( img, x, y, width, height, observer ); } + + protected Rectangle2D getRealBounds() + { + return new Rectangle2D.Double(0, 0, owner.width, owner.height); + } } |