Hi Phillip,
I have written a desktop application which, on start up, refreshes a cache of 
fonts (using FOP code) and subsequently allows the user to refresh that cache 
by hitting a button (again, calls the same FOP code).
See attached.
When the application starts up I call FOPManager.refreshFonts( false );

Before allowing the user to initiate a print, I call FOPManager.isReady()
 When the user forces a cache update, I call FOPManager.refreshFonts( true );
My fopConfiguration.xml is standard and doesn't do anything fancy.

Cheers,
Bernard.

> From: phillip.old...@gmail.com
> Date: Tue, 12 Jun 2012 16:58:49 +0100
> Subject: Still having trouble loading fonts at runtime - suggestions?
> To: fop-users@xmlgraphics.apache.org
> 
> Hi All
> 
> I'm still having trouble loading & using fonts while my app is
> running. I can load fonts without issue when configuring them via the
> XML config, but unfortunately the fonts are provided by a 3rd party at
> runtime and I therefore need to find a way to load them via java.
> 
> Here's my current process (not working):
> 
> 1. create a new FOP instance
> 2. load a number of default settings from an XML file
> 3. override some of these settings (eg. resolution) based on certain
> preferences passed in at runtime
> 
> then, specifically regarding fonts:
> 
> 4. create a temporary directory to store the font(s) that the 3rd
> party is providing
> 5. write each font to the temp directory
> 6. pass the temp dir to FontManager.getFontBaseURL()
> 7. process the FO file
> 
> However, even though the FontBaseURL is changed, the fonts aren't
> loaded/used during processing. Is there a way to tell FOP/the
> FontManager to refresh it's cache/search the new directory and load
> the fonts? Is there a better approach to this?
> 
> -- 
> Phillip B Oldham
> phillip.old...@gmail.com
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: fop-users-unsubscr...@xmlgraphics.apache.org
> For additional commands, e-mail: fop-users-h...@xmlgraphics.apache.org
> 
                                          
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.Vector;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.fonts.FontEventListener;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.autodetect.FontFileFinder;
import org.apache.fop.tools.fontlist.FontListGenerator;
import org.apache.log4j.Logger;


public class FOPManager
{
	private static final String PROPERTY_FONT_LIST = "FontList"; //$NON-NLS-1$
	private static final String PROPERTY_FONT_FILES = "FontFiles"; //$NON-NLS-1$

	protected static final FopFactory ms_fopFactory = FopFactory.newInstance();
	protected static final Logger ms_logger = Logger.getLogger( FOPManager.class.getName() );

	public static final boolean IS_MAC_OS_X = System.getProperty( "os.name" ).startsWith( "Mac OS X" ); //$NON-NLS-1$ //$NON-NLS-2$

	protected static Vector<String> ms_fonts = null;
	protected static boolean ms_ready = false;

	protected static final HashMap<String, String> ms_fontsForMacOSX = new HashMap<String, String>();
	protected static final HashMap<String, String> ms_fontsForWindows = new HashMap<String, String>();


	static
    {
		try { ms_fopFactory.setUserConfig( new File( "fopConfiguration.xml" ) ); } //$NON-NLS-1$
		catch( Exception exception ) { throw new RuntimeException( exception ); }

		ms_fontsForMacOSX.put( "en", "Arial" ); //$NON-NLS-1$ //$NON-NLS-2$
		ms_fontsForWindows.put( "en", "Arial" ); //$NON-NLS-1$ //$NON-NLS-2$

		// http://www.pinyinjoe.com/pinyin/pinyin_xpfonts.htm
		// http://www.yale.edu/chinesemac/pages/fonts.html
		ms_fontsForMacOSX.put( "zh", "Hei" ); //$NON-NLS-1$ //$NON-NLS-2$
		ms_fontsForWindows.put( "zh", "SimHei" ); //$NON-NLS-1$ //$NON-NLS-2$
    }


	public static FopFactory getFOPFactory() { return ms_fopFactory; }


    public static Vector<String> getFontList() { return ms_fonts; }


    public static boolean isReady() { return ms_ready; }


	public static void refreshFonts( boolean flush )
	{
		ms_ready = false;

		if( flush )
		{
			new InitialiseFonts().start();
			return;
		}

		// Get the list of cached font names...
		ms_fonts = PropertiesManager.getInstance().getList( PROPERTY_FONT_LIST );
		if( ms_fonts.isEmpty() )
		{
			new InitialiseFonts().start();
			return;
		}

		// We have a list of font names, assume it's good.
		// Now check the cached font files list against the actual font files list.
		Vector<String> fontFilesFromProperties = PropertiesManager.getInstance().getList( PROPERTY_FONT_FILES );
		Vector<String> fontFiles = loadFontFiles();
		if( fontFilesFromProperties.size() != fontFiles.size() )
		{
			new InitialiseFonts().start();
			return;
		}

		// Compare the font files lists, element by element...
		for( String fontFile : fontFiles )
			for( int i = 0; i < fontFilesFromProperties.size(); i++ )
				if( fontFile.compareTo( fontFilesFromProperties.get( i ) ) == 0 )
				{
					fontFilesFromProperties.remove( i );
					break;
				}

		if( ! fontFilesFromProperties.isEmpty() )
		{
			new InitialiseFonts().start();
			return;
		}

		// Font names are good and the font file lists match, so all good...
		ms_ready = true;
	}


	public static String getDefaultFont()
	{
		if( IS_MAC_OS_X )
			return ms_fontsForMacOSX.get( Locale.getDefault().getLanguage() );

		return ms_fontsForWindows.get( Locale.getDefault().getLanguage() );
	}


	protected static Vector<String> loadFontFiles()
	{
		try
		{
			@SuppressWarnings("unchecked") List<URL> fontFiles = new FontFileFinder().find();
			Vector<String> fontFilesAsStrings = new Vector<String>( fontFiles.size() );
			for( URL url : fontFiles )
				fontFilesAsStrings.add( url.toString() );

			return fontFilesAsStrings;
		}
		catch( IOException ioException ) { throw new RuntimeException( ioException ); }
	}


	private static class InitialiseFonts extends Thread
    {
    	public InitialiseFonts() { super(); }


    	@Override
		public void run()
    	{
    		FontEventListener fontEventListener =
    				new FontEventListener()
    				{
    					@Override public void fontLoadingErrorAtAutoDetection( Object source, String fontURL, Exception exception ) { ms_logger.error( "Could not load font '" + fontURL + "'.", exception ); } //$NON-NLS-1$ //$NON-NLS-2$

    					@Override public void fontSubstituted( Object source, FontTriplet requested, FontTriplet effective ) { /** Ignore. */ }

    					@Override public void glyphNotAvailable( Object source, char ch, String fontName ) { /** Ignore. */ }
    				};

			try
			{
				SortedMap<?,?> fontFamilies = new FontListGenerator().listFonts( ms_fopFactory, org.apache.xmlgraphics.util.MimeConstants.MIME_PDF, fontEventListener );
				ms_fonts = new Vector<String>( fontFamilies.size() );
				Iterator<?> iterator = fontFamilies.entrySet().iterator();
				while( iterator.hasNext() )
					ms_fonts.add( ( (Map.Entry<?,?>)iterator.next() ).getKey().toString() );

				PropertiesManager.getInstance().setList( PROPERTY_FONT_LIST, ms_fonts );
				PropertiesManager.getInstance().setList( PROPERTY_FONT_FILES, loadFontFiles() );
				PropertiesManager.getInstance().store();
	    		ms_ready = true;
			}
			catch( FOPException fopException ) { throw new RuntimeException( fopException ); }
    	}
    }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-users-unsubscr...@xmlgraphics.apache.org
For additional commands, e-mail: fop-users-h...@xmlgraphics.apache.org

Reply via email to