eTeks

PJA Toolkit


What is PJA ?
PJA contents
Tested platforms

FAQ
History
What's next ?

Copyright and license

PJA documentation
PJA feedback


What is PJA ?

PJA (Pure Java AWT) Toolkit is a JavaTM library for drawing graphics developed by eTeks. It is 100% Pure Java and doesn't use any native graphics resource of the system on which the Java Virtual Machine runs.
java.awt.Graphics methods such as drawLine (), fillOval (), drawString (),... are implemented in the default JVM with native graphical functions (except in some cases for Java2D) : That means that drawLine () finally calls a GDI system function on Windows or X11 function on a X11/UNIX machine even if the drawing is done in an off-screen image using the class java.awt.Image. This ensures the best performance for drawing graphics with Java.
But in a few cases, this default behavior can cause problems that PJA library improves :

PJA contents

PJA library is supplied with :

Servlet host providers can use it for their customers, if they provide copyright information and a link to http://www.eteks.com on their web site and other documentation.

Tested platforms

eTeks made successful tests of PJA on the following systems :

JDK version
Windows
MacOS
UNIX
1.0
Win 98/SunJDK 1.0.2    
1.1
Win 98/SunJDK 1.1.8 MacOS 9/MRJ 2.2

Linux/JDK 1.1.7 (without DISPLAY)

1.2
Win 98/SunJDK 1.2.2  

Linux/JDK 1.2.2 (with and without DISPLAY)

1.3
Win 98/SunJDK 1.3.0    

Other users reported they succeeded to use PJA on the following systems :

FAQ

In which cases should I use PJA ?

Audience
Problem
Solution
User / Developer
You wonder if graphics servlets and applications can work on your server. Test com.eteks.servlet.DefaultToolkitTest servlet and/or PJAToolkitDemo application.
User
You have problems to run graphics servlets on your server.

You can't change java command line options.

Test com.eteks.servlet.PJAServletTest.
If it works fine use
com.eteks.awt.servlet.PJARedirectServlet to run graphics servlets.
Otherwise, ask your servlet server administrator to add these options to java command line (at least -Xbootclasspath/a:pja.jar)

You can change java command line options. See which options to use.
Developer
You want to develop graphics servlets that will work everywhere. Extend the class com.eteks.awt.servlet.PJAServlet to minimize support to customer who don't have access to a Display (see com.eteks.servlet.TeksSurveyPie as an actual case)
You may also use only PJA Graphics methods.

 

What options do I have to add to java command line to use PJA with my servlet server on UNIX platform ?

(JDK version is obtained with the command java -version)

For your information, the JDK version >= 1.4 includes its own headless system (see AWT Enhancements in JDK 1.4 docs) : Just set the system property java.awt.headless to true or add the -Djava.awt.headless=true option to your Java command line to use it.

How can I add pja.jar to bootclasspath in JServ with JDK version >= 1.2 ?

Add the following line in the jserv.properties file with the good path to pja.jar :

wrapper.bin.parameter = -Xbootclasspath/a:/path/pja.jar

Why do I still get the exception java.awt.AWTError : Toolkit not Found in a java.awt.Toolkit.getDefaultToolkit () call, as I can instantiate the class com.eteks.awt.PJAToolkit ?

getDefaultToolkit () tries to instantiate the class described by the system property awt.toolkit. This method uses the system classpath of the default class loader to find this toolkit class. If com.eteks.awt.PJAToolkit is in a user or servlet classpath, your program may be able to instantiate this class but getDefaultToolkit () won't still be able to find it.
That's why pja.jar must be in the options -classpath (JDK <= 1.1) or -Xbootclasspath (JDK >= 1.2) of the java command line. If you don't have access to the command line, see the parts In which cases should I use PJA ? and What methods can be called in a servlet with no problem of Toolkit access for end users ?

Why the Java Virtual Machine crashes when I use fonts on UNIX platform ?

With some implementations of JDK >= 1.2 (particulary on Solaris), sun.java2d.SunGraphicsEnvironment class uses the method private static native boolean validPropertiesFile (java.lang.String, java.lang.String). This static method must have a bug which makes the JVM crashes when it's called without a correct Display. The following ugly patch works :

Some users reported that inner classes of sun.java2d.SunGraphicsEnvironment (all the files named SunGraphicsEnvironment$*.class) must be included also in rtgraphics.jar to make this patch work (this depends on the JDK version).
This bug doesn't appear with the latest version of the JDK 1.3.

What methods can be called in a servlet with no problem of Toolkit access for end users ?

Problems with graphics servlet may occure because users can't access to AWT default toolkit on UNIX platform where no Display is available. In this case, the classes java.awt.Toolkit and java.awt.Font can't be instantiated and the methods of java.awt.Component requiring a Toolkit instance can't be called.
Providing PJA Toolkit to these users instead of default toolkit may be a good solution, except if they can't modify themselves the options of their Java Virtual Machine because they are not the servlet server administrator :

The class com.eteks.awt.servlet.PJAServlet resolves the problem of the classpath option, but may cause some security problems on java environment running with strong security manager : this class requires the access to classpath and other system properties, the ability to instantiate a class loader,...
PJA provides also a way to perform graphics even if no default toolkit was instantiated. Here's the list of the methods you can call without using an AWT Toolkit instantiated by a java.awt.Toolkit.getDefaultToolkit () call :

Default AWT toolkit
 
PJA toolkit (package com.eteks.awt)
Toolkit getImage (URL url)   PJAToolkit getImage (URL url)
Toolkit getImage (String file)   PJAToolkit getImage (String file)
Toolkit createImage (ImageProducer producer)   PJAToolkit createImage (ImageProducer producer)
Toolkit createImage (byte[] imagedata, int imageoffset, int imagelength)   PJAToolkit createImage (byte[] imagedata, int imageoffset, int imagelength)
Toolkit prepareImage (Image image, int width, int height, ImageObserver observer)   PJAToolkit prepareImage (Image image, int width, int height, ImageObserver observer)
Toolkit checkImage (Image image, int width, int height, ImageObserver observer)   PJAToolkit checkImage (Image image, int width, int height, ImageObserver observer)
Toolkit getColorModel ()   PJAToolkit getColorModel ()
Component createImage (int width, int height)     new PJAImage (int width, int height)
Component createImage (ImageProducer producer)   PJAToolkit createImage (ImageProducer producer)
Graphics

getFont ()

  PJAGraphicsExtension

getFontName ()
getFontStyle ()
getFontSize ()

Graphics

setFont (Font font)

  PJAGraphicsExtension

setFont (String fontName, int fontStyle, int fontSize)

PJAToolkit can be instantiated by a new PJAToolkit () call.
PJAGraphicsExtension
is implemented by PJAGraphics used to draw in PJAImage instances. This means you can cast the Graphics instance returned by new PJAImage (width, height).getGraphics () to PJAGraphicsExtension.

As com.eteks.awt.PJAImage doesn't implement Java2D, this solution implies that your program doesn't use Java2D and Graphics2D capabilities.
.pjaf font files will be used to draw strings.

Why the methods show () or setVisible () of the class java.awt.Component throws ClassCastException with JDK >= 1.3 ?

These methods use the class sun.awt.GlobalCursorManager which supposes that the AWT toolkit returned by the method getDefaultToolkit () of the class java.awt.Toolkit inherits from sun.awt.SunToolkit ! As com.eteks.awt.PJAToolkit inherits directly from java.awt.Toolkit, it throws a ClassCastException exception.
Using addNotify () on an instance of java.awt.Frame instead of these methods is enough to enable the creation of off-screen images with the createImage () method of java.awt.Frame class, and avoids to wonder where will appear such a frame once the method show () is executed.

What fonts can I use to draw strings with PJA ?

With JDK >= 1.2, True Type fonts are used.
With JDK <= 1.1 or if com.eteks.awt.nojava2d system property is equal to true with JDK >= 1.2, .pjaf font files are used. You can build these files from existing fonts with PJAFontCapture utility.

What are these .pjaf files for ?

With the default toolkit of JDK <= 1.1, strings are drawn using native functions and fonts of the platform where the JVM runs (UNIX, Windows,...). To be able to draw strings with only pure Java, PJA toolkit needs some font information. Instead of implementing a decoder for X format or True Type font, it was decided to retrieve fonts drawing information from a new format stored in files with the .pjaf extension. These portable files store the bitmap drawing of each character of a font. PJAFontCapture utility allows to capture native fonts and save them in .pjaf files.
As Java2D includes its own decoder for True Type Font files, .pjaf files are useless with JDK >= 1.2. Use instead existing True Type Font files.

Why PJAFontCapture (or java com.eteks.tools.fontcapture.PJAFontCapture) can't work ?

PJAFontCapture captures native fonts using default toolkit of the Java Virtual Machine. You can't run it on a UNIX machine with no Display available.
If you need .pjaf fonts on a UNIX machine with no Display, launch PJAFontCapture on a machine where default toolkit can run (Windows, MacOS, UNIX with X11 Display). Then, ftp (in binary mode) or copy the .pjaf files to the UNIX machine.

How can I save my images ?

Off-screen images computed by PJA toolkit and more generally any Java images can be saved with encoders that generate images files or streams at different formats. The encoding operation can be programmed easily in a few lines. Please read the ToolkitDemo.java file for an example using ACME's GIF encoder.
Here are 3 small and free encoders that were successfully tested with PJA toolkit (with little modifications to ToolkitDemo.java) :

Encoder
format
JDK version
supported
Link
GIF 1.1 http://www.acme.com/java/
The modified class Acme.JPM.Encoders.GifEncoder provided with PJA distribution supports also the JDK 1.0
JPEG 1.1 http://www.obrador.com/essentialjpeg/
PNG 1.1 http://catcode.com/pngencoder/

Sun Microsystems provides also the 2 following libraries that include decoders/encoders :

For your information, the JDK version >= 1.2 provides the class com.sun.image.codec.jpeg.JPEGImageEncoder to encode images that are instances of the class java.awt.image.BufferedImage, in JPEG format.

Drawing with PJA is too slow. How can I improve performances ?

If you use PJA toolkit with a JDK >= 1.2, most AWT methods are implemented by existing classes of the Java standard library, except the methods that read image files. As a lot of these methods are implemented in C librairies by Sun, it's difficult to expect a speed improvement in the future.
PJA drawing methods are used if JDK <= 1.1, if the com.eteks.awt.nojava2d system property is set to true or if you use directly com.eteks.awt.PJAImage and com.eteks.awt.PJAGraphics classes. In this case, PJA toolkit is slower than default toolkit because com.eteks.awt.PJAGraphics drawing methods were implemented with classical drawing algorithms and could be optimized. That's one of the reasons why PJA is free : if you know any algorithm that could improve PJA performance, let us know so we could implement it and let other PJA users share this improvement.
In all cases, check if your JIT (Just In Time) or HotSpot compiler is on.

Is PJA toolkit 100% Pure Java ?

PJA isn't 100% Pure Java according to Sun JavaPureCheck tool test.
It lists the two following errors because PJA uses sun.awt.image.ByteArrayImageSource and sun.java2d.SunGraphicsEnvironment JDK internal classes :

 

History

Version 2.4 03/14/2002

Version 2.3.1 07/05/2001

Version 2.3 03/23/2001

Version 2.2 11/02/2000

Version 2.1 07/30/2000

Version 2.0 06/23/2000

The result of this research told roughly :

All the native classes of java.awt package and sub packages are named initIDs (). The implementation of initIDs () is only used by native objects to initialize their struct data and don't use any X11 Display but requires the awt library to be loaded.
Almost all the methods of the class java.awt.image.BufferedImage used to render Java2D are implemented in common Java classes or C programs, except a few ones that are corrected by the following classes.

The following new classes belong to the package com.eteks.java2d. The classes of com.eteks.awt package don't require them if you wish to work with JDK 1.1 or if a DISPLAY is available.

Version 1.2 06/08/2000

Version 1.1 05/30/2000

Version 1.0 05/17/2000

First version. JDK 1.1 compliant.

What's next

Javadoc documentation should be clearer and more consistent. Meanwhile, if you have problems using PJA library, please read first the FAQ.

Features that may be interesting to implement in PJA :

If you have any suggestion about how PJA should evolve, please send them to info@eteks.com or fill the PJA feedback form.

Copyright and license

Copyright © 2000-2001 Emmanuel PUYBARET / eTeks info@eteks.com. All Rights Reserved.

This program 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 of the License, or (at your option) any later version.

This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Visit eTeks web site for up-to-date versions of PJA and other Java tools and tutorials : http://www.eteks.com/


Copyright © 1996,1998 by Jef Poskanzer jef@acme.com. All rights reserved. (for the use of Acme.JPM.Encoders.GifEncoder class)

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Visit the ACME Labs Java page for up-to-date versions of this and other fine Java utilities : http://www.acme.com/java/



PJA version 2.4
Last update : 03/14/2002


eTeks
© 2000-2002
eTeks - All rights reserved