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: [email protected]
> Date: Tue, 12 Jun 2012 16:58:49 +0100
> Subject: Still having trouble loading fonts at runtime - suggestions?
> To: [email protected]
>
> 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
> [email protected]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
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: [email protected]
For additional commands, e-mail: [email protected]