OSDN Git Service

2003-10-14 Graydon Hoare <graydon@redhat.com>
authorgraydon <graydon@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 25 Oct 2003 18:41:45 +0000 (18:41 +0000)
committergraydon <graydon@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 25 Oct 2003 18:41:45 +0000 (18:41 +0000)
* gnu/java/awt/ClasspathToolkit.java: New abstract class.
* gnu/java/awt/peer/ClasspathFontPeer.java: New abstract class.
* gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java,
jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c:
New concrete implementation of ClasspathFontPeer, with native part.
* gnu/java/awt/peer/gtk/GdkGlyphVector.java,
jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c:
New class, with native part.
* gnu/java/awt/peer/gtk/GdkGraphics2D.java,
jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c:
implement setFont, cairoSetFont, drawGlyphVector, cairoShowGlyphs.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72931 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/gnu/java/awt/ClasspathToolkit.java [new file with mode: 0644]
libjava/gnu/java/awt/peer/ClasspathFontPeer.java [new file with mode: 0644]
libjava/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java [new file with mode: 0644]
libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java [new file with mode: 0644]
libjava/gnu/java/awt/peer/gtk/GdkGraphics2D.java
libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c [new file with mode: 0644]
libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c [new file with mode: 0644]
libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c

index 4aef656..b628831 100644 (file)
@@ -1,3 +1,17 @@
+2003-10-25  Graydon Hoare  <graydon@redhat.com>
+
+       * gnu/java/awt/ClasspathToolkit.java: New abstract class.
+       * gnu/java/awt/peer/ClasspathFontPeer.java: New abstract class.
+       * gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java,
+       jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c:
+       New concrete implementation of ClasspathFontPeer, with native part.
+       * gnu/java/awt/peer/gtk/GdkGlyphVector.java,
+       jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c:
+       New class, with native part.
+       * gnu/java/awt/peer/gtk/GdkGraphics2D.java,
+       jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c:
+       implement setFont, cairoSetFont, drawGlyphVector, cairoShowGlyphs.
+
 2003-10-25  Bryce McKinlay  <bryce@mckinlay.net.nz>
 
        * java/lang/reflect/Method.java (toString): Avoid extra whitespace
 2003-10-25  Bryce McKinlay  <bryce@mckinlay.net.nz>
 
        * java/lang/reflect/Method.java (toString): Avoid extra whitespace
diff --git a/libjava/gnu/java/awt/ClasspathToolkit.java b/libjava/gnu/java/awt/ClasspathToolkit.java
new file mode 100644 (file)
index 0000000..91401f4
--- /dev/null
@@ -0,0 +1,334 @@
+/* ClasspathToolkit.java -- Abstract superclass for Classpath toolkits.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt;
+
+import java.awt.Image;
+import java.awt.Dimension;
+import java.awt.DisplayMode;
+import java.awt.Font;
+import java.awt.FontFormatException;
+import java.awt.FontMetrics;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Toolkit;
+import java.awt.image.ColorModel;
+import java.io.File;
+import java.io.InputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import gnu.java.awt.peer.ClasspathFontPeer;
+
+
+/**
+ * An abstract superclass for Classpath toolkits.
+ *
+ * <p>There exist some parts of AWT and Java2D that are specific to
+ * the underlying platform, but for which the {@link Toolkit} class
+ * does not provide suitable abstractions. Examples include some
+ * methods of {@link Font} or {@link GraphicsEnvironment}. Those
+ * methods use ClasspathToolkit as a central place for obtaining
+ * platform-specific functionality.
+ *
+ * <p>In addition, ClasspathToolkit implements some abstract methods
+ * of {@link java.awt.Toolkit} that are not really platform-specific,
+ * such as the maintenance of a cache of loaded images.
+ *
+ * <p><b>Thread Safety:</b> The methods of this class may safely be
+ * called without external synchronization. This also hold for any
+ * inherited {@link Toolkit} methods. Subclasses are responsible for
+ * the necessary synchronization.
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ */
+public abstract class ClasspathToolkit
+  extends Toolkit
+{
+  /**
+   * A map from URLs to previously loaded images, used by {@link
+   * #getImage(java.net.URL)}. For images that were loaded via a path
+   * to an image file, the map contains a key with a file URL.
+   */
+  private Map imageCache;
+
+
+  /**
+   * Returns a shared instance of the local, platform-specific
+   * graphics environment.
+   *
+   * <p>This method is specific to GNU Classpath. It gets called by
+   * the Classpath implementation of {@link
+   * GraphicsEnvironment.getLocalGraphcisEnvironment()}.
+   */
+  public abstract GraphicsEnvironment getLocalGraphicsEnvironment();
+
+
+  /**
+   * Determines the current size of the default, primary screen.
+   *
+   * @throws HeadlessException if the local graphics environment is
+   * headless, which means that no screen is attached and no user
+   * interaction is allowed.
+   */
+  public Dimension getScreenSize()
+  {
+    DisplayMode mode;
+
+    // getDefaultScreenDevice throws HeadlessException if the
+    // local graphics environment is headless.
+    mode = GraphicsEnvironment.getLocalGraphicsEnvironment()
+      .getDefaultScreenDevice().getDisplayMode();
+
+    return new Dimension(mode.getWidth(), mode.getHeight());
+  }
+
+
+  /**
+   * Determines the current color model of the default, primary
+   * screen.
+   *
+   * @see GraphicsEnvironment#getDefaultScreenDevice()
+   * @see java.awt.GraphicsDevice#getDefaultConfiguration()
+   * @see java.awt.GraphicsConfiguration#getColorModel()
+   *
+   * @throws HeadlessException if the local graphics environment is
+   * headless, which means that no screen is attached and no user
+   * interaction is allowed.
+   */
+  public ColorModel getColorModel()
+  {
+    // getDefaultScreenDevice throws HeadlessException if the
+    // local graphics environment is headless.
+    return GraphicsEnvironment.getLocalGraphicsEnvironment()
+      .getDefaultScreenDevice().getDefaultConfiguration()
+      .getColorModel();
+  }
+
+  /**
+   * Retrieves the metrics for rendering a font on the screen.
+   *
+   * @param font the font whose metrics are requested.
+   */
+  public FontMetrics getFontMetrics(Font font)
+  {
+    return ((ClasspathFontPeer) font.getPeer ()).getFontMetrics (font);
+  }
+
+
+  /**
+   * Acquires an appropriate {@link ClasspathFontPeer}, for use in
+   * classpath's implementation of {@link java.awt.Font}.
+   *
+   * @param name The logical name of the font. This may be either a face
+   * name or a logical font name, or may even be null. A default
+   * implementation of name decoding is provided in 
+   * {@link ClasspathFontPeer}, but may be overridden in other toolkits.
+   *
+   * @param attrs Any extra {@link java.awt.font.TextAttribute} attributes
+   * this font peer should have, such as size, weight, family name, or
+   * transformation.
+   */
+
+  public abstract ClasspathFontPeer getClasspathFontPeer (String name, Map attrs); 
+
+
+  /** 
+   * Creates a {@link Font}, in a platform-specific manner.
+   * 
+   * The default implementation simply constructs a {@link Font}, but some
+   * toolkits may wish to override this, to return {@link Font} subclasses which
+   * implement {@link java.awt.font.OpenType} or
+   * {@link java.awt.font.MultipleMaster}.
+   */
+
+  public Font getFont (String name, Map attrs) 
+  {
+    return new Font (name, attrs);
+  }
+
+
+  /**
+   * Creates a font, reading the glyph definitions from a stream.
+   *
+   * <p>This method provides the platform-specific implementation for
+   * the static factory method {@link Font#createFont(int,
+   * java.io.InputStream)}.
+   *
+   * @param format the format of the font data, such as {@link
+   * Font#TRUETYPE_FONT}. An implementation may ignore this argument
+   * if it is able to automatically recognize the font format from the
+   * provided data.
+   *
+   * @param stream an input stream from where the font data is read
+   * in. The stream will be advanced to the position after the font
+   * data, but not closed.
+   *
+   * @throws IllegalArgumentException if <code>format</code> is
+   * not supported.
+   * 
+   * @throws FontFormatException if <code>stream</code> does not
+   * contain data in the expected format, or if required tables are
+   * missing from a font.
+   *
+   * @throws IOException if a problem occurs while reading in the
+   * contents of <code>stream</code>.
+   */
+  public abstract Font createFont(int format, InputStream stream);
+
+
+  /**
+   * Returns an image from the specified file, which must be in a
+   * recognized format. The set of recognized image formats may vary
+   * from toolkit to toolkit.
+   *
+   * <p>This method maintains a cache for images. If an image has been
+   * loaded from the same path before, the cached copy will be
+   * returned. The implementation may hold cached copies for an
+   * indefinite time, which can consume substantial resources with
+   * large images. Users are therefore advised to use {@link
+   * #createImage(java.lang.String)} instead.
+   *
+   * <p>The default implementation creates a file URL for the
+   * specified path and invokes {@link #getImage(URL)}.
+   *
+   * @param path A path to the image file.
+   *
+   * @return IllegalArgumentException if <code>path</code> does not
+   * designate a valid path.
+   */
+  public Image getImage(String path)
+  {
+    try
+    {
+      return getImage(new File(path).toURL());
+    }
+    catch (MalformedURLException muex)
+    {
+      throw (IllegalArgumentException) new IllegalArgumentException(path)
+        .initCause(muex);
+    }
+  }
+
+
+  /**
+   * Loads an image from the specified URL. The image data must be in
+   * a recognized format. The set of recognized image formats may vary
+   * from toolkit to toolkit.
+   *
+   * <p>This method maintains a cache for images. If an image has been
+   * loaded from the same URL before, the cached copy will be
+   * returned. The implementation may hold cached copies for an
+   * indefinite time, which can consume substantial resources with
+   * large images. Users are therefore advised to use {@link
+   * #createImage(java.net.URL)} instead.
+   *
+   * @param url the URL from where the image is read.
+   */
+  public Image getImage(URL url)
+  {
+    Image result;
+
+    synchronized (this)
+    {
+      // Many applications never call getImage. Therefore, we lazily
+      // create the image cache when it is actually needed.
+      if (imageCache == null)
+        imageCache = new HashMap();
+      else
+      {
+        result = (Image) imageCache.get(url);
+        if (result != null)
+          return result;
+      }
+
+      // The createImage(URL) method, which is specified by
+      // java.awt.Toolkit, is not implemented by this abstract class
+      // because it is platform-dependent. Once Classpath has support
+      // for the javax.imageio package, it might be worth considering
+      // that toolkits provide native stream readers. Then, the class
+      // ClasspathToolkit could provide a general implementation that
+      // delegates the image format parsing to javax.imageio.
+      result = createImage(url);
+
+      // It is not clear whether it would be a good idea to use weak
+      // references here. The advantage would be reduced memory
+      // consumption, since loaded images would not be kept
+      // forever. But on VMs that frequently perform garbage
+      // collection (which includes VMs with a parallel or incremental
+      // collector), the image might frequently need to be re-loaded,
+      // possibly over a slow network connection.
+      imageCache.put(url, result);
+
+      return result;
+    }
+  }
+
+
+  /**
+   * Returns an image from the specified file, which must be in a
+   * recognized format.  The set of recognized image formats may vary
+   * from toolkit to toolkit.
+   *
+   * <p>A new image is created every time this method gets called,
+   * even if the same path has been passed before.
+   *
+   * <p>The default implementation creates a file URL for the
+   * specified path and invokes {@link #createImage(URL)}.
+   *
+   * @param path A path to the file to be read in.
+   */
+  public Image createImage(String path)
+  {
+    try
+    {
+      // The abstract method createImage(URL) is defined by
+      // java.awt.Toolkit, but intentionally not implemented by
+      // ClasspathToolkit because it is platform specific.
+      return createImage(new File(path).toURL());
+    }
+    catch (MalformedURLException muex)
+    {
+      throw (IllegalArgumentException) new IllegalArgumentException(path)
+        .initCause(muex);
+    }
+  }
+}
diff --git a/libjava/gnu/java/awt/peer/ClasspathFontPeer.java b/libjava/gnu/java/awt/peer/ClasspathFontPeer.java
new file mode 100644 (file)
index 0000000..3d151c8
--- /dev/null
@@ -0,0 +1,795 @@
+/* ClasspathFontPeer.java -- Font peer used by GNU Classpath.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING.  If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library.  Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.awt.peer;
+
+import java.awt.*;
+import java.awt.peer.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.text.*;
+import java.util.*;
+import gnu.java.awt.*;
+
+
+/**
+ * A peer for fonts that are used inside Classpath. The purpose of
+ * this interface is to abstract from platform-specific font handling
+ * in the Classpath implementation of java.awt.Font and related
+ * classes.
+ *
+ * <p><b>State kept by the peer:</b> a peer is generated for each Font
+ * object in the default implementation. If you wish to share peers between
+ * fonts, you will need to subclass both ClasspathFontPeer and
+ * {@link ClasspathToolKit}.
+ * 
+ * <p><b>Thread Safety:</b> Methods of this interface may be called
+ * from arbitrary threads at any time. Implementations of the
+ * <code>ClasspathFontPeer</code> interface are required to perform
+ * the necessary synchronization.
+ *
+ * @see java.awt.Font#getPeer
+ * @see java.awt.Toolkit#getFontPeer
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Graydon Hoare (graydon@redhat.com)
+ */
+public abstract class ClasspathFontPeer
+  implements FontPeer
+{
+
+  /*************************************************************************/
+  
+  /*
+   * Instance Variables
+   */
+  
+  /**
+   * The 3 names of this font. all fonts have 3 names, some of which
+   * may be equal:
+   *
+   * logical -- name the font was constructed from
+   * family  -- a designer or brand name (Helvetica)
+   * face -- specific instance of a design (Helvetica Regular)
+   *
+   * @see isLogicalFontName 
+   */
+  
+  protected String logicalName;
+  protected String familyName;
+  protected String faceName;
+  
+  /**
+   * The font style, which is a combination (by OR-ing) of the font style
+   * constants PLAIN, BOLD and ITALIC, in this class.
+   */
+  protected int style;
+  
+  /**
+   * The font point size. A point is 1/72 of an inch.
+   */
+  protected float size;
+
+  /**
+   * The affine transformation the font is currently subject to.
+   */
+  protected AffineTransform transform;
+
+  protected static ClasspathToolkit tk()
+  {
+    return (ClasspathToolkit)(Toolkit.getDefaultToolkit ());
+  }
+
+  /* 
+   * Confusingly, a Logical Font is a concept unrelated to
+   * a Font's Logical Name. 
+   *
+   * A Logical Font is one of 6 built-in, abstract font types
+   * which must be supported by any java environment: SansSerif,
+   * Serif, Monospaced, Dialog, and DialogInput. 
+   *
+   * A Font's Logical Name is the name the font was constructed
+   * from. This might be the name of a Logical Font, or it might
+   * be the name of a Font Face.
+   */
+
+  protected static boolean isLogicalFontName(String name)
+  {
+    String uname = name.toUpperCase ();
+    return (uname.equals ("SANSSERIF") ||
+            uname.equals ("SERIF") ||
+            uname.equals ("MONOSPACED") ||
+            uname.equals ("DIALOG") ||
+            uname.equals ("DIALOGINPUT"));
+  }
+
+  protected static String logicalFontNameToFaceName (String name)
+  {
+    String uname = name.toUpperCase ();
+    if (uname.equals("SANSSERIF"))
+      return "Helvetica";
+    else if (uname.equals ("SERIF"))
+      return "Times";
+    else if (uname.equals ("MONOSPACED"))
+      return "Courier";
+    else if (uname.equals ("DIALOG"))
+      return "Helvetica";
+    else if (uname.equals ("DIALOGINPUT"))
+      return "Helvetica";
+    else
+      return "Helvetica";
+  }
+
+  protected static String faceNameToFamilyName (String name)
+  {
+    return name;
+  }
+
+  protected static void copyStyleToAttrs (int style, Map attrs)
+  {
+    if ((style & Font.BOLD) == Font.BOLD)
+      attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
+    else
+      attrs.put (TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
+
+    if ((style & Font.ITALIC) == Font.ITALIC)
+      attrs.put (TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
+    else
+      attrs.put (TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
+  }
+
+  protected static void copyFamilyToAttrs (String fam, Map attrs)
+  {
+    if (fam != null)
+      attrs.put (TextAttribute.FAMILY, fam);
+  }
+  
+  protected static void copySizeToAttrs (float size, Map attrs)
+  {
+    attrs.put (TextAttribute.SIZE, new Float (size));
+  }
+  
+  protected static void copyTransformToAttrs (AffineTransform trans, Map attrs)
+  {
+    if (trans != null)
+      attrs.put(TextAttribute.TRANSFORM, new TransformAttribute (trans));
+  }
+
+
+  protected void setStandardAttributes (String name, String family, int style, 
+                                        float size, AffineTransform trans)
+  {
+    this.logicalName = name;
+
+    if (isLogicalFontName (name))
+      this.faceName = logicalFontNameToFaceName (name);
+    else
+      this.faceName = name;
+
+    if (family != null)
+      this.familyName = family;
+    else
+      this.familyName = faceNameToFamilyName (faceName);
+    
+    this.style = style;
+    this.size = size;
+    this.transform = trans;
+  }
+
+
+  protected void setStandardAttributes (String name, Map attribs)
+  {
+    String family = this.familyName;
+    AffineTransform trans = this.transform;
+    float size = this.size;
+    int style = this.style;
+    
+    if (attribs.containsKey (TextAttribute.FAMILY))
+      family = (String) attribs.get (TextAttribute.FAMILY);
+
+    if (name == null)
+      name = "SansSerif";
+
+    if (attribs.containsKey (TextAttribute.WEIGHT))
+      {
+        Float weight = (Float) attribs.get (TextAttribute.WEIGHT);
+        if (weight.floatValue () >= TextAttribute.WEIGHT_BOLD.floatValue ())
+          style += Font.BOLD;
+      }
+
+    if (attribs.containsKey (TextAttribute.POSTURE))
+      {
+        Float posture = (Float) attribs.get (TextAttribute.POSTURE);
+        if (posture.floatValue () >= TextAttribute.POSTURE_OBLIQUE.floatValue ())
+          style += Font.ITALIC;
+      }
+
+    if (attribs.containsKey (TextAttribute.SIZE))
+      {
+        Float sz = (Float) attribs.get (TextAttribute.SIZE);
+        size = sz.floatValue ();
+      }
+
+    if (attribs.containsKey (TextAttribute.TRANSFORM))
+      {
+        TransformAttribute ta = (TransformAttribute) 
+          attribs.get(TextAttribute.TRANSFORM);
+        trans = ta.getTransform ();        
+      }
+
+    setStandardAttributes (name, family, style, size, trans);
+  }
+
+  protected void getStandardAttributes (Map attrs)
+  {    
+    copyFamilyToAttrs (this.familyName, attrs);
+    copySizeToAttrs (this.size, attrs);
+    copyStyleToAttrs (this.style, attrs);
+    copyTransformToAttrs (this.transform, attrs);
+  }
+
+
+  /* Begin public API */
+
+  public ClasspathFontPeer (String name, Map attrs)
+  {
+    setStandardAttributes (name, attrs);
+  }
+
+  public ClasspathFontPeer (String name, int style, int size)
+  {
+    setStandardAttributes (name, (String)null, style, 
+                           (float)size, (AffineTransform)null);
+  }
+
+  /** 
+   * Implementation of {@link Font#getName}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public String getName (Font font) 
+  { 
+    return logicalName; 
+  }
+
+  /** 
+   * Implementation of {@link Font#getFamily()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public String getFamily (Font font) 
+  { 
+    return familyName; 
+  }
+
+  /** 
+   * Implementation of {@link Font#getFamily(Locale)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public String getFamily (Font font, Locale lc) 
+  { 
+    return familyName; 
+  }
+
+  /** 
+   * Implementation of {@link Font#getFontName()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public String getFontName (Font font) 
+  { 
+    return faceName; 
+  }
+
+  /** 
+   * Implementation of {@link Font#getFontName(Locale)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public String getFontName (Font font, Locale lc) 
+  { 
+    return faceName; 
+  }
+
+  /** 
+   * Implementation of {@link Font#getSize}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public float getSize (Font font) 
+  { 
+    return size; 
+  }
+
+  /** 
+   * Implementation of {@link Font#isPlain}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+  
+  public boolean isPlain (Font font) 
+  { 
+    return style == Font.PLAIN; 
+  }
+
+  /** 
+   * Implementation of {@link Font#isBold}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+  
+  public boolean isBold (Font font) 
+  { 
+    return ((style & Font.BOLD) == Font.BOLD); 
+  }
+
+  /** 
+   * Implementation of {@link Font#isItalic}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public boolean isItalic (Font font) 
+  { 
+    return ((style & Font.ITALIC) == Font.ITALIC); 
+  }
+
+  /** 
+   * Implementation of {@link Font#deriveFont(float)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public Font deriveFont (Font font, float size)
+  {
+    Map attrs = new HashMap ();
+    getStandardAttributes (attrs);
+    copySizeToAttrs (size, attrs);
+    return tk().getFont (logicalName, attrs);
+  }
+
+  /** 
+   * Implementation of {@link Font#deriveFont(int)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public Font deriveFont (Font font, int style)
+  {
+    Map attrs = new HashMap ();
+    getStandardAttributes (attrs);
+    copyStyleToAttrs (style, attrs);
+    return tk().getFont (logicalName, attrs);
+  }
+
+  /** 
+   * Implementation of {@link Font#deriveFont(int, AffineTransform)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public Font deriveFont (Font font, int style, AffineTransform t)
+  {
+    Map attrs = new HashMap ();
+    getStandardAttributes (attrs);
+    copyStyleToAttrs (style, attrs);
+    copyTransformToAttrs (t, attrs);
+    return tk().getFont (logicalName, attrs);
+  }
+
+  /** 
+   * Implementation of {@link Font#deriveFont(Map)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public Font deriveFont (Font font, Map attrs)
+  {
+    return tk().getFont (logicalName, attrs);
+  }
+
+  /** 
+   * Implementation of {@link Font#getAttributes()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public Map getAttributes (Font font)
+  {
+    HashMap h = new HashMap ();
+    getStandardAttributes (h);
+    return h;
+  }
+
+  /** 
+   * Implementation of {@link Font#getAvailableAttributes()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public AttributedCharacterIterator.Attribute[] getAvailableAttributes(Font font)
+  {
+    AttributedCharacterIterator.Attribute a[] = 
+      new AttributedCharacterIterator.Attribute[5];
+    a[0] = TextAttribute.FAMILY;
+    a[1] = TextAttribute.SIZE;
+    a[2] = TextAttribute.POSTURE;
+    a[3] = TextAttribute.WEIGHT;
+    a[4] = TextAttribute.TRANSFORM;
+    return a;
+  }
+
+  /** 
+   * Implementation of {@link Font#getTransform()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public AffineTransform getTransform (Font font)
+  {
+    return transform;
+  }
+
+  /** 
+   * Implementation of {@link Font#isTransformed()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public boolean isTransformed (Font font)
+  {
+    return ! transform.isIdentity ();
+  }
+
+  /** 
+   * Implementation of {@link Font#getItalicAngle()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public float getItalicAngle (Font font)
+  {
+    if ((style & Font.ITALIC) == Font.ITALIC)
+      return TextAttribute.POSTURE_OBLIQUE.floatValue ();
+    else
+      return TextAttribute.POSTURE_REGULAR.floatValue ();
+  }
+
+
+  /** 
+   * Implementation of {@link Font#getStyle()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public int getStyle (Font font) 
+  { 
+    return style; 
+  }
+
+
+
+
+  /* Remaining methods are abstract */
+
+  /** 
+   * Implementation of {@link Font#canDisplay(char)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract boolean canDisplay (Font font, char c);
+
+  /** 
+   * Implementation of {@link Font#canDisplay(String)},
+   * {@link Font#canDisplay(char [], int, int)}, and
+   * {@link Font#canDisplay(CharacterIterator, int, int)}.
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit);
+
+
+  /**
+   * Returns the name of this font face inside the family, for example
+   * <i>&#x201c;Light&#x201d;</i>.
+   *
+   * <p>This method is currently not used by {@link Font}. However,
+   * this name would be needed by any serious desktop publishing
+   * application.
+   *
+   * @param font the font whose sub-family name is requested.
+   *
+   * @param locale the locale for which to localize the name.  If
+   * <code>locale</code> is <code>null</code>, the returned name is
+   * localized to the user&#x2019;s default locale.
+   *
+   * @return the name of the face inside its family, or
+   * <code>null</code> if the font does not provide a sub-family name.
+   */
+
+  public abstract String getSubFamilyName (Font font, Locale locale);
+  
+
+  /** 
+   * Implementation of {@link Font#getPSName()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract String getPostScriptName (Font font);
+
+
+  /** 
+   * Implementation of {@link Font#getNumGlyphs()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract int getNumGlyphs (Font font);
+
+
+  /** 
+   * Implementation of {@link Font#getMissingGlyphCode()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract int getMissingGlyphCode (Font font);
+
+
+  /** 
+   * Implementation of {@link Font#getBaselineFor(char)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract byte getBaselineFor (Font font, char c);
+
+
+  /**
+   * Returns a name for the specified glyph. This is useful for
+   * generating PostScript or PDF files that embed some glyphs of a
+   * font. If the implementation follows glyph naming conventions
+   * specified by Adobe, search engines can extract the original text
+   * from the generated PostScript and PDF files.
+   *
+   * <p>This method is currently not used by GNU Classpath. However,
+   * it would be very useful for someone wishing to write a good
+   * PostScript or PDF stream provider for the
+   * <code>javax.print</code> package.
+   *
+   * <p><b>Names are not unique:</b> Under some rare circumstances,
+   * the same name can be returned for different glyphs. It is
+   * therefore recommended that printer drivers check whether the same
+   * name has already been returned for antoher glyph, and make the
+   * name unique by adding the string ".alt" followed by the glyph
+   * index.</p>
+   *
+   * <p>This situation would occur for an OpenType or TrueType font
+   * that has a <code>post</code> table of format 3 and provides a
+   * mapping from glyph IDs to Unicode sequences through a
+   * <code>Zapf</code> table. If the same sequence of Unicode
+   * codepoints leads to different glyphs (depending on contextual
+   * position, for example, or on typographic sophistication level),
+   * the same name would get synthesized for those glyphs. To avoid
+   * this, the font peer would have to go through the names of all
+   * glyphs, which would make this operation very inefficient with
+   * large fonts.
+   *
+   * @param font the font containing the glyph whose name is
+   * requested.
+   *
+   * @param glyphIndex the glyph whose name the caller wants to
+   * retrieve.
+   *
+   * @return the glyph name, or <code>null</code> if a font does not
+   * provide glyph names.
+   */
+
+  public abstract String getGlyphName (Font font, int glyphIndex);
+
+
+  /** 
+   * Implementation of {@link
+   * Font#createGlyphVector(FontRenderContext, String)}, {@link
+   * Font#createGlyphVector(FontRenderContext, char[])}, and {@link
+   * Font#createGlyphVector(FontRenderContext, CharacterIterator)}.
+   *
+   * @param font the font object that the created GlyphVector will return
+   * when it gets asked for its font. This argument is needed because the
+   * public API of {@link GlyphVector} works with {@link java.awt.Font},
+   * not with font peers.
+   */
+
+  public abstract GlyphVector createGlyphVector (Font font,
+                                                 FontRenderContext frc,
+                                                 CharacterIterator ci);
+  
+
+  /** 
+   * Implementation of {@link Font#createGlyphVector(FontRenderContext,
+   * int[])}.
+   *
+   * @param font the font object that the created GlyphVector will return
+   * when it gets asked for its font. This argument is needed because the
+   * public API of {@link GlyphVector} works with {@link java.awt.Font},
+   * not with font peers.
+   */
+
+  public abstract GlyphVector createGlyphVector (Font font, 
+                                                 FontRenderContext ctx, 
+                                                 int[] glyphCodes);
+
+
+  /** 
+   * Implementation of {@link Font#layoutGlyphVector(FontRenderContext,
+   * char[], int, int, int)}.
+   *
+   * @param font the font object that the created GlyphVector will return
+   * when it gets asked for its font. This argument is needed because the
+   * public API of {@link GlyphVector} works with {@link java.awt.Font},
+   * not with font peers.
+   */
+
+  public abstract GlyphVector layoutGlyphVector (Font font, 
+                                                 FontRenderContext frc, 
+                                                 char[] chars, int start, 
+                                                 int limit, int flags);
+
+
+  /** 
+   * Implementation of {@link Font#getFontMetrics()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract FontMetrics getFontMetrics (Font font);
+
+
+  /** 
+   * Implementation of {@link Font#hasUniformLineMetrics()}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract boolean hasUniformLineMetrics (Font font);
+
+
+  /** 
+   * Implementation of {@link Font#getLineMetrics(CharacterIterator, int,
+   * int, FontRenderContext)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract LineMetrics getLineMetrics (Font font, 
+                                              CharacterIterator ci, 
+                                              int begin, int limit, 
+                                              FontRenderContext rc);
+
+  /** 
+   * Implementation of {@link Font#getMaxCharBounds(FontRenderContext)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract Rectangle2D getMaxCharBounds (Font font, 
+                                                FontRenderContext rc);
+
+  /** 
+   * Implementation of {@link Font#getStringBounds(CharacterIterator, int,
+   * int, FontRenderContext)}
+   *
+   * @param font the font this peer is being called from. This may be
+   * useful if you are sharing peers between Font objects. Otherwise it may
+   * be ignored.
+   */
+
+  public abstract Rectangle2D getStringBounds (Font font, 
+                                               CharacterIterator ci, 
+                                               int begin, int limit, 
+                                               FontRenderContext frc);
+
+}
diff --git a/libjava/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java b/libjava/gnu/java/awt/peer/gtk/GdkClasspathFontPeer.java
new file mode 100644 (file)
index 0000000..7e31700
--- /dev/null
@@ -0,0 +1,239 @@
+/* GdkClasspathFontPeer.java -- backend implementation for Font object
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import java.awt.font.TextAttribute;
+import gnu.classpath.Configuration;
+import gnu.java.awt.peer.ClasspathFontPeer;
+
+/**
+ * This class represents a windowing system font using the Pango
+ * unicode/glyph/font library and the Cairo rendering library.
+ *
+ * @author Graydon Hoare (graydon@redhat.com)
+ */
+
+public class GdkClasspathFontPeer extends ClasspathFontPeer
+{
+  
+  static 
+  {
+    if (Configuration.INIT_LOAD_LIBRARY)
+      {
+        System.loadLibrary("gtkpeer");
+      }
+    initStaticState ();
+  }
+  native static void initStaticState ();
+  private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+
+  /* Instance Variables */
+
+  private native void initState ();
+  private native void dispose ();
+  private native void setFont (String family, int style, int size);
+
+  protected void sync ()
+  {
+    this.setFont (this.familyName, this.style, (int)this.size);
+  }
+
+  protected void finalize ()
+  {
+    dispose ();
+  }
+
+  /* 
+   * Helpers for the 3-way overloading that this class seems to suffer
+   * from. Remove them if you feel like they're a performance bottleneck,
+   * for the time being I prefer my code not be written and debugged in
+   * triplicate.
+   */
+
+  private String buildString(CharacterIterator i) {
+    String s = new String ();
+    for(char c = i.first(); c != CharacterIterator.DONE; c = i.next()) 
+      s += c;
+    return s;
+  }
+
+  private String buildString(CharacterIterator iter, int begin, int limit) {
+    String s = new String ();
+    int i = 0;
+    for(char c = iter.first(); c != CharacterIterator.DONE; c = iter.next(), i++) 
+      {
+        if (begin <= i)
+          s += c;
+        if (limit <= i)
+          break;
+      }
+    return s;
+  }
+  
+  private String buildString(char[] chars, int begin, int limit) {
+    String s = new String ();
+    for(int i = begin; i <= limit; i++)
+      s += chars[i];
+    return s;
+  }
+
+  /* Public API */
+
+  public GdkClasspathFontPeer (String name, int style, int size)
+  {  
+    super(name, style, size);    
+    initState ();
+    setFont (this.familyName, this.style, (int)this.size);
+  }
+
+  public GdkClasspathFontPeer (String name, Map attributes)
+  {
+    super(name, attributes);
+    initState ();
+    setFont (this.familyName, this.style, (int)this.size);
+  }
+
+  public String getSubFamilyName(Font font, Locale locale)
+  {
+    return null;
+  }
+
+  public String getPostScriptName(Font font)
+  {
+    return null;
+  }
+
+  public boolean canDisplay (Font font, char c)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public int canDisplayUpTo (Font font, CharacterIterator i, int start, int limit)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public GlyphVector createGlyphVector (Font font, 
+                                        FontRenderContext ctx, 
+                                        CharacterIterator i)
+  {
+    return new GdkGlyphVector(font, this, ctx, buildString (i));
+  }
+
+  public GlyphVector createGlyphVector (Font font, 
+                                        FontRenderContext ctx, 
+                                        int[] glyphCodes)
+  {
+    return new GdkGlyphVector (font, this, ctx, glyphCodes);
+  }
+
+  public byte getBaselineFor (Font font, char c)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public LineMetrics getLineMetrics (Font font, CharacterIterator ci, 
+                                     int begin, int limit, FontRenderContext rc)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public Rectangle2D getMaxCharBounds (Font font, FontRenderContext rc)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public int getMissingGlyphCode (Font font)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public String getGlyphName (Font font, int glyphIndex)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public int getNumGlyphs (Font font)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public Rectangle2D getStringBounds (Font font, CharacterIterator ci, 
+                                      int begin, int limit, FontRenderContext frc)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public boolean hasUniformLineMetrics (Font font)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public GlyphVector layoutGlyphVector (Font font, FontRenderContext frc, 
+                                        char[] chars, int start, int limit, 
+                                        int flags)
+  {
+    throw new UnsupportedOperationException ();  
+  }
+
+  public LineMetrics getLineMetrics (Font font, String str, 
+                                     FontRenderContext frc)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+  public FontMetrics getFontMetrics (Font font)
+  {
+    throw new UnsupportedOperationException();
+  }
+
+}
+
diff --git a/libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java b/libjava/gnu/java/awt/peer/gtk/GdkGlyphVector.java
new file mode 100644 (file)
index 0000000..0ba4539
--- /dev/null
@@ -0,0 +1,342 @@
+/* GdkGlyphVector.java -- Glyph vector object
+   Copyright (C) 2003 Free Software Foundation, Inc.
+
+   This file is part of GNU Classpath.
+
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
+
+
+package gnu.java.awt.peer.gtk;
+
+import java.awt.*;
+import java.awt.font.*;
+import java.awt.geom.*;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.text.CharacterIterator;
+import java.text.AttributedCharacterIterator;
+import gnu.classpath.Configuration;
+
+public class GdkGlyphVector extends GlyphVector 
+{
+
+  static 
+  {
+    if (Configuration.INIT_LOAD_LIBRARY)
+      {
+        System.loadLibrary("gtkpeer");
+      }
+    initStaticState ();
+  }
+  native static void initStaticState ();
+  private final int native_state = GtkGenericPeer.getUniqueInteger ();
+
+  private Font font;
+  private FontRenderContext ctx;
+    
+  private native void initState (GdkClasspathFontPeer peer, FontRenderContext ctx);
+  private native void setChars (String s);
+  private native void setGlyphCodes (int codes[]);
+  private native void dispose ();
+  private native int glyphCode (int idx);
+  private native int numGlyphs ();
+  private native int glyphCharIndex (int idx);
+  private native double[] allLogicalExtents ();
+  private native double[] allInkExtents ();
+  private native double[] glyphLogicalExtents (int idx);
+  private native double[] glyphInkExtents (int idx);
+  private native boolean glyphIsHorizontal (int idx);
+  private native boolean isEqual (GdkGlyphVector ggv);
+
+
+  /* 
+     geometric notes:
+
+     the FRC contains a mapping from points -> pixels.
+
+     typographics points are typically 1/72 of an inch.
+
+     pixel displays are often around 72 dpi.
+
+     so the FRC can get away with using an identity transform on a screen,
+     often. behavior is documented by sun to fall back to an identity
+     transform if the internal transformation is null.
+
+     coordinates coming up from pango are expressed as floats -- in device
+     space, so basically pixels-with-fractional-bits -- derived from their
+     storage format in pango (1024ths of pixels). 
+
+     it is not clear from the javadocs whether the results of methods like
+     getGlyphPositions ought to return coordinates in device space, or
+     "point" space, or what. for now I'm returning them in device space.
+     
+   */
+
+
+  public GdkGlyphVector (Font f, GdkClasspathFontPeer peer, FontRenderContext c, String s)
+  {
+    font = f;
+    ctx = c;
+    initState (peer, ctx);
+    setChars (s);
+  }
+
+  public GdkGlyphVector (Font f, GdkClasspathFontPeer peer, FontRenderContext c, int codes[])
+  {
+    font = f;
+    ctx = c;
+    initState (peer, ctx);
+    setGlyphCodes (codes);
+  }
+
+  protected void finalize ()
+  {
+    dispose ();
+  }
+
+  public Font getFont () 
+  { 
+    return font; 
+  }
+
+  public FontRenderContext getFontRenderContext () 
+  { 
+    return ctx; 
+  }
+
+  public int getGlyphCharIndex (int glyphIndex) 
+  { 
+    return glyphCharIndex (glyphIndex); 
+  }
+
+  public int[] getGlyphCharIndices (int beginGlyphIndex, 
+                                    int numEntries,
+                                    int[] codeReturn)
+  {
+    int ix[] = codeReturn;
+    if (ix == null)
+      ix = new int[numEntries];
+
+    for (int i = 0; i < numEntries; i++)
+      ix[i] = glyphCharIndex (beginGlyphIndex + i);
+    return ix;
+  }
+
+  public int getGlyphCode (int glyphIndex) 
+  { 
+    return glyphCode (glyphIndex); 
+  }
+
+  public int[] getGlyphCodes (int beginGlyphIndex, int numEntries,
+                              int[] codeReturn)
+  {
+    int ix[] = codeReturn;
+    if (ix == null)
+      ix = new int[numEntries];
+
+    for (int i = 0; i < numEntries; i++)
+      ix[i] = glyphCode (beginGlyphIndex + i);
+    return ix;
+  }
+
+  public Shape getGlyphLogicalBounds (int glyphIndex)
+  {
+    double extents[] = glyphLogicalExtents (glyphIndex);
+    return new Rectangle2D.Double (extents[0], extents[1],
+                                   extents[2], extents[3]);
+  }
+    
+  public GlyphMetrics getGlyphMetrics (int glyphIndex)
+  {
+    double extents[] = glyphLogicalExtents (glyphIndex);
+    Rectangle2D log_bounds = new Rectangle2D.Double (extents[0], extents[1],
+                                                     extents[2], extents[3]);
+
+    extents = glyphInkExtents (glyphIndex);
+    Rectangle2D ink_bounds = new Rectangle2D.Double (extents[0], extents[1],
+                                                     extents[2], extents[3]);
+      
+    boolean is_horizontal = glyphIsHorizontal (glyphIndex);
+
+    return new GlyphMetrics (is_horizontal,
+                             (float)(log_bounds.getWidth() + log_bounds.getX()), 
+                             (float)(log_bounds.getHeight() + log_bounds.getY()),
+                             ink_bounds, GlyphMetrics.STANDARD);
+  }
+
+  public Shape getGlyphOutline (int glyphIndex)
+  {
+    throw new UnsupportedOperationException ();      
+  }
+
+  public Shape getGlyphOutline (int glyphIndex, float x, float y)
+  {
+    throw new UnsupportedOperationException ();
+  }
+
+  public Rectangle getGlyphPixelBounds (int glyphIndex, 
+                                        FontRenderContext renderFRC,
+                                        float x, float y)
+  {
+    double extents[] = glyphInkExtents(glyphIndex);
+    return new Rectangle ((int)x, (int)y, (int)extents[2], (int)extents[3]);
+  }
+    
+  public Point2D getGlyphPosition (int glyphIndex)
+  {
+    float[] ret = new float[2 * (glyphIndex + 1)];
+    getGlyphPositions (0, glyphIndex + 1, ret);
+    return new Point2D.Float (ret[2 * glyphIndex], 
+                              ret[2 * glyphIndex + 1]);
+  }
+
+  public float[] getGlyphPositions (int beginGlyphIndex,
+                                    int numEntries,
+                                    float[] positionReturn)
+  {
+    float fx[] = positionReturn;
+    if (fx == null)
+      fx = new float[numEntries * 2];
+
+
+    float x = 0.0f;
+    float y = 0.0f;
+    for (int i = 0; i < numEntries; ++i)
+      {
+        boolean is_horizontal = glyphIsHorizontal (beginGlyphIndex + i);
+        double log_extents[] = glyphLogicalExtents (beginGlyphIndex + i);
+        fx[2*i]     = x + (float)log_extents[0]; // x offset
+        fx[2*i + 1] = y + (float)log_extents[1]; // y offset
+        if (is_horizontal)
+          x += (float)log_extents[2]; // x advance ("logical width") in pango-ese
+        else
+          y += (float)log_extents[3]; // y advance ("logical height") in pango-ese
+      }
+    return fx;
+  }
+
+  public AffineTransform getGlyphTransform (int glyphIndex)
+  {
+    // glyphs don't have independent transforms in these simple glyph
+    // vectors; docs specify null is an ok return here.
+    return null;  
+  }
+    
+  public Shape getGlyphVisualBounds (int glyphIndex)
+  {
+    double extents[] = glyphInkExtents (glyphIndex);
+    return new Rectangle2D.Double (extents[0], extents[1], 
+                                   extents[2], extents[3]);
+  }
+    
+  public int getLayoutFlags ()
+  {
+    return 0;
+  }
+
+  public Rectangle2D getLogicalBounds ()
+  {
+    double extents[] = allLogicalExtents ();
+    return new Rectangle2D.Double (extents[0], extents[1], 
+                                   extents[2], extents[3]);
+  }
+
+  public int getNumGlyphs ()
+  {
+    return numGlyphs ();
+  }
+
+  public Shape getOutline ()
+  {
+    throw new UnsupportedOperationException ();      
+  }
+
+  public Rectangle getPixelBounds (FontRenderContext renderFRC,
+                                   float x, float y)
+  {
+    double extents[] = allInkExtents();
+    return new Rectangle ((int)x, (int)y, 
+                          (int)extents[2], (int)extents[3]);
+  }
+    
+  public Rectangle2D getVisualBounds ()
+  {
+    double extents[] = allInkExtents();
+    return new Rectangle2D.Double (extents[0], extents[1], 
+                                   extents[2], extents[3]);
+  }
+
+  public void performDefaultLayout ()
+  {
+  }
+    
+  public void setGlyphPosition (int glyphIndex, Point2D newPos)
+  {
+    // should we be ok twiddling pango's structure here?
+    throw new UnsupportedOperationException ();      
+  }
+
+  public void setGlyphTransform (int glyphIndex,
+                                 AffineTransform newTX)
+  {
+    // not yet.. maybe not ever?
+    throw new UnsupportedOperationException ();      
+  }
+
+  public boolean equals(GlyphVector gv)
+  {
+    if (gv == null)
+      return false;
+
+    if (! (gv instanceof GdkGlyphVector))
+      return false;
+
+    GdkGlyphVector ggv = (GdkGlyphVector)gv;
+    return isEqual(ggv);
+  }
+
+  public GlyphJustificationInfo getGlyphJustificationInfo(int idx)
+  {
+    throw new UnsupportedOperationException ();      
+  }
+
+  public Shape getOutline(float x, float y)    
+  {
+    throw new UnsupportedOperationException ();      
+  }
+
+}
index 11c0371..7adb307 100644 (file)
@@ -48,6 +48,8 @@ import java.awt.image.renderable.*;
 import java.text.AttributedCharacterIterator;
 import java.util.Map;
 import java.lang.Integer;
 import java.text.AttributedCharacterIterator;
 import java.util.Map;
 import java.lang.Integer;
+import gnu.java.awt.ClasspathToolkit;
+import gnu.java.awt.peer.ClasspathFontPeer;
 import gnu.classpath.Configuration;
 
 public class GdkGraphics2D extends Graphics2D
 import gnu.classpath.Configuration;
 
 public class GdkGraphics2D extends Graphics2D
@@ -75,8 +77,8 @@ public class GdkGraphics2D extends Graphics2D
   private Shape clip;
   private AffineTransform transform;
   private GtkComponentPeer component;
   private Shape clip;
   private AffineTransform transform;
   private GtkComponentPeer component;
-  private GdkFont font;  
-
+  private Font font;  
+  
   native private int[] initState (GtkComponentPeer component);
   native private void initState (int width, int height);
   native private void copyState (GdkGraphics2D g);
   native private int[] initState (GtkComponentPeer component);
   native private void initState (int width, int height);
   native private void copyState (GdkGraphics2D g);
@@ -172,6 +174,10 @@ public class GdkGraphics2D extends Graphics2D
   private native void cairoSetMatrix (double m00, double m10, 
                                       double m01, double m11,
                                       double m02, double m12);
   private native void cairoSetMatrix (double m00, double m10, 
                                       double m01, double m11,
                                       double m02, double m12);
+  private native void cairoSetFont (GdkClasspathFontPeer peer);
+  private native void cairoShowGlyphs (int codes[],
+                                       float positions[],
+                                       int nglyphs);
   private native void cairoSetOperator (int cairoOperator);
   private native void cairoSetRGBColor (double red, double green, double blue);
   private native void cairoSetAlpha (double alpha);
   private native void cairoSetOperator (int cairoOperator);
   private native void cairoSetRGBColor (double red, double green, double blue);
   private native void cairoSetAlpha (double alpha);
@@ -1024,8 +1030,14 @@ public class GdkGraphics2D extends Graphics2D
   }
 
   public void drawGlyphVector (GlyphVector g, float x, float y)
   }
 
   public void drawGlyphVector (GlyphVector g, float x, float y)
-  {
-    throw new java.lang.UnsupportedOperationException ();
+  {    
+    cairoSave ();
+    cairoTranslate ((double)x, (double)y);
+    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 ();
   }
 
   public void copyArea (int x, int y, int width, int height, int dx, int dy)
   }
 
   public void copyArea (int x, int y, int width, int height, int dx, int dy)
@@ -1132,10 +1144,16 @@ public class GdkGraphics2D extends Graphics2D
 
   public void setFont (Font f)
   {
 
   public void setFont (Font f)
   {
-    if (f instanceof GdkFont)
-      font = (GdkFont) f;
+    if (f.getPeer() instanceof GdkClasspathFontPeer)
+      font = f;
     else
     else
-      font = new GdkFont (f.getAttributes ());
+      font = 
+        ((ClasspathToolkit)(Toolkit.getDefaultToolkit ()))
+        .getFont (f.getName(), f.getAttributes ());
+
+    if (f != null && 
+        f.getPeer() instanceof GdkClasspathFontPeer)
+      cairoSetFont ((GdkClasspathFontPeer) f.getPeer());
   }
 
   public String toString()
   }
 
   public String toString()
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeer.c
new file mode 100644 (file)
index 0000000..092979b
--- /dev/null
@@ -0,0 +1,160 @@
+/* gnu_java_awt_GdkFont.c
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   
+   This file is part of GNU Classpath.
+   
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+   
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+   
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
+
+#include "gdkfont.h"
+#include "gnu_java_awt_peer_gtk_GdkClasspathFontPeer.h"
+
+struct state_table *native_font_state_table;
+
+/*
+rough sketch of the mapping between java and 
+pango text objects:
+  
+  Font              <->    - PangoFont
+                           - PangoFontDescription
+                           - PangoContext
+
+  GlyphVector       <->    - GList of PangoGlyphItem
+                           - PangoFontDescription
+                           - PangoContext
+
+  FontRenderContext <->    stays in plain java
+
+*/
+
+enum java_awt_font_style {
+  java_awt_font_PLAIN = 0,
+  java_awt_font_BOLD = 1,
+  java_awt_font_ITALIC = 2
+};
+
+enum java_awt_font_baseline {
+  java_awt_font_ROMAN_BASELINE = 0,
+  java_awt_font_CENTER_BASELINE = 1,
+  java_awt_font_HANGING_BASELINE = 2
+};
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeer_initStaticState 
+  (JNIEnv *env, jclass clazz)
+{
+  NSA_FONT_INIT (env, clazz);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeer_initState
+  (JNIEnv *env, jobject self)
+{
+  struct peerfont *pfont = NULL;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  pfont = (struct peerfont *) g_malloc0 (sizeof (struct peerfont));
+  g_assert (pfont != NULL);
+  NSA_SET_FONT_PTR (env, self, pfont);
+  gdk_threads_leave ();
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeer_dispose
+  (JNIEnv *env, jobject self)
+{
+  struct peerfont *pfont = NULL;
+
+  gdk_threads_enter ();
+  pfont = (struct peerfont *)NSA_DEL_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);
+  g_free (pfont);
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkClasspathFontPeer_setFont
+  (JNIEnv *env, jobject self, jstring family_name_str, jint style_int, jint size)
+{
+  struct peerfont *pfont = NULL;
+  PangoFontMap *map = NULL; 
+  char const *family_name = NULL;
+
+  gdk_threads_enter ();
+  enum java_awt_font_style style = (enum java_awt_font_style) style_int;
+
+  g_assert (self != NULL);
+  pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, self);
+  g_assert (pfont != NULL);
+
+  pfont->desc = pango_font_description_new ();
+  g_assert (pfont->desc != NULL);
+
+  family_name = (*env)->GetStringUTFChars(env, family_name_str, 0);
+  g_assert (family_name != NULL);
+  pango_font_description_set_family (pfont->desc, family_name);
+  (*env)->ReleaseStringUTFChars(env, family_name_str, family_name);
+
+  pango_font_description_set_size (pfont->desc, size * PANGO_SCALE);  
+
+  if (style & java_awt_font_BOLD)
+    pango_font_description_set_weight (pfont->desc, PANGO_WEIGHT_BOLD);
+
+  if (style & java_awt_font_ITALIC)
+    pango_font_description_set_style (pfont->desc, PANGO_STYLE_ITALIC);
+  
+  /* 
+     FIXME: these are possibly wrong, and should in any case
+     probably be cached between calls.
+   */
+
+  map = pango_ft2_font_map_for_display ();
+  g_assert (map != NULL);
+  
+  if (pfont->ctx == NULL)
+    pfont->ctx = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (map));  
+  g_assert (pfont->ctx != NULL);
+
+  if (pfont->font != NULL)
+    g_object_unref (pfont->font);
+
+  pfont->font = pango_font_map_load_font (map, pfont->ctx, pfont->desc);
+  g_assert (pfont->font != NULL);
+  
+  gdk_threads_leave ();
+}
+
+
diff --git a/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c b/libjava/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c
new file mode 100644 (file)
index 0000000..052f7e9
--- /dev/null
@@ -0,0 +1,571 @@
+/* gdkglyphvector.c
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   
+   This file is part of GNU Classpath.
+   
+   GNU Classpath is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   GNU Classpath is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with GNU Classpath; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.
+   
+   Linking this library statically or dynamically with other modules is
+   making a combined work based on this library.  Thus, the terms and
+   conditions of the GNU General Public License cover the whole
+   combination.
+   
+   As a special exception, the copyright holders of this library give you
+   permission to link this library with independent modules to produce an
+   executable, regardless of the license terms of these independent
+   modules, and to copy and distribute the resulting executable under
+   terms of your choice, provided that you also meet, for each linked
+   independent module, the terms and conditions of the license of that
+   module.  An independent module is a module which is not derived from
+   or based on this library.  If you modify this library, you may extend
+   this exception to your version of the library, but you are not
+   obligated to do so.  If you do not wish to do so, delete this
+   exception statement from your version. */
+
+#include "gdkfont.h"
+#include "gnu_java_awt_peer_gtk_GdkGlyphVector.h"
+
+struct state_table *native_glyphvector_state_table;
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initStaticState 
+  (JNIEnv *env, jclass clazz)
+{
+  NSA_GV_INIT (env, clazz);
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_initState 
+  (JNIEnv *env, jobject self, jobject font, jobject ctx)
+{
+  struct glyphvec *vec = NULL;
+  struct peerfont *pfont = NULL;
+
+  gdk_threads_enter ();
+  g_assert (font != NULL);
+  pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
+  g_assert (pfont != NULL);
+  g_assert (pfont->ctx != NULL);
+  g_assert (pfont->desc != NULL);
+
+  g_assert (self != NULL);
+  vec = (struct glyphvec *) g_malloc0 (sizeof (struct glyphvec));
+  g_assert (vec != NULL);
+
+  vec->desc = pango_font_description_copy (pfont->desc);
+  g_assert (vec->desc != NULL);
+    
+  vec->ctx = pfont->ctx;
+  g_object_ref (vec->ctx);
+
+  NSA_SET_GV_PTR (env, self, vec);
+  gdk_threads_leave ();
+}
+
+static void free_glyphitems (GList *list)
+{
+  GList *i = NULL;
+  PangoGlyphItem *gi = NULL;
+
+  for (i = g_list_first (list); i != NULL; i = g_list_next (i))
+    {
+      g_assert (i->data != NULL);
+      gi = (PangoGlyphItem *)i->data;
+
+      if (gi->glyphs != NULL)
+       pango_glyph_string_free (gi->glyphs);
+
+      if (gi->item != NULL)
+       g_free (gi->item);
+    }      
+  g_list_free (list);
+}
+
+static void seek_glyphstring_idx (GList *list, int idx, 
+                                 int *nidx, 
+                                 PangoGlyphString **gs,
+                                 PangoFont **fnt)
+{
+  GList *i = NULL;
+  PangoGlyphItem *gi = NULL;
+
+  g_assert (list != NULL);
+  g_assert (gs != NULL);
+  g_assert (nidx != NULL);
+
+  int begin = 0;
+  for (i = g_list_first (list); i != NULL; i = g_list_next (i))
+    {
+      g_assert (i->data != NULL);
+      gi = (PangoGlyphItem *)i->data;
+
+      g_assert (gi->glyphs != NULL);
+      
+      if (begin <= idx && idx < begin + gi->glyphs->num_glyphs)
+       {         
+         *gs = gi->glyphs;
+         *nidx = idx - begin;
+         if (fnt && gi->item)
+           *fnt = gi->item->analysis.font;
+         return;
+       }
+      else
+       {
+         begin += gi->glyphs->num_glyphs;
+       }
+    }
+  *gs = NULL;
+  *nidx = -1;
+}
+
+static void seek_glyph_idx (GList *list, int idx, 
+                           PangoGlyphInfo **g,
+                           PangoFont **fnt)
+{
+  PangoGlyphString *gs = NULL;
+  int nidx = -1;
+
+  g_assert (list != NULL);
+  g_assert (g != NULL);
+
+  seek_glyphstring_idx (list, idx, &nidx, &gs, fnt);
+
+  g_assert (gs != NULL);
+  g_assert (nidx != -1);
+  g_assert (nidx < gs->num_glyphs);
+  g_assert (gs->glyphs != NULL);
+
+  *g = gs->glyphs + nidx;
+}
+
+static void union_rects (PangoRectangle *r1, 
+                        const PangoRectangle *r2)
+{
+  PangoRectangle r;
+
+  g_assert (r1 != NULL);
+  g_assert (r2 != NULL);
+
+  /* 
+     x is the left edge of the rect,
+     y is the top edge of the rect
+  */
+
+#ifndef min
+#define min(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+#ifndef max
+#define max(x,y) ((x) < (y) ? (y) : (x))
+#endif
+
+  r.x = min(r1->x, r2->x);
+
+  r.y = min(r1->y, r2->y);
+
+  r.width = max(r1->x + r1->width,
+               r2->x + r2->width) - r.x;
+
+  r.height = max(r1->y + r1->height,
+                r2->y + r2->height) - r.y;
+
+  *r1 = r;  
+}
+
+static jdoubleArray rect_to_array (JNIEnv *env, const PangoRectangle *r)
+{
+  /* We often return rectangles as arrays : { x, y, w, h } */
+  jdoubleArray ret;
+  double *rp = NULL;
+  g_assert (r != NULL);
+  ret = (*env)->NewDoubleArray (env, 4);
+  rp = (*env)->GetDoubleArrayElements (env, ret, NULL);
+  g_assert (rp != NULL);
+  rp[0] = r->x / (double)PANGO_SCALE;
+  /* 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;
+  (*env)->ReleaseDoubleArrayElements (env, ret, rp, 0);
+  return ret;
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_dispose
+  (JNIEnv *env, jobject self)
+{
+  struct glyphvec *vec = NULL;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_DEL_GV_PTR (env, self);
+  g_assert (vec != NULL);
+
+  if (vec->glyphitems != NULL)
+    {
+      free_glyphitems (vec->glyphitems);
+      vec->glyphitems = NULL;
+    }
+      
+  if (vec->desc != NULL)
+    pango_font_description_free (vec->desc);
+
+  if (vec->ctx != NULL)
+    g_object_unref (vec->ctx);
+
+  g_free (vec);
+  gdk_threads_leave ();
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setChars 
+  (JNIEnv *env, jobject self, jstring chars)
+{
+  struct glyphvec *vec = NULL;
+  gchar *str = NULL;
+  GList *items = NULL, *item = NULL;
+  PangoGlyphItem *gi;
+  PangoAttrList *attrs = NULL; 
+  gint len = 0;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->desc != NULL);
+  g_assert (vec->ctx != NULL);
+  
+  len = (*gdk_env)->GetStringUTFLength (env, chars);
+  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 */
+
+  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_attr_list_insert (attrs, da);
+  items = pango_itemize (vec->ctx, str, 0, len, attrs, NULL);
+  g_assert (items != NULL);
+  
+  /*
+    step 2: for each item:
+    - shape the item into a glyphstring
+    - store the (item, glyphstring) pair in the vec->glyphitems list
+  */
+  
+  if (vec->glyphitems != NULL)
+    {
+      free_glyphitems (vec->glyphitems);
+      vec->glyphitems = NULL;
+    }
+
+  for (item = g_list_first (items); item != NULL; item = g_list_next (item))
+    {
+      g_assert (item->data != NULL);
+
+      gi = NULL;
+      gi = g_malloc0 (sizeof(PangoGlyphItem));
+      g_assert (gi != NULL);
+
+      gi->item = (PangoItem *)item->data;
+      gi->glyphs = pango_glyph_string_new ();
+      g_assert (gi->glyphs != NULL);
+
+      pango_shape (str + gi->item->offset, 
+                  gi->item->length, 
+                  &(gi->item->analysis), 
+                  gi->glyphs);
+
+      vec->glyphitems = g_list_append (vec->glyphitems, gi);
+    }
+
+  /* 
+     ownership of each item has been transferred to glyphitems, 
+     but the list should be freed.
+  */
+
+  g_list_free (items);
+  pango_attr_list_unref (attrs);
+
+  (*env)->ReleaseStringUTFChars (env, chars, str);
+  gdk_threads_leave ();
+}
+
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_setGlyphCodes 
+  (JNIEnv *env, jobject self, jintArray codes)
+{
+  struct glyphvec *vec = NULL;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+
+  /*
+    FIXME: setting glyph codes doesn't seem particularly plausible at the
+    moment. 
+   */
+
+  gdk_threads_leave ();
+
+}
+
+
+JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCode 
+  (JNIEnv *env, jobject self, jint idx)
+{
+  struct glyphvec *vec = NULL;
+  PangoGlyphInfo *gi = NULL;
+  jint ret = 0;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->glyphitems != NULL);
+
+  seek_glyph_idx (vec->glyphitems, idx, &gi, NULL);
+  g_assert (gi != NULL);
+  ret = gi->glyph;
+  gdk_threads_leave ();
+
+  return (jint)(ret);  
+}
+
+
+JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_numGlyphs 
+  (JNIEnv *env, jobject self)
+{
+  GList *i = NULL;
+  PangoGlyphItem *gi = NULL;
+  struct glyphvec *vec = NULL;
+  jint count = 0;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+
+  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);
+      count += gi->glyphs->num_glyphs;
+    }      
+  gdk_threads_leave ();
+
+  return count;
+}
+
+
+JNIEXPORT jint JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphCharIndex 
+  (JNIEnv *env, jobject self, jint idx)
+{
+  /* 
+     FIXME: this is not correct, rather it assumes a (broken) 1:1
+     glyph:char model. it can be implemented in terms of bytes (also
+     broken) using pango's current interface, or perhaps in terms of
+     characters if some better byte->character conversion operator is
+     found. for the time being we leave it broken.
+  */
+  return idx;
+}
+
+
+JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allLogicalExtents 
+  (JNIEnv *env, jobject self)
+{
+  struct glyphvec *vec = NULL;
+  GList *i;
+  PangoGlyphItem *gi = NULL;
+  PangoRectangle rect = {0,0,0,0};
+  PangoRectangle tmp, dummy;  
+  jdoubleArray ret;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->glyphitems != NULL);
+
+  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);
+      union_rects (&rect, &tmp);
+    }      
+
+  ret = rect_to_array (env, &rect);
+  gdk_threads_leave ();
+  return ret;
+}
+
+
+JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_allInkExtents 
+  (JNIEnv *env, jobject self)
+{
+  struct glyphvec *vec = NULL;
+  GList *i;
+  PangoGlyphItem *gi = NULL;
+  PangoRectangle rect = {0,0,0,0};
+  PangoRectangle tmp, dummy;  
+  jdoubleArray ret;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->glyphitems != NULL);
+
+  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);
+      union_rects (&rect, &tmp);
+    }      
+
+  ret = rect_to_array (env, &rect);
+  gdk_threads_leave ();
+  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;  
+  PangoGlyphInfo *gi = NULL;
+  PangoFont *font = NULL;
+  jdoubleArray ret;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->glyphitems != NULL);
+
+  seek_glyph_idx (vec->glyphitems, idx, &gi, &font);
+  g_assert (gi != NULL);
+  g_assert (font != NULL);
+
+  pango_font_get_glyph_extents (font, gi->glyph, &dummy, &rect);
+
+  ret = rect_to_array (env, &rect);
+  gdk_threads_leave ();
+  return ret;
+}
+
+
+JNIEXPORT jdoubleArray JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_glyphInkExtents 
+  (JNIEnv *env, jobject self, jint idx)
+{
+  struct glyphvec *vec = NULL;
+  PangoRectangle rect = {0,0,0,0};
+  PangoRectangle dummy;  
+  PangoGlyphInfo *gi = NULL;
+  PangoFont *font = NULL;
+  jdoubleArray ret;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->glyphitems != NULL);
+
+  seek_glyph_idx (vec->glyphitems, idx, &gi, &font);
+  g_assert (gi != NULL);
+  g_assert (font != NULL);
+
+  pango_font_get_glyph_extents (font, gi->glyph, &rect, &dummy);
+
+  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)
+{
+  struct glyphvec *vec = NULL;
+  PangoDirection dir;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  g_assert (vec != NULL);
+  g_assert (vec->desc != NULL);
+  g_assert (vec->ctx != NULL);
+
+  /* 
+     FIXME: this is an approximation; it's not clear to me whether
+     glyphs themselves are horizontal or vertical so much as the
+     writing system or writing context. pango thinks it's a context
+     issue, so we use that for now.
+   */
+
+  dir = pango_context_get_base_dir (vec->ctx);
+
+  gdk_threads_leave ();
+
+  return 
+    ((dir == PANGO_DIRECTION_LTR) ||
+     (dir == PANGO_DIRECTION_RTL));    
+}
+
+
+JNIEXPORT jboolean JNICALL Java_gnu_java_awt_peer_gtk_GdkGlyphVector_isEqual 
+  (JNIEnv *env, jobject self, jobject other)
+{
+  struct glyphvec *vec1 = NULL, *vec2 = NULL;
+  jboolean eq = 0;
+
+  gdk_threads_enter ();
+  g_assert (self != NULL);
+  vec1 = (struct glyphvec *)NSA_GET_GV_PTR (env, self);
+  vec2 = (struct glyphvec *)NSA_GET_GV_PTR (env, other);
+  g_assert (vec1 != NULL);
+  g_assert (vec2 != NULL);
+  
+  /* FIXME: is there some more advantageous definition of equality for
+     glyph vectors? */
+  eq = (vec1 == vec2);
+  
+  gdk_threads_leave ();
+  return eq;
+}
+
+
index 04eb2e5..08a9742 100644 (file)
@@ -36,6 +36,7 @@
    exception statement from your version. */
 
 #include "gtkpeer.h"
    exception statement from your version. */
 
 #include "gtkpeer.h"
+#include "gdkfont.h"
 #include "gnu_java_awt_peer_gtk_GdkGraphics2D.h"
 #include <gdk/gdktypes.h>
 #include <gdk/gdkprivate.h>
 #include "gnu_java_awt_peer_gtk_GdkGraphics2D.h"
 #include <gdk/gdktypes.h>
 #include <gdk/gdkprivate.h>
@@ -45,6 +46,8 @@
 #include <gdk-pixbuf/gdk-pixdata.h>
 
 #include <cairo.h>
 #include <gdk-pixbuf/gdk-pixdata.h>
 
 #include <cairo.h>
+#include <cairo-xlib.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -198,9 +201,9 @@ init_graphics2d_as_renderable (struct graphics2d *gr)
   vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable));
   g_assert (vis != NULL);
   
   vis = gdk_x11_visual_get_xvisual (gdk_drawable_get_visual (gr->drawable));
   g_assert (vis != NULL);
   
-  gr->surface = cairo_surface_create_for_drawable (dpy, draw, vis, 
-                                                  CAIRO_FORMAT_ARGB32,
-                                                  DefaultColormap (dpy, DefaultScreen (dpy)));
+  gr->surface = cairo_xlib_surface_create (dpy, draw, vis, 
+                                          CAIRO_FORMAT_ARGB32,
+                                          DefaultColormap (dpy, DefaultScreen (dpy)));
   g_assert (gr->surface != NULL);
   g_assert (gr->cr != NULL);
   cairo_set_target_surface (gr->cr, gr->surface);
   g_assert (gr->surface != NULL);
   g_assert (gr->cr != NULL);
   cairo_set_target_surface (gr->cr, gr->surface);
@@ -378,8 +381,8 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_gdkDrawDrawable
   gc = gdk_gc_new (dst->drawable);
   g_assert (gc != NULL);
 
   gc = gdk_gc_new (dst->drawable);
   g_assert (gc != NULL);
 
-  gdk_draw_drawable(dst->drawable, gc, src->drawable,
-                   0, 0, x, y, width, height);
+  gdk_draw_drawable(dst->drawable, gc, src->drawable, 
+                   0, 0, x, y, width, height); 
 
   g_object_unref (gc);
 
 
   g_object_unref (gc);
 
@@ -474,7 +477,6 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose
     g_object_unref (gr->drawbuf); 
 
   g_object_unref (gr->drawable);
     g_object_unref (gr->drawbuf); 
 
   g_object_unref (gr->drawable);
-  free (gr);
 
   if (gr->pattern)
     cairo_surface_destroy (gr->pattern);
 
   if (gr->pattern)
     cairo_surface_destroy (gr->pattern);
@@ -483,6 +485,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_dispose
     free (gr->pattern_pixels);
 
   if (gr->debug) printf ("disposed of graphics2d\n");
     free (gr->pattern_pixels);
 
   if (gr->debug) printf ("disposed of graphics2d\n");
+  free (gr);
 
   gdk_threads_leave ();
 }
 
   gdk_threads_leave ();
 }
@@ -662,6 +665,7 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels
 
   begin_drawing_operation (gr);
 
 
   begin_drawing_operation (gr);
 
+  
  {
    cairo_surface_t *surf = cairo_surface_create_for_image ((char *)jpixels, 
                                                           CAIRO_FORMAT_ARGB32, 
  {
    cairo_surface_t *surf = cairo_surface_create_for_image ((char *)jpixels, 
                                                           CAIRO_FORMAT_ARGB32, 
@@ -670,8 +674,9 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_drawPixels
    cairo_show_surface (gr->cr, surf, w, h);
    cairo_surface_destroy (surf);
  }
    cairo_show_surface (gr->cr, surf, w, h);
    cairo_surface_destroy (surf);
  }
+  
 
 
 end_drawing_operation (gr);
+ end_drawing_operation (gr);
 
   (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
 
 
   (*env)->ReleaseIntArrayElements (env, jarr, jpixels, 0);
 
@@ -723,6 +728,82 @@ JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetMatrix
   update_pattern_transform (gr);
 }
 
   update_pattern_transform (gr);
 }
 
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetFont 
+   (JNIEnv *env, jobject obj, jobject font)
+{
+  struct graphics2d *gr = NULL;
+  struct peerfont *pfont = NULL;
+  cairo_font_t *ft = NULL;
+  FT_Face face = NULL;
+
+  gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+  g_assert (gr != NULL);
+
+  pfont = (struct peerfont *)NSA_GET_FONT_PTR (env, font);
+  g_assert (pfont != NULL);
+
+  gdk_threads_enter ();
+
+  face = pango_ft2_font_get_face (pfont->font);
+  g_assert (face != NULL);
+
+  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);
+  
+  cairo_set_font (gr->cr, ft);
+
+  cairo_scale_font (gr->cr, 
+                   pango_font_description_get_size (pfont->desc) / 
+                   (double)PANGO_SCALE);
+
+  cairo_font_destroy (ft);
+
+  gdk_threads_leave ();
+}
+
+JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoShowGlyphs
+   (JNIEnv *env, jobject obj, jintArray jcodes, jfloatArray jposns, jint nglyphs)
+{
+  struct graphics2d *gr = NULL;
+  cairo_glyph_t *glyphs = NULL;
+  jfloat *posns = NULL;
+  jint *codes = NULL;
+  jint i;
+
+  gr = (struct graphics2d *) NSA_GET_G2D_PTR (env, obj);
+  g_assert (gr != NULL);
+
+  if (gr->debug) printf ("cairo_show_glyphs (%d glyphs)\n", nglyphs);
+
+  glyphs = malloc (sizeof(cairo_glyph_t) * nglyphs);
+  g_assert (glyphs);
+
+  codes = (*env)->GetIntArrayElements (env, jcodes, NULL);  
+  g_assert (codes != NULL);
+
+  posns = (*env)->GetFloatArrayElements (env, jposns, NULL);  
+  g_assert (posns != NULL);
+
+  for (i = 0; i < nglyphs; ++i)
+    {
+      glyphs[i].index = codes[i];
+      glyphs[i].x = (double) posns[2*i];
+      glyphs[i].y = (double) posns[2*i + 1];
+    }
+
+  (*env)->ReleaseIntArrayElements (env, jcodes, codes, 0);
+  (*env)->ReleaseFloatArrayElements (env, jposns, posns, 0);
+
+  begin_drawing_operation (gr);
+  cairo_show_glyphs (gr->cr, glyphs, nglyphs);
+  end_drawing_operation (gr);
+
+  free(glyphs);
+}
+
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator 
    (JNIEnv *env, jobject obj, jint op)
 {
 JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_GdkGraphics2D_cairoSetOperator 
    (JNIEnv *env, jobject obj, jint op)
 {