classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: extended peers


From: Sascha Brawer
Subject: Re: extended peers
Date: Wed, 17 Sep 2003 11:15:38 +0200

Hi Graydon,

>> [ClasspathToolkit, ClasspathFontPeer]
>
>In principle I like the direction, but I would make two changes to
>these interfaces:
>
>First, the font-related factory method on the toolkit should produce a
>ClasspathFontPeer, not a java.awt.Font. The factory method will be
>called *from* a java.awt.Font constructor in user code, thus has no
>opportunity to influence the identity of the Font object being
>constructed.

Would you say that Font.createFont and Font.deriveFont should be fully
implemented by java.awt.Font, so that they would construct the new Font
without calling the Toolkit? I'd agree with this, although it makes
things even more complicated.

If the toolkit produces ClasspathFontPeers instead of java.awt.Fonts, the
implementations of java.awt.Font.createFont and deriveFont somehow need
to know whether the constructed Font should implement the
java.awt.font.[OpenType, MultipleMaster] interfaces. What do you think
about the following proposal, which puts a special key for "pre-created
peers" into the attribute Map?

package java.awt;
import ...;
public class Font
{
  private Map attributes;
  private ClasspathFontPeer peer;

  public Font(Map attrs)
  {
    init((Map) attrs.clone());
  }
  // The other Font constructors create a Map and pass it to init.

  private void init(Map attrs)
  {
    peer = getPeer(attrs);

    attributes = attrs;
    attributes.remove("CLASSPATH_FONT_PEER");
  }


  /**
   * Retrieves a ClasspathFontPeer that is suitable for the specified
   * attributes. If attrs contains a key "CLASSPATH_FONT_PEER", the
   * corresponding value is retrieved and returned. Otherwise, the
   * toolkit is asked for a font peer for the attributes,
   * and the peer is stored in attrs under "CLASSPATH_FONT_PEER"
   * before being returned.
   */
  private static ClasspathFontPeer getPeer(Map attrs)
  {
    ClasspathFontPeer peer;

    peer = attrs.get("CLASSPATH_FONT_PEER");
    if (peer == null)
    {
      peer = ((ClasspathToolkit) Toolkit.getDefaultToolkit())
        .getFontPeer(attrs);
      attrs.put("CLASSPATH_FONT_PEER", peer);
    }

    return peer;
  }


  public static Font getFont(Map attrs)
  {
    ClasspathFontPeer peer;

    peer = getPeer(attrs);

    if (peer.isOpenType())
      f = new ClasspathOpenTypeFont(attrs);
    else if (peer.getNumDesignAxes() > 0)
      return new ClasspathMultipleMasterFont(attrs);
    else
      return new Font(attrs);
  }


  public static Font createFont(int format, InputStream stream)
    throws FontFormatException, IOException
  {
    ClasspathFontPeer peer;

    peer = ((ClasspathToolkit) Toolkit.getDefaultToolkit())
      .createFontPeer(format, stream));
    attrs = new HashMap();
    attrs.put("CLASSPATH_FONT_PEER", peer);
    return getFont(attrs);
  }


  public Font deriveFont(float size)
  {
    // Retrieve a clone of this font's attribute map.
    Map attrs = getAttributes();
    attrs.put(TextAttribute.SIZE, new Float(size));
    return getFont(attrs);
  }

  // the other deriveFont methods are similar to deriveFont(float)
}


package gnu.java.awt.font;
import java.util.Map;
import gnu.java.awt.peer;

public class ClasspathOpenTypeFont
  extends java.awt.Font
  implements java.awt.font.OpenType
{
  public ClasspathOpenTypeFont(Map attrs)
  {
    super(attrs);
  }

  ... OpenType methods delegated to peer
}

public class ClasspathMultipleMasterFont
  extends java.awt.Font
  implements java.awt.font.MultipleMaster
{
  public ClasspathMultipleMasterFont(Map attrs)
  {
    super(attrs);
  }

  ... MultipleMaster methods delegated to peer
}


ClasspathOpenTypeMultipleMasterFont is left as an exercise to the reader
:-) The ClasspathXXXFont classes could also be made private static inner
classes of java.awt.Font.

This is terribly complicated. But do you see an easier way that would
allow createFont and deriveFont to return a Font that implements a
certain interface, such as java.awt.font.OpenType?


>Second, I think the ClasspathFontPeer should not be passed
>java.awt.Font objects as arguments to its methods. This practise
>implies an 'instanceof' operation, and (possibly failing) downcast on
>every operation, or at least some sort of hashtable lookup.

Hm, I guess we'll have something like the following:

package java.awt;
import gnu.java.awt.peer.ClasspathFontPeer;

public class Font
{
  protected ClasspathFontPeer peer;

  public float getItalicAngle()
  {
    // float ClasspathFontPeer.getItalicAngle(java.awt.Font)
    return peer.getItalicAngle(this);
  }
}

Would you mind explaining where exactly the cast is performed?

>I figure a 1:1 relationship between Font and
>ClasspathFontPeer objects is likely anyways.

Some toolkits might have a peer for each unscaled font (i.e., before
scaling or the application of affine transformations). In this case,
there would be a peer object for the 'Univers' font, which gets shared
e.g. between 10-point and (13-point, 30-degree slanted) Univers. For this
platform, the peer's getItalicAngle method would be something like the
following:

  public float getItalicAngle(Font font)
  {
    float angle = ...;

    if (font.isTransformed())
    {
      // Retrieve a clone of the font's transform.
      AffineTransform tx = font.getTransform();
      angle = someFunction(tx, angle);
    }

    return angle;
  }

I thought it would not hurt to allow that a single font peer is shared
between scaled/transformed fonts.  On the other hand, if you think that
passing the Font to the peer's methods is bad, I wouldn't have a problem
to omit that argument.

If we let ClasspathToolkit return ClasspathFontPeers instead of Fonts, as
you suggested, a singleton-peer-for-all-fonts variant wouldn't work. So,
what would you think about keeping the Font argument in those peer
methods where the result is influenced by scaling and transforming (e.g.
getItalicAngle or getFontMetrics), but removing it from the others (such
as getFamilyName, getNumGlyphs, getMissingGlyphCode, isOpenType, etc.)?

About the 'getGlyphName' method that I had proposed for
ClasspathFontPeer: On a second thought, it seems better to omit this
until someone actually writes a PDF/PostScript stream provider. The beast
is already hairy enough.

-- Sascha

Sascha Brawer, address@hidden, http://www.dandelis.ch/people/brawer/ 






reply via email to

[Prev in Thread] Current Thread [Next in Thread]