Browse Source

* Added font substitution configuration reader, model, business logic, junit test and docs.

* Added java 1.5 generics comments to many methods.
* Performed some preparatory cleanup and refactoring which includes (but is not limited to..)
   - Creating a FontManager delegating class that is called upon when renderers are setting up fonts
   - A new FontCollection interface and concrete implementing classes to supercede the static FontSetup mechanism.


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@653826 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-1_0
Adrian Cumiskey 16 years ago
parent
commit
cff8a3713f
50 changed files with 2425 additions and 827 deletions
  1. 53
    24
      src/documentation/content/xdocs/trunk/fonts.xml
  2. 28
    0
      src/java/org/apache/fop/apps/FOURIResolver.java
  3. 1
    1
      src/java/org/apache/fop/apps/FOUserAgent.java
  4. 47
    59
      src/java/org/apache/fop/apps/FopFactory.java
  5. 6
    20
      src/java/org/apache/fop/apps/FopFactoryConfigurator.java
  6. 82
    0
      src/java/org/apache/fop/fonts/CustomFontCollection.java
  7. 18
    15
      src/java/org/apache/fop/fonts/EmbedFontInfo.java
  8. 10
    1
      src/java/org/apache/fop/fonts/Font.java
  9. 45
    25
      src/java/org/apache/fop/fonts/FontCache.java
  10. 38
    0
      src/java/org/apache/fop/fonts/FontCollection.java
  11. 1
    1
      src/java/org/apache/fop/fonts/FontDescriptor.java
  12. 114
    80
      src/java/org/apache/fop/fonts/FontInfo.java
  13. 221
    0
      src/java/org/apache/fop/fonts/FontManager.java
  14. 89
    0
      src/java/org/apache/fop/fonts/FontManagerConfigurator.java
  15. 111
    114
      src/java/org/apache/fop/fonts/FontSetup.java
  16. 10
    3
      src/java/org/apache/fop/fonts/FontTriplet.java
  17. 19
    17
      src/java/org/apache/fop/fonts/FontUtil.java
  18. 1
    1
      src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
  19. 2
    2
      src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
  20. 149
    0
      src/java/org/apache/fop/fonts/base14/Base14FontCollection.java
  21. 65
    0
      src/java/org/apache/fop/fonts/substitute/AttributeValue.java
  22. 305
    0
      src/java/org/apache/fop/fonts/substitute/FontQualifier.java
  23. 61
    0
      src/java/org/apache/fop/fonts/substitute/FontSubstitution.java
  24. 66
    0
      src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java
  25. 83
    0
      src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java
  26. 115
    0
      src/java/org/apache/fop/fonts/substitute/FontWeightRange.java
  27. 3
    1
      src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
  28. 2
    4
      src/java/org/apache/fop/render/AbstractRendererConfigurator.java
  29. 25
    13
      src/java/org/apache/fop/render/PrintRenderer.java
  30. 93
    67
      src/java/org/apache/fop/render/PrintRendererConfigurator.java
  31. 2
    2
      src/java/org/apache/fop/render/afp/AFPRenderer.java
  32. 181
    0
      src/java/org/apache/fop/render/java2d/Base14FontCollection.java
  33. 111
    0
      src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java
  34. 0
    353
      src/java/org/apache/fop/render/java2d/FontSetup.java
  35. 138
    0
      src/java/org/apache/fop/render/java2d/InstalledFontCollection.java
  36. 5
    4
      src/java/org/apache/fop/render/java2d/Java2DRenderer.java
  37. 4
    4
      src/java/org/apache/fop/render/pcl/PCLRenderer.java
  38. 1
    1
      src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java
  39. 1
    1
      src/java/org/apache/fop/render/ps/NativeTextHandler.java
  40. 1
    1
      src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
  41. 8
    4
      src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
  42. 1
    1
      src/java/org/apache/fop/svg/PDFGraphics2D.java
  43. 4
    0
      status.xml
  44. 33
    0
      test/config/test_fonts_substitution.xconf
  45. 1
    1
      test/java/org/apache/fop/config/BaseUserConfigTestCase.java
  46. 63
    0
      test/java/org/apache/fop/config/FontsSubstitutionTestCase.java
  47. 1
    0
      test/java/org/apache/fop/config/UserConfigTestSuite.java
  48. 2
    2
      test/java/org/apache/fop/layoutengine/LayoutEngineTester.java
  49. 1
    1
      test/java/org/apache/fop/render/pdf/BasePDFTestCase.java
  50. 4
    4
      test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java

+ 53
- 24
src/documentation/content/xdocs/trunk/fonts.xml View File

support fonts. These fonts will then automatically be registered. support fonts. These fonts will then automatically be registered.
</p> </p>
<source><![CDATA[ <source><![CDATA[
<fonts>
<!-- register all the fonts found in a directory -->
<directory>C:\MyFonts1</directory>
<renderers>
<renderer mime="application/pdf">
<fonts>
<!-- register all the fonts found in a directory -->
<directory>C:\MyFonts1</directory>
<!-- register all the fonts found in a directory
and all of its sub directories (use with care) -->
<directory recursive="true">C:\MyFonts2</directory>
<!-- register all the fonts found in a directory and all of its sub directories (use with care) -->
<directory recursive="true">C:\MyFonts2</directory>


<!-- automatically detect operating system installed fonts -->
<auto-detect/>
</fonts>]]></source>
<!-- automatically detect operating system installed fonts -->
<auto-detect/>
</fonts>
</renderer>
</renderers>]]></source>
<note> <note>
Review the documentation for <a href="configuration.html">FOP Configuration</a> Review the documentation for <a href="configuration.html">FOP Configuration</a>
for instructions on making the FOP configuration available to FOP when it runs. for instructions on making the FOP configuration available to FOP when it runs.
<title>Register Fonts with FOP</title> <title>Register Fonts with FOP</title>
<p>You must tell FOP how to find and use the font metrics files by registering them in the <a href="configuration.html">FOP Configuration</a>. Add entries for your custom fonts, regardless of font type, to the configuration file in a manner similar to the following:</p> <p>You must tell FOP how to find and use the font metrics files by registering them in the <a href="configuration.html">FOP Configuration</a>. Add entries for your custom fonts, regardless of font type, to the configuration file in a manner similar to the following:</p>
<source><![CDATA[ <source><![CDATA[
<fonts>
<!-- register a particular font -->
<font metrics-url="file:///C:/myfonts/FTL_____.xml" kerning="yes"
embed-url="file:///C:/myfonts/FTL_____.pfb">
<font-triplet name="FrutigerLight" style="normal" weight="normal"/>
</font>
<renderers>
<renderer mime="application/pdf">
<fonts>
<!-- register a particular font -->
<font metrics-url="file:///C:/myfonts/FTL_____.xml" kerning="yes" embed-url="file:///C:/myfonts/FTL_____.pfb">
<font-triplet name="FrutigerLight" style="normal" weight="normal"/>
</font>
<!-- register all the fonts found in a directory -->
<directory>C:\MyFonts1</directory>
<!-- register all the fonts found in a directory -->
<directory>C:\MyFonts1</directory>
<!-- register all the fonts found in a directory
and all of its sub directories (use with care) -->
<directory recursive="true">C:\MyFonts2</directory>
<!-- register all the fonts found in a directory and all of its sub directories (use with care) -->
<directory recursive="true">C:\MyFonts2</directory>


<!-- automatically detect operating system installed fonts -->
<auto-detect/>
</fonts>]]></source>
<!-- automatically detect operating system installed fonts -->
<auto-detect/>
</fonts>
</renderer>
</renderers>]]></source>
<ul> <ul>
<li> <li>
URLs are used to access the font metric and font files. URLs are used to access the font metric and font files.
<!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note--> <!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note-->
</section> </section>
<section id="autodetect"> <section id="autodetect">
<title>Auto-Detect and auto-embedd feature</title>
<title>Auto-Detect and auto-embed feature</title>
<p>When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.</p> <p>When the "auto-detect" flag is set in the configuration, FOP will automatically search for fonts in the default paths for your operating system.</p>
<p>FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:</p> <p>FOP will also auto-detect fonts which are available in the classpath, if they are described as "application/x-font" in the MANIFEST.MF file. For example, if your .jar file contains font/myfont.ttf:</p>
<source>Manifest-Version: 1.0 <source>Manifest-Version: 1.0
<p>When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the <p>When embedding TrueType fonts (ttf) or TrueType Collections (ttc), a subset of the
original font, containing only the glyphs used, is embedded in the output document.</p> original font, containing only the glyphs used, is embedded in the output document.</p>
</section> </section>
<section id="substitution">
<title>Substitution</title>
<p>When a &lt;substitutions/&gt; section is defined in the configuration, FOP will re-map any font-family references found in your FO input to a given substitution font.</p>
<ul>
<li>If a &lt;substitution/&gt; is declared, it is mandatory that both a &lt;from/&gt; and &lt;to/&gt; child element is declared with a font-family attribute.</li>
<li>Both font-weight and font-style are optional attributes, if they are provided then a value of 'normal' is assumed.</li>
</ul>
<p>For example you could make all FO font-family references to 'Arial' with weights between 700 and 900 reference the normal 'Arial Black' font.</p>
<source><![CDATA[
<fop version="1.0">
<fonts>
<substitutions>
<substitution>
<from font-family="Arial" font-weight="700..900"/>
<to font-family="Arial Black"/>
</substitution>
<substitution>
<from font-family="FrutigerLight"/>
<to font-family="Times" font-weight="bold" font-style="italic"/>
</substitution>
</substitutions>
</fonts>
</fop>]]></source>
</section>
<!-- The following section should no longer be required <!-- The following section should no longer be required
<section id="embedding-base14"> <section id="embedding-base14">
<title>Explicitly embedding the base 14 fonts</title> <title>Explicitly embedding the base 14 fonts</title>

+ 28
- 0
src/java/org/apache/fop/apps/FOURIResolver.java View File

/** true if exceptions are to be thrown if the URIs cannot be resolved. */ /** true if exceptions are to be thrown if the URIs cannot be resolved. */
private boolean throwExceptions = false; private boolean throwExceptions = false;


/**
* Checks if the given base URL is acceptable. It also normalizes the URL.
* @param base the base URL to check
* @return the normalized URL
* @throws MalformedURLException if there's a problem with a file URL
*/
public String checkBaseURL(String base) throws MalformedURLException {
if (!base.endsWith("/")) {
// The behavior described by RFC 3986 regarding resolution of relative
// references may be misleading for normal users:
// file://path/to/resources + myResource.res -> file://path/to/myResource.res
// file://path/to/resources/ + myResource.res -> file://path/to/resources/myResource.res
// We assume that even when the ending slash is missing, users have the second
// example in mind
base += "/";
}
File dir = new File(base);
try {
base = (dir.isDirectory() ? dir.toURL() : new URL(base)).toExternalForm();
} catch (MalformedURLException mfue) {
if (throwExceptions) {
throw mfue;
}
log.error(mfue.getMessage());
}
return base;
}

/** /**
* Default constructor * Default constructor
*/ */

+ 1
- 1
src/java/org/apache/fop/apps/FOUserAgent.java View File

} }
this.factory = factory; this.factory = factory;
setBaseURL(factory.getBaseURL()); setBaseURL(factory.getBaseURL());
setFontBaseURL(factory.getFontBaseURL());
setFontBaseURL(factory.getFontManager().getFontBaseURL());
setTargetResolution(factory.getTargetResolution()); setTargetResolution(factory.getTargetResolution());
} }

+ 47
- 59
src/java/org/apache/fop/apps/FopFactory.java View File

import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import org.apache.fop.fo.ElementMapping; import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry; import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fonts.FontCache; import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.hyphenation.HyphenationTreeResolver; import org.apache.fop.hyphenation.HyphenationTreeResolver;
import org.apache.fop.layoutmgr.LayoutManagerMaker; import org.apache.fop.layoutmgr.LayoutManagerMaker;
import org.apache.fop.render.RendererFactory; import org.apache.fop.render.RendererFactory;
/** Image manager for loading and caching image objects */ /** Image manager for loading and caching image objects */
private ImageManager imageManager; private ImageManager imageManager;


/** Font manager for font substitution, autodetection and caching **/
private FontManager fontManager;
/** Configuration layer used to configure fop */ /** Configuration layer used to configure fop */
private FopFactoryConfigurator config = null; private FopFactoryConfigurator config = null;
*/ */
private String base = null; private String base = null;


/** The base URL for all font URL resolutions. */
private String fontBase = null;

/** The base URL for all hyphen URL resolutions. */ /** The base URL for all hyphen URL resolutions. */
private String hyphenBase = null; private String hyphenBase = null;


*/ */
private boolean strictUserConfigValidation private boolean strictUserConfigValidation
= FopFactoryConfigurator.DEFAULT_STRICT_USERCONFIG_VALIDATION; = FopFactoryConfigurator.DEFAULT_STRICT_USERCONFIG_VALIDATION;

/** Font cache to speed up auto-font configuration (null if disabled) */
private FontCache fontCache = null;

/** Allows enabling kerning on the base 14 fonts, default is false */
private boolean enableBase14Kerning = false;
/** Source resolution in dpi */ /** Source resolution in dpi */
private float sourceResolution = FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION; private float sourceResolution = FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION;
this.rendererFactory = new RendererFactory(); this.rendererFactory = new RendererFactory();
this.xmlHandlers = new XMLHandlerRegistry(); this.xmlHandlers = new XMLHandlerRegistry();
this.ignoredNamespaces = new java.util.HashSet(); this.ignoredNamespaces = new java.util.HashSet();
setUseCache(FopFactoryConfigurator.DEFAULT_USE_CACHE);
} }
/** /**
public LayoutManagerMaker getLayoutManagerMakerOverride() { public LayoutManagerMaker getLayoutManagerMakerOverride() {
return this.lmMakerOverride; return this.lmMakerOverride;
} }

/**
* Checks if the given base URL is acceptable. It also normalizes the URL.
* @param base the base URL to check
* @return the normalized URL
* @throws MalformedURLException if there's a problem with a file URL
*/
private String checkBaseURL(String base) throws MalformedURLException {
if (!base.endsWith("/")) {
// The behavior described by RFC 3986 regarding resolution of relative
// references may be misleading for normal users:
// file://path/to/resources + myResource.res -> file://path/to/myResource.res
// file://path/to/resources/ + myResource.res -> file://path/to/resources/myResource.res
// We assume that even when the ending slash is missing, users have the second
// example in mind
base += "/";
}
File dir = new File(base);
try {
base = (dir.isDirectory() ? dir.toURL() : new URL(base)).toExternalForm();
} catch (MalformedURLException mfue) {
if (strictUserConfigValidation) {
throw mfue;
}
log.error(mfue.getMessage());
}
return base;
}
/** /**
* Sets the base URL. * Sets the base URL.
* @param base base URL
* @param base the base URL
* @throws MalformedURLException if there's a problem with a file URL * @throws MalformedURLException if there's a problem with a file URL
*/ */
public void setBaseURL(String base) throws MalformedURLException { public void setBaseURL(String base) throws MalformedURLException {
this.base = checkBaseURL(base);
this.base = foURIResolver.checkBaseURL(base);
} }


/** /**
* Sets the font base URL. * Sets the font base URL.
* @param fontBase font base URL * @param fontBase font base URL
* @throws MalformedURLException if there's a problem with a file URL * @throws MalformedURLException if there's a problem with a file URL
* @deprecated use getFontManager().setFontBaseURL(fontBase) instead
*/ */
public void setFontBaseURL(String fontBase) throws MalformedURLException { public void setFontBaseURL(String fontBase) throws MalformedURLException {
this.fontBase = checkBaseURL(fontBase);
getFontManager().setFontBaseURL(fontBase);
} }


/** @return the font base URL */
/**
* @return the font base URL
* @deprecated use getFontManager().setFontBaseURL(fontBase) instead
*/
public String getFontBaseURL() { public String getFontBaseURL() {
return this.fontBase;
return getFontManager().getFontBaseURL();
} }


/** @return the hyphen base URL */ /** @return the hyphen base URL */
} }
}); });
} }
this.hyphenBase = checkBaseURL(hyphenBase);
this.hyphenBase = foURIResolver.checkBaseURL(hyphenBase);
} }
/** /**
return foURIResolver; return foURIResolver;
} }


/**
* Returns the FO URI Resolver.
* @return the FO URI Resolver
*/
public FOURIResolver getFOURIResolver() {
return foURIResolver;
}

/** @return the HyphenationTreeResolver for resolving user-supplied hyphenation patterns. */ /** @return the HyphenationTreeResolver for resolving user-supplied hyphenation patterns. */
public HyphenationTreeResolver getHyphenationTreeResolver() { public HyphenationTreeResolver getHyphenationTreeResolver() {
return this.hyphResolver; return this.hyphResolver;
this.breakIndentInheritanceOnReferenceAreaBoundary = value; this.breakIndentInheritanceOnReferenceAreaBoundary = value;
} }
/** @return true if kerning on base 14 fonts is enabled */
/**
* @return true if kerning on base 14 fonts is enabled
* @deprecated use getFontManager().isBase14KerningEnabled() instead
*/
public boolean isBase14KerningEnabled() { public boolean isBase14KerningEnabled() {
return this.enableBase14Kerning;
return getFontManager().isBase14KerningEnabled();
} }
/** /**
* Controls whether kerning is activated on base 14 fonts. * Controls whether kerning is activated on base 14 fonts.
* @param value true if kerning should be activated * @param value true if kerning should be activated
* @deprecated use getFontManager().setBase14KerningEnabled(boolean) instead
*/ */
public void setBase14KerningEnabled(boolean value) { public void setBase14KerningEnabled(boolean value) {
this.enableBase14Kerning = value;
getFontManager().setBase14KerningEnabled(value);
} }
/** @return the resolution for resolution-dependant input */ /** @return the resolution for resolution-dependant input */
return this.strictUserConfigValidation; return this.strictUserConfigValidation;
} }


//------------------------------------------- Cache related stuff
//------------------------------------------- Font related stuff


/** /**
* Whether or not to cache results of font triplet detection/auto-config * Whether or not to cache results of font triplet detection/auto-config
* @param useCache use cache or not * @param useCache use cache or not
* @deprecated use getFontManager().setUseCache(boolean) instead
*/ */
public void setUseCache(boolean useCache) { public void setUseCache(boolean useCache) {
if (useCache) {
this.fontCache = FontCache.load();
if (this.fontCache == null) {
this.fontCache = new FontCache();
}
} else {
this.fontCache = null;
}
getFontManager().setUseCache(useCache);
} }


/** /**
* Cache results of font triplet detection/auto-config? * Cache results of font triplet detection/auto-config?
* @return whether this factory is uses the cache * @return whether this factory is uses the cache
* @deprecated use getFontManager().useCache() instead
*/ */
public boolean useCache() { public boolean useCache() {
return (this.fontCache != null);
return getFontManager().useCache();
} }


/** /**
* Returns the font cache instance used by this factory. * Returns the font cache instance used by this factory.
* @return the font cache * @return the font cache
* @deprecated use getFontManager().getFontCache() instead
*/ */
public FontCache getFontCache() { public FontCache getFontCache() {
return this.fontCache;
return getFontManager().getFontCache();
}
/**
* Returns the font manager
* @return the font manager
*/
public FontManager getFontManager() {
if (fontManager == null) {
this.fontManager = new FontManager(this);
}
return this.fontManager;
} }
/** /**

+ 6
- 20
src/java/org/apache/fop/apps/FopFactoryConfigurator.java View File

import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder; import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontManagerConfigurator;
import org.apache.fop.util.LogUtil; import org.apache.fop.util.LogUtil;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;


/** Defines the default target resolution (72dpi) for FOP */ /** Defines the default target resolution (72dpi) for FOP */
public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi
/** Use cache (record previously detected font triplet info) */
public static final boolean DEFAULT_USE_CACHE = true;

/** logger instance */ /** logger instance */
private final Log log = LogFactory.getLog(FopFactoryConfigurator.class); private final Log log = LogFactory.getLog(FopFactoryConfigurator.class);


LogUtil.handleException(log, mfue, strict); LogUtil.handleException(log, mfue, strict);
} }
} }
if (cfg.getChild("font-base", false) != null) {
try {
factory.setFontBaseURL(
cfg.getChild("font-base").getValue(null));
} catch (MalformedURLException mfue) {
LogUtil.handleException(log, mfue, strict);
}
}
if (cfg.getChild("hyphenation-base", false) != null) { if (cfg.getChild("hyphenation-base", false) != null) {
try { try {
factory.setHyphenBaseURL( factory.setHyphenBaseURL(
} }
} }


// caching (fonts)
if (cfg.getChild("use-cache", false) != null) {
try {
factory.setUseCache(
cfg.getChild("use-cache").getValueAsBoolean());
} catch (ConfigurationException mfue) {
LogUtil.handleException(log, mfue, strict);
}
}
// configure font manager
FontManager fontManager = factory.getFontManager();
FontManagerConfigurator fontManagerConfigurator = new FontManagerConfigurator(cfg);
fontManagerConfigurator.configure(fontManager);
} }
/** /**

+ 82
- 0
src/java/org/apache/fop/fonts/CustomFontCollection.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */
package org.apache.fop.fonts;

import java.util.List;

import org.apache.fop.render.PrintRenderer;

/**
* Sets up a set of custom (embedded) fonts
*/
public class CustomFontCollection implements FontCollection {
private PrintRenderer renderer = null;

/**
* A print renderer to configure
* @param renderer a print renderer
*/
public CustomFontCollection(PrintRenderer renderer) {
this.renderer = renderer;
}

/**
* {@inheritDoc}
*/
public int setup(int num, FontInfo fontInfo) {
List/*<EmbedFontInfo>*/ embedFontInfoList = renderer.getFontList();
if (embedFontInfoList == null) {
return num; //No fonts to process
}

FontResolver resolver = renderer.getFontResolver();
if (resolver == null) {
//Ensure that we have minimal font resolution capabilities
resolver = FontManager.createMinimalFontResolver();
}
String internalName = null;
//FontReader reader = null;

for (int i = 0; i < embedFontInfoList.size(); i++) {
EmbedFontInfo embedFontInfo = (EmbedFontInfo)embedFontInfoList.get(i);

//String metricsFile = configFontInfo.getMetricsFile();
internalName = "F" + num;
num++;
/*
reader = new FontReader(metricsFile);
reader.useKerning(configFontInfo.getKerning());
reader.setFontEmbedPath(configFontInfo.getEmbedFile());
fontInfo.addMetrics(internalName, reader.getFont());
*/
LazyFont font = new LazyFont(embedFontInfo, resolver);
fontInfo.addMetrics(internalName, font);

List triplets = embedFontInfo.getFontTriplets();
for (int tripletIndex = 0; tripletIndex < triplets.size(); tripletIndex++) {
FontTriplet triplet = (FontTriplet) triplets.get(tripletIndex);
fontInfo.addFontProperties(internalName, triplet);
}
}
return num;
}
}

+ 18
- 15
src/java/org/apache/fop/fonts/EmbedFontInfo.java View File

protected String embedFile; protected String embedFile;
/** false, to disable kerning */ /** false, to disable kerning */
protected boolean kerning; protected boolean kerning;
/** the list of associated font triplets */
protected List fontTriplets;
/** the PostScript name of the font */ /** the PostScript name of the font */
protected String postScriptName = null; protected String postScriptName = null;
/** the sub-fontname of the font (used for TrueType Collections, null otherwise) */ /** the sub-fontname of the font (used for TrueType Collections, null otherwise) */
protected String subFontName = null; protected String subFontName = null;


/** the list of associated font triplets */
private List/*<FontTriplet>*/ fontTriplets = null;

/** /**
* Main constructor * Main constructor
* @param metricsFile Path to the xml file containing font metrics * @param metricsFile Path to the xml file containing font metrics
* @param subFontName the sub-fontname used for TrueType Collections (null otherwise) * @param subFontName the sub-fontname used for TrueType Collections (null otherwise)
*/ */
public EmbedFontInfo(String metricsFile, boolean kerning, public EmbedFontInfo(String metricsFile, boolean kerning,
List fontTriplets, String embedFile, String subFontName) {
List/*<FontTriplet>*/ fontTriplets, String embedFile, String subFontName) {
this.metricsFile = metricsFile; this.metricsFile = metricsFile;
this.embedFile = embedFile; this.embedFile = embedFile;
this.kerning = kerning; this.kerning = kerning;
public boolean getKerning() { public boolean getKerning() {
return kerning; return kerning;
} }

/**
* Returns the list of font triplets associated with this font.
* @return List of font triplets
*/
public List getFontTriplets() {
return fontTriplets;
}
/** /**
* Returns the sub-fontname name of the font. This is primarily used for TrueType Collections
* Returns the sub-font name name of the font. This is primarily used for TrueType Collections
* to select one of the sub-fonts. For all other fonts, this is always null. * to select one of the sub-fonts. For all other fonts, this is always null.
* @return the sub-fontname (or null)
* @return the sub-font name (or null)
*/ */
public String getSubFontName() { public String getSubFontName() {
return this.subFontName; return this.subFontName;
this.postScriptName = postScriptName; this.postScriptName = postScriptName;
} }
/** {@inheritDoc} */
/**
* Returns the list of font triplets associated with this font.
* @return List of font triplets
*/
public List/*<FontTriplet>*/ getFontTriplets() {
return fontTriplets;
}
/**
* {@inheritDoc}
*/
public String toString() { public String toString() {
return "metrics-url=" + metricsFile + ",embed-url=" + embedFile return "metrics-url=" + metricsFile + ",embed-url=" + embedFile
+ ", kerning=" + kerning + ", font-triplet=" + fontTriplets
+ ", kerning=" + kerning + ", " + "font-triplet=" + fontTriplets
+ (getSubFontName() != null ? ", sub-font=" + getSubFontName() : ""); + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : "");
} }
} }

+ 10
- 1
src/java/org/apache/fop/fonts/Font.java View File

/** Italic font style */ /** Italic font style */
public static final String STYLE_ITALIC = "italic"; public static final String STYLE_ITALIC = "italic";


/** Oblique font style */
public static final String STYLE_OBLIQUE = "oblique";

/** Inclined font style */
public static final String STYLE_INCLINED = "inclined";

/** Default selection priority */
public static final int PRIORITY_DEFAULT = 0;
/** Default fallback key */ /** Default fallback key */
public static final FontTriplet DEFAULT_FONT = new FontTriplet( public static final FontTriplet DEFAULT_FONT = new FontTriplet(
"any", STYLE_NORMAL, WEIGHT_NORMAL);
"any", STYLE_NORMAL, WEIGHT_NORMAL, PRIORITY_DEFAULT);


/** logger */ /** logger */
private static Log log = LogFactory.getLog(Font.class); private static Log log = LogFactory.getLog(Font.class);

+ 45
- 25
src/java/org/apache/fop/fonts/FontCache.java View File

/** font cache file path */ /** font cache file path */
private static final String DEFAULT_CACHE_FILENAME = "fop-fonts.cache"; private static final String DEFAULT_CACHE_FILENAME = "fop-fonts.cache";


/** has this cache been changed since it was last read? */ /** has this cache been changed since it was last read? */
private transient boolean changed = false; private transient boolean changed = false;
/** master mapping of font url -> font info. This needs to be /** master mapping of font url -> font info. This needs to be
* a list, since a TTC file may contain more than 1 font. */ * a list, since a TTC file may contain more than 1 font. */
private Map fontfileMap = new java.util.HashMap(); //Map<String, CachedFontFile>
private Map/*<String, CachedFontFile>*/ fontfileMap = null;


/** mapping of font url -> file modified date (for all fonts that have failed to load) */ /** mapping of font url -> file modified date (for all fonts that have failed to load) */
private Map failedFontMap = new java.util.HashMap();
private Map failedFontMap/*<String, Long>*/ = null;


/** /**
* Default constructor * Default constructor
*/ */
public boolean containsFont(String embedUrl) { public boolean containsFont(String embedUrl) {
if (embedUrl != null) { if (embedUrl != null) {
return fontfileMap.containsKey(embedUrl);
return getFontFileMap().containsKey(embedUrl);
} }
return false; return false;
} }
*/ */
public boolean containsFont(EmbedFontInfo fontInfo) { public boolean containsFont(EmbedFontInfo fontInfo) {
if (fontInfo != null) { if (fontInfo != null) {
return fontfileMap.containsKey(getCacheKey(fontInfo));
return getFontFileMap().containsKey(getCacheKey(fontInfo));
} }
return false; return false;
} }
return null; return null;
} }


private Map/*<String, CachedFontFile>*/ getFontFileMap() {
if (fontfileMap == null) {
fontfileMap = new java.util.HashMap/*<String, CachedFontFile>*/();
}
return fontfileMap;
}
/** /**
* Adds a font info to cache * Adds a font info to cache
* @param fontInfo font info * @param fontInfo font info
synchronized (changeLock) { synchronized (changeLock) {
CachedFontFile cachedFontFile; CachedFontFile cachedFontFile;
if (containsFont(cacheKey)) { if (containsFont(cacheKey)) {
cachedFontFile = (CachedFontFile)fontfileMap.get(cacheKey);
cachedFontFile = (CachedFontFile)getFontFileMap().get(cacheKey);
if (!cachedFontFile.containsFont(fontInfo)) { if (!cachedFontFile.containsFont(fontInfo)) {
cachedFontFile.put(fontInfo); cachedFontFile.put(fontInfo);
} }
log.trace("Font added to cache: " + cacheKey); log.trace("Font added to cache: " + cacheKey);
} }
cachedFontFile.put(fontInfo); cachedFontFile.put(fontInfo);
fontfileMap.put(cacheKey, cachedFontFile);
getFontFileMap().put(cacheKey, cachedFontFile);
changed = true; changed = true;
} }
} }
*/ */
public CachedFontFile getFontFile(String embedUrl) { public CachedFontFile getFontFile(String embedUrl) {
if (containsFont(embedUrl)) { if (containsFont(embedUrl)) {
return (CachedFontFile)fontfileMap.get(embedUrl);
return (CachedFontFile)getFontFileMap().get(embedUrl);
} }
return null; return null;
} }
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.trace("Font removed from cache: " + embedUrl); log.trace("Font removed from cache: " + embedUrl);
} }
fontfileMap.remove(embedUrl);
getFontFileMap().remove(embedUrl);
changed = true; changed = true;
} }
} }
* @return whether this is a failed font * @return whether this is a failed font
*/ */
public boolean isFailedFont(String embedUrl, long lastModified) { public boolean isFailedFont(String embedUrl, long lastModified) {
if (failedFontMap.containsKey(embedUrl)) {
if (getFailedFontMap().containsKey(embedUrl)) {
synchronized (changeLock) { synchronized (changeLock) {
long failedLastModified = ((Long)failedFontMap.get(embedUrl)).longValue();
long failedLastModified = ((Long)getFailedFontMap().get(embedUrl)).longValue();
if (lastModified != failedLastModified) { if (lastModified != failedLastModified) {
// this font has been changed so lets remove it // this font has been changed so lets remove it
// from failed font map for now // from failed font map for now
failedFontMap.remove(embedUrl);
getFailedFontMap().remove(embedUrl);
changed = true; changed = true;
} }
} }
} }


/** /**
* registers a failed font with the cache
* Registers a failed font with the cache
* @param embedUrl embed url * @param embedUrl embed url
* @param lastModified time last modified * @param lastModified time last modified
*/ */
public void registerFailedFont(String embedUrl, long lastModified) { public void registerFailedFont(String embedUrl, long lastModified) {
synchronized (changeLock) { synchronized (changeLock) {
if (!failedFontMap.containsKey(embedUrl)) {
failedFontMap.put(embedUrl, new Long(lastModified));
if (!getFailedFontMap().containsKey(embedUrl)) {
getFailedFontMap().put(embedUrl, new Long(lastModified));
changed = true; changed = true;
} }
} }
} }


private Map/*<String, Long>*/ getFailedFontMap() {
if (failedFontMap == null) {
failedFontMap = new java.util.HashMap/*<String, Long>*/();
}
return failedFontMap;
}
/** /**
* Clears font cache * Clears font cache
*/ */
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.trace("Font cache cleared."); log.trace("Font cache cleared.");
} }
fontfileMap.clear();
failedFontMap.clear();
fontfileMap = null;
failedFontMap = null;
changed = true; changed = true;
} }
} }
} }
private static class CachedFontFile implements Serializable { private static class CachedFontFile implements Serializable {
private static final long serialVersionUID = 4524237324330578883L;

/** file modify date (if available) */ /** file modify date (if available) */
private long lastModified = -1; private long lastModified = -1;


private Map filefontsMap = new java.util.HashMap(); //Map<String, EmbedFontInfo>
private Map/*<String, EmbedFontInfo>*/ filefontsMap = null;
public CachedFontFile(long lastModified) { public CachedFontFile(long lastModified) {
setLastModified(lastModified); setLastModified(lastModified);
} }


private Map/*<String, EmbedFontInfo>*/ getFileFontsMap() {
if (filefontsMap == null) {
filefontsMap = new java.util.HashMap/*<String, EmbedFontInfo>*/();
}
return filefontsMap;
}
void put(EmbedFontInfo efi) { void put(EmbedFontInfo efi) {
filefontsMap.put(efi.getPostScriptName(), efi);
getFileFontsMap().put(efi.getPostScriptName(), efi);
} }


public boolean containsFont(EmbedFontInfo efi) { public boolean containsFont(EmbedFontInfo efi) {
if (efi.getPostScriptName() != null) { if (efi.getPostScriptName() != null) {
return filefontsMap.containsKey(efi.getPostScriptName());
return getFileFontsMap().containsKey(efi.getPostScriptName());
} }
return false; return false;
} }


public Map getFilefontsMap() {
return filefontsMap;
}

public EmbedFontInfo[] getEmbedFontInfos() { public EmbedFontInfo[] getEmbedFontInfos() {
return (EmbedFontInfo[])this.filefontsMap.values().toArray(
new EmbedFontInfo[this.filefontsMap.size()]);
return (EmbedFontInfo[])getFileFontsMap().values().toArray(
new EmbedFontInfo[getFileFontsMap().size()]);
} }
/** /**

+ 38
- 0
src/java/org/apache/fop/fonts/FontCollection.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts;


/**
* Sets up a set of fonts
*/
public interface FontCollection {
/**
* Sets up fonts in a font info object.
*
* Adds metrics for basic fonts and useful family-style-weight
* triplets for lookup.
*
* @param start the font starting number
* @param fontInfo the font info to set up
* @return the starting font number for the next font to be added
*/
int setup(int start, FontInfo fontInfo);
}

+ 1
- 1
src/java/org/apache/fop/fonts/FontDescriptor.java View File

/** /**
* Returns the capital height of the font. * Returns the capital height of the font.
* @return the capiptal height
* @return the capital height
*/ */
int getCapHeight(); int getCapHeight();

+ 114
- 80
src/java/org/apache/fop/fonts/FontInfo.java View File



package org.apache.fop.fonts; package org.apache.fop.fonts;


import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;


import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;



/** /**
* The FontInfo for the layout and rendering of a fo document.
* The FontInfo holds font information for the layout and rendering of a fo document.
* This stores the list of available fonts that are setup by * This stores the list of available fonts that are setup by
* the renderer. The font name can be retrieved for the * the renderer. The font name can be retrieved for the
* family style and weight. * family style and weight.
protected static Log log = LogFactory.getLog(FontInfo.class); protected static Log log = LogFactory.getLog(FontInfo.class);


/** Map containing fonts that have been used */ /** Map containing fonts that have been used */
private Map usedFonts; //Map<String,FontMetrics> (String = font key)
private Map/*<String,FontMetrics>*/ usedFonts = null; //(String = font key)
/** look up a font-triplet to find a font-name */ /** look up a font-triplet to find a font-name */
private Map triplets; //Map<FontTriplet,String> (String = font key)
private Map/*<FontTriplet,String>*/ triplets = null; //(String = font key)
/** look up a font-triplet to find its priority /** look up a font-triplet to find its priority
* (only used inside addFontProperties()) */ * (only used inside addFontProperties()) */
private Map tripletPriorities; //Map<FontTriplet,Integer>
private Map/*<FontTriplet,Integer>*/ tripletPriorities = null; //Map<FontTriplet,Integer>


/** look up a font-name to get a font (that implements FontMetrics at least) */ /** look up a font-name to get a font (that implements FontMetrics at least) */
private Map fonts; //Map<String,FontMetrics> (String = font key)
private Map/*<String,FontMetrics>*/ fonts = null; //(String = font key)
/** collection of missing fonts; used to make sure the user gets
/**
* a collection of missing fonts; used to make sure the user gets
* a warning for a missing font only once (not every time the font is used) * a warning for a missing font only once (not every time the font is used)
*/ */
private Collection loggedFontKeys;
private Set/*<FontTriplet>*/ loggedFontKeys = null;


/** Cache for Font instances. */ /** Cache for Font instances. */
private Map fontInstanceCache = new java.util.HashMap();
private FontEventListener eventListener;
private Map/*<FontTriplet, Map>*/ fontInstanceCache = null;
/** Event listener for font events */
private FontEventListener eventListener = null;

/** /**
* Main constructor * Main constructor
*/ */
public FontInfo() { public FontInfo() {
this.triplets = new java.util.HashMap();
this.tripletPriorities = new java.util.HashMap();
this.fonts = new java.util.HashMap();
this.usedFonts = new java.util.HashMap();
this.triplets = new java.util.HashMap/*<FontTriplet, String>*/();
this.tripletPriorities = new java.util.HashMap/*<FontTriplet, Integer>*/();
this.fonts = new java.util.HashMap/*<String, FontMetrics>*/();
this.usedFonts = new java.util.HashMap/*<String,FontMetrics>*/();
} }
/** /**
* Sets the font event listener that can be used to receive events about particular events * Sets the font event listener that can be used to receive events about particular events
* in this class. * in this class.


/** /**
* Adds a new font triplet. * Adds a new font triplet.
* @param name internal key
* @param internalFontKey internal font key
* @param triplet the font triplet to associate with the internal key * @param triplet the font triplet to associate with the internal key
*/ */
public void addFontProperties(String name, FontTriplet triplet) {
public void addFontProperties(String internalFontKey, FontTriplet triplet) {
/* /*
* add the given family, style and weight as a lookup for the font * add the given family, style and weight as a lookup for the font
* with the given name * with the given name
*/ */
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Registering: " + triplet + " under " + name);
log.debug("Registering: " + triplet + " under " + internalFontKey);
} }
String oldName = (String)triplets.get(triplet); String oldName = (String)triplets.get(triplet);
int newPriority = triplet.getPriority(); int newPriority = triplet.getPriority();
int oldPriority = ((Integer)tripletPriorities.get(triplet)).intValue(); int oldPriority = ((Integer)tripletPriorities.get(triplet)).intValue();
if (oldPriority < newPriority) { if (oldPriority < newPriority) {
logDuplicateFont(triplet, false, oldName, oldPriority, logDuplicateFont(triplet, false, oldName, oldPriority,
name, newPriority);
internalFontKey, newPriority);
return; return;
} else { } else {
logDuplicateFont(triplet, true, oldName, oldPriority, logDuplicateFont(triplet, true, oldName, oldPriority,
name, newPriority);
internalFontKey, newPriority);
} }
} }
this.triplets.put(triplet, name);
this.triplets.put(triplet, internalFontKey);
this.tripletPriorities.put(triplet, new Integer(newPriority)); this.tripletPriorities.put(triplet, new Integer(newPriority));
} }


/** Log warning about duplicate font triplets.
/**
* Log warning about duplicate font triplets.
*
* @param triplet the duplicate font triplet * @param triplet the duplicate font triplet
* @param replacing true iff the new font will replace the old one * @param replacing true iff the new font will replace the old one
* @param oldKey the old internal font name * @param oldKey the old internal font name
log.debug(triplet log.debug(triplet
+ (replacing ? ": Replacing " : ": Not replacing ") + (replacing ? ": Replacing " : ": Not replacing ")
+ ((FontMetrics)fonts.get(triplets.get(triplet))).getFullName() + ((FontMetrics)fonts.get(triplets.get(triplet))).getFullName()
+ " (" + oldPriority + ") by "
+ " (priority=" + oldPriority + ") by "
+ ((FontMetrics)fonts.get(newKey)).getFullName() + ((FontMetrics)fonts.get(newKey)).getFullName()
+ " (" + newPriority + ")");
+ " (priority=" + newPriority + ")");
} }
} }


/** /**
* Adds font metrics for a specific font. * Adds font metrics for a specific font.
* @param name internal key
* @param internalFontKey internal key
* @param metrics metrics to register * @param metrics metrics to register
*/ */
public void addMetrics(String name, FontMetrics metrics) {
public void addMetrics(String internalFontKey, FontMetrics metrics) {
// add the given metrics as a font with the given name // add the given metrics as a font with the given name


if (metrics instanceof Typeface) { if (metrics instanceof Typeface) {
((Typeface)metrics).setEventListener(this.eventListener); ((Typeface)metrics).setEventListener(this.eventListener);
} }
this.fonts.put(name, metrics);
this.fonts.put(internalFontKey, metrics);
} }


/** /**
* @param weight font weight * @param weight font weight
* @param substFont true if the font may be substituted with the * @param substFont true if the font may be substituted with the
* default font if not found * default font if not found
* @return internal key
* @return internal font triplet key
*/ */
private FontTriplet fontLookup(String family, String style, private FontTriplet fontLookup(String family, String style,
int weight, boolean substFont) { int weight, boolean substFont) {
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.trace("Font lookup: " + family + " " + style + " " + weight); log.trace("Font lookup: " + family + " " + style + " " + weight);
}
}
FontTriplet startKey = createFontKey(family, style, weight); FontTriplet startKey = createFontKey(family, style, weight);
FontTriplet key = startKey;
FontTriplet fontTriplet = startKey;
// first try given parameters // first try given parameters
String f = getInternalFontKey(key);
if (f == null) {
key = doAdjustedLookup(family, style, weight, startKey, substFont);
String internalFontKey = getInternalFontKey(fontTriplet);
if (internalFontKey == null) {
fontTriplet = fuzzyFontLookup(family, style, weight, startKey, substFont);
} }


if (key != null) {
if (key != startKey) {
notifyFontReplacement(startKey, key);
if (fontTriplet != null) {
if (fontTriplet != startKey) {
notifyFontReplacement(startKey, fontTriplet);
} }
return key;
return fontTriplet;
} else { } else {
return null; return null;
} }
} }


private FontTriplet doAdjustedLookup(String family, String style,
private FontTriplet fuzzyFontLookup(String family, String style,
int weight, FontTriplet startKey, boolean substFont) { int weight, FontTriplet startKey, boolean substFont) {
FontTriplet key; FontTriplet key;
String f;
String internalFontKey;
if (!family.equals(startKey.getName())) { if (!family.equals(startKey.getName())) {
key = createFontKey(family, style, weight); key = createFontKey(family, style, weight);
f = getInternalFontKey(key);
if (f != null) {
internalFontKey = getInternalFontKey(key);
if (internalFontKey != null) {
return key; return key;
} }
} }
// adjust weight, favouring normal or bold // adjust weight, favouring normal or bold
key = findAdjustWeight(family, style, weight); key = findAdjustWeight(family, style, weight);
f = getInternalFontKey(key);
internalFontKey = getInternalFontKey(key);


if (!substFont && f == null) {
if (!substFont && internalFontKey == null) {
return null; return null;
} }
// only if the font may be substituted // only if the font may be substituted
// fallback 1: try the same font-family and weight with default style // fallback 1: try the same font-family and weight with default style
if (f == null && style != Font.STYLE_NORMAL) {
if (internalFontKey == null && style != Font.STYLE_NORMAL) {
key = createFontKey(family, Font.STYLE_NORMAL, weight); key = createFontKey(family, Font.STYLE_NORMAL, weight);
f = getInternalFontKey(key);
internalFontKey = getInternalFontKey(key);
} }


if (f == null && weight != Font.WEIGHT_NORMAL) {
if (internalFontKey == null && weight != Font.WEIGHT_NORMAL) {
int diffWeight = (Font.WEIGHT_NORMAL - weight) / 100; int diffWeight = (Font.WEIGHT_NORMAL - weight) / 100;
int direction = diffWeight > 0 ? 1 : -1; int direction = diffWeight > 0 ? 1 : -1;
int tryWeight = weight; int tryWeight = weight;
while (tryWeight != Font.WEIGHT_NORMAL) { while (tryWeight != Font.WEIGHT_NORMAL) {
tryWeight += 100 * direction; tryWeight += 100 * direction;
key = createFontKey(family, style, weight); key = createFontKey(family, style, weight);
f = getInternalFontKey(key);
if (f == null) {
internalFontKey = getInternalFontKey(key);
if (internalFontKey == null) {
key = createFontKey(family, Font.STYLE_NORMAL, weight); key = createFontKey(family, Font.STYLE_NORMAL, weight);
f = getInternalFontKey(key);
internalFontKey = getInternalFontKey(key);
} }
if (f != null) {
if (internalFontKey != null) {
break; break;
} }
} }
}*/ }*/
// fallback 3: try any family with orig style/weight // fallback 3: try any family with orig style/weight
if (f == null) {
return doAdjustedLookup("any", style, weight, startKey, false);
if (internalFontKey == null) {
return fuzzyFontLookup("any", style, weight, startKey, false);
} }


// last resort: use default // last resort: use default
if (f == null) {
if (internalFontKey == null) {
key = Font.DEFAULT_FONT; key = Font.DEFAULT_FONT;
f = getInternalFontKey(key);
internalFontKey = getInternalFontKey(key);
} }


if (f != null) {
if (internalFontKey != null) {
return key; return key;
} else { } else {
return null; return null;
usedFonts.put(internalName, fonts.get(internalName)); usedFonts.put(internalName, fonts.get(internalName));
} }
private Map/*<FontTriplet,Map<Integer,Font>>*/ getFontInstanceCache() {
if (fontInstanceCache == null) {
fontInstanceCache = new java.util.HashMap/*<FontTriplet, Map<Integer,Font>>*/();
}
return fontInstanceCache;
}

/** /**
* Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size. * Retrieves a (possibly cached) Font instance based on a FontTriplet and a font size.
* @param triplet the font triplet designating the requested font * @param triplet the font triplet designating the requested font
* @return the requested Font instance * @return the requested Font instance
*/ */
public Font getFontInstance(FontTriplet triplet, int fontSize) { public Font getFontInstance(FontTriplet triplet, int fontSize) {
Map sizes = (Map)fontInstanceCache.get(triplet);
Map/*<Integer,Font>*/ sizes
= (Map/*<Integer,Font>*/)getFontInstanceCache().get(triplet);
if (sizes == null) { if (sizes == null) {
sizes = new java.util.HashMap();
fontInstanceCache.put(triplet, sizes);
sizes = new java.util.HashMap/*<Integer,Font>*/();
getFontInstanceCache().put(triplet, sizes);
} }
Integer size = new Integer(fontSize); Integer size = new Integer(fontSize);
Font font = (Font)sizes.get(size); Font font = (Font)sizes.get(size);
throw new IllegalArgumentException("Specify at least one font family"); throw new IllegalArgumentException("Specify at least one font family");
} }
FontTriplet triplet; FontTriplet triplet;
List tmpTriplets = new ArrayList();
List tmpTriplets = new java.util.ArrayList();
for (int i = 0, c = families.length; i < c; i++) { for (int i = 0, c = families.length; i < c; i++) {
triplet = fontLookup(families[i], style, weight, (i >= families.length - 1)); triplet = fontLookup(families[i], style, weight, (i >= families.length - 1));
if (triplet != null) { if (triplet != null) {
+ "FontTriplet on the last call. Lookup: " + sb.toString()); + "FontTriplet on the last call. Lookup: " + sb.toString());
} }
private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) {
private Set/*<FontTriplet>*/ getLoggedFontKeys() {
if (loggedFontKeys == null) { if (loggedFontKeys == null) {
loggedFontKeys = new java.util.HashSet();
loggedFontKeys = new java.util.HashSet/*<FontTriplet>*/();
} }
if (!loggedFontKeys.contains(replacedKey)) {
loggedFontKeys.add(replacedKey);
return loggedFontKeys;
}
private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) {
if (!getLoggedFontKeys().contains(replacedKey)) {
getLoggedFontKeys().add(replacedKey);
if (this.eventListener != null) { if (this.eventListener != null) {
this.eventListener.fontSubstituted(this, replacedKey, newKey); this.eventListener.fontSubstituted(this, replacedKey, newKey);
} else { } else {
* Gets a Map of all registered fonts. * Gets a Map of all registered fonts.
* @return a read-only Map with font key/FontMetrics pairs * @return a read-only Map with font key/FontMetrics pairs
*/ */
public Map getFonts() {
public Map/*<String,FontMetrics>*/ getFonts() {
return java.util.Collections.unmodifiableMap(this.fonts); return java.util.Collections.unmodifiableMap(this.fonts);
} }


/** /**
* Gets a Map of all registered font triplets. * Gets a Map of all registered font triplets.
* @return a read-only Map with FontTriplet/font key pairs
* @return a Map with FontTriplet/font key pairs
*/ */
public Map getFontTriplets() {
return java.util.Collections.unmodifiableMap(this.triplets);
public Map/*<FontTriplet,String>*/ getFontTriplets() {
return this.triplets;
} }
/** /**
* This is for embedded font or creating a list of used fonts. * This is for embedded font or creating a list of used fonts.
* @return a read-only Map with font key/FontMetrics pairs * @return a read-only Map with font key/FontMetrics pairs
*/ */
public Map getUsedFonts() {
public Map/*<String,FontMetrics>*/ getUsedFonts() {
return this.usedFonts; return this.usedFonts;
} }


} }


/** /**
* Returns the first triplet matching the given font name.
* As there may be multiple triplets matching the font name
* the result set is sorted first to guarantee consistent results.
* Returns all font triplet matching the given font name.
* @param fontName The font name we are looking for * @param fontName The font name we are looking for
* @return The first triplet for the given font name
* @return A list of matching font triplets
*/ */
public FontTriplet getTripletFor(String fontName) {
List foundTriplets = new ArrayList();
public List/*<FontTriplet>*/ getTripletsFor(String fontName) {
List/*<FontTriplet>*/ foundTriplets = new java.util.ArrayList();
for (Iterator iter = triplets.entrySet().iterator(); iter.hasNext();) { for (Iterator iter = triplets.entrySet().iterator(); iter.hasNext();) {
Map.Entry tripletEntry = (Map.Entry) iter.next(); Map.Entry tripletEntry = (Map.Entry) iter.next();
if (fontName.equals(((String)tripletEntry.getValue()))) { if (fontName.equals(((String)tripletEntry.getValue()))) {
foundTriplets.add(tripletEntry.getKey()); foundTriplets.add(tripletEntry.getKey());
} }
} }
return foundTriplets;
}
/**
* Returns the first triplet matching the given font name.
* As there may be multiple triplets matching the font name
* the result set is sorted first to guarantee consistent results.
* @param fontName The font name we are looking for
* @return The first triplet for the given font name
*/
public FontTriplet getTripletFor(String fontName) {
List/*<FontTriplet>*/ foundTriplets = getTripletsFor(fontName);
if (foundTriplets.size() > 0) { if (foundTriplets.size() > 0) {
Collections.sort(foundTriplets); Collections.sort(foundTriplets);
return (FontTriplet)foundTriplets.get(0); return (FontTriplet)foundTriplets.get(0);
* Diagnostic method for logging all registered fonts to System.out. * Diagnostic method for logging all registered fonts to System.out.
*/ */
public void dumpAllTripletsToSystemOut() { public void dumpAllTripletsToSystemOut() {
System.out.print(toString());
}
/**
* {@inheritDoc}
*/
public String toString() {
Collection entries = new java.util.TreeSet(); Collection entries = new java.util.TreeSet();
Iterator iter = this.triplets.keySet().iterator(); Iterator iter = this.triplets.keySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
FontTriplet triplet = (FontTriplet)iter.next(); FontTriplet triplet = (FontTriplet)iter.next();
String key = getInternalFontKey(triplet); String key = getInternalFontKey(triplet);
FontMetrics metrics = getMetricsFor(key); FontMetrics metrics = getMetricsFor(key);
entries.add(triplet.toString() + " -> " + key + " -> " + metrics.getFontName());
entries.add(triplet.toString() + " -> " + key + " -> " + metrics.getFontName() + "\n");
} }
iter = entries.iterator();
while (iter.hasNext()) {
System.out.println(iter.next());
StringBuffer stringBuffer = new StringBuffer();
for (iter = entries.iterator(); iter.hasNext();) {
stringBuffer.append(iter.next());
} }
return stringBuffer.toString();
} }
} }

+ 221
- 0
src/java/org/apache/fop/fonts/FontManager.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts;

import java.awt.Graphics2D;
import java.net.MalformedURLException;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FopFactory;
import org.apache.fop.fonts.substitute.FontSubstitutions;
import org.apache.fop.render.PrintRenderer;

// TODO: Refactor fonts package so major font activities (autodetection etc)
// are all centrally managed and delegated from this class, also remove dependency on FopFactory
// and start using POJO config/properties type classes

/**
* The manager of fonts
*/
public class FontManager {
/** Use cache (record previously detected font triplet info) */
public static final boolean DEFAULT_USE_CACHE = true;

/** The base URL for all font URL resolutions. */
private String fontBase = null;

/** Font cache to speed up auto-font configuration (null if disabled) */
private FontCache fontCache = null;

/** Font substitutions */
private FontSubstitutions fontSubstitutions = null;

private FopFactory fopFactory = null;

/** Allows enabling kerning on the base 14 fonts, default is false */
private boolean enableBase14Kerning = false;

/**
* Main constructor
*
* @param fopFactory the fo URI resolver
*/
public FontManager(FopFactory fopFactory) {
this(fopFactory, DEFAULT_USE_CACHE);
}
/**
* Constructor
*
* @param fopFactory the fo URI resolver
* @param useCache true if the FontCache should be used
*/
public FontManager(FopFactory fopFactory, boolean useCache) {
this.fopFactory = fopFactory;
setUseCache(useCache);
}
/**
* Sets the font base URL.
* @param fontBase font base URL
* @throws MalformedURLException if there's a problem with a file URL
*/
public void setFontBaseURL(String fontBase) throws MalformedURLException {
this.fontBase = fopFactory.getFOURIResolver().checkBaseURL(fontBase);
}

/**
* @return the font base URL
*/
public String getFontBaseURL() {
return this.fontBase;
}

/** @return true if kerning on base 14 fonts is enabled */
public boolean isBase14KerningEnabled() {
return this.enableBase14Kerning;
}

/**
* Controls whether kerning is activated on base 14 fonts.
* @param value true if kerning should be activated
*/
public void setBase14KerningEnabled(boolean value) {
this.enableBase14Kerning = value;
}

/**
* Sets the font substitutions
* @param substitutions font substitutions
*/
public void setFontSubstitutions(FontSubstitutions substitutions) {
this.fontSubstitutions = substitutions;
}
/**
* Returns the font substitution catalog
* @return the font substitution catalog
*/
protected FontSubstitutions getFontSubstitutions() {
if (fontSubstitutions == null) {
this.fontSubstitutions = new FontSubstitutions();
}
return fontSubstitutions;
}

/**
* Whether or not to cache results of font triplet detection/auto-config
* @param useCache use cache or not
*/
public void setUseCache(boolean useCache) {
if (useCache) {
this.fontCache = FontCache.load();
if (this.fontCache == null) {
this.fontCache = new FontCache();
}
} else {
this.fontCache = null;
}
}

/**
* Cache results of font triplet detection/auto-config?
* @return true if this font manager uses the cache
*/
public boolean useCache() {
return (this.fontCache != null);
}

/**
* Returns the font cache instance used by this font manager.
* @return the font cache
*/
public FontCache getFontCache() {
return this.fontCache;
}
/**
* Sets up the fonts on a given PrintRenderer
* @param renderer a print renderer
*/
public void setupRenderer(PrintRenderer renderer) {
FontInfo fontInfo = renderer.getFontInfo();

int startNum = 1;
// Configure base 14 fonts
org.apache.fop.fonts.base14.Base14FontCollection base14FontCollection
= new org.apache.fop.fonts.base14.Base14FontCollection(this.enableBase14Kerning);
startNum = base14FontCollection.setup(startNum, fontInfo);

// Configure any custom font collection
org.apache.fop.fonts.CustomFontCollection customFontCollection
= new org.apache.fop.fonts.CustomFontCollection(renderer);
startNum = customFontCollection.setup(startNum, fontInfo);
// Make any defined substitutions in the font info
getFontSubstitutions().adjustFontInfo(fontInfo);
}

/**
* Sets up the fonts on a given PrintRenderer with Graphics2D
* @param renderer a print renderer
* @param graphics2D a graphics 2D
*/
public void setupRenderer(PrintRenderer renderer, Graphics2D graphics2D) {
FontInfo fontInfo = renderer.getFontInfo();

int startNum = 1;

// setup base 14 fonts
org.apache.fop.render.java2d.Base14FontCollection base14FontCollection
= new org.apache.fop.render.java2d.Base14FontCollection(graphics2D);
// setup any custom font collection
startNum = base14FontCollection.setup(startNum, fontInfo);

// setup any installed fonts
org.apache.fop.render.java2d.InstalledFontCollection installedFontCollection
= new org.apache.fop.render.java2d.InstalledFontCollection(graphics2D);
startNum = installedFontCollection.setup(startNum, fontInfo);

// setup any configured fonts
org.apache.fop.render.java2d.ConfiguredFontCollection configuredFontCollection
= new org.apache.fop.render.java2d.ConfiguredFontCollection(renderer);
startNum = configuredFontCollection.setup(startNum, fontInfo);

// Make any defined substitutions in the font info
getFontSubstitutions().adjustFontInfo(fontInfo);
}

/** @return a new FontResolver to be used by the font subsystem */
public static FontResolver createMinimalFontResolver() {
return new FontResolver() {

/** {@inheritDoc} */
public Source resolve(String href) {
//Minimal functionality here
return new StreamSource(href);
}
};
}
}

+ 89
- 0
src/java/org/apache/fop/fonts/FontManagerConfigurator.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts;

import java.net.MalformedURLException;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fonts.substitute.FontSubstitutions;
import org.apache.fop.fonts.substitute.FontSubstitutionsConfigurator;
import org.apache.fop.util.LogUtil;

/**
* Configurator of the FontManager
*/
public class FontManagerConfigurator {
/** logger instance */
private static Log log = LogFactory.getLog(FontManagerConfigurator.class);

private Configuration cfg;
/**
* Main constructor
* @param cfg the font manager configuration object
*/
public FontManagerConfigurator(Configuration cfg) {
this.cfg = cfg;
}

/**
* Initializes font settings from the user configuration
* @param fontManager a font manager
* @throws FOPException fop exception
*/
public void configure(FontManager fontManager) throws FOPException {
// caching (fonts)
if (cfg.getChild("use-cache", false) != null) {
try {
fontManager.setUseCache(
cfg.getChild("use-cache").getValueAsBoolean());
} catch (ConfigurationException mfue) {
LogUtil.handleException(log, mfue, true);
}
}
if (cfg.getChild("font-base", false) != null) {
try {
fontManager.setFontBaseURL(
cfg.getChild("font-base").getValue(null));
} catch (MalformedURLException mfue) {
LogUtil.handleException(log, mfue, true);
}
}

// global font configuration
Configuration fontsCfg = cfg.getChild("fonts", false);
if (fontsCfg != null) {
// font substitution
Configuration substitutionsCfg = fontsCfg.getChild("substitutions", false);
if (substitutionsCfg != null) {
FontSubstitutionsConfigurator fontSubstitutionsConfigurator
= new FontSubstitutionsConfigurator(substitutionsCfg);
FontSubstitutions substitutions = new FontSubstitutions();
fontSubstitutionsConfigurator.configure(substitutions);
fontManager.setFontSubstitutions(substitutions);
}
}
}
}

+ 111
- 114
src/java/org/apache/fop/fonts/FontSetup.java View File

import org.apache.fop.fonts.base14.TimesRoman; import org.apache.fop.fonts.base14.TimesRoman;
import org.apache.fop.fonts.base14.ZapfDingbats; import org.apache.fop.fonts.base14.ZapfDingbats;


//TODO remove small dependency on and refactor this

/** /**
* Default fonts for FOP application; currently this uses PDF's fonts * Default fonts for FOP application; currently this uses PDF's fonts
* by default. * by default.
protected static Log log = LogFactory.getLog(FontSetup.class); protected static Log log = LogFactory.getLog(FontSetup.class);


/** /**
* Sets up the font info object.
*
* Adds metrics for basic fonts and useful family-style-weight
* triplets for lookup.
*
* @param fontInfo the font info object to set up
* @param embedList a list of EmbedFontInfo objects
* @param resolver the font resolver
* Sets up a font info
* @param fontInfo font info
*/ */
public static void setup(FontInfo fontInfo, List embedList, FontResolver resolver) {
setup(fontInfo, embedList, resolver, false);
public static void setup(FontInfo fontInfo) {
setup(fontInfo, null, null);
} }


/** /**
* triplets for lookup. * triplets for lookup.
* *
* @param fontInfo the font info object to set up * @param fontInfo the font info object to set up
* @param embedList a list of EmbedFontInfo objects
* @param embedFontInfoList a list of EmbedFontInfo objects
* @param resolver the font resolver * @param resolver the font resolver
* @param enableBase14Kerning true if kerning should be enabled for base 14 fonts
*/ */
public static void setup(FontInfo fontInfo, List embedList, FontResolver resolver,
boolean enableBase14Kerning) {

fontInfo.addMetrics("F1", new Helvetica(enableBase14Kerning));
fontInfo.addMetrics("F2", new HelveticaOblique(enableBase14Kerning));
fontInfo.addMetrics("F3", new HelveticaBold(enableBase14Kerning));
fontInfo.addMetrics("F4", new HelveticaBoldOblique(enableBase14Kerning));
fontInfo.addMetrics("F5", new TimesRoman(enableBase14Kerning));
fontInfo.addMetrics("F6", new TimesItalic(enableBase14Kerning));
fontInfo.addMetrics("F7", new TimesBold(enableBase14Kerning));
fontInfo.addMetrics("F8", new TimesBoldItalic(enableBase14Kerning));
fontInfo.addMetrics("F9", new Courier(enableBase14Kerning));
fontInfo.addMetrics("F10", new CourierOblique(enableBase14Kerning));
fontInfo.addMetrics("F11", new CourierBold(enableBase14Kerning));
fontInfo.addMetrics("F12", new CourierBoldOblique(enableBase14Kerning));
public static void setup(FontInfo fontInfo, List embedFontInfoList, FontResolver resolver) {
final boolean base14Kerning = false;
fontInfo.addMetrics("F1", new Helvetica(base14Kerning));
fontInfo.addMetrics("F2", new HelveticaOblique(base14Kerning));
fontInfo.addMetrics("F3", new HelveticaBold(base14Kerning));
fontInfo.addMetrics("F4", new HelveticaBoldOblique(base14Kerning));
fontInfo.addMetrics("F5", new TimesRoman(base14Kerning));
fontInfo.addMetrics("F6", new TimesItalic(base14Kerning));
fontInfo.addMetrics("F7", new TimesBold(base14Kerning));
fontInfo.addMetrics("F8", new TimesBoldItalic(base14Kerning));
fontInfo.addMetrics("F9", new Courier(base14Kerning));
fontInfo.addMetrics("F10", new CourierOblique(base14Kerning));
fontInfo.addMetrics("F11", new CourierBold(base14Kerning));
fontInfo.addMetrics("F12", new CourierBoldOblique(base14Kerning));
fontInfo.addMetrics("F13", new Symbol()); fontInfo.addMetrics("F13", new Symbol());
fontInfo.addMetrics("F14", new ZapfDingbats()); fontInfo.addMetrics("F14", new ZapfDingbats());


// fontInfo.addMetrics("F17", new BauerBodoniBoldItalic()); // fontInfo.addMetrics("F17", new BauerBodoniBoldItalic());


/* any is treated as serif */ /* any is treated as serif */
fontInfo.addFontProperties("F5", "any", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "any", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "sans-serif", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "SansSerif", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "SansSerif", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "SansSerif", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "SansSerif", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "SansSerif", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "SansSerif", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "serif", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "serif", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "monospace", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "monospace", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Monospaced", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Monospaced", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Monospaced", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Monospaced", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Monospaced", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Monospaced", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "Helvetica", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Courier", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Courier", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F13", "Symbol", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F5", "any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "SansSerif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "SansSerif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "SansSerif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "SansSerif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "SansSerif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "SansSerif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Monospaced", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Monospaced", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Monospaced", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Monospaced", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Monospaced", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Monospaced", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F13", "Symbol", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);


// Custom type 1 fonts step 2/2 // Custom type 1 fonts step 2/2
// fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL); // fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD); // fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD);


/* for compatibility with PassiveTex */ /* for compatibility with PassiveTex */
fontInfo.addFontProperties("F5", "Times-Roman", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times Roman", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter", fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
"normal", Font.WEIGHT_NORMAL);
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);


// All base 14 configured now, so any custom embedded fonts start from 15
final int startNum = 15;
/* Add configured fonts */ /* Add configured fonts */
addConfiguredFonts(fontInfo, embedList, 15, resolver);
addConfiguredFonts(fontInfo, embedFontInfoList, startNum, resolver);
} }


/** /**
* Add fonts from configuration file starting with internal name F<num>. * Add fonts from configuration file starting with internal name F<num>.
* @param fontInfo the font info object to set up
* @param fontInfoList a list of EmbedFontInfo objects
* @param fontInfo the font info to set up
* @param embedFontInfoList a list of EmbedFontInfo objects
* @param num starting index for internal font numbering * @param num starting index for internal font numbering
* @param resolver the font resolver * @param resolver the font resolver
*/ */
public static void addConfiguredFonts(FontInfo fontInfo, List fontInfoList
, int num, FontResolver resolver) {
if (fontInfoList == null) {
private static void addConfiguredFonts(FontInfo fontInfo,
List/*<EmbedFontInfo>*/ embedFontInfoList, int num, FontResolver resolver) {
if (embedFontInfoList == null) {
return; //No fonts to process return; //No fonts to process
} }


if (resolver == null) { if (resolver == null) {
//Ensure that we have minimal font resolution capabilities //Ensure that we have minimal font resolution capabilities
resolver = createMinimalFontResolver();
resolver = createMinimalFontResolver1();
} }
String internalName = null; String internalName = null;
//FontReader reader = null; //FontReader reader = null;


for (int i = 0; i < fontInfoList.size(); i++) {
EmbedFontInfo configFontInfo = (EmbedFontInfo) fontInfoList.get(i);
for (int i = 0; i < embedFontInfoList.size(); i++) {
EmbedFontInfo embedFontInfo = (EmbedFontInfo)embedFontInfoList.get(i);


String metricsFile = configFontInfo.getMetricsFile();
//String metricsFile = configFontInfo.getMetricsFile();
internalName = "F" + num; internalName = "F" + num;
num++; num++;
/* /*
reader.setFontEmbedPath(configFontInfo.getEmbedFile()); reader.setFontEmbedPath(configFontInfo.getEmbedFile());
fontInfo.addMetrics(internalName, reader.getFont()); fontInfo.addMetrics(internalName, reader.getFont());
*/ */
LazyFont font = new LazyFont(configFontInfo, resolver);
LazyFont font = new LazyFont(embedFontInfo, resolver);
fontInfo.addMetrics(internalName, font); fontInfo.addMetrics(internalName, font);


List triplets = configFontInfo.getFontTriplets();
for (int c = 0; c < triplets.size(); c++) {
FontTriplet triplet = (FontTriplet) triplets.get(c);

List triplets = embedFontInfo.getFontTriplets();
for (int tripletIndex = 0; tripletIndex < triplets.size(); tripletIndex++) {
FontTriplet triplet = (FontTriplet) triplets.get(tripletIndex);
fontInfo.addFontProperties(internalName, triplet); fontInfo.addFontProperties(internalName, triplet);
} }
} }
} }


/** @return a new FontResolver to be used by the font subsystem */ /** @return a new FontResolver to be used by the font subsystem */
public static FontResolver createMinimalFontResolver() {
public static FontResolver createMinimalFontResolver1() {
return new FontResolver() { return new FontResolver() {


/** {@inheritDoc} */ /** {@inheritDoc} */

+ 10
- 3
src/java/org/apache/fop/fonts/FontTriplet.java View File

//This is only a cache //This is only a cache
private transient String key; private transient String key;


/**
* Creates a new font triplet (for base14 use).
* @param name font name
*/
public FontTriplet(String name) {
this.name = name;
}

/** /**
* Creates a new font triplet. * Creates a new font triplet.
* @param name font name * @param name font name
* @param weight font weight (100, 200, 300...800, 900) * @param weight font weight (100, 200, 300...800, 900)
*/ */
public FontTriplet(String name, String style, int weight) { public FontTriplet(String name, String style, int weight) {
this(name, style, weight, 0);
this(name, style, weight, Font.PRIORITY_DEFAULT);
} }


/** /**
* @param priority priority of this triplet/font mapping * @param priority priority of this triplet/font mapping
*/ */
public FontTriplet(String name, String style, int weight, int priority) { public FontTriplet(String name, String style, int weight, int priority) {
this.name = name;
this(name);
this.style = style; this.style = style;
this.weight = weight; this.weight = weight;
this.priority = priority; this.priority = priority;
public String toString() { public String toString() {
return getKey(); return getKey();
} }

} }



+ 19
- 17
src/java/org/apache/fop/fonts/FontUtil.java View File



/** /**
* Removes all white space from a string (used primarily for font names) * Removes all white space from a string (used primarily for font names)
* @param s the string
* @param str the string
* @return the processed result * @return the processed result
*/ */
public static String stripWhiteSpace(String s) {
StringBuffer sb = new StringBuffer(s.length());
for (int i = 0, c = s.length(); i < c; i++) {
final char ch = s.charAt(i);
if (ch != ' '
&& ch != '\r'
&& ch != '\n'
&& ch != '\t') {
sb.append(ch);
public static String stripWhiteSpace(String str) {
if (str != null) {
StringBuffer stringBuffer = new StringBuffer(str.length());
for (int i = 0, strLen = str.length(); i < strLen; i++) {
final char ch = str.charAt(i);
if (ch != ' ' && ch != '\r' && ch != '\n' && ch != '\t') {
stringBuffer.append(ch);
}
} }
return stringBuffer.toString();
} }
return sb.toString();
return str;
} }


/** font constituent names which identify a font as being of "italic" style */ /** font constituent names which identify a font as being of "italic" style */
private static final String[] ITALIC_WORDS = {"italic", "oblique", "inclined"};
private static final String[] ITALIC_WORDS = {
Font.STYLE_ITALIC, Font.STYLE_OBLIQUE, Font.STYLE_INCLINED
};


/** font constituent names which identify a font as being of "light" weight */ /** font constituent names which identify a font as being of "light" weight */
private static final String[] LIGHT_WORDS = {"light"}; private static final String[] LIGHT_WORDS = {"light"};
* @return "normal" or "italic" * @return "normal" or "italic"
*/ */
public static String guessStyle(String fontName) { public static String guessStyle(String fontName) {
for (int i = 0; i < ITALIC_WORDS.length; i++) {
if (fontName.indexOf(ITALIC_WORDS[i]) != -1) {
return Font.STYLE_ITALIC;
if (fontName != null) {
for (int i = 0; i < ITALIC_WORDS.length; i++) {
if (fontName.indexOf(ITALIC_WORDS[i]) != -1) {
return Font.STYLE_ITALIC;
}
} }
} }
return Font.STYLE_NORMAL; return Font.STYLE_NORMAL;
} }
return weight; return weight;
} }
} }

+ 1
- 1
src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java View File

* *
* @param dir directory to search * @param dir directory to search
* @return list of font files * @return list of font files
* @throws IOException io exception
* @throws IOException thrown if an I/O exception of some sort has occurred
*/ */
public List find(String dir) throws IOException { public List find(String dir) throws IOException {
List results = new java.util.ArrayList(); List results = new java.util.ArrayList();

+ 2
- 2
src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java View File



//Full Name usually includes style/weight info so don't use these traits //Full Name usually includes style/weight info so don't use these traits
//If we still want to use these traits, we have to make FontInfo.fontLookup() smarter //If we still want to use these traits, we have to make FontInfo.fontLookup() smarter
triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0));
triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL));
if (!fullName.equals(strippedName)) { if (!fullName.equals(strippedName)) {
triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0));
triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL));
} }
Set familyNames = customFont.getFamilyNames(); Set familyNames = customFont.getFamilyNames();
Iterator iter = familyNames.iterator(); Iterator iter = familyNames.iterator();

+ 149
- 0
src/java/org/apache/fop/fonts/base14/Base14FontCollection.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.base14;

import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontInfo;

/**
* Sets up Base 14 fonts
*/
public class Base14FontCollection implements FontCollection {
private boolean kerning = false;

/**
* Main constructor
*
* @param kerning set to true when font kerning is enabled
*/
public Base14FontCollection(boolean kerning) {
this.kerning = kerning;
}
/**
* {@inheritDoc}
*/
public int setup(int start, FontInfo fontInfo) {
fontInfo.addMetrics("F1", new Helvetica(kerning));
fontInfo.addMetrics("F2", new HelveticaOblique(kerning));
fontInfo.addMetrics("F3", new HelveticaBold(kerning));
fontInfo.addMetrics("F4", new HelveticaBoldOblique(kerning));
fontInfo.addMetrics("F5", new TimesRoman(kerning));
fontInfo.addMetrics("F6", new TimesItalic(kerning));
fontInfo.addMetrics("F7", new TimesBold(kerning));
fontInfo.addMetrics("F8", new TimesBoldItalic(kerning));
fontInfo.addMetrics("F9", new Courier(kerning));
fontInfo.addMetrics("F10", new CourierOblique(kerning));
fontInfo.addMetrics("F11", new CourierBold(kerning));
fontInfo.addMetrics("F12", new CourierBoldOblique(kerning));
fontInfo.addMetrics("F13", new Symbol());
fontInfo.addMetrics("F14", new ZapfDingbats());

// Custom type 1 fonts step 1/2
// fontInfo.addMetrics("F15", new OMEP());
// fontInfo.addMetrics("F16", new GaramondLightCondensed());
// fontInfo.addMetrics("F17", new BauerBodoniBoldItalic());

/* any is treated as serif */
fontInfo.addFontProperties("F5", "any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);

fontInfo.addFontProperties("F1", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F1", "SansSerif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "SansSerif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "SansSerif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "SansSerif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "SansSerif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "SansSerif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Monospaced", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Monospaced", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Monospaced", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Monospaced", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Monospaced", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Monospaced", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);

fontInfo.addFontProperties("F1", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F13", "Symbol", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);

// Custom type 1 fonts step 2/2
// fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD);

/* for compatibility with PassiveTex */
fontInfo.addFontProperties("F5", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
return 15;
}
}

+ 65
- 0
src/java/org/apache/fop/fonts/substitute/AttributeValue.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.substitute;

import java.util.StringTokenizer;

/**
* Encapsulates a font attribute value
*/
public class AttributeValue extends java.util.ArrayList {
private static final long serialVersionUID = 748610847500940557L;

/**
* Returns an <code>AttributeValue</code> object holding the
* value of the specified <code>String</code>.
*
* @param valuesString the value to be parsed
* @return an <code>AttributeValue</code> object holding the value
* represented by the string argument.
*/
public static AttributeValue valueOf(String valuesString) {
AttributeValue attribute = new AttributeValue();
StringTokenizer stringTokenzier = new StringTokenizer(valuesString, ",");
if (stringTokenzier.countTokens() > 1) {
while (stringTokenzier.hasMoreTokens()) {
String token = stringTokenzier.nextToken().trim();
AttributeValue tokenAttribute = AttributeValue.valueOf(token);
attribute.addAll(tokenAttribute);
}
} else {
String token = stringTokenzier.nextToken().trim();
Object value = null;
try {
value = Integer.valueOf(token);
} catch (NumberFormatException ex) {
value = FontWeightRange.valueOf(token);
if (value == null) {
value = token;
}
}
if (value != null) {
attribute.add(value);
}
}
return attribute;
}
}

+ 305
- 0
src/java/org/apache/fop/fonts/substitute/FontQualifier.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.substitute;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;

/**
* Encapsulates a font substitution qualifier
*/
public class FontQualifier {

/** logger instance */
private static Log log = LogFactory.getLog(FontQualifier.class);

/** font family attribute value */
private AttributeValue fontFamilyAttributeValue = null;

/** font style attribute value */
private AttributeValue fontStyleAttributeValue = null;

/** font weight attribute value */
private AttributeValue fontWeightAttributeValue = null;
/**
* Default constructor
*/
public FontQualifier() {
}
/**
* Sets the font family
* @param fontFamily the font family
*/
public void setFontFamily(String fontFamily) {
AttributeValue fontFamilyAttribute = AttributeValue.valueOf(fontFamily);
if (fontFamilyAttribute == null) {
log.error("Invalid font-family value '" + fontFamily + "'");
return;
}
this.fontFamilyAttributeValue = fontFamilyAttribute;
}
/**
* Sets the font style
* @param fontStyle the font style
*/
public void setFontStyle(String fontStyle) {
AttributeValue fontStyleAttribute = AttributeValue.valueOf(fontStyle);
if (fontStyleAttribute != null) {
this.fontStyleAttributeValue = fontStyleAttribute;
}
}

/**
* Sets the font weight
* @param fontWeight the font weight
*/
public void setFontWeight(String fontWeight) {
AttributeValue fontWeightAttribute = AttributeValue.valueOf(fontWeight);
if (fontWeightAttribute != null) {
for (Iterator it = fontWeightAttribute.iterator(); it.hasNext();) {
Object weightObj = it.next();
if (weightObj instanceof String) {
String weightString = ((String)weightObj).trim();
try {
FontUtil.parseCSS2FontWeight(weightString);
} catch (IllegalArgumentException ex) {
log.error("Invalid font-weight value '" + weightString + "'");
return;
}
}
}
this.fontWeightAttributeValue = fontWeightAttribute;
}
}
/**
* @return the font family attribute
*/
public AttributeValue getFontFamily() {
return this.fontFamilyAttributeValue;
}

/**
* @return the font style attribute
*/
public AttributeValue getFontStyle() {
if (fontStyleAttributeValue == null) {
return AttributeValue.valueOf(Font.STYLE_NORMAL);
}
return this.fontStyleAttributeValue;
}
/**
* @return the font weight attribute
*/
public AttributeValue getFontWeight() {
if (fontWeightAttributeValue == null) {
return AttributeValue.valueOf(Integer.toString(Font.WEIGHT_NORMAL));
}
return this.fontWeightAttributeValue;
}

/**
* @return true if this rule has a font weight
*/
public boolean hasFontWeight() {
return this.fontWeightAttributeValue != null;
}

/**
* @return true if this rule has a font style
*/
public boolean hasFontStyle() {
return this.fontStyleAttributeValue != null;
}
/**
* Returns a list of matching font triplet found in a given font info
*
* @param fontInfo the font info
* @return a list of matching font triplets
*/
protected List/*<FontTriplet>*/ match(FontInfo fontInfo) {
AttributeValue fontFamilyValue = getFontFamily();
AttributeValue weightValue = getFontWeight();
AttributeValue styleValue = getFontStyle();

List/*<FontTriplet>*/ matchingTriplets = new java.util.ArrayList/*<FontTriplet>*/();
// try to find matching destination font triplet
for (Iterator attrIt = fontFamilyValue.iterator(); attrIt.hasNext();) {
String fontFamilyString = (String)attrIt.next();
Map/*<FontTriplet>*/ triplets = (Map/*<FontTriplet>*/)fontInfo.getFontTriplets();
if (triplets != null) {
Set/*<FontTriplet>*/ tripletSet = triplets.keySet();
for (Iterator/*<FontTriplet>*/ tripletIt = tripletSet.iterator();
tripletIt.hasNext();) {
FontTriplet triplet = (FontTriplet)tripletIt.next();
String fontName = triplet.getName();
// matched font family name
if (fontFamilyString.toLowerCase().equals(fontName.toLowerCase())) {

// try and match font weight
boolean weightMatched = false;
int fontWeight = triplet.getWeight();
for (Iterator weightIt = weightValue.iterator(); weightIt.hasNext();) {
Object weightObj = weightIt.next();
if (weightObj instanceof FontWeightRange) {
FontWeightRange intRange = (FontWeightRange)weightObj;
if (intRange.isWithinRange(fontWeight)) {
weightMatched = true;
}
} else if (weightObj instanceof String) {
String fontWeightString = (String)weightObj;
int fontWeightValue = FontUtil.parseCSS2FontWeight(
fontWeightString);
if (fontWeightValue == fontWeight) {
weightMatched = true;
}
} else if (weightObj instanceof Integer) {
Integer fontWeightInteger = (Integer)weightObj;
int fontWeightValue = fontWeightInteger.intValue();
if (fontWeightValue == fontWeight) {
weightMatched = true;
}
}
}
// try and match font style
boolean styleMatched = false;
String fontStyleString = triplet.getStyle();
for (Iterator styleIt = styleValue.iterator(); styleIt.hasNext();) {
String style = (String)styleIt.next();
if (fontStyleString.equals(style)) {
styleMatched = true;
}
}
if (weightMatched && styleMatched) {
matchingTriplets.add(triplet);
}
}
}
}
}
return matchingTriplets;
}
/**
* Returns the highest priority matching font triplet found in a given font info
* @param fontInfo the font info
* @return the highest priority matching font triplet
*/
protected FontTriplet bestMatch(FontInfo fontInfo) {
List/*<FontTriplet>*/ matchingTriplets = match(fontInfo);
FontTriplet bestTriplet = null;
if (matchingTriplets.size() == 1) {
bestTriplet = (FontTriplet)matchingTriplets.get(0);
} else {
for (Iterator iterator = matchingTriplets.iterator(); iterator.hasNext();) {
FontTriplet triplet = (FontTriplet)iterator.next();
if (bestTriplet == null) {
bestTriplet = triplet;
} else {
int priority = triplet.getPriority();
if (priority < bestTriplet.getPriority()) {
bestTriplet = triplet;
}
}
}
}
return bestTriplet;
}
/**
* @return a list of font triplets matching this qualifier
*/
public List/*<FontTriplet>*/ getTriplets() {
List/*<FontTriplet>*/ triplets = new java.util.ArrayList/*<FontTriplet>*/();
AttributeValue fontFamilyValue = getFontFamily();
for (Iterator fontFamilyIt = fontFamilyValue.iterator(); fontFamilyIt.hasNext();) {
String name = (String)fontFamilyIt.next();
AttributeValue styleValue = getFontStyle();
for (Iterator styleIt = styleValue.iterator(); styleIt.hasNext();) {
String style = (String)styleIt.next();
AttributeValue weightValue = getFontWeight();
for (Iterator weightIt = weightValue.iterator(); weightIt.hasNext();) {
Object weightObj = weightIt.next();
if (weightObj instanceof FontWeightRange) {
FontWeightRange fontWeightRange = (FontWeightRange)weightObj;
int[] weightRange = fontWeightRange.toArray();
for (int i = 0; i < weightRange.length; i++) {
triplets.add(new FontTriplet(name, style, weightRange[i]));
}
} else if (weightObj instanceof String) {
String weightString = (String)weightObj;
int weight = FontUtil.parseCSS2FontWeight(weightString);
triplets.add(new FontTriplet(name, style, weight));
} else if (weightObj instanceof Integer) {
Integer weightInteger = (Integer)weightObj;
int weight = weightInteger.intValue();
triplets.add(new FontTriplet(name, style, weight));
}
}
}
}
return triplets;
}

/**
* {@inheritDoc}
*/
public String toString() {
String str = new String();
if (fontFamilyAttributeValue != null) {
str += "font-family=" + fontFamilyAttributeValue;
}
if (fontStyleAttributeValue != null) {
if (str.length() > 0) {
str += ", ";
}
str += "font-style=" + fontStyleAttributeValue;
}
if (fontWeightAttributeValue != null) {
if (str.length() > 0) {
str += ", ";
}
str += "font-weight=" + fontWeightAttributeValue;
}
return str;
}
}

+ 61
- 0
src/java/org/apache/fop/fonts/substitute/FontSubstitution.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.substitute;

/**
* Encapsulates a pair of substitution qualifiers
*/
public class FontSubstitution {
private FontQualifier fromQualifier;
private FontQualifier toQualifier;

/**
* Main constructor
*
* @param fromQualifier the substitution from qualifier
* @param toQualifier the substitution to qualifier
*/
public FontSubstitution(FontQualifier fromQualifier, FontQualifier toQualifier) {
this.fromQualifier = fromQualifier;
this.toQualifier = toQualifier;
}

/**
* @return the substitution from qualifier
*/
public FontQualifier getFromQualifier() {
return fromQualifier;
}

/**
* @return the substitution to qualifier
*/
public FontQualifier getToQualifier() {
return toQualifier;
}
/**
* {@inheritDoc}
*/
public String toString() {
return "from=" + fromQualifier + ", to=" + toQualifier;
}
}

+ 66
- 0
src/java/org/apache/fop/fonts/substitute/FontSubstitutions.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.substitute;

import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;

/**
* Font substitutions
*/
public class FontSubstitutions extends java.util.ArrayList/*<Substitutions>*/ {

private static final long serialVersionUID = -9173104935431899722L;

/** logging instance */
protected static Log log = LogFactory.getLog(FontSubstitutions.class);

/**
* Adjusts a given fontInfo using this font substitution catalog
* @param fontInfo font info
*/
public void adjustFontInfo(FontInfo fontInfo) {
for (Iterator/*<FontSubstitution>*/ subsIt = super.iterator(); subsIt.hasNext();) {
FontSubstitution substitution = (FontSubstitution)subsIt.next();
// find the best matching font triplet
FontQualifier toQualifier = substitution.getToQualifier();
FontTriplet fontTriplet = toQualifier.bestMatch(fontInfo);
if (fontTriplet == null) {
log.error("Unable to match font substitution for destination qualifier "
+ toQualifier);
continue;
}
String internalFontKey = fontInfo.getInternalFontKey(fontTriplet);
FontQualifier fromQualifier = substitution.getFromQualifier();
List/*<FontTriplet>*/ tripletList = fromQualifier.getTriplets();
for (Iterator tripletit = tripletList.iterator(); tripletit.hasNext();) {
FontTriplet triplet = (FontTriplet) tripletit.next();
fontInfo.addFontProperties(internalFontKey, triplet);
}
}
}
}

+ 83
- 0
src/java/org/apache/fop/fonts/substitute/FontSubstitutionsConfigurator.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.substitute;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOPException;

/**
* Configures a font substitution catalog
*/
public class FontSubstitutionsConfigurator {

private Configuration cfg = null;

/**
* Main constructor
*
* @param cfg a configuration
*/
public FontSubstitutionsConfigurator(Configuration cfg) {
this.cfg = cfg;
}
private static FontQualifier getQualfierFromConfiguration(Configuration cfg)
throws FOPException {
String fontFamily = cfg.getAttribute("font-family", null);
if (fontFamily == null) {
throw new FOPException("substitution qualifier must have a font-family");
}
FontQualifier qualifier = new FontQualifier();
qualifier.setFontFamily(fontFamily);
String fontWeight = cfg.getAttribute("font-weight", null);
if (fontWeight != null) {
qualifier.setFontWeight(fontWeight);
}
String fontStyle = cfg.getAttribute("font-style", null);
if (fontStyle != null) {
qualifier.setFontStyle(fontStyle);
}
return qualifier;
}
/**
* Configures a font substitution catalog
*
* @param substitutions font substitutions
* @throws FOPException if something's wrong with the config data
*/
public void configure(FontSubstitutions substitutions) throws FOPException {
Configuration[] substitutionCfgs = cfg.getChildren("substitution");
for (int i = 0; i < substitutionCfgs.length; i++) {
Configuration fromCfg = substitutionCfgs[i].getChild("from", false);
if (fromCfg == null) {
throw new FOPException("'substitution' element without child 'from' element");
}
Configuration toCfg = substitutionCfgs[i].getChild("to", false);
if (fromCfg == null) {
throw new FOPException("'substitution' element without child 'to' element");
}
FontQualifier fromQualifier = getQualfierFromConfiguration(fromCfg);
FontQualifier toQualifier = getQualfierFromConfiguration(toCfg);
FontSubstitution substitution = new FontSubstitution(fromQualifier, toQualifier);
substitutions.add(substitution);
}
}
}

+ 115
- 0
src/java/org/apache/fop/fonts/substitute/FontWeightRange.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.fonts.substitute;

import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.FontUtil;

/**
* Encapsulates a range of font weight values
*/
public class FontWeightRange {
/** logging instance */
protected static Log log = LogFactory.getLog("org.apache.fop.render.fonts");

/**
* Returns an <code>FontWeightRange</code> object holding the
* range values of the specified <code>String</code>.
*
* @param weightRangeString the value range string
* @return an <code>FontWeightRange</code> object holding the value ranges
*/
public static FontWeightRange valueOf(String weightRangeString) {
StringTokenizer rangeToken = new StringTokenizer(weightRangeString, "..");
FontWeightRange weightRange = null;
if (rangeToken.countTokens() == 2) {
String weightString = rangeToken.nextToken().trim();
try {
int start = Integer.parseInt(weightString);
if (start % 100 != 0) {
log.error("font-weight start range is not a multiple of 100");
}
int end = Integer.parseInt(rangeToken.nextToken());
if (end % 100 != 0) {
log.error("font-weight end range is not a multiple of 100");
}
if (start <= end) {
weightRange = new FontWeightRange(start, end);
} else {
log.error("font-weight start range is greater than end range");
}
} catch (NumberFormatException e) {
log.error("invalid font-weight value " + weightString);
}
}
return weightRange;
}

/** the start range */
private int start;
/** the end range */
private int end;

/**
* Main constructor
* @param start the start value range
* @param end the end value range
*/
public FontWeightRange(int start, int end) {
this.start = start;
this.end = end;
}
/**
* Returns true if the given integer value is within this integer range
* @param value the integer value
* @return true if the given integer value is within this integer range
*/
public boolean isWithinRange(int value) {
return (value >= start && value <= end);
}
/**
* {@inheritDoc}
*/
public String toString() {
return start + ".." + end;
}

/**
* @return an integer array containing the weight ranges
*/
public int[] toArray() {
int cnt = 0;
for (int i = start; i <= end; i += 100) {
cnt++;
}
int[] range = new int[cnt];
for (int i = 0; i < cnt; i++) {
range[i] = start + (i * 100);
}
return range;
}
}

+ 3
- 1
src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java View File

/** True if this LayoutManager has handled all of its content. */ /** True if this LayoutManager has handled all of its content. */
private boolean bFinished = false; private boolean bFinished = false;
/** child LM and child LM iterator during getNextKnuthElement phase */
/** child LM during getNextKnuthElement phase */
protected LayoutManager curChildLM = null; protected LayoutManager curChildLM = null;
/** child LM iterator during getNextKnuthElement phase */
protected ListIterator childLMiter = null; protected ListIterator childLMiter = null;
private int lastGeneratedPosition = -1; private int lastGeneratedPosition = -1;

+ 2
- 4
src/java/org/apache/fop/render/AbstractRendererConfigurator.java View File

super(); super();
this.userAgent = userAgent; this.userAgent = userAgent;
} }

/** /**
* Returns the configuration subtree for a specific renderer. * Returns the configuration subtree for a specific renderer.
return null; return null;
} }
return getRendererConfig(userAgent, mimeType);
return getRendererConfig(mimeType);
} }


/** /**
* Returns the configuration subtree for a specific renderer. * Returns the configuration subtree for a specific renderer.
* @param userAgent the user agent containing the user configuration
* @param mimeType the MIME type of the renderer * @param mimeType the MIME type of the renderer
* @return the requested configuration subtree, null if there's no configuration * @return the requested configuration subtree, null if there's no configuration
*/ */
public static Configuration getRendererConfig(FOUserAgent userAgent, String mimeType) {
private Configuration getRendererConfig(String mimeType) {
Configuration cfg = userAgent.getFactory().getUserConfig(); Configuration cfg = userAgent.getFactory().getUserConfig();
if (cfg == null) { if (cfg == null) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {

+ 25
- 13
src/java/org/apache/fop/render/PrintRenderer.java View File

import org.apache.fop.fonts.Font; import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.FontTriplet;
import org.w3c.dom.Document; import org.w3c.dom.Document;


protected FontResolver fontResolver = null; protected FontResolver fontResolver = null;


/** list of fonts */ /** list of fonts */
protected List fontList = null;
protected List/*<EmbedFontInfo>*/ embedFontInfoList = null;
/** /**
* adds a font list to current list of fonts
* @param fontInfoList font list
* Adds a font list to current list of fonts
* @param fontList a font info list
*/ */
public void addFontList(List fontInfoList) {
if (this.fontList == null) {
setFontList(fontInfoList);
public void addFontList(List/*<EmbedFontInfo>*/ fontList) {
if (embedFontInfoList == null) {
setFontList(fontList);
} else { } else {
this.fontList.addAll(fontInfoList);
fontList.addAll(fontList);
} }
} }
/** /**
* @param fontList list of available fonts
* @param embedFontInfoList list of available fonts
*/ */
public void setFontList(List fontList) {
this.fontList = fontList;
public void setFontList(List/*<EmbedFontInfo>*/ embedFontInfoList) {
this.embedFontInfoList = embedFontInfoList;
}

/**
* @return list of available embedded fonts
*/
public List/*<EmbedFontInfo>*/ getFontList() {
return this.embedFontInfoList;
} }


/** /**
*/ */
public void setupFontInfo(FontInfo inFontInfo) { public void setupFontInfo(FontInfo inFontInfo) {
this.fontInfo = inFontInfo; this.fontInfo = inFontInfo;
FontSetup.setup(fontInfo, fontList, fontResolver,
userAgent.getFactory().isBase14KerningEnabled());
userAgent.getFactory().getFontManager().setupRenderer(this);
} }


/** /**
} }
return this.fontResolver; return this.fontResolver;
} }
/**
* @return the font info
*/
public FontInfo getFontInfo() {
return this.fontInfo;
}
} }

+ 93
- 67
src/java/org/apache/fop/render/PrintRendererConfigurator.java View File

import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.FontCache; import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil; import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.autodetect.FontFileFinder; import org.apache.fop.fonts.autodetect.FontFileFinder;
public void configure(Renderer renderer) throws FOPException { public void configure(Renderer renderer) throws FOPException {
Configuration cfg = getRendererConfig(renderer); Configuration cfg = getRendererConfig(renderer);
if (cfg == null) { if (cfg == null) {
log.trace("no configuration found for " + renderer);
return; return;
} }


PrintRenderer printRenderer = (PrintRenderer)renderer; PrintRenderer printRenderer = (PrintRenderer)renderer;
FontResolver fontResolver = printRenderer.getFontResolver(); FontResolver fontResolver = printRenderer.getFontResolver();
FopFactory factory = userAgent.getFactory();
FontManager fontManager = factory.getFontManager();
if (fontResolver == null) { if (fontResolver == null) {
//Ensure that we have minimal font resolution capabilities //Ensure that we have minimal font resolution capabilities
fontResolver = FontSetup.createMinimalFontResolver();
fontResolver = FontManager.createMinimalFontResolver();
} }


FopFactory factory = userAgent.getFactory();
boolean strict = factory.validateUserConfigStrictly(); boolean strict = factory.validateUserConfigStrictly();
FontCache fontCache = factory.getFontCache();
FontCache fontCache = fontManager.getFontCache();


List fontInfoList = buildFontListFromConfiguration(cfg,
List/*<EmbedFontInfo>*/ embedFontInfoList = buildFontListFromConfiguration(cfg,
userAgent.getFontBaseURL(), fontResolver, strict, userAgent.getFontBaseURL(), fontResolver, strict,
fontCache); fontCache);
if (fontCache != null && fontCache.hasChanged()) { if (fontCache != null && fontCache.hasChanged()) {
fontCache.save(); fontCache.save();
} }
printRenderer.addFontList(fontInfoList);
printRenderer.addFontList(embedFontInfoList);
} }


/** /**
* @return a List of EmbedFontInfo objects. * @return a List of EmbedFontInfo objects.
* @throws FOPException If an error occurs while processing the configuration * @throws FOPException If an error occurs while processing the configuration
*/ */
public static List buildFontListFromConfiguration(Configuration cfg,
public static List/*<EmbedFontInfo>*/ buildFontListFromConfiguration(Configuration cfg,
String fontBaseURL, FontResolver fontResolver, String fontBaseURL, FontResolver fontResolver,
boolean strict, FontCache fontCache) throws FOPException { boolean strict, FontCache fontCache) throws FOPException {
List fontInfoList = new java.util.ArrayList();
List/*<EmbedFontInfo>*/ fontInfoList
= new java.util.ArrayList/*<EmbedFontInfo>*/();


Configuration fonts = cfg.getChild("fonts", false); Configuration fonts = cfg.getChild("fonts", false);
if (fonts != null) { if (fonts != null) {
// font file (singular) configuration // font file (singular) configuration
Configuration[] font = fonts.getChildren("font"); Configuration[] font = fonts.getChildren("font");
for (int i = 0; i < font.length; i++) { for (int i = 0; i < font.length; i++) {
EmbedFontInfo fontInfo = getFontInfoFromConfiguration(
EmbedFontInfo embedFontInfo = getFontInfoFromConfiguration(
font[i], fontResolver, strict, fontCache); font[i], fontResolver, strict, fontCache);
if (fontInfo != null) {
fontInfoList.add(fontInfo);
if (embedFontInfo != null) {
fontInfoList.add(embedFontInfo);
} }
} }
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Finished font configuration in " log.debug("Finished font configuration in "
+ (System.currentTimeMillis() - start) + "ms"); + (System.currentTimeMillis() - start) + "ms");
/** /**
* Iterates over font file list adding font info to list * Iterates over font file list adding font info to list
* @param fontFileList font file list * @param fontFileList font file list
* @param fontInfoList font info list
* @param embedFontInfoList a configured font info list
* @param resolver font resolver * @param resolver font resolver
*/ */
private static void addFontInfoListFromFileList( private static void addFontInfoListFromFileList(
List fontFileList, List fontInfoList, FontResolver resolver, FontCache fontCache) {
List fontFileList, List/*<EmbedFontInfo>*/ embedFontInfoList,
FontResolver resolver, FontCache fontCache) {
for (Iterator iter = fontFileList.iterator(); iter.hasNext();) { for (Iterator iter = fontFileList.iterator(); iter.hasNext();) {
URL fontUrl = (URL)iter.next(); URL fontUrl = (URL)iter.next();
// parse font to ascertain font info // parse font to ascertain font info
for (int i = 0, c = embedFontInfos.length; i < c; i++) { for (int i = 0, c = embedFontInfos.length; i < c; i++) {
EmbedFontInfo fontInfo = embedFontInfos[i]; EmbedFontInfo fontInfo = embedFontInfos[i];
if (fontInfo != null) { if (fontInfo != null) {
fontInfoList.add(fontInfo);
embedFontInfoList.add(fontInfo);
} }
} }
} }
} }
} }


/**
* Creates a new FontTriplet given a triple Configuration
*
* @param tripletCfg a triplet configuration
* @param strict use strict validation
* @return a font triplet font key
* @throws FOPException thrown if a FOP exception occurs
*/
private static FontTriplet getFontTripletFromConfiguration(
Configuration tripletCfg, boolean strict) throws FOPException {
try {
String name = tripletCfg.getAttribute("name");
if (name == null) {
LogUtil.handleError(log, "font-triplet without name", strict);
return null;
}
String weightStr = tripletCfg.getAttribute("weight");
if (weightStr == null) {
LogUtil.handleError(log, "font-triplet without weight", strict);
return null;
}
int weight = FontUtil.parseCSS2FontWeight(FontUtil.stripWhiteSpace(weightStr));
String style = tripletCfg.getAttribute("style");
if (style == null) {
LogUtil.handleError(log, "font-triplet without style", strict);
return null;
} else {
style = FontUtil.stripWhiteSpace(style);
}
return FontInfo.createFontKey(name, style, weight);
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, strict);
}
return null;
}
/** /**
* Returns a font info from a font node Configuration definition * Returns a font info from a font node Configuration definition
* *
* @param fontResolver font resolver used to resolve font * @param fontResolver font resolver used to resolve font
* @param strict validate configuration strictly * @param strict validate configuration strictly
* @param fontCache the font cache (or null if it is disabled) * @param fontCache the font cache (or null if it is disabled)
* @return font info
* @return the embedded font info
* @throws FOPException if something's wrong with the config data * @throws FOPException if something's wrong with the config data
*/ */
public static EmbedFontInfo getFontInfoFromConfiguration(
private static EmbedFontInfo getFontInfoFromConfiguration(
Configuration fontCfg, FontResolver fontResolver, boolean strict, FontCache fontCache) Configuration fontCfg, FontResolver fontResolver, boolean strict, FontCache fontCache)
throws FOPException { throws FOPException {
String metricsUrl = fontCfg.getAttribute("metrics-url", null); String metricsUrl = fontCfg.getAttribute("metrics-url", null);
String embedUrl = fontCfg.getAttribute("embed-url", null); String embedUrl = fontCfg.getAttribute("embed-url", null);
String subFont = fontCfg.getAttribute("sub-font", null); String subFont = fontCfg.getAttribute("sub-font", null);
if (metricsUrl == null && embedUrl == null) { if (metricsUrl == null && embedUrl == null) {
LogUtil.handleError(log, "Font configuration without metric-url or embed-url", strict);
LogUtil.handleError(log,
"Font configuration without metric-url or embed-url attribute",
strict);
return null; return null;
} }
if (strict) { if (strict) {
} }
} }
} }
boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true);
EmbedFontInfo fontInfo = null;
Configuration[] tripletCfg = fontCfg.getChildren("font-triplet"); Configuration[] tripletCfg = fontCfg.getChildren("font-triplet");
// no font triplet info // no font triplet info
if (tripletCfg.length == 0) { if (tripletCfg.length == 0) {
LogUtil.handleError(log, "font without font-triplet", strict); LogUtil.handleError(log, "font without font-triplet", strict);

// if not strict try to determine font info from the embed/metrics url
File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl}); File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl});
URL fontUrl; URL fontUrl;
try { try {
} else { } else {
return null; return null;
} }
} else {
List tripleList = new java.util.ArrayList();
for (int j = 0; j < tripletCfg.length; j++) {
try {
String name = tripletCfg[j].getAttribute("name");
if (name == null) {
LogUtil.handleError(log, "font-triplet without name", strict);
continue;
}
String weightStr = tripletCfg[j].getAttribute("weight");
if (weightStr == null) {
LogUtil.handleError(log, "font-triplet without weight", strict);
continue;
}
int weight = FontUtil.parseCSS2FontWeight(weightStr);
String style = tripletCfg[j].getAttribute("style");
if (style == null) {
LogUtil.handleError(log, "font-triplet without style", strict);
continue;
}
tripleList.add(FontInfo.createFontKey(name, style, weight));
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, strict);
}
}
fontInfo = new EmbedFontInfo(metricsUrl, useKerning, tripleList, embedUrl, subFont);
if (fontCache != null) {
if (!fontCache.containsFont(fontInfo)) {
fontCache.addFont(fontInfo);
}
}
List/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/();
for (int j = 0; j < tripletCfg.length; j++) {
FontTriplet fontTriplet = getFontTripletFromConfiguration(tripletCfg[j], strict);
tripletList.add(fontTriplet);
}
boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true);
EmbedFontInfo embedFontInfo
= new EmbedFontInfo(metricsUrl, useKerning, tripletList, embedUrl, subFont);
if (fontCache != null) {
if (!fontCache.containsFont(embedFontInfo)) {
fontCache.addFont(embedFontInfo);
} }

if (log.isDebugEnabled()) {
log.debug("Adding font " + fontInfo.getEmbedFile()
+ ", metric file " + fontInfo.getMetricsFile());
for (int j = 0; j < tripleList.size(); ++j) {
FontTriplet triplet = (FontTriplet) tripleList.get(j);
log.debug(" Font triplet "
+ triplet.getName() + ", "
+ triplet.getStyle() + ", "
+ triplet.getWeight());
}
}
} }
return fontInfo;
if (log.isDebugEnabled()) {
String embedFile = embedFontInfo.getEmbedFile();
log.debug("Adding font " + (embedFile != null ? embedFile + ", " : "")
+ "metric file " + embedFontInfo.getMetricsFile());
for (int j = 0; j < tripletList.size(); ++j) {
FontTriplet triplet = (FontTriplet) tripletList.get(j);
log.debug(" Font triplet "
+ triplet.getName() + ", "
+ triplet.getStyle() + ", "
+ triplet.getWeight());
}
}
return embedFontInfo;
} }
} }

+ 2
- 2
src/java/org/apache/fop/render/afp/AFPRenderer.java View File

public void setupFontInfo(FontInfo inFontInfo) { public void setupFontInfo(FontInfo inFontInfo) {
this.fontInfo = inFontInfo; this.fontInfo = inFontInfo;
int num = 1; int num = 1;
if (this.fontList != null && this.fontList.size() > 0) {
for (Iterator it = this.fontList.iterator(); it.hasNext();) {
if (super.embedFontInfoList != null && super.embedFontInfoList.size() > 0) {
for (Iterator it = super.embedFontInfoList.iterator(); it.hasNext();) {
AFPFontInfo afi = (AFPFontInfo)it.next(); AFPFontInfo afi = (AFPFontInfo)it.next();
AFPFont bf = (AFPFont)afi.getAFPFont(); AFPFont bf = (AFPFont)afi.getAFPFont();
for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) { for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) {

+ 181
- 0
src/java/org/apache/fop/render/java2d/Base14FontCollection.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.render.java2d;

import java.awt.Graphics2D;

import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontInfo;

/**
* A base 14 font collection for graphics 2D
*/
public class Base14FontCollection implements FontCollection {

private Graphics2D graphics2d = null;
/**
* Main constructor
* @param graphics2d a graphics 2D
*/
public Base14FontCollection(Graphics2D graphics2d) {
this.graphics2d = graphics2d;
}
/**
* {@inheritDoc}
*/
public int setup(int start, FontInfo fontInfo) {
/*
* available java fonts are:
* Serif - bold, normal, italic, bold-italic
* SansSerif - bold, normal, italic, bold-italic
* MonoSpaced - bold, normal, italic, bold-italic
*/
final int normal = java.awt.Font.PLAIN;
final int bold = java.awt.Font.BOLD;
final int italic = java.awt.Font.ITALIC;
final int bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC;

FontMetricsMapper metric;
metric = new SystemFontMetricsMapper("SansSerif", normal, graphics2d);
// --> goes to F1
fontInfo.addMetrics("F1", metric);
metric = new SystemFontMetricsMapper("SansSerif", italic, graphics2d);
// --> goes to F2
fontInfo.addMetrics("F2", metric);
metric = new SystemFontMetricsMapper("SansSerif", bold, graphics2d);
// --> goes to F3
fontInfo.addMetrics("F3", metric);
metric = new SystemFontMetricsMapper("SansSerif", bolditalic, graphics2d);
// --> goes to F4
fontInfo.addMetrics("F4", metric);


metric = new SystemFontMetricsMapper("Serif", normal, graphics2d);
// --> goes to F5
fontInfo.addMetrics("F5", metric);
metric = new SystemFontMetricsMapper("Serif", italic, graphics2d);
// --> goes to F6
fontInfo.addMetrics("F6", metric);
metric = new SystemFontMetricsMapper("Serif", bold, graphics2d);
// --> goes to F7
fontInfo.addMetrics("F7", metric);
metric = new SystemFontMetricsMapper("Serif", bolditalic, graphics2d);
// --> goes to F8
fontInfo.addMetrics("F8", metric);

metric = new SystemFontMetricsMapper("MonoSpaced", normal, graphics2d);
// --> goes to F9
fontInfo.addMetrics("F9", metric);
metric = new SystemFontMetricsMapper("MonoSpaced", italic, graphics2d);
// --> goes to F10
fontInfo.addMetrics("F10", metric);
metric = new SystemFontMetricsMapper("MonoSpaced", bold, graphics2d);
// --> goes to F11
fontInfo.addMetrics("F11", metric);
metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, graphics2d);
// --> goes to F12
fontInfo.addMetrics("F12", metric);

metric = new SystemFontMetricsMapper("Serif", normal, graphics2d);
//"Symbol" doesn't seem to work here, but "Serif" does the job just fine. *shrug*
// --> goes to F13 and F14
fontInfo.addMetrics("F13", metric);
fontInfo.addMetrics("F14", metric);

// Custom type 1 fonts step 1/2
// fontInfo.addMetrics("F15", new OMEP());
// fontInfo.addMetrics("F16", new GaramondLightCondensed());
// fontInfo.addMetrics("F17", new BauerBodoniBoldItalic());

/* any is treated as serif */
fontInfo.addFontProperties("F5", "any", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "any", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);

fontInfo.addFontProperties("F1", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "serif", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "serif", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "monospace", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);

fontInfo.addFontProperties("F1", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Courier", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F13", "Symbol", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);

// Custom type 1 fonts step 2/2
// fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD);

/* for compatibility with PassiveTex */
fontInfo.addFontProperties("F5", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", Font.STYLE_NORMAL, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_OBLIQUE, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", Font.STYLE_ITALIC, Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
"normal", Font.WEIGHT_NORMAL);
return 15;
}
}

+ 111
- 0
src/java/org/apache/fop/render/java2d/ConfiguredFontCollection.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.render.java2d;

import java.util.List;

import javax.xml.transform.Source;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.render.PrintRenderer;

/**
* A java2d configured font collection
*/
public class ConfiguredFontCollection implements FontCollection {

private static Log log = LogFactory.getLog(ConfiguredFontCollection.class);

private PrintRenderer renderer = null;

/**
* Main constructor
*
* @param renderer a print renderer
*/
public ConfiguredFontCollection(PrintRenderer renderer) {
this.renderer = renderer;
}
/**
* {@inheritDoc}
*/
public int setup(int start, FontInfo fontInfo) {
List/*<EmbedFontInfo>*/ fontList = renderer.getFontList();
FontResolver resolver = renderer.getFontResolver();
int num = start;
if (fontList == null || fontList.size() < 1) {
log.debug("No user configured fonts found.");
return num;
}
if (resolver == null) {
// Ensure that we have minimal font resolution capabilities
resolver = FontManager.createMinimalFontResolver();
}
String internalName = null;

for (int i = 0; i < fontList.size(); i++) {

EmbedFontInfo configFontInfo = (EmbedFontInfo) fontList.get(i);
String fontFile = configFontInfo.getEmbedFile();
internalName = "F" + num;
num++;
try {
FontMetricsMapper font = null;
String metricsUrl = configFontInfo.getMetricsFile();
// If the user specified an XML-based metrics file, we'll use it
// Otherwise, calculate metrics directly from the font file.
if (metricsUrl != null) {
LazyFont fontMetrics = new LazyFont(configFontInfo, resolver);
Source fontSource = resolver.resolve(configFontInfo.getEmbedFile());
font = new CustomFontMetricsMapper(fontMetrics, fontSource);
} else {
CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver);
font = new CustomFontMetricsMapper(fontMetrics);
}

fontInfo.addMetrics(internalName, font);

List triplets = configFontInfo.getFontTriplets();
for (int c = 0; c < triplets.size(); c++) {
FontTriplet triplet = (FontTriplet) triplets.get(c);

if (log.isDebugEnabled()) {
log.debug("Registering: " + triplet + " under " + internalName);
}
fontInfo.addFontProperties(internalName, triplet);
}
} catch (Exception e) {
log.warn("Unable to load custom font from file '" + fontFile + "'", e);
}
}
return num;
}
}

+ 0
- 353
src/java/org/apache/fop/render/java2d/FontSetup.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id$ */

package org.apache.fop.render.java2d;

// FOP
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.util.List;
import java.util.Set;

import javax.xml.transform.Source;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.LazyFont;

/**
* Sets up the Java2D/AWT fonts. It is similar to
* org.apache.fop.render.fonts.FontSetup.
* Assigns the font (with metrics) to internal names like "F1" and
* assigns family-style-weight triplets to the fonts.
*/
public class FontSetup {

/** logging instance */
protected static Log log = LogFactory.getLog(FontSetup.class);

private static final int LAST_PREDEFINED_FONT_NUMBER = 14;

private static final Set HARDCODED_FONT_NAMES;

static {
HARDCODED_FONT_NAMES = new java.util.HashSet();
HARDCODED_FONT_NAMES.add("any");
HARDCODED_FONT_NAMES.add("sans-serif");
HARDCODED_FONT_NAMES.add("serif");
HARDCODED_FONT_NAMES.add("monospace");

HARDCODED_FONT_NAMES.add("Helvetica");
HARDCODED_FONT_NAMES.add("Times");
HARDCODED_FONT_NAMES.add("Courier");
HARDCODED_FONT_NAMES.add("Symbol");
HARDCODED_FONT_NAMES.add("ZapfDingbats");
HARDCODED_FONT_NAMES.add("Times Roman");
HARDCODED_FONT_NAMES.add("Times-Roman");
HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter");
}

/**
* Sets up the font info object.
*
* Adds metrics for basic fonts and useful family-style-weight
* triplets for lookup.
*
* @param fontInfo the font info object to set up
* @param configuredFontList of fop config fonts
* @param resolver for resolving the font file URI
* @param graphics needed for access to font metrics
*/
public static void setup(FontInfo fontInfo, List configuredFontList,
FontResolver resolver, Graphics2D graphics) {
FontMetricsMapper metric;
int normal, bold, bolditalic, italic;

/*
* available java fonts are:
* Serif - bold, normal, italic, bold-italic
* SansSerif - bold, normal, italic, bold-italic
* MonoSpaced - bold, normal, italic, bold-italic
*/
normal = java.awt.Font.PLAIN;
bold = java.awt.Font.BOLD;
italic = java.awt.Font.ITALIC;
bolditalic = java.awt.Font.BOLD + java.awt.Font.ITALIC;

metric = new SystemFontMetricsMapper("SansSerif", normal, graphics);
// --> goes to F1
fontInfo.addMetrics("F1", metric);
metric = new SystemFontMetricsMapper("SansSerif", italic, graphics);
// --> goes to F2
fontInfo.addMetrics("F2", metric);
metric = new SystemFontMetricsMapper("SansSerif", bold, graphics);
// --> goes to F3
fontInfo.addMetrics("F3", metric);
metric = new SystemFontMetricsMapper("SansSerif", bolditalic, graphics);
// --> goes to F4
fontInfo.addMetrics("F4", metric);


metric = new SystemFontMetricsMapper("Serif", normal, graphics);
// --> goes to F5
fontInfo.addMetrics("F5", metric);
metric = new SystemFontMetricsMapper("Serif", italic, graphics);
// --> goes to F6
fontInfo.addMetrics("F6", metric);
metric = new SystemFontMetricsMapper("Serif", bold, graphics);
// --> goes to F7
fontInfo.addMetrics("F7", metric);
metric = new SystemFontMetricsMapper("Serif", bolditalic, graphics);
// --> goes to F8
fontInfo.addMetrics("F8", metric);

metric = new SystemFontMetricsMapper("MonoSpaced", normal, graphics);
// --> goes to F9
fontInfo.addMetrics("F9", metric);
metric = new SystemFontMetricsMapper("MonoSpaced", italic, graphics);
// --> goes to F10
fontInfo.addMetrics("F10", metric);
metric = new SystemFontMetricsMapper("MonoSpaced", bold, graphics);
// --> goes to F11
fontInfo.addMetrics("F11", metric);
metric = new SystemFontMetricsMapper("MonoSpaced", bolditalic, graphics);
// --> goes to F12
fontInfo.addMetrics("F12", metric);

metric = new SystemFontMetricsMapper("Serif", normal, graphics);
//"Symbol" doesn't seem to work here, but "Serif" does the job just fine. *shrug*
// --> goes to F13 and F14
fontInfo.addMetrics("F13", metric);
fontInfo.addMetrics("F14", metric);

// Custom type 1 fonts step 1/2
// fontInfo.addMetrics("F15", new OMEP());
// fontInfo.addMetrics("F16", new GaramondLightCondensed());
// fontInfo.addMetrics("F17", new BauerBodoniBoldItalic());

/* any is treated as serif */
fontInfo.addFontProperties("F5", "any", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "any", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "any", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "any", "oblique", Font.WEIGHT_BOLD);

fontInfo.addFontProperties("F1", "sans-serif", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "serif", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "serif", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "serif", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "serif", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "monospace", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "monospace", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "monospace", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "monospace", "italic", Font.WEIGHT_BOLD);

fontInfo.addFontProperties("F1", "Helvetica", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Courier", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F10", "Courier", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F11", "Courier", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F12", "Courier", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F13", "Symbol", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", Font.WEIGHT_NORMAL);

// Custom type 1 fonts step 2/2
// fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F16", "Garamond-LightCondensed", "normal", FontInfo.NORMAL);
// fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD);

/* for compatibility with PassiveTex */
fontInfo.addFontProperties("F5", "Times-Roman", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F5", "Times Roman", "normal", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "oblique", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "italic", Font.WEIGHT_NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", "normal", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "oblique", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.WEIGHT_BOLD);
fontInfo.addFontProperties("F9", "Computer-Modern-Typewriter",
"normal", Font.WEIGHT_NORMAL);

int lastNum = configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1);
addConfiguredFonts(fontInfo, configuredFontList, resolver, lastNum++);
}

private static int configureInstalledAWTFonts(FontInfo fontInfo, Graphics2D graphics,
int startNumber) {
int num = startNumber;
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();

java.awt.Font[] fonts = env.getAllFonts();
for (int i = 0; i < fonts.length; i++) {
java.awt.Font f = fonts[i];
if (HARDCODED_FONT_NAMES.contains(f.getName())) {
continue; //skip
}

if (log.isTraceEnabled()) {
log.trace("AWT Font: " + f.getFontName()
+ ", family: " + f.getFamily()
+ ", PS: " + f.getPSName()
+ ", Name: " + f.getName()
+ ", Angle: " + f.getItalicAngle()
+ ", Style: " + f.getStyle());
}

String searchName = FontUtil.stripWhiteSpace(f.getName()).toLowerCase();
String guessedStyle = FontUtil.guessStyle(searchName);
int guessedWeight = FontUtil.guessWeight(searchName);

num++;
String fontKey = "F" + num;
int style = convertToAWTFontStyle(guessedStyle, guessedWeight);
addFontMetricsMapper(fontInfo, f.getName(), fontKey, graphics, style);

//Register appropriate font triplets matching the font. Two different strategies:
//Example: "Arial Bold", normal, normal
addFontTriplet(fontInfo, f.getName(),
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, fontKey);
if (!f.getName().equals(f.getFamily())) {
//Example: "Arial", bold, normal
addFontTriplet(fontInfo, f.getFamily(),
guessedStyle, guessedWeight, fontKey);
}
}
return num;

}

/**
* Add fonts from configuration file starting with internal name F<num>.
*
* @param fontInfo the font info object to set up
* @param fontList a list of EmbedFontInfo objects
* @param num starting index for internal font numbering
* @param resolver the font resolver
*/
private static void addConfiguredFonts(FontInfo fontInfo, List fontList, FontResolver resolver, int num) {

if (fontList == null || fontList.size() < 1) {
log.debug("No user configured fonts found.");
return;
}
if (resolver == null) {
// Ensure that we have minimal font resolution capabilities
resolver = org.apache.fop.fonts.FontSetup
.createMinimalFontResolver();
}
String internalName = null;

for (int i = 0; i < fontList.size(); i++) {

EmbedFontInfo configFontInfo = (EmbedFontInfo) fontList.get(i);
String fontFile = configFontInfo.getEmbedFile();
internalName = "F" + num;
num++;
try {
FontMetricsMapper font = null;
String metricsUrl = configFontInfo.getMetricsFile();
// If the user specified an XML-based metrics file, we'll use it
// Otherwise, calculate metrics directly from the font file.
if (metricsUrl != null) {
LazyFont fontMetrics = new LazyFont(configFontInfo, resolver);
Source fontSource = resolver.resolve(configFontInfo.getEmbedFile());
font = new CustomFontMetricsMapper(fontMetrics, fontSource);
} else {
CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver);
font = new CustomFontMetricsMapper(fontMetrics);
}

fontInfo.addMetrics(internalName, font);

List triplets = configFontInfo.getFontTriplets();
for (int c = 0; c < triplets.size(); c++) {
FontTriplet triplet = (FontTriplet) triplets.get(c);

if (log.isDebugEnabled()) {
log.debug("Registering: " + triplet + " under " + internalName);
}
fontInfo.addFontProperties(internalName, triplet);
}
} catch (Exception e) {
log.warn("Unable to load custom font from file '" + fontFile + "'", e);
}
}
}


private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle,
int fontWeight, String fontKey) {
FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight);
fontInfo.addFontProperties(fontKey, triplet);
}

private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey,
Graphics2D graphics, int style) {
FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics);
fontInfo.addMetrics(fontKey, metric);
}

private static int convertToAWTFontStyle(String fontStyle, int fontWeight) {
int style = java.awt.Font.PLAIN;
if (fontWeight >= Font.WEIGHT_BOLD) {
style |= java.awt.Font.BOLD;
}
if (!"normal".equals(fontStyle)) {
style |= java.awt.Font.ITALIC;
}
return style;
}

}


+ 138
- 0
src/java/org/apache/fop/render/java2d/InstalledFontCollection.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.render.java2d;

import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;

/**
* A custom AWT font collection
*/
public class InstalledFontCollection implements FontCollection {

private static Log log = LogFactory.getLog(InstalledFontCollection.class);

private static final Set HARDCODED_FONT_NAMES;

static {
HARDCODED_FONT_NAMES = new java.util.HashSet();
HARDCODED_FONT_NAMES.add("any");
HARDCODED_FONT_NAMES.add("sans-serif");
HARDCODED_FONT_NAMES.add("serif");
HARDCODED_FONT_NAMES.add("monospace");

HARDCODED_FONT_NAMES.add("Helvetica");
HARDCODED_FONT_NAMES.add("Times");
HARDCODED_FONT_NAMES.add("Courier");
HARDCODED_FONT_NAMES.add("Symbol");
HARDCODED_FONT_NAMES.add("ZapfDingbats");
HARDCODED_FONT_NAMES.add("Times Roman");
HARDCODED_FONT_NAMES.add("Times-Roman");
HARDCODED_FONT_NAMES.add("Computer-Modern-Typewriter");
}

private Graphics2D graphics2D = null;

/**
* Main constructor
*
* @param graphics2D a graphics 2D
*/
public InstalledFontCollection(Graphics2D graphics2D) {
this.graphics2D = graphics2D;
}
/**
* {@inheritDoc}
*/
public int setup(int start, FontInfo fontInfo) {
int num = start;
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();

java.awt.Font[] fonts = env.getAllFonts();
for (int i = 0; i < fonts.length; i++) {
java.awt.Font f = fonts[i];
if (HARDCODED_FONT_NAMES.contains(f.getName())) {
continue; //skip
}

if (log.isTraceEnabled()) {
log.trace("AWT Font: " + f.getFontName()
+ ", family: " + f.getFamily()
+ ", PS: " + f.getPSName()
+ ", Name: " + f.getName()
+ ", Angle: " + f.getItalicAngle()
+ ", Style: " + f.getStyle());
}

String searchName = FontUtil.stripWhiteSpace(f.getName()).toLowerCase();
String guessedStyle = FontUtil.guessStyle(searchName);
int guessedWeight = FontUtil.guessWeight(searchName);

num++;
String fontKey = "F" + num;
int style = convertToAWTFontStyle(guessedStyle, guessedWeight);
addFontMetricsMapper(fontInfo, f.getName(), fontKey, graphics2D, style);

//Register appropriate font triplets matching the font. Two different strategies:
//Example: "Arial Bold", normal, normal
addFontTriplet(fontInfo, f.getName(),
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, fontKey);
if (!f.getName().equals(f.getFamily())) {
//Example: "Arial", bold, normal
addFontTriplet(fontInfo, f.getFamily(),
guessedStyle, guessedWeight, fontKey);
}
}
return num;
}

private static void addFontTriplet(FontInfo fontInfo, String fontName, String fontStyle,
int fontWeight, String fontKey) {
FontTriplet triplet = FontInfo.createFontKey(fontName, fontStyle, fontWeight);
fontInfo.addFontProperties(fontKey, triplet);
}

private static void addFontMetricsMapper(FontInfo fontInfo, String family, String fontKey,
Graphics2D graphics, int style) {
FontMetricsMapper metric = new SystemFontMetricsMapper(family, style, graphics);
fontInfo.addMetrics(fontKey, metric);
}

private static int convertToAWTFontStyle(String fontStyle, int fontWeight) {
int style = java.awt.Font.PLAIN;
if (fontWeight >= Font.WEIGHT_BOLD) {
style |= java.awt.Font.BOLD;
}
if (!"normal".equals(fontStyle)) {
style |= java.awt.Font.ITALIC;
}
return style;
}
}

+ 5
- 4
src/java/org/apache/fop/render/java2d/Java2DRenderer.java View File

public void setupFontInfo(FontInfo inFontInfo) { public void setupFontInfo(FontInfo inFontInfo) {
//Don't call super.setupFontInfo() here! Java2D needs a special font setup //Don't call super.setupFontInfo() here! Java2D needs a special font setup
// create a temp Image to test font metrics on // create a temp Image to test font metrics on
fontInfo = inFontInfo;
this.fontInfo = inFontInfo;
BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage fontImage = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_RGB); BufferedImage.TYPE_INT_RGB);
Graphics2D g = fontImage.createGraphics();
Graphics2D graphics2D = fontImage.createGraphics();
//The next line is important to get accurate font metrics! //The next line is important to get accurate font metrics!
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON); RenderingHints.VALUE_FRACTIONALMETRICS_ON);
FontSetup.setup(fontInfo, fontList, fontResolver, g);
userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D);
} }


/** {@inheritDoc} */ /** {@inheritDoc} */

+ 4
- 4
src/java/org/apache/fop/render/pcl/PCLRenderer.java View File

import org.apache.fop.render.RendererContextConstants; import org.apache.fop.render.RendererContextConstants;
import org.apache.fop.render.RendererEventProducer; import org.apache.fop.render.RendererEventProducer;
import org.apache.fop.render.java2d.FontMetricsMapper; import org.apache.fop.render.java2d.FontMetricsMapper;
import org.apache.fop.render.java2d.FontSetup;
import org.apache.fop.render.java2d.Java2DRenderer; import org.apache.fop.render.java2d.Java2DRenderer;
import org.apache.fop.render.pcl.extensions.PCLElementMapping; import org.apache.fop.render.pcl.extensions.PCLElementMapping;
import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.BorderProps;
fontInfo = inFontInfo; fontInfo = inFontInfo;
BufferedImage fontImage = new BufferedImage(100, 100, BufferedImage fontImage = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_RGB); BufferedImage.TYPE_INT_RGB);
Graphics2D g = fontImage.createGraphics();
Graphics2D graphics2D = fontImage.createGraphics();
//The next line is important to get accurate font metrics! //The next line is important to get accurate font metrics!
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON); RenderingHints.VALUE_FRACTIONALMETRICS_ON);
FontSetup.setup(fontInfo, fontList, fontResolver, g);
userAgent.getFactory().getFontManager().setupRenderer(this, graphics2D);
} }


/** /**

+ 1
- 1
src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java View File

if (!isTextStroked()) { if (!isTextStroked()) {
FontInfo fontInfo = new FontInfo(); FontInfo fontInfo = new FontInfo();
//TODO Do custom font configuration here somewhere/somehow //TODO Do custom font configuration here somewhere/somehow
FontSetup.setup(fontInfo, null, null);
FontSetup.setup(fontInfo);
graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo));
} }



+ 1
- 1
src/java/org/apache/fop/render/ps/NativeTextHandler.java View File

private void setupFontInfo() { private void setupFontInfo() {
//Sets up a FontInfo with default fonts //Sets up a FontInfo with default fonts
fontInfo = new FontInfo(); fontInfo = new FontInfo();
FontSetup.setup(fontInfo, null, null);
FontSetup.setup(fontInfo);
} }
/** /**

+ 1
- 1
src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java View File

if (fontInfo == null) { if (fontInfo == null) {
//Default minimal fonts //Default minimal fonts
FontInfo fontInfo = new FontInfo(); FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, null, null);
FontSetup.setup(fontInfo);
setFontInfo(fontInfo); setFontInfo(fontInfo);
} }
} }

+ 8
- 4
src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java View File

import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOPException;
import org.apache.fop.fonts.FontCache; import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver; import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontSetup;
import org.apache.fop.pdf.PDFDocument; import org.apache.fop.pdf.PDFDocument;
//Fonts //Fonts
try { try {
FontResolver fontResolver = FontSetup.createMinimalFontResolver();
FontResolver fontResolver = FontManager.createMinimalFontResolver();
//TODO The following could be optimized by retaining the FontCache somewhere //TODO The following could be optimized by retaining the FontCache somewhere
FontCache fontCache = FontCache.load(); FontCache fontCache = FontCache.load();
if (fontCache == null) { if (fontCache == null) {
fontCache = new FontCache(); fontCache = new FontCache();
} }
List fontList = PrintRendererConfigurator.buildFontListFromConfiguration(
cfg, null, fontResolver, false, fontCache);
//TODO Provide fontBaseURL to this method call
final String fontBaseURL = null;
List/*<EmbedFontInfo>*/ embedFontInfoList
= PrintRendererConfigurator.buildFontListFromConfiguration(
cfg, fontBaseURL, fontResolver, false, fontCache);
fontCache.save(); fontCache.save();
FontInfo fontInfo = new FontInfo(); FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, fontList, fontResolver);
FontSetup.setup(fontInfo, embedFontInfoList, fontResolver);
graphics.setFontInfo(fontInfo); graphics.setFontInfo(fontInfo);
} catch (FOPException e) { } catch (FOPException e) {
throw new ConfigurationException("Error while setting up fonts", e); throw new ConfigurationException("Error while setting up fonts", e);

+ 1
- 1
src/java/org/apache/fop/svg/PDFGraphics2D.java View File

preparePainting(); preparePainting();


FontInfo specialFontInfo = new FontInfo(); FontInfo specialFontInfo = new FontInfo();
FontSetup.setup(specialFontInfo, null, null);
FontSetup.setup(specialFontInfo);


PDFResources res = pdfDoc.getFactory().makeResources(); PDFResources res = pdfDoc.getFactory().makeResources();
PDFResourceContext context = new PDFResourceContext(res); PDFResourceContext context = new PDFResourceContext(res);

+ 4
- 0
status.xml View File

<action context="Renderers" dev="AC" importance="high" type="add"> <action context="Renderers" dev="AC" importance="high" type="add">
Added SVG support for AFP (GOCA). Added SVG support for AFP (GOCA).
</action --> </action -->
<action context="Fonts" dev="AC" type="add">
Add support for font substitution.
</action>
<action context="Code" dev="AD" type="fix" fixed-bug="44203">
<action context="Renderers" dev="JM" type="fix" fixes-bug="43650"> <action context="Renderers" dev="JM" type="fix" fixes-bug="43650">
PCL Renderer: Improved page format selection so it doesn't interfere with PCL Renderer: Improved page format selection so it doesn't interfere with
duplex printing. duplex printing.

+ 33
- 0
test/config/test_fonts_substitution.xconf View File

<?xml version="1.0"?>
<fop version="1.0">
<!-- Strict configuration On -->
<strict-configuration>true</strict-configuration>

<!-- Switch off font caching for the purposes of the unit test -->
<use-cache>false</use-cache>

<!-- Base URL for resolving relative URLs -->
<base>./</base>

<!-- Font Base URL for resolving relative font URLs -->
<font-base>./</font-base>
<fonts>
<substitutions>
<substitution>
<from font-family="Times" font-style="italic"/>
<to font-family="Gladiator" font-style="normal" font-weight="bold"/>
</substitution>
</substitutions>
</fonts>

<renderers>
<renderer mime="application/pdf">
<fonts>
<font metrics-url="test/resources/fonts/glb12.ttf.xml" embed-url="test/resources/fonts/glb12.ttf">
<font-triplet name="Gladiator" style="normal" weight="bold"/>
</font>
</fonts>
</renderer>
</renderers>
</fop>

+ 1
- 1
test/java/org/apache/fop/config/BaseUserConfigTestCase.java View File

final File baseDir = getBaseDir(); final File baseDir = getBaseDir();
final String fontFOFilePath = getFontFOFilePath(); final String fontFOFilePath = getFontFOFilePath();
File foFile = new File(baseDir, fontFOFilePath); File foFile = new File(baseDir, fontFOFilePath);
final boolean dumpOutput = false;
final boolean dumpOutput = true;
FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
convertFO(foFile, foUserAgent, dumpOutput); convertFO(foFile, foUserAgent, dumpOutput);
} }

+ 63
- 0
test/java/org/apache/fop/config/FontsSubstitutionTestCase.java View File

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/* $Id: $ */

package org.apache.fop.config;

import java.io.File;

import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.render.PrintRenderer;

public class FontsSubstitutionTestCase extends BaseConstructiveUserConfigTestCase {

public FontsSubstitutionTestCase(String name) {
super(name);
}

/**
* {@inheritDoc}
*/
protected byte[] convertFO(File foFile, FOUserAgent ua, boolean dumpPdfFile) throws Exception {
PrintRenderer renderer = (PrintRenderer)ua.getRendererFactory().createRenderer(ua, MimeConstants.MIME_PDF);
FontInfo fontInfo = new FontInfo();
renderer.setupFontInfo(fontInfo);
FontManager fontManager = ua.getFactory().getFontManager();
fontManager.setupRenderer(renderer);
FontTriplet triplet = new FontTriplet("Times", "italic", Font.WEIGHT_NORMAL);
String internalFontKey = fontInfo.getInternalFontKey(triplet);
// Times italic should now be mapped to the 15th font (custom font)
// not the original base 14 (F6)
if (!"F15".equals(internalFontKey)) {
throw new Exception("font substitution failed :" + triplet);
}
return null;
}

/**
* {@inheritDoc}
*/
public String getUserConfigFilename() {
return "test_fonts_substitution.xconf";
}
}

+ 1
- 0
test/java/org/apache/fop/config/UserConfigTestSuite.java View File

suite.addTest(new TestSuite(FontEmbedUrlMalformedTestCase.class)); suite.addTest(new TestSuite(FontEmbedUrlMalformedTestCase.class));
suite.addTest(new TestSuite(FontsDirectoryRecursiveTestCase.class)); suite.addTest(new TestSuite(FontsDirectoryRecursiveTestCase.class));
suite.addTest(new TestSuite(FontsAutoDetectTestCase.class)); suite.addTest(new TestSuite(FontsAutoDetectTestCase.class));
suite.addTest(new TestSuite(FontsSubstitutionTestCase.class));
//$JUnit-END$ //$JUnit-END$
return suite; return suite;
} }

+ 2
- 2
test/java/org/apache/fop/layoutengine/LayoutEngineTester.java View File

*/ */
public LayoutEngineTester(File areaTreeBackupDir) { public LayoutEngineTester(File areaTreeBackupDir) {
this.areaTreeBackupDir = areaTreeBackupDir; this.areaTreeBackupDir = areaTreeBackupDir;
fopFactory.setBase14KerningEnabled(false);
fopFactoryWithBase14Kerning.setBase14KerningEnabled(true);
fopFactory.getFontManager().setBase14KerningEnabled(false);
fopFactoryWithBase14Kerning.getFontManager().setBase14KerningEnabled(true);
} }
private Templates getTestcase2FOStylesheet() throws TransformerConfigurationException { private Templates getTestcase2FOStylesheet() throws TransformerConfigurationException {

+ 1
- 1
test/java/org/apache/fop/render/pdf/BasePDFTestCase.java View File

} }
} }


private static Exception extractOriginalException(Exception e) {
protected static Exception extractOriginalException(Exception e) {
if (e.getCause() != null) { if (e.getCause() != null) {
return extractOriginalException((Exception)e.getCause()); return extractOriginalException((Exception)e.getCause());
} else if (e instanceof SAXException) { } else if (e instanceof SAXException) {

+ 4
- 4
test/java/org/apache/fop/render/pdf/PDFAConformanceTestCase.java View File

* @return an initialized FOUserAgent * @return an initialized FOUserAgent
* */ * */
protected FOUserAgent getUserAgent() { protected FOUserAgent getUserAgent() {
final FOUserAgent a = fopFactory.newFOUserAgent();
a.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");
return a;
final FOUserAgent userAgent = fopFactory.newFOUserAgent();
userAgent.getRendererOptions().put("pdf-a-mode", "PDF/A-1b");
return userAgent;
} }
/** /**
//Good! //Good!
} }
} }
} }

Loading…
Cancel
Save