Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / January 2006

Tip: Looking for answers? Try searching our database.

How do you reliably extract a font from a JAR file?

Thread view: 
Oliver - 07 Jan 2006 07:03 GMT
I've discovered that the method I use to extract a font from a jar file
is flawed, and causing problems in my program. Providing code will not
help, what I need is a code example of how to do this reliably. The
code I have works on every platform except Windows XP. So I need 100%
portable java code. thanks.

Oliver
Andrew Thompson - 07 Jan 2006 08:53 GMT
> I've discovered that the method I use to extract a font from a jar file

Is it on the application's class path?  If so, you can..

  URL theFontURL = this.getClass().getResource("theFontFile");

..then..

  InputStream stream = theFontURL.openStream();

HTH

Signature

Andrew Thompson
physci, javasaver, 1point1c, lensescapes - athompson.info/andrew

Oliver - 09 Jan 2006 04:26 GMT
Hi Andrew Thompson, thanks for replying.

My method uses InputStream in =
getClass().getResourceAsStream(fileName); which is similar but
different than what you describe. I'll change it around a bit and see
if that works. Thanks again sir :)

Oliver Richman
Roedy Green - 07 Jan 2006 19:49 GMT
>I've discovered that the method I use to extract a font from a jar file
>is flawed, and causing problems in my program. Providing code will not
>help, what I need is a code example of how to do this reliably. The
>code I have works on every platform except Windows XP. So I need 100%
>portable java code. thanks.

here is my SCCE.  It baffles me. It seems to find and construct the
Font from the jar just fine, but when I use it, I just see Dialog. I
tried in with three different TTF files, same result.

package com.mindprod.example;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Frame;
import java.awt.Label;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.InputStream;
/**
* How to include a custom font with your application.<br>
* Demonstrate use of java.awt.Font.createFont<br>
* Accessing an uninstalled Font bundled in a jar or on the
classpath.<br>
* Note this technique is illegal if you don't have licensing
permission from
* the font designer.
*
* @author Roedy Green
*/
public class TestCreateFont {

   /**
    * Debugging harness for a Frame
    *
    * @param args
    *        command line arguments are ignored.
    * @throws FontFormatException
    *         if font is not a valid TrueType font
    * @throws IOException
    *         if there is some problem reading the font file.
    */
   public static void main ( String args[] ) throws
FontFormatException,
       IOException
       {
       final Frame frame = new Frame();
       // Uninstalled font is a resource on classpath or in jar named
       // "com/mindprod/example/verdana.ttf"

       InputStream fontStream = TestCreateFont.class
           .getResourceAsStream( "verdana.ttf" );
       Font onePoint = Font.createFont( Font.TRUETYPE_FONT,
fontStream );
       fontStream.close();
       Font snowFont = onePoint.deriveFont( Font.PLAIN, 18 );
       System.out.println ( snowFont);
       
       Label Label = new Label( "Snow Alert" );
       Label.setBackground( Color.BLACK );
       Label.setForeground( Color.WHITE );
       Label.setFont( snowFont );
     
       frame.add( Label );
       frame.setSize( 100, 100 );
       frame.addWindowListener( new WindowAdapter() {

           /**
            * Handle request to shutdown.
            *
            * @param e
            *        event giving details of closing.
            */
           public void windowClosing ( WindowEvent e )
               {
               System.exit( 0 );
               } // end WindowClosing
       } // end anonymous class
           ); // end addWindowListener line
       frame.validate();
       frame.setVisible( true );
       } // end main
}
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Oliver - 09 Jan 2006 03:40 GMT
Hi Roedy Green. Thanks for replying to my question. Your answer
probably helped me :)

After looking at your code I thought to myself, "Interesting, that is
basically the way I was doing it." That is,
////////////////////////////////////////////
// roedy green's way
////////////////////////////////////////////
       InputStream fontStream = TestCreateFont.class
           .getResourceAsStream( "verdana.ttf" );
       Font onePoint = Font.createFont( Font.TRUETYPE_FONT, fontStream
);
////////////////////////////////////////////

However, I had heard there "might be" some "compatability" problems
with "netscape", all very vague, so I did it this way:

////////////////////////////////////////////
// Oliver's way that he read about somewhere (I deny all
responsibility)
////////////////////////////////////////////
       byte[] buffer;
       InputStream in = getClass().getResourceAsStream(fileName);

       int length = in.available();
       buffer = new byte[length];
       in.read( buffer );

       InputStream is = new ByteArrayInputStream(buffer);
       the_font = Font.createFont(Font.TRUETYPE_FONT, is);
////////////////////////////////////////////

By moving the data through a 'buffer' you are supposed to get around a
problem in netscape. I read this method on
http://www.javaworld.com/javaworld/jw-07-1998/jw-07-jar-p2.html and
adapted it for use with fonts. As it turns out this may not be the best
way to do things after all. I am only concerned that my code will not
work somewhere. I think it's odd and stupid that Java code will work on
many platforms but not one platform, it must be a bug in the windows
implementation of Java because "oliver's way" works on other systems.
Oh well.

Thanks guys. I hope this works :>

Oliver Richman
Roedy Green - 09 Jan 2006 04:18 GMT
>// Oliver's way that he read about somewhere (I deny all
>responsibility)
[quoted text clipped - 9 lines]
>        the_font = Font.createFont(Font.TRUETYPE_FONT, is);
>////////////////////////////////////////////

What you may be thinking of is the old Netscape bug that getResource
did not work.

What your code looks like it is trying to do is bypass a bug in
createFont if it did a zero read and gave up, rather than reading
again.  This would only happen if you were reading the font as a
resource over the net. It would not likely happen if you read the
resource from a jar or from the local file system.

However, your code does not do that.  See
http://mindprod.com/jgloss/readeverything.html

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Roedy Green - 09 Jan 2006 04:20 GMT
>http://www.javaworld.com/javaworld/jw-07-1998/jw-07-jar-p2.html and

this code is nonsense:

try{
      int length = in.available();
      thanksToNetscape = new byte[length];
      in.read( thanksToNetscape );
      image = toolkit.createImage( thanksToNetscape );
   }

I don't think the author understands the meaning of in.available.  It
is not the same thing at the total size of the image.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Roedy Green - 08 Jan 2006 13:12 GMT
>I've discovered that the method I use to extract a font from a jar file
>is flawed, and causing problems in my program. Providing code will not
>help, what I need is a code example of how to do this reliably. The
>code I have works on every platform except Windows XP. So I need 100%
>portable java code. thanks.

This works. The trick is this does not work in AWT, only Swing. see
http://mindprod.com/jgloss/font.html#BUNDLING
and
http://mindprod.com/jgloss/font.html#GOTCHAS

package com.mindprod.example;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.JFrame;
import javax.swing.JLabel;
/**
* How to include a custom font with your application.<br>
* Demonstrate use of java.awt.Font.createFont<br>
* Accessing an uninstalled Font bundled in a jar or on the
classpath.<br>
* Note this technique is illegal if you don't have licensing
permission from
* the font designer.
* This only works in Swing!
*
* @author Roedy Green
*/
public class TestCreateFont {

   /**
    * Debugging harness for a Frame
    *
    * @param args
    *        command line arguments are ignored.
    * @throws FontFormatException
    *         if font is not a valid TrueType font
    * @throws IOException
    *         if there is some problem reading the font file.
    */
   public static void main ( String args[] ) throws
FontFormatException,
       IOException
       {
       final JFrame frame = new JFrame();

       // Uninstalled font is a resource on classpath or in jar named
       // "com/mindprod/example/IGLOOLAS.TTF"
       // This example font is a decorative font with snowcaps
       // on the capital letters.

       InputStream fontStream = TestCreateFont.class
           .getResourceAsStream( "IGLOOLAS.TTF" );
       Font onePoint = Font.createFont( Font.TRUETYPE_FONT,
fontStream );
       fontStream.close();
       Font snowFont = onePoint.deriveFont( Font.PLAIN, 18 );
       System.out.println( snowFont );

       JLabel label = new JLabel( "SNOW ALERT" );
       label.setBackground( Color.WHITE );
       label.setForeground( Color.BLACK );
       label.setFont( snowFont );

       frame.add( label );
       frame.setSize( 300, 100 );
       frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
       frame.validate();
       frame.setVisible( true );
       } // end main
} // end class
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Oliver - 08 Jan 2006 15:51 GMT
Thanks Roedy, you're a lifesaver. It appears to work.

Here is the core difference:

My old method (works on everything but Win XP)

InputStream in = getClass().getResourceAsStream(fileName);
           the_font = Font.createFont(Font.TRUETYPE_FONT, in);
           the_font = the_font.deriveFont((float)pointsize);

Your "new" and working method (works everywhere):

InputStream in = Screen.class.getResourceAsStream(fileName);
           the_font = Font.createFont(Font.TRUETYPE_FONT, in);
           in.close();
           the_font = the_font.deriveFont(Font.PLAIN, pointsize);

As you can see, there are a couple of subtle differences. Regardless of
the details it works, and it's a great relief to me. THANKS.. ^^

Oliver
Roedy Green - 09 Jan 2006 09:31 GMT
>My old method (works on everything but Win XP)
>
[quoted text clipped - 11 lines]
>As you can see, there are a couple of subtle differences. Regardless of
>the details it works, and it's a great relief to me. THANKS.. ^^

I can't see why your code would fail.  Leaving the stream open just
wastes RAM. It should have no effect on the result. Your float cast is
not needed, but it should not hurt.  What is this?  perhaps you are
getting a different resource with a different package.

   public Font deriveFont(int style, float size){
       Hashtable newAttributes =
(Hashtable)getRequestedAttributes().clone();
       applyStyle(style, newAttributes);
       applySize(size, newAttributes);
       return new Font(newAttributes, createdFont, font2DHandle);
   }

is almost identical to:

   public Font deriveFont(float size){
       Hashtable newAttributes =
(Hashtable)getRequestedAttributes().clone();
       applySize(size, newAttributes);
       return new Font(newAttributes, createdFont, font2DHandle);
   }

If I were redesigning this createFont would give you a default font
size somewhere in the range 10 to 12 so that if you used it plain,it
would still be readable.

The other key is you must use Swing not AWT. AWT peers don't
understand anything but the basic logical fonts.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.