classpath
[Top][All Lists]
Advanced

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

Re: request for comment on java2d stuff


From: Sascha Brawer
Subject: Re: request for comment on java2d stuff
Date: Thu, 11 Sep 2003 11:57:33 +0200

Hi Graydon,

you wrote on Tue, 2 Sep 2003 20:25:19 -0400:

> I recently posted some new files to the java-patches list of the gcj
> project, containing the beginnings of my cairo java2d
> implementation. I was wondering if anyone here had comments on the
> work.

>From a coarse view, I'd say your code looks really good. I've just a few
remarks:

(1) In GdkGraphics2D.walkPath(PathIterator), the treatment of quadratic
splines is almost, but not entirely correct. The page

  http://pfaedit.sourceforge.net/bezier.html

describes how to convert quadratic splines into cubic ones (they call
them "TrueType" and "PostScript", respectively). In case you find this a
useful reference, you might want to include a comment in the code that
points to that page.



(2) Strokes that are not a BasicStroke: The drawing methods could check
whether the value of the stroke field is an instance of BasicStroke. If
not, they would not directly call into Cairo. For example,
GdkGraphics2D.draw(Shape) could look as follows:

public void draw(Shape s)
{
  if (!(stroke instanceof BasicStroke))
  {
    fill(stroke.createStrokedShape(s));
    return;
  }

  /* here comes your current implementation */
}


Methods like GdkGraphics2D.drawRect(int, int, int, int) would need
adjustments:

public void drawRect(int x, int y, int width, int height)
{
  if (!(stroke instanceof BasicStroke))
  {
    draw(new Rectangle(x, y, width, height));
    return;
  }

  /* here comes your current implementation */
}


When GdkGraphics2D.setStroke(Stroke) gets passed a non-BasicStroke, it
would just store the stroke without calling into Cairo.



(3) When GdkGraphics2D.drawImage gets passed a BufferedImage, you now
copy all pixels into a freshly allocated int[]. This has the advantage
that it works for all pixel formats, but it is inefficient for large
images. The problem is that copying pixel data is an expensive operation,
which should be avoided whenever possible.

To increase performance, you could check whether the image is in a format
that is directly supported by Cairo, such as TYPE_INT_ARGB with an sRGB
ColorSpace. If this is the case, you could retrieve the underlying
DataBufferInt (via getRaster().getDataBuffer()) and directly pass its
int[] to GdkGraphics2D.drawPixels.



(4) Methods like GdkGraphics2D.drawRenderedImage can be implemented by
fetching a Raster from the RenderedImage and proceeding as with
BufferedImage. My proposal would be to define a private drawRaster method
that gets called by the various public image drawing methods.



(5) It might be worth extending the native method
GdkGraphics2D.drawPixels to include an offset into the int[]. This might
be useful for cases where pixel (0,0) is not at index 0 of the int[] that
belongs to the DataBuffer.



(6) You could further avoid copying pixel data by slightly changing the
native implementation of GdkGraphics2D.drawPixels. Instead of
GetIntArrayElements, I'd recommend using GetPrimitiveArrayCritical and
ReleasePrimitiveArrayCritical. See

  http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-
12.html#GetPrimitiveArrayCritical

(It depends on the JVM whether or not this makes a difference).

Like the above, this is not a micro-optimization. It is likely to make a
noticeable difference whether several megabytes of pixel data are
accessed in place, or copied several times.



(7) As of how to implement Font.getFamily(java.util.Locale) etc., (you
have FIXMEs in that code), I've written some Java code for parsing the
'name' table of TrueType or OpenType fonts.  Of course, you'll need a
means to retrieve the contents of font tables -- but this is anyway a
necessity for supporting java.awt.font.OpenType.

See http://www.dandelis.ch/development/fonts/doc/. (It may be confusing
that private classes/methods are also listed). Only one class is relevant
here, namely gnu.java.awt.font.opentype.NameDecoder with the method

  public static String getName(java.nio.ByteBuffer nameTable,
                               int name, java.util.Locale locale);

For the "name" parameter, you'd pass e.g. NameDecoder.NAME_FAMILY.

The NameDecoder is actually quite independent from the rest of my code,
so you could use just that part. You would not have to include a large
code base just for the font names. We could also put the name decoding
into another package.


(8) Maybe you could have a look at the interface which is described at

  http://www.dandelis.ch/development/fonts/doc/gnu/java/awt/font/
FontDelegate.html

Maybe we can use an extended version of this interface for the FontPeers
that you've proposed in your recent e-mail. (The getGlyphName method is
not needed for Java2D, but it would be necessary if someone wanted to
write a decent PostScript or PDF provider for javax.print.)

Best regards,

-- Sascha

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






reply via email to

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