This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] various graphics2d fixes


hi,

these are just miscellaneous fixes which have accumulated to the
graphics2d implementation I did atop cairo. nothing revolutionary,
just a lot of minor fixups, so I bundled them up here in one
patch. changes to other areas (eg. swing) will follow in separate
patches.

comments? ok to commit?

-graydon

(patch is against gcj's libjava, but I'm also asking classpath because
 a similar one with pathnames altered is implied, for it)


2003-11-17  Graydon Hoare  <graydon@redhat.com>

	* gnu/java/awt/peer/gtk/GdkClasspathFontPeerMetrics.java: New file.
	* gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java 
	(GdkFontLineMetrics): New inner class.
	(getLineMetrics): Return new GdkFontLineMetrics.
	(getFontMetrics): Return new GdkClasspathFontPeerMetrics.
	(layoutGlyphVector): Create GdkGlyphVector.
	* gnu/java/awt/peer/gtk/GdkGraphics2D.java (stateStack): New member.
	(GdkGraphics2D): Initialize state via mathod calls.
	(cairoSetMatrix, cairoShowGlyphs): Simplify native calls.
	(cairoTranslate, cairoScale, cairoRotate): Remove.
	(various methods): use setTransform for special transform cases.
	(DrawState): New inner class.
	(stateSave): New method.
	(stateRestore): New method.
	(various methods): use stateSave, stateRestore.
	(getClipInDevSpace): New method.
	(clip, clipRect, setClip, getClip, getClipBounds): 
	Follow spec more closely.
	(getTransform): Return clone of transform.
	(setStroke): Set linewidth to passed width / 2.0.
	(setPaintMode): Set SrcOver rather than Xor.
	(setColor): Set paint to passed color.
	(drawRaster, drawImage, PainterThread, drawPixels): Take affine
	transform from image to user space.
	(drawRenderedImage, drawRenderableImage): Implement.
	(getFontRenderContext, getFontMetrics, drawString, getFont): 
	Implement
	(drawArc, drawOval, drawRoundRect, fillArc, fillOval, fillRoundRect): 
	Implement.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c: 
	Match changes to java side.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c: 
	Release resources.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c: 
	Don't use pango for metrics.
	* jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c: 
	New file.

Attachment: GdkClasspathFontPeerMetrics.java
Description: Binary data

Attachment: gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c
Description: Binary data

--- gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java	25 Oct 2003 18:41:45 -0000	1.1
+++ gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java	18 Nov 2003 18:34:16 -0000
@@ -49,6 +49,7 @@
 import java.util.StringTokenizer;
 import java.text.CharacterIterator;
 import java.text.AttributedCharacterIterator;
+import java.text.StringCharacterIterator;
 import java.awt.font.TextAttribute;
 import gnu.classpath.Configuration;
 import gnu.java.awt.peer.ClasspathFontPeer;
@@ -180,10 +181,56 @@
     throw new UnsupportedOperationException ();
   }
 
+  protected class GdkFontLineMetrics extends LineMetrics
+  {
+    FontMetrics fm;
+    int nchars; 
+
+    public GdkFontLineMetrics (FontMetrics m, int n)
+    {
+      fm = m;
+      nchars = n;
+    }
+
+    public float getAscent()
+    {
+      return (float) fm.getAscent ();
+    }
+  
+    public int getBaselineIndex()
+    {
+      return Font.ROMAN_BASELINE;
+    }
+    
+    public float[] getBaselineOffsets()
+    {
+      return new float[3];
+    }
+    
+    public float getDescent()
+    {
+      return (float) fm.getDescent ();
+    }
+    
+    public float getHeight()
+    {
+      return (float) fm.getHeight ();
+    }
+    
+    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 LineMetrics getLineMetrics (Font font, CharacterIterator ci, 
                                      int begin, int limit, FontRenderContext rc)
   {
-    throw new UnsupportedOperationException ();
+    return new GdkFontLineMetrics (getFontMetrics (font), limit - begin);
   }
 
   public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
@@ -214,25 +261,32 @@
 
   public boolean hasUniformLineMetrics (Font font)
   {
-    throw new UnsupportedOperationException ();
+    return true;
   }
 
   public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc, 
                                         char[] chars, int start, int limit, 
                                         int flags)
   {
-    throw new UnsupportedOperationException ();  
+    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)));
   }
 
   public LineMetrics getLineMetrics (Font font, String str, 
                                      FontRenderContext frc)
   {
-    throw new UnsupportedOperationException();
+    return new GdkFontLineMetrics (getFontMetrics (font), str.length ());
   }
 
   public FontMetrics getFontMetrics (Font font)
   {
-    throw new UnsupportedOperationException();
+    return new GdkClasspathFontPeerMetrics (font);
   }
 
 }
--- gnu/java/awt/peer/gtk/GdkGraphics2D.java	25 Oct 2003 18:41:45 -0000	1.2
+++ gnu/java/awt/peer/gtk/GdkGraphics2D.java	18 Nov 2003 18:34:16 -0000
@@ -47,6 +47,7 @@
 
 import java.text.AttributedCharacterIterator;
 import java.util.Map;
+import java.util.Stack;
 import java.lang.Integer;
 import gnu.java.awt.ClasspathToolkit;
 import gnu.java.awt.peer.ClasspathFontPeer;
@@ -79,6 +80,8 @@
   private GtkComponentPeer component;
   private Font font;  
   
+  private Stack stateStack;
+  
   native private int[] initState (GtkComponentPeer component);
   native private void initState (int width, int height);
   native private void copyState (GdkGraphics2D g);
@@ -122,33 +125,50 @@
       clip = new Rectangle (g.getClipBounds ());
 
     if (g.transform == null)
-      transform = null;
+      transform = AffineTransform.getTranslateInstance (0.5, 0.5);
     else
       transform = new AffineTransform (g.transform);
 
+    font = g.font;
     component = g.component;
     copyState (g);
 
     setColor (fg);
+    setBackground (bg);
+    setPaint (paint);
+    setStroke (stroke);
     setClip (clip);
     setTransform (transform);
+    stateStack = new Stack();
   }
 
   GdkGraphics2D (int width, int height)
   {
     initState (width, height);
-    bg = Color.black;
-    fg = Color.black;
-    transform = new AffineTransform ();
+
+    setColor(Color.black);
+    setBackground (Color.black);
+    setPaint (getColor());
+    setFont (new Font("SansSerif", Font.PLAIN, 12));
+    setTransform (AffineTransform.getTranslateInstance (0.5, 0.5));
+    setStroke (new BasicStroke ());
+
+    stateStack = new Stack();
   }
 
   GdkGraphics2D (GtkComponentPeer component)
   {
     this.component = component;
     int rgb[] = initState (component);
-    fg = new Color (rgb[0], rgb[1], rgb[2]);
-    bg = new Color (rgb[3], rgb[4], rgb[5]);
-    transform = new AffineTransform ();
+
+    setColor (new Color (rgb[0], rgb[1], rgb[2]));
+    setBackground (new Color (rgb[3], rgb[4], rgb[5]));
+    setPaint (getColor());
+    setFont (new Font("SansSerif", Font.PLAIN, 12));
+    setTransform (AffineTransform.getTranslateInstance (0.5, 0.5));
+    setStroke (new BasicStroke ());
+
+    stateStack = new Stack ();
   }
 
 
@@ -160,7 +180,7 @@
   private native void gdkDrawDrawable (GdkGraphics2D other, int x, int y);
 
   // drawing utility methods
-  private native void drawPixels (int pixels[], int w, int h, int stride);
+  private native void drawPixels (int pixels[], int w, int h, int stride, double i2u[]);
   private native void setTexturePixels (int pixels[], int w, int h, int stride);
   private native void setGradient (double x1, double y1,
                                    double x2, double y2,
@@ -171,13 +191,10 @@
   // simple passthroughs to cairo
   private native void cairoSave ();
   private native void cairoRestore ();
-  private native void cairoSetMatrix (double m00, double m10, 
-                                      double m01, double m11,
-                                      double m02, double m12);
+  private native void cairoSetMatrix (double m[]);
   private native void cairoSetFont (GdkClasspathFontPeer peer);
   private native void cairoShowGlyphs (int codes[],
-                                       float positions[],
-                                       int nglyphs);
+                                       float positions[]);
   private native void cairoSetOperator (int cairoOperator);
   private native void cairoSetRGBColor (double red, double green, double blue);
   private native void cairoSetAlpha (double alpha);
@@ -187,9 +204,6 @@
   private native void cairoSetLineJoin (int cairoLineJoin);
   private native void cairoSetDash (double dashes[], int ndash, double offset);
   private native void cairoSetMiterLimit (double limit);
-  private native void cairoTranslate (double tx, double ty);
-  private native void cairoScale (double sx, double sy);
-  private native void cairoRotate (double angle);
   private native void cairoNewPath ();
   private native void cairoMoveTo (double x, double y);
   private native void cairoLineTo (double x, double y);
@@ -213,6 +227,51 @@
   ////// General Drawing Support Methods //////
   /////////////////////////////////////////////
 
+    private class DrawState
+    {
+	private Paint paint;
+	private Stroke stroke;
+	private Color fg;
+	private Color bg;
+	private Shape clip;
+	private AffineTransform transform;
+	private Font font;  
+	DrawState (GdkGraphics2D g)
+	{
+	    this.paint = g.paint;
+	    this.stroke = g.stroke;
+	    this.fg = g.fg;
+	    this.bg = g.bg;
+	    this.clip = g.clip;
+	    if (g.transform != null)
+		this.transform = (AffineTransform) g.transform.clone();
+	    this.font = g.font;
+	}
+	public void restore(GdkGraphics2D g)
+	{
+	    g.paint = this.paint;
+	    g.stroke = this.stroke;
+	    g.fg = this.fg;
+	    g.bg = this.bg;
+	    g.clip = this.clip;
+	    g.transform = this.transform;
+	    g.font = this.font;
+	}
+    }
+    
+    private void stateSave ()
+    {
+	stateStack.push (new DrawState (this));
+	cairoSave ();
+    }
+
+    private void stateRestore ()
+    {
+	((DrawState)(stateStack.pop ())).restore (this);
+	cairoRestore ();
+    }
+
+
   double x;
   double y;
   private void setPos (double nx, double ny)
@@ -288,7 +347,7 @@
         return;
       }
 
-    cairoSave ();
+    stateSave ();
     cairoNewPath ();
     if (s instanceof Rectangle2D)
       {
@@ -298,12 +357,12 @@
     else      
       walkPath (s.getPathIterator (null));
     cairoStroke ();
-    cairoRestore ();
+    stateRestore ();
   }
 
   public void fill(Shape s)
   {
-    cairoSave();
+    stateSave();
     cairoNewPath ();
     if (s instanceof Rectangle2D)
       {
@@ -313,24 +372,41 @@
     else      
       walkPath (s.getPathIterator (null));
     cairoFill ();
-    cairoRestore ();
+    stateRestore ();
   }
 
   public void clip (Shape s)
   {
+      // update it
+
+      if (clip == null || s == null)
     clip = s;
-    cairoNewPath ();
-    if (s instanceof Rectangle2D)
+      else if (s instanceof Rectangle2D
+	       && clip instanceof Rectangle2D)
       {
         Rectangle2D r = (Rectangle2D)s;
+	      Rectangle2D curr = (Rectangle2D)clip;
+	      clip = curr.createIntersection (r);
+	  }
+      else
+	  throw new UnsupportedOperationException ();
+
+      // draw it
+      if (clip != null)
+	  {
+	      cairoNewPath ();
+	      if (clip instanceof Rectangle2D)
+		  {
+		      Rectangle2D r = (Rectangle2D)clip;
         cairoRectangle (r.getX (), r.getY (), 
                         r.getWidth (), r.getHeight ());
       }
     else      
-      walkPath (s.getPathIterator (null));
+		  walkPath (clip.getPathIterator (null));
     cairoClosePath ();
     cairoClip ();
   }
+  }
 
   public Paint getPaint ()
   {
@@ -339,11 +415,14 @@
 
   public AffineTransform getTransform ()
   {
-    return transform;
+      return (AffineTransform) transform.clone ();
   }
 
   public void setPaint (Paint p)
   {
+    if (paint == null)
+        return;
+      
     paint = p;
     if (paint instanceof Color)
       {
@@ -385,7 +464,7 @@
       {
         double m[] = new double[6];
         transform.getMatrix (m);
-        cairoSetMatrix (m[0], m[1], m[2], m[3], m[4], m[5]);
+        cairoSetMatrix (m);
       }
   }
 
@@ -400,32 +479,22 @@
 
   public void rotate(double theta)
   {
-    if (transform != null)
-      transform.rotate (theta);
-    cairoRotate (theta);
+    transform (AffineTransform.getRotateInstance (theta));
   }
 
   public void rotate(double theta, double x, double y)
   {
-    if (transform != null)
-      transform.rotate (theta, x, y);
-    cairoTranslate (x, y);
-    cairoRotate (theta);
-    cairoTranslate (-x, -y);
+    transform (AffineTransform.getRotateInstance (theta, x, y));
   }
 
   public void scale(double sx, double sy)
   {
-    if (transform != null)
-      transform.scale (sx, sy);
-    cairoScale (sx, sy);
+    transform (AffineTransform.getScaleInstance (sx, sy));
   }
 
   public void translate (double tx, double ty)
   {
-    if (transform != null)
-      transform.translate (tx, ty);
-    cairoTranslate (tx, ty);
+    transform (AffineTransform.getTranslateInstance (tx, ty));
   }
 
   public void translate (int x, int y)
@@ -433,6 +502,11 @@
     translate ((double) x, (double) y);
   }
 
+  public void shear(double shearX, double shearY)
+  {
+    transform (AffineTransform.getShearInstance (shearX, shearY));
+  }
+
   public Stroke getStroke()
   {
     return stroke;
@@ -445,7 +519,7 @@
       {
         BasicStroke bs = (BasicStroke) stroke;
         cairoSetLineCap (bs.getEndCap());
-        cairoSetLineWidth (bs.getLineWidth());
+        cairoSetLineWidth (bs.getLineWidth() / 2.0);
         cairoSetLineJoin (bs.getLineJoin());
         cairoSetMiterLimit (bs.getMiterLimit());
         float dashes[] = bs.getDashArray();
@@ -467,7 +541,7 @@
 
   public void setPaintMode () 
   { 
-    setComposite (java.awt.AlphaComposite.Xor); 
+    setComposite (java.awt.AlphaComposite.SrcOver); 
   }
 
   public void setXORMode (Color c) 
@@ -478,6 +552,7 @@
   public void setColor (Color c)
   {
     fg = c;
+    paint = c;
     cairoSetRGBColor (fg.getRed() / 255.0, 
                       fg.getGreen() / 255.0, 
                       fg.getBlue() / 255.0);
@@ -491,29 +566,12 @@
 
   public void clipRect (int x, int y, int width, int height)
   {
-    // this is *slightly* different than all the other clip functions: it
-    // intersects the clip area with the new clip rectangle. obviously.  of
-    // course, since Shape doesn't *have* any way of intersecting with a
-    // rectangle, we will promote the current clipping region to its
-    // bounding rectangle and then intersect with that.
-    if (clip == null)
-      {
-        cairoNewPath ();
-        cairoRectangle (x, y, width, height);
-        cairoClosePath ();
-        cairoClip ();
-        clip = new Rectangle (x, y, width, height);
-      }
-    else
-      {
-        clip (clip.getBounds ().intersection 
-              (new Rectangle (x, y, width, height)));
-      }
+      clip (new Rectangle (x, y, width, height));
   }
 
   public Shape getClip ()
   {
-    return clip;
+    return getClipInDevSpace ();
   }
 
   public Rectangle getClipBounds ()
@@ -524,13 +582,32 @@
       return clip.getBounds ();
   }
 
+    protected Rectangle2D getClipInDevSpace ()
+    {
+	Rectangle2D uclip = clip.getBounds2D ();
+	if (transform == null)
+	    return uclip;
+	else
+	    {
+		Point2D pos = transform.transform (new Point2D.Double(uclip.getX (), 
+								      uclip.getY ()), 
+						   (Point2D)null);		
+		Point2D extent = transform.deltaTransform (new Point2D.Double(uclip.getWidth (), 
+									      uclip.getHeight ()), 
+							   (Point2D)null);
+		return new Rectangle2D.Double (pos.getX (), pos.getY (),
+					       extent.getX (), extent.getY ());	      
+	    }
+    }
+
   public void setClip (int x, int y, int width, int height)
   {
     cairoNewPath ();
     cairoRectangle (x, y, width, height);
     cairoClosePath ();
     cairoClip ();
-    clip = new Rectangle (x, y, width, height);
+      clip = new Rectangle2D.Double ((double)x, (double)y, 
+				     (double)width, (double)height);
   }
 
   public void setClip (Shape s)
@@ -558,7 +635,7 @@
     double y1 = (double) y;
     double y2 = (double) y + height;
 
-    cairoSave ();
+    stateSave ();
     
     cairoNewPath ();
     setColor (light);
@@ -574,9 +651,7 @@
     cairoLineTo (x2, y2);
     cairoStroke ();
     
-    cairoRestore ();    
-    setColor (std);
-
+    stateRestore ();    
   }
 
   public void fill3DRect(int x, int y, int width, 
@@ -594,15 +669,15 @@
       
     draw3DRect (x, y, width, height, raised);
     
-    cairoSave ();
-    cairoTranslate (step/2.0, step/2.0);
+    stateSave ();
+    translate (step/2.0, step/2.0);
     cairoNewPath ();
     cairoRectangle ((double) x, (double) y, 
                     ((double) width) - step, 
                     ((double) height) - step );
     cairoClosePath ();
     cairoFill ();
-    cairoRestore ();
+    stateRestore ();
   }
 
 
@@ -618,7 +693,7 @@
 
   public void clearRect (int x, int y, int width, int height)
   {
-    cairoSave ();
+    stateSave ();
     cairoSetRGBColor (bg.getRed() / 255.0, 
                       bg.getGreen() / 255.0, 
                       bg.getBlue() / 255.0);
@@ -627,7 +702,7 @@
     cairoRectangle (x, y, width, height);
     cairoClosePath ();
     cairoFill ();
-    cairoRestore ();
+    stateRestore ();
   }
 
   public void setBackground(Color c)
@@ -635,13 +710,11 @@
     bg = c;
   }
 
-
   public Color getBackground()
   {
     return bg;
   }
 
-
   private void doPolygon(int[] xPoints, int[] yPoints, int nPoints, 
                          boolean close, boolean fill)
   {    
@@ -698,7 +771,8 @@
     doPolygon (xPoints, yPoints, nPoints, false, false);
   }
 
-  private boolean drawRaster (ColorModel cm, Raster r)
+  private boolean drawRaster (ColorModel cm, Raster r, 
+                              AffineTransform imageToUser)
   {
     if (r == null)
       return false;
@@ -712,6 +786,16 @@
     if (cm == null)
       cm = ColorModel.getRGBdefault ();
 
+    double[] i2u = new double[6];
+    if (imageToUser != null)
+      imageToUser.getMatrix(i2u);
+    else
+      {
+        i2u[0] = 1; i2u[1] = 0;
+        i2u[2] = 0; i2u[3] = 1;
+        i2u[2] = 0; i2u[3] = 0;
+      }
+
     int pixels[] = null;
 
     if (sm.getDataType () == DataBuffer.TYPE_INT &&
@@ -735,23 +819,39 @@
         pixels = pixels2;
       }
     
-    cairoSave ();
-    cairoTranslate (x, y);
-    drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth ());
-    cairoRestore ();    
+    stateSave ();
+    translate (x, y);
+    drawPixels (pixels, r.getWidth (), r.getHeight (), r.getWidth (), i2u);
+    stateRestore ();    
     return true;
   }
 
-  public boolean drawImage (Image img, int x, int y, 
-                            ImageObserver observer)
+  public void drawRenderedImage(RenderedImage image,
+                                AffineTransform xform)
+  {
+    drawRaster (image.getColorModel(), image.getData(), xform);
+  }
+  
+  public void drawRenderableImage(RenderableImage image,
+                                  AffineTransform xform)
+  {
+    drawRenderedImage (image.createRendering (new RenderContext (xform)), xform);
+  }
+  
+  public boolean drawImage(Image img, 
+                           AffineTransform xform,
+                           ImageObserver obs)
   {
     if (img instanceof GtkOffScreenImage &&
         img.getGraphics () instanceof GdkGraphics2D &&            
-        (transform == null || transform.isIdentity ())) 
+        (xform == null 
+         || xform.getType () == AffineTransform.TYPE_IDENTITY 
+         || xform.getType () == AffineTransform.TYPE_TRANSLATION)
+        ) 
       {
         // we are being asked to flush a double buffer from Gdk
         GdkGraphics2D g2 = (GdkGraphics2D) img.getGraphics ();
-        gdkDrawDrawable (g2, x, y);
+        gdkDrawDrawable (g2, (int)xform.getTranslateX(), (int)xform.getTranslateY());
         return true;
       }
     else
@@ -760,17 +860,32 @@
           {
             // draw an image which has actually been loaded into memory fully
             BufferedImage b = (BufferedImage) img;
-            return drawRaster (b.getColorModel (), b.getData ());
+            return drawRaster (b.getColorModel (), b.getData (), xform);
           }        
         else
           {
             // begin progressive loading in a separate thread
-            new PainterThread (this, img);
+            new PainterThread (this, img, xform);
             return false;
           }
       }
   }
 
+  public void drawImage(BufferedImage image,
+                        BufferedImageOp op,
+                        int x,
+                        int y)
+  {
+    Image filtered = op.filter(image, null);
+    drawImage(filtered, new AffineTransform(1f,0f,0f,1f,x,y), null);
+  }
+
+  public boolean drawImage (Image img, int x, int y, 
+                            ImageObserver observer)
+  {
+    return drawImage(img, new AffineTransform(1f,0f,0f,1f,x,y), observer);    
+  }
+
 
   ////////////////////////////////////////
   ////// Supporting Private Classes //////
@@ -790,10 +905,12 @@
     GdkGraphics2D gr;
     Image image;
     ColorModel defaultModel;
+    AffineTransform xform;
 
-    public PainterThread (GdkGraphics2D g, Image im)
+    public PainterThread (GdkGraphics2D g, Image im, AffineTransform xf)
     {
       image = im;
+      xform = xf;
       this.gr = (GdkGraphics2D) g.create ();
       new Thread (this).start ();
     }
@@ -823,8 +940,8 @@
     public void setPixels (int x, int y, int w, int h, ColorModel model, 
                            int[] pixels, int off, int scansize)
       {
-        gr.cairoSave ();
-        gr.cairoTranslate (x, y);
+        gr.stateSave ();
+        gr.translate (x, y);
 
         if (model == null)
           model = defaultModel;
@@ -843,8 +960,10 @@
         else
           pixels2 = pixels;
 
-        gr.drawPixels (pixels2, w, h, scansize);
-        gr.cairoRestore ();
+        double[] xf = new double[6];
+        xform.getMatrix(xf);        
+        gr.drawPixels (pixels2, w, h, scansize, xf);
+        gr.stateRestore ();
       }
 
     public void setProperties (java.util.Hashtable props)
@@ -934,43 +1053,7 @@
   ////// Unimplemented Stubs and Overloads //////
   ///////////////////////////////////////////////
 
-  public boolean drawImage(Image image, 
-                           AffineTransform xform,
-                           ImageObserver obs)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
-  
-  public void drawImage(BufferedImage image,
-                        BufferedImageOp op,
-                        int x,
-                        int y)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
-  
-  public void drawRenderedImage(RenderedImage image,
-                                AffineTransform xform)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
-  
-  public void drawRenderableImage(RenderableImage image,
-                                  AffineTransform xform)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
 
-  public void drawString(String text, float x, float y)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
-  
-  public void drawString(AttributedCharacterIterator iterator,
-                         float x, float y)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
     
   public boolean hit(Rectangle rect, Shape text,
                      boolean onStroke)
@@ -1014,11 +1097,6 @@
     throw new java.lang.UnsupportedOperationException ();
   }
 
-  public void shear(double shearX, double shearY)
-  {
-    throw new java.lang.UnsupportedOperationException ();
-  }
-
   public Composite getComposite()
   {
     throw new java.lang.UnsupportedOperationException ();
@@ -1026,18 +1104,20 @@
 
   public FontRenderContext getFontRenderContext ()
   {
-    throw new java.lang.UnsupportedOperationException ();
+    return new FontRenderContext (transform, true, true);
   }
 
   public void drawGlyphVector (GlyphVector g, float x, float y)
   {    
-    cairoSave ();
-    cairoTranslate ((double)x, (double)y);
+    stateSave ();
+    setFont (g.getFont ());
+    translate ((double)x, (double)y);
+    cairoMoveTo (0, 0);
     int nglyphs = g.getNumGlyphs ();
     int codes[] = g.getGlyphCodes (0, nglyphs, (int []) null);
     float posns[] = g.getGlyphPositions (0, nglyphs, (float []) null);
-    cairoShowGlyphs (codes, posns, nglyphs);
-    cairoRestore ();
+    cairoShowGlyphs (codes, posns);
+    stateRestore ();
   }
 
   public void copyArea (int x, int y, int width, int height, int dx, int dy)
@@ -1048,7 +1128,10 @@
   public void drawArc (int x, int y, int width, int height,
                        int startAngle, int arcAngle)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    draw (new Arc2D.Double((double)x, (double)y, 
+                           (double)width, (double)height,
+                           (double)startAngle, (double)arcAngle,
+                           Arc2D.OPEN));
   }
 
   public boolean drawImage (Image img, int x, int y, Color bgcolor, 
@@ -1085,61 +1168,84 @@
 
   public void drawOval(int x, int y, int width, int height)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    drawArc (x, y, width, height, 0, 360);
   }
 
   public void drawRoundRect(int x, int y, int width, int height, 
                             int arcWidth, int arcHeight)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    int x1 = x + arcWidth, x2 = x + width - arcWidth;
+    int y1 = y + arcHeight, y2 = y + height - arcHeight;
+    fillRect (x1, y, x2 - x1, height);
+    fillRect (x, y1, width, y2 - y1);
+    fillArc (x, y, arcWidth, arcHeight, 90, 90);
+    fillArc (x1, y, arcWidth, arcHeight, 0, 90);
+    fillArc (x2, y2, arcWidth, arcHeight, 270, 90);
+    fillArc (x, y2, arcWidth, arcHeight, 180, 90);
   }
 
   public void drawString (String str, int x, int y)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    drawString (str, (float)x, (float)y);
+  }
+
+  public void drawString (String str, float x, float y)
+  {
+    GlyphVector gv = font.createGlyphVector (getFontRenderContext(), str);
+    drawGlyphVector (gv, x, y);
   }
 
   public void drawString (AttributedCharacterIterator ci, int x, int y)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    drawString (ci, (float)x, (float)y);
+  }
+
+  public void drawString (AttributedCharacterIterator ci, float x, float y)
+  {
+    GlyphVector gv = font.createGlyphVector (getFontRenderContext(), ci);
+    drawGlyphVector (gv, x, y);
   }
 
   public void fillArc (int x, int y, int width, int height, 
                        int startAngle, int arcAngle)
   {
-    cairoNewPath ();
-    walkPath (new Arc2D.Double((double)x, (double)y, 
+    fill (new Arc2D.Double((double)x, (double)y, 
                                (double)width, (double)height,
                                (double)startAngle, (double)arcAngle,
-                               Arc2D.PIE).getPathIterator (null));
-    cairoClosePath ();
-    cairoFill ();
+                           Arc2D.OPEN));
   }
 
   public void fillOval(int x, int y, int width, int height)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    fillArc (x, y, width, height, 0, 360);
   }
 
   public void fillRoundRect (int x, int y, int width, int height, 
                              int arcWidth, int arcHeight)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    int x1 = x + arcWidth, x2 = x + width - arcWidth;
+    int y1 = y + arcHeight, y2 = y + height - arcHeight;
+    fillRect (x1, y, x2 - x1, height);
+    fillRect (x, y1, width, y2 - y1);
+    fillArc (x, y, arcWidth, arcHeight, 90, 90);
+    fillArc (x1, y, arcWidth, arcHeight, 0, 90);
+    fillArc (x2, y2, arcWidth, arcHeight, 270, 90);
+    fillArc (x, y2, arcWidth, arcHeight, 180, 90);
   }
 
   public Font getFont ()
   {
-    throw new java.lang.UnsupportedOperationException ();
+    return font;
   }
 
   public FontMetrics getFontMetrics ()
   {
-    throw new java.lang.UnsupportedOperationException ();
+    return Toolkit.getDefaultToolkit ().getFontMetrics (font);
   }
 
   public FontMetrics getFontMetrics (Font f)
   {
-    throw new java.lang.UnsupportedOperationException ();
+    return Toolkit.getDefaultToolkit ().getFontMetrics (f);
   }
 
   public void setFont (Font f)
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c	25 Oct 2003 18:41:45 -0000	1.2
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c	18 Nov 2003 18:34:16 -0000
@@ -302,6 +302,8 @@
   g_old = (struct graphics2d *) NSA_GET_G2D_PTR (env, old);
   g_assert (g_old != NULL);
 
+  if (g_old->debug) printf ("copying state from existing graphics2d\n");
+
   g->drawable = g_old->drawable;
   g->debug = g_old->debug; 
 
@@ -316,7 +318,7 @@
   else
     init_graphics2d_as_pixbuf (g);
 
-  cairo_surface_set_filter (g->surface, CAIRO_FILTER_BILINEAR);
+  cairo_surface_set_filter (g->surface, CAIRO_FILTER_FAST);
 
   gdk_threads_leave ();
 
@@ -649,36 +651,61 @@
 }
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels 
-  (JNIEnv *env, jobject obj, jintArray jarr, jint w, jint h, jint stride)
+  (JNIEnv *env, jobject obj, jintArray java_pixels, 
+   jint w, jint h, jint stride, jdoubleArray java_matrix)
 {
   struct graphics2d *gr = NULL;
-  jint *jpixels = NULL;
+  jint *native_pixels = NULL;
+  jdouble *native_matrix = NULL;
 
   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
   g_assert (gr != NULL);
 
   if (gr->debug) printf ("drawPixels (%d pixels, %dx%d, stride: %d)\n",
-			 (*env)->GetArrayLength (env, jarr), w, h, stride);
+			 (*env)->GetArrayLength (env, java_pixels), w, h, stride);
 
-  jpixels = (*env)->GetIntArrayElements (env, jarr, NULL);
-  g_assert (jpixels != NULL);
+  native_pixels = (*env)->GetIntArrayElements (env, java_pixels, NULL);
+  native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);
+  g_assert (native_pixels != NULL);
+  g_assert (native_matrix != NULL);
+  g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
 
   begin_drawing_operation (gr);
 
-  
  {
-   cairo_surface_t *surf = cairo_surface_create_for_image ((char *)jpixels, 
+   cairo_matrix_t *mat = NULL;
+   cairo_surface_t *surf = cairo_surface_create_for_image ((char *)native_pixels, 
 							   CAIRO_FORMAT_ARGB32, 
 							   w, h, stride * 4);   
+   mat = cairo_matrix_create ();
+   cairo_matrix_set_affine (mat, 
+			    native_matrix[0], native_matrix[1],
+			    native_matrix[2], native_matrix[3],
+			    native_matrix[4], native_matrix[5]);
+   cairo_surface_set_matrix (surf, mat);
+   if (native_matrix[0] != 1.
+       || native_matrix[1] != 0.
+       || native_matrix[2] != 0.
+       || native_matrix[3] != 1.)
+     {
    cairo_surface_set_filter (surf, CAIRO_FILTER_BILINEAR);
+       cairo_surface_set_filter (gr->surface, CAIRO_FILTER_BILINEAR);
+     }
+   else
+     {
+       cairo_surface_set_filter (surf, CAIRO_FILTER_FAST);
+       cairo_surface_set_filter (gr->surface, CAIRO_FILTER_FAST);
+     }
    cairo_show_surface (gr->cr, surf, w, h);
+   cairo_surface_set_filter (gr->surface, CAIRO_FILTER_FAST);
+   cairo_matrix_destroy (mat);
    cairo_surface_destroy (surf);
  }
   
-
  end_drawing_operation (gr);
 
-  (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
+  (*env)->ReleaseIntArrayElements (env, java_pixels, native_pixels, 0);
+  (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
 
 }
 
@@ -706,25 +733,34 @@
 }
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix 
-   (JNIEnv *env, jobject obj,
-    jdouble m00, jdouble m10,
-    jdouble m01, jdouble m11,
-    jdouble m02, jdouble m12)
+   (JNIEnv *env, jobject obj, jdoubleArray java_matrix)
 {
   struct graphics2d *gr = NULL;
+  jdouble *native_matrix = NULL;
+
   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
   g_assert (gr != NULL);
-  if (gr->debug) printf ("cairo_set_matrix\n");
+
+  native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);  
+  g_assert (native_matrix != NULL);
+  g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
+
+  if (gr->debug) printf ("cairo_set_matrix [ %f, %f, %f, %f, %f, %f ]\n",
+			 native_matrix[0], native_matrix[1],
+			 native_matrix[2], native_matrix[3],
+			 native_matrix[4], native_matrix[5]);
 
   {
     cairo_matrix_t * mat = cairo_matrix_create ();
     cairo_matrix_set_affine (mat,
-			     m00, m10,
-			     m01, m11,
-			     m02, m12);
+			     native_matrix[0], native_matrix[1],
+			     native_matrix[2], native_matrix[3],
+			     native_matrix[4], native_matrix[5]);
     cairo_set_matrix (gr->cr, mat);
     cairo_matrix_destroy (mat);
   }
+
+  (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
   update_pattern_transform (gr);
 }
 
@@ -750,8 +786,7 @@
   ft = cairo_ft_font_create_for_ft_face (face);
   g_assert (ft != NULL);
 
-  if (gr->debug) printf ("cairo_set_font '%s'\n", 
-			 face->family_name);
+  if (gr->debug) printf ("cairo_set_font '%s'\n", face->family_name);
   
   cairo_set_font (gr->cr, ft);
 
@@ -765,40 +800,46 @@
 }
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs
-   (JNIEnv *env, jobject obj, jintArray jcodes, jfloatArray jposns, jint nglyphs)
+   (JNIEnv *env, jobject obj, jintArray java_codes, jfloatArray java_posns)
 {
   struct graphics2d *gr = NULL;
   cairo_glyph_t *glyphs = NULL;
-  jfloat *posns = NULL;
-  jint *codes = NULL;
+  jfloat *native_posns = NULL;
+  jint *native_codes = NULL;
   jint i;
+  jint ncodes, nposns;
 
   gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
   g_assert (gr != NULL);
 
-  if (gr->debug) printf ("cairo_show_glyphs (%d glyphs)\n", nglyphs);
+  native_codes = (*env)->GetIntArrayElements (env, java_codes, NULL);  
+  native_posns = (*env)->GetFloatArrayElements (env, java_posns, NULL);  
+  g_assert (native_codes != NULL);
+  g_assert (native_posns != NULL);
 
-  glyphs = malloc (sizeof(cairo_glyph_t) * nglyphs);
-  g_assert (glyphs);
+  ncodes = (*env)->GetArrayLength (env, java_codes);
+  nposns = (*env)->GetArrayLength (env, java_posns);
+  g_assert (2 * ncodes == nposns);
 
-  codes = (*env)->GetIntArrayElements (env, jcodes, NULL);  
-  g_assert (codes != NULL);
+  if (gr->debug) printf ("cairo_show_glyphs (%d glyphs)\n", ncodes);
 
-  posns = (*env)->GetFloatArrayElements (env, jposns, NULL);  
-  g_assert (posns != NULL);
+  glyphs = malloc (sizeof(cairo_glyph_t) * ncodes);
+  g_assert (glyphs);
 
-  for (i = 0; i < nglyphs; ++i)
+  for (i = 0; i < ncodes; ++i)
     {
-      glyphs[i].index = codes[i];
-      glyphs[i].x = (double) posns[2*i];
-      glyphs[i].y = (double) posns[2*i + 1];
+      glyphs[i].index = native_codes[i];
+      glyphs[i].x = (double) native_posns[2*i];
+      glyphs[i].y = (double) native_posns[2*i + 1];
+      if (gr->debug) printf ("cairo_show_glyphs (glyph %d (code %d) : %f,%f)\n", 
+			     i, glyphs[i].index, glyphs[i].x, glyphs[i].y);
     }
 
-  (*env)->ReleaseIntArrayElements (env, jcodes, codes, 0);
-  (*env)->ReleaseFloatArrayElements (env, jposns, posns, 0);
+  (*env)->ReleaseIntArrayElements (env, java_codes, native_codes, 0);
+  (*env)->ReleaseFloatArrayElements (env, java_posns, native_posns, 0);
 
   begin_drawing_operation (gr);
-  cairo_show_glyphs (gr->cr, glyphs, nglyphs);
+  cairo_show_glyphs (gr->cr, glyphs, ncodes);
   end_drawing_operation (gr);
 
   free(glyphs);
@@ -991,38 +1032,6 @@
   cairo_set_miter_limit (gr->cr, miter);
 }
 
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoTranslate 
-   (JNIEnv *env, jobject obj, jdouble dx, jdouble dy)
-{
-  struct graphics2d *gr = NULL;
-  gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
-  g_assert (gr != NULL);
-  if (gr->debug) printf ("cairo_translate (%f, %f)\n", dx, dy);
-  cairo_translate (gr->cr, dx, dy);
-  update_pattern_transform (gr);
-}
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoScale 
-   (JNIEnv *env, jobject obj, jdouble sx, jdouble sy)
-{
-  struct graphics2d *gr = NULL;
-  gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
-  g_assert (gr != NULL);
-  if (gr->debug) printf ("cairo_scale (%f, %f)\n", sx, sy);
-  cairo_scale (gr->cr, sx, sy);
-  update_pattern_transform (gr);
-}
-
-JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoRotate 
-   (JNIEnv *env, jobject obj, jdouble angle)
-{
-  struct graphics2d *gr = NULL;
-  gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
-  g_assert (gr != NULL);
-  if (gr->debug) printf ("cairo_rotate %f\n", angle);
-  cairo_rotate (gr->cr, angle);
-  update_pattern_transform (gr);
-}
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoNewPath 
    (JNIEnv *env, jobject obj)
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c	25 Oct 2003 18:41:45 -0000	1.1
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c	18 Nov 2003 18:34:16 -0000
@@ -120,6 +120,13 @@
   pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self);
   g_assert (pfont != NULL);
 
+  if (pfont->ctx != NULL)
+    g_object_unref (pfont->ctx);
+  if (pfont->font != NULL)
+    g_object_unref (pfont->font);
+  if (pfont->desc != NULL)
+    pango_font_description_free (pfont->desc);
+
   pfont->desc = pango_font_description_new ();
   g_assert (pfont->desc != NULL);
 
--- jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c	25 Oct 2003 18:41:45 -0000	1.1
+++ jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c	18 Nov 2003 18:34:16 -0000
@@ -40,6 +40,16 @@
 
 struct state_table *native_glyphvector_state_table;
 
+typedef struct { 
+  double x;
+  double y;
+  double width;
+  double height;
+} rect_t;
+
+#define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 63.0))
+#define DOUBLE_FROM_26_6(t) (((double)((t) >> 6)) \
+			     + ((double)((t) & 0x3F) / 63.0))
 
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initStaticState 
   (JNIEnv *env, jclass clazz)
@@ -64,9 +74,12 @@
   vec = (struct glyphvec *) g_malloc0 (sizeof (struct glyphvec));
   g_assert (vec != NULL);
 
-  vec->desc = pango_font_description_copy (pfont->desc);
+  vec->desc = pango_font_describe (pfont->font); 
   g_assert (vec->desc != NULL);
     
+  vec->font = pfont->font;
+  g_object_ref (vec->font);
+    
   vec->ctx = pfont->ctx;
   g_object_ref (vec->ctx);
 
@@ -150,10 +163,10 @@
   *g = gs->glyphs + nidx;
 }
 
-static void union_rects (PangoRectangle *r1, 
-			 const PangoRectangle *r2)
+static void union_rects (rect_t *r1, 
+			 const rect_t *r2)
 {
-  PangoRectangle r;
+  rect_t r;
 
   g_assert (r1 != NULL);
   g_assert (r2 != NULL);
@@ -184,7 +197,7 @@
   *r1 = r;  
 }
 
-static jdoubleArray rect_to_array (JNIEnv *env, const PangoRectangle *r)
+static jdoubleArray rect_to_array (JNIEnv *env, const rect_t *r)
 {
   /* We often return rectangles as arrays : { x, y, w, h } */
   jdoubleArray ret;
@@ -193,11 +206,11 @@
   ret = (*env)->NewDoubleArray (env, 4);
   rp = (*env)->GetDoubleArrayElements (env, ret, NULL);
   g_assert (rp != NULL);
-  rp[0] = r->x / (double)PANGO_SCALE;
+  rp[0] = r->x;
   /* freetype and pango's view of space is upside down from java2d's */
-  rp[1] = (r->y / (double)PANGO_SCALE) * -1;
-  rp[2] = r->width / (double)PANGO_SCALE;
-  rp[3] = r->height / (double)PANGO_SCALE;
+  rp[1] = r->y * -1;
+  rp[2] = r->width;
+  rp[3] = r->height;
   (*env)->ReleaseDoubleArrayElements (env, ret, rp, 0);
   return ret;
 }
@@ -251,18 +264,14 @@
   str = (gchar *)(*env)->GetStringUTFChars (env, chars, NULL);
   g_assert (str != NULL);
 
-  /* step 1: mark the text as having our FontFescription as an 
-     attribute, then "itemize" the text */
+  /* step 1: set our FontFescription in the context, then "itemize" the
+     text */
 
   attrs = pango_attr_list_new ();
   g_assert (attrs != NULL);
   
-  PangoAttribute *da = pango_attr_font_desc_new(vec->desc);
-  g_assert (da != NULL);
-  da->start_index = 0;
-  da->end_index = len;
+  pango_context_set_font_description (vec->ctx, vec->desc);
   
-  pango_attr_list_insert (attrs, da);
   items = pango_itemize (vec->ctx, str, 0, len, attrs, NULL);
   g_assert (items != NULL);
   
@@ -393,15 +402,19 @@
 }
 
 
-JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents 
+JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents 
   (JNIEnv *env, jobject self)
 {
   struct glyphvec *vec = NULL;
+  int j;
   GList *i;
   PangoGlyphItem *gi = NULL;
-  PangoRectangle rect = {0,0,0,0};
-  PangoRectangle tmp, dummy;  
+  rect_t rect = {0,0,0,0};
+  rect_t tmp;  
   jdoubleArray ret;
+  double x = 0, y = 0;
+  double pointsize;
+  FT_Face face;
 
   gdk_threads_enter ();
   g_assert (self != NULL);
@@ -409,17 +422,33 @@
   g_assert (vec != NULL);
   g_assert (vec->glyphitems != NULL);
 
+  pointsize = pango_font_description_get_size (vec->desc);
+  pointsize /= (double) PANGO_SCALE;
+
   for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
     {
       g_assert (i->data != NULL);
       gi = (PangoGlyphItem *)i->data;
       g_assert (gi->glyphs != NULL);
       
-      pango_glyph_string_extents (gi->glyphs,
-				  gi->item->analysis.font,
-				  &dummy,
-				  &tmp);
+      face = pango_ft2_font_get_face (gi->item->analysis.font);
+      FT_Set_Char_Size( face, 
+			DOUBLE_TO_26_6 (pointsize),
+			DOUBLE_TO_26_6 (pointsize),
+			0, 0);
+      
+      for (j = 0; j < gi->glyphs->num_glyphs; ++j)
+	{
+	  FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT);
+	  /* FIXME: this needs to change for vertical layouts */
+	  tmp.x = x + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX);
+	  tmp.y = y + DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY);
+	  tmp.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width);
+	  tmp.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height);
       union_rects (&rect, &tmp);
+	  x += DOUBLE_FROM_26_6 (face->glyph->advance.x);
+	  y += DOUBLE_FROM_26_6 (face->glyph->advance.y);
+	}
     }      
 
   ret = rect_to_array (env, &rect);
@@ -428,15 +457,19 @@
 }
 
 
-JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents 
+JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents 
   (JNIEnv *env, jobject self)
 {
   struct glyphvec *vec = NULL;
+  int j;
   GList *i;
   PangoGlyphItem *gi = NULL;
-  PangoRectangle rect = {0,0,0,0};
-  PangoRectangle tmp, dummy;  
+  rect_t rect = {0,0,0,0};
+  rect_t tmp;  
   jdoubleArray ret;
+  double x = 0, y = 0;
+  double pointsize;
+  FT_Face face;
 
   gdk_threads_enter ();
   g_assert (self != NULL);
@@ -444,17 +477,38 @@
   g_assert (vec != NULL);
   g_assert (vec->glyphitems != NULL);
 
+  pointsize = pango_font_description_get_size (vec->desc);
+  pointsize /= (double) PANGO_SCALE;
+
   for (i = g_list_first (vec->glyphitems); i != NULL; i = g_list_next (i))
     {
       g_assert (i->data != NULL);
       gi = (PangoGlyphItem *)i->data;
       g_assert (gi->glyphs != NULL);
       
-      pango_glyph_string_extents (gi->glyphs,
-				  gi->item->analysis.font,
-				  &tmp,
-				  &dummy);
+      face = pango_ft2_font_get_face (gi->item->analysis.font);
+      FT_Set_Char_Size( face, 
+			DOUBLE_TO_26_6 (pointsize),
+			DOUBLE_TO_26_6 (pointsize),
+			0, 0);
+      
+      for (j = 0; j < gi->glyphs->num_glyphs; ++j)
+	{
+	  FT_Load_Glyph (face, gi->glyphs->glyphs[j].glyph, FT_LOAD_DEFAULT);
+
+	  /* FIXME: also, this is probably not the correct set of metrics;
+	     the "logical bounds" are some fancy combination of hori
+	     advance and height such that it's good for inverting as a
+	     highlight. revisit. */
+
+	  tmp.x = x;
+	  tmp.y = y;
+	  tmp.width = DOUBLE_FROM_26_6 (face->glyph->advance.x);
+	  tmp.height = DOUBLE_FROM_26_6 (face->glyph->advance.y);
       union_rects (&rect, &tmp);
+	  x += DOUBLE_FROM_26_6 (face->glyph->advance.x);
+	  y += DOUBLE_FROM_26_6 (face->glyph->advance.y);
+	}
     }      
 
   ret = rect_to_array (env, &rect);
@@ -462,15 +516,17 @@
   return ret;
 }
 
+
 JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphLogicalExtents 
   (JNIEnv *env, jobject self, jint idx)
 {
   struct glyphvec *vec = NULL;
-  PangoRectangle rect = {0,0,0,0};
-  PangoRectangle dummy;  
+  rect_t rect = {0,0,0,0};
   PangoGlyphInfo *gi = NULL;
   PangoFont *font = NULL;
   jdoubleArray ret;
+  double pointsize;
+  FT_Face face;
 
   gdk_threads_enter ();
   g_assert (self != NULL);
@@ -482,7 +538,25 @@
   g_assert (gi != NULL);
   g_assert (font != NULL);
 
-  pango_font_get_glyph_extents (font, gi->glyph, &dummy, &rect);
+  pointsize = pango_font_description_get_size (vec->desc);
+  pointsize /= (double) PANGO_SCALE;
+  face = pango_ft2_font_get_face (font);
+  FT_Set_Char_Size( face, 
+		    DOUBLE_TO_26_6 (pointsize),
+		    DOUBLE_TO_26_6 (pointsize),
+		    0, 0);
+  
+  FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT);
+
+  /* FIXME: this is probably not the correct set of metrics;
+     the "logical bounds" are some fancy combination of hori
+     advance and height such that it's good for inverting as a
+     highlight. revisit. */
+  
+  rect.x = 0; 
+  rect.y = 0; 
+  rect.width = DOUBLE_FROM_26_6 (face->glyph->advance.x);
+  rect.height = DOUBLE_FROM_26_6 (face->glyph->advance.y);
 
   ret = rect_to_array (env, &rect);
   gdk_threads_leave ();
@@ -494,11 +568,12 @@
   (JNIEnv *env, jobject self, jint idx)
 {
   struct glyphvec *vec = NULL;
-  PangoRectangle rect = {0,0,0,0};
-  PangoRectangle dummy;  
+  rect_t rect = {0,0,0,0};
   PangoGlyphInfo *gi = NULL;
   PangoFont *font = NULL;
   jdoubleArray ret;
+  double pointsize;
+  FT_Face face;
 
   gdk_threads_enter ();
   g_assert (self != NULL);
@@ -510,12 +585,26 @@
   g_assert (gi != NULL);
   g_assert (font != NULL);
 
-  pango_font_get_glyph_extents (font, gi->glyph, &rect, &dummy);
+  pointsize = pango_font_description_get_size (vec->desc);
+  pointsize /= (double) PANGO_SCALE;
+  face = pango_ft2_font_get_face (font);
+  FT_Set_Char_Size( face, 
+		    DOUBLE_TO_26_6 (pointsize),
+		    DOUBLE_TO_26_6 (pointsize),
+		    0, 0);
+  
+  FT_Load_Glyph (face, gi->glyph, FT_LOAD_DEFAULT);
+  /* FIXME: this needs to change for vertical layouts */
+  rect.x = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingX);
+  rect.y = DOUBLE_FROM_26_6 (face->glyph->metrics.horiBearingY);
+  rect.width = DOUBLE_FROM_26_6 (face->glyph->metrics.width);
+  rect.height = DOUBLE_FROM_26_6 (face->glyph->metrics.height);
 
   ret = rect_to_array (env, &rect);
   gdk_threads_leave ();
   return ret;
 }
+
 
 JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphIsHorizontal 
   (JNIEnv *env, jobject self, jint idx)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]