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

@@ -201,17 +201,20 @@
support fonts. These fonts will then automatically be registered.
</p>
<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>
Review the documentation for <a href="configuration.html">FOP Configuration</a>
for instructions on making the FOP configuration available to FOP when it runs.
@@ -318,23 +321,25 @@
<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>
<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>
<li>
URLs are used to access the font metric and font files.
@@ -359,7 +364,7 @@
<!--note>Cocoon users will need to setup the config, see FOPSerializer for more information.</note-->
</section>
<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>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
@@ -385,6 +390,30 @@
<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>
</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
<section id="embedding-base14">
<title>Explicitly embedding the base 14 fonts</title>

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

@@ -59,6 +59,34 @@ public class FOURIResolver implements javax.xml.transform.URIResolver {
/** true if exceptions are to be thrown if the URIs cannot be resolved. */
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
*/

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

@@ -147,7 +147,7 @@ public class FOUserAgent {
}
this.factory = factory;
setBaseURL(factory.getBaseURL());
setFontBaseURL(factory.getFontBaseURL());
setFontBaseURL(factory.getFontManager().getFontBaseURL());
setTargetResolution(factory.getTargetResolution());
}

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

@@ -24,7 +24,6 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
@@ -45,6 +44,7 @@ import org.apache.xmlgraphics.image.loader.ImageManager;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.hyphenation.HyphenationTreeResolver;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
import org.apache.fop.render.RendererFactory;
@@ -84,6 +84,9 @@ public class FopFactory implements ImageContext {
/** Image manager for loading and caching image objects */
private ImageManager imageManager;

/** Font manager for font substitution, autodetection and caching **/
private FontManager fontManager;
/** Configuration layer used to configure fop */
private FopFactoryConfigurator config = null;
@@ -93,9 +96,6 @@ public class FopFactory implements ImageContext {
*/
private String base = null;

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

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

@@ -113,12 +113,6 @@ public class FopFactory implements ImageContext {
*/
private boolean strictUserConfigValidation
= 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 */
private float sourceResolution = FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION;
@@ -155,7 +149,6 @@ public class FopFactory implements ImageContext {
this.rendererFactory = new RendererFactory();
this.xmlHandlers = new XMLHandlerRegistry();
this.ignoredNamespaces = new java.util.HashSet();
setUseCache(FopFactoryConfigurator.DEFAULT_USE_CACHE);
}
/**
@@ -317,42 +310,14 @@ public class FopFactory implements ImageContext {
public LayoutManagerMaker getLayoutManagerMakerOverride() {
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.
* @param base base URL
* @param base the base URL
* @throws MalformedURLException if there's a problem with a file URL
*/
public void setBaseURL(String base) throws MalformedURLException {
this.base = checkBaseURL(base);
this.base = foURIResolver.checkBaseURL(base);
}

/**
@@ -367,14 +332,18 @@ public class FopFactory implements ImageContext {
* Sets the font base URL.
* @param fontBase font base 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 {
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() {
return this.fontBase;
return getFontManager().getFontBaseURL();
}

/** @return the hyphen base URL */
@@ -396,7 +365,7 @@ public class FopFactory implements ImageContext {
}
});
}
this.hyphenBase = checkBaseURL(hyphenBase);
this.hyphenBase = foURIResolver.checkBaseURL(hyphenBase);
}
/**
@@ -416,6 +385,14 @@ public class FopFactory implements ImageContext {
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. */
public HyphenationTreeResolver getHyphenationTreeResolver() {
return this.hyphResolver;
@@ -471,17 +448,21 @@ public class FopFactory implements ImageContext {
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() {
return this.enableBase14Kerning;
return getFontManager().isBase14KerningEnabled();
}
/**
* Controls whether kerning is activated on base 14 fonts.
* @param value true if kerning should be activated
* @deprecated use getFontManager().setBase14KerningEnabled(boolean) instead
*/
public void setBase14KerningEnabled(boolean value) {
this.enableBase14Kerning = value;
getFontManager().setBase14KerningEnabled(value);
}
/** @return the resolution for resolution-dependant input */
@@ -681,37 +662,44 @@ public class FopFactory implements ImageContext {
return this.strictUserConfigValidation;
}

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

/**
* Whether or not to cache results of font triplet detection/auto-config
* @param useCache use cache or not
* @deprecated use getFontManager().setUseCache(boolean) instead
*/
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?
* @return whether this factory is uses the cache
* @deprecated use getFontManager().useCache() instead
*/
public boolean useCache() {
return (this.fontCache != null);
return getFontManager().useCache();
}

/**
* Returns the font cache instance used by this factory.
* @return the font cache
* @deprecated use getFontManager().getFontCache() instead
*/
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

@@ -28,6 +28,8 @@ import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
import org.apache.commons.logging.Log;
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.xml.sax.SAXException;

@@ -57,9 +59,6 @@ public class FopFactoryConfigurator {
/** Defines the default target resolution (72dpi) for FOP */
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 */
private final Log log = LogFactory.getLog(FopFactoryConfigurator.class);

@@ -119,14 +118,6 @@ public class FopFactoryConfigurator {
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) {
try {
factory.setHyphenBaseURL(
@@ -180,15 +171,10 @@ public class FopFactoryConfigurator {
}
}

// 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

@@ -0,0 +1,82 @@
/*
* 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

@@ -36,14 +36,15 @@ public class EmbedFontInfo implements Serializable {
protected String embedFile;
/** false, to disable kerning */
protected boolean kerning;
/** the list of associated font triplets */
protected List fontTriplets;
/** the PostScript name of the font */
protected String postScriptName = null;
/** the sub-fontname of the font (used for TrueType Collections, null otherwise) */
protected String subFontName = null;

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

/**
* Main constructor
* @param metricsFile Path to the xml file containing font metrics
@@ -53,7 +54,7 @@ public class EmbedFontInfo implements Serializable {
* @param subFontName the sub-fontname used for TrueType Collections (null otherwise)
*/
public EmbedFontInfo(String metricsFile, boolean kerning,
List fontTriplets, String embedFile, String subFontName) {
List/*<FontTriplet>*/ fontTriplets, String embedFile, String subFontName) {
this.metricsFile = metricsFile;
this.embedFile = embedFile;
this.kerning = kerning;
@@ -84,19 +85,11 @@ public class EmbedFontInfo implements Serializable {
public boolean getKerning() {
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.
* @return the sub-fontname (or null)
* @return the sub-font name (or null)
*/
public String getSubFontName() {
return this.subFontName;
@@ -118,10 +111,20 @@ public class EmbedFontInfo implements Serializable {
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() {
return "metrics-url=" + metricsFile + ",embed-url=" + embedFile
+ ", kerning=" + kerning + ", font-triplet=" + fontTriplets
+ ", kerning=" + kerning + ", " + "font-triplet=" + fontTriplets
+ (getSubFontName() != null ? ", sub-font=" + getSubFontName() : "");
}
}

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

@@ -48,9 +48,18 @@ public class Font {
/** Italic font style */
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 */
public static final FontTriplet DEFAULT_FONT = new FontTriplet(
"any", STYLE_NORMAL, WEIGHT_NORMAL);
"any", STYLE_NORMAL, WEIGHT_NORMAL, PRIORITY_DEFAULT);

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

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

@@ -59,6 +59,7 @@ public final class FontCache implements Serializable {
/** font cache file path */
private static final String DEFAULT_CACHE_FILENAME = "fop-fonts.cache";

/** has this cache been changed since it was last read? */
private transient boolean changed = false;
@@ -67,10 +68,10 @@ public final class FontCache implements Serializable {
/** master mapping of font url -> font info. This needs to be
* 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) */
private Map failedFontMap = new java.util.HashMap();
private Map failedFontMap/*<String, Long>*/ = null;

/**
* Default constructor
@@ -221,7 +222,7 @@ public final class FontCache implements Serializable {
*/
public boolean containsFont(String embedUrl) {
if (embedUrl != null) {
return fontfileMap.containsKey(embedUrl);
return getFontFileMap().containsKey(embedUrl);
}
return false;
}
@@ -233,7 +234,7 @@ public final class FontCache implements Serializable {
*/
public boolean containsFont(EmbedFontInfo fontInfo) {
if (fontInfo != null) {
return fontfileMap.containsKey(getCacheKey(fontInfo));
return getFontFileMap().containsKey(getCacheKey(fontInfo));
}
return false;
}
@@ -268,6 +269,13 @@ public final class FontCache implements Serializable {
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
* @param fontInfo font info
@@ -277,7 +285,7 @@ public final class FontCache implements Serializable {
synchronized (changeLock) {
CachedFontFile cachedFontFile;
if (containsFont(cacheKey)) {
cachedFontFile = (CachedFontFile)fontfileMap.get(cacheKey);
cachedFontFile = (CachedFontFile)getFontFileMap().get(cacheKey);
if (!cachedFontFile.containsFont(fontInfo)) {
cachedFontFile.put(fontInfo);
}
@@ -291,7 +299,7 @@ public final class FontCache implements Serializable {
log.trace("Font added to cache: " + cacheKey);
}
cachedFontFile.put(fontInfo);
fontfileMap.put(cacheKey, cachedFontFile);
getFontFileMap().put(cacheKey, cachedFontFile);
changed = true;
}
}
@@ -304,7 +312,7 @@ public final class FontCache implements Serializable {
*/
public CachedFontFile getFontFile(String embedUrl) {
if (containsFont(embedUrl)) {
return (CachedFontFile)fontfileMap.get(embedUrl);
return (CachedFontFile)getFontFileMap().get(embedUrl);
}
return null;
}
@@ -336,7 +344,7 @@ public final class FontCache implements Serializable {
if (log.isTraceEnabled()) {
log.trace("Font removed from cache: " + embedUrl);
}
fontfileMap.remove(embedUrl);
getFontFileMap().remove(embedUrl);
changed = true;
}
}
@@ -349,13 +357,13 @@ public final class FontCache implements Serializable {
* @return whether this is a failed font
*/
public boolean isFailedFont(String embedUrl, long lastModified) {
if (failedFontMap.containsKey(embedUrl)) {
if (getFailedFontMap().containsKey(embedUrl)) {
synchronized (changeLock) {
long failedLastModified = ((Long)failedFontMap.get(embedUrl)).longValue();
long failedLastModified = ((Long)getFailedFontMap().get(embedUrl)).longValue();
if (lastModified != failedLastModified) {
// this font has been changed so lets remove it
// from failed font map for now
failedFontMap.remove(embedUrl);
getFailedFontMap().remove(embedUrl);
changed = true;
}
}
@@ -365,19 +373,26 @@ public final class FontCache implements Serializable {
}

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

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

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

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

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

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

public Map getFilefontsMap() {
return filefontsMap;
}

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

@@ -0,0 +1,38 @@
/*
* 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

@@ -35,7 +35,7 @@ public interface FontDescriptor extends FontMetrics {
/**
* Returns the capital height of the font.
* @return the capiptal height
* @return the capital height
*/
int getCapHeight();

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

@@ -19,19 +19,18 @@

package org.apache.fop.fonts;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
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;


/**
* 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
* the renderer. The font name can be retrieved for the
* family style and weight.
@@ -47,38 +46,40 @@ public class FontInfo {
protected static Log log = LogFactory.getLog(FontInfo.class);

/** 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 */
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
* (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) */
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)
*/
private Collection loggedFontKeys;
private Set/*<FontTriplet>*/ loggedFontKeys = null;

/** 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
*/
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
* in this class.
@@ -112,16 +113,16 @@ public class FontInfo {

/**
* 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
*/
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
* with the given name
*/
if (log.isDebugEnabled()) {
log.debug("Registering: " + triplet + " under " + name);
log.debug("Registering: " + triplet + " under " + internalFontKey);
}
String oldName = (String)triplets.get(triplet);
int newPriority = triplet.getPriority();
@@ -129,18 +130,20 @@ public class FontInfo {
int oldPriority = ((Integer)tripletPriorities.get(triplet)).intValue();
if (oldPriority < newPriority) {
logDuplicateFont(triplet, false, oldName, oldPriority,
name, newPriority);
internalFontKey, newPriority);
return;
} else {
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));
}

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

/**
* Adds font metrics for a specific font.
* @param name internal key
* @param internalFontKey internal key
* @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

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

/**
@@ -187,71 +190,72 @@ public class FontInfo {
* @param weight font weight
* @param substFont true if the font may be substituted with the
* default font if not found
* @return internal key
* @return internal font triplet key
*/
private FontTriplet fontLookup(String family, String style,
int weight, boolean substFont) {
if (log.isTraceEnabled()) {
log.trace("Font lookup: " + family + " " + style + " " + weight);
}
}
FontTriplet startKey = createFontKey(family, style, weight);
FontTriplet key = startKey;
FontTriplet fontTriplet = startKey;
// 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 {
return null;
}
}

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

if (!substFont && f == null) {
if (!substFont && internalFontKey == null) {
return null;
}
// only if the font may be substituted
// 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);
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 direction = diffWeight > 0 ? 1 : -1;
int tryWeight = weight;
while (tryWeight != Font.WEIGHT_NORMAL) {
tryWeight += 100 * direction;
key = createFontKey(family, style, weight);
f = getInternalFontKey(key);
if (f == null) {
internalFontKey = getInternalFontKey(key);
if (internalFontKey == null) {
key = createFontKey(family, Font.STYLE_NORMAL, weight);
f = getInternalFontKey(key);
internalFontKey = getInternalFontKey(key);
}
if (f != null) {
if (internalFontKey != null) {
break;
}
}
@@ -265,17 +269,17 @@ public class FontInfo {
}*/
// 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
if (f == null) {
if (internalFontKey == null) {
key = Font.DEFAULT_FONT;
f = getInternalFontKey(key);
internalFontKey = getInternalFontKey(key);
}

if (f != null) {
if (internalFontKey != null) {
return key;
} else {
return null;
@@ -290,6 +294,13 @@ public class FontInfo {
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.
* @param triplet the font triplet designating the requested font
@@ -297,10 +308,11 @@ public class FontInfo {
* @return the requested Font instance
*/
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) {
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);
Font font = (Font)sizes.get(size);
@@ -350,7 +362,7 @@ public class FontInfo {
throw new IllegalArgumentException("Specify at least one font family");
}
FontTriplet triplet;
List tmpTriplets = new ArrayList();
List tmpTriplets = new java.util.ArrayList();
for (int i = 0, c = families.length; i < c; i++) {
triplet = fontLookup(families[i], style, weight, (i >= families.length - 1));
if (triplet != null) {
@@ -372,12 +384,16 @@ public class FontInfo {
+ "FontTriplet on the last call. Lookup: " + sb.toString());
}
private void notifyFontReplacement(FontTriplet replacedKey, FontTriplet newKey) {
private Set/*<FontTriplet>*/ getLoggedFontKeys() {
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) {
this.eventListener.fontSubstituted(this, replacedKey, newKey);
} else {
@@ -477,16 +493,16 @@ public class FontInfo {
* Gets a Map of all registered fonts.
* @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);
}

/**
* 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;
}
/**
@@ -495,7 +511,7 @@ public class FontInfo {
* This is for embedded font or creating a list of used fonts.
* @return a read-only Map with font key/FontMetrics pairs
*/
public Map getUsedFonts() {
public Map/*<String,FontMetrics>*/ getUsedFonts() {
return this.usedFonts;
}

@@ -511,20 +527,30 @@ public class FontInfo {
}

/**
* 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
* @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();) {
Map.Entry tripletEntry = (Map.Entry) iter.next();
if (fontName.equals(((String)tripletEntry.getValue()))) {
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) {
Collections.sort(foundTriplets);
return (FontTriplet)foundTriplets.get(0);
@@ -570,17 +596,25 @@ public class FontInfo {
* Diagnostic method for logging all registered fonts to System.out.
*/
public void dumpAllTripletsToSystemOut() {
System.out.print(toString());
}
/**
* {@inheritDoc}
*/
public String toString() {
Collection entries = new java.util.TreeSet();
Iterator iter = this.triplets.keySet().iterator();
while (iter.hasNext()) {
FontTriplet triplet = (FontTriplet)iter.next();
String key = getInternalFontKey(triplet);
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

@@ -0,0 +1,221 @@
/*
* 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

@@ -0,0 +1,89 @@
/*
* 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

@@ -42,6 +42,8 @@ import org.apache.fop.fonts.base14.TimesItalic;
import org.apache.fop.fonts.base14.TimesRoman;
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
* by default.
@@ -57,17 +59,11 @@ public class FontSetup {
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);
}

/**
@@ -77,25 +73,23 @@ public class FontSetup {
* triplets for lookup.
*
* @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 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("F14", new ZapfDingbats());

@@ -105,64 +99,64 @@ public class FontSetup {
// 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("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
// fontInfo.addFontProperties("F15", "OMEP", "normal", FontInfo.NORMAL);
@@ -170,50 +164,53 @@ public class FontSetup {
// 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("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);
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 */
addConfiguredFonts(fontInfo, embedList, 15, resolver);
addConfiguredFonts(fontInfo, embedFontInfoList, startNum, resolver);
}

/**
* 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 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
}

if (resolver == null) {
//Ensure that we have minimal font resolution capabilities
resolver = createMinimalFontResolver();
resolver = createMinimalFontResolver1();
}
String internalName = 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;
num++;
/*
@@ -222,20 +219,20 @@ public class FontSetup {
reader.setFontEmbedPath(configFontInfo.getEmbedFile());
fontInfo.addMetrics(internalName, reader.getFont());
*/
LazyFont font = new LazyFont(configFontInfo, resolver);
LazyFont font = new LazyFont(embedFontInfo, resolver);
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);
}
}
}

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

/** {@inheritDoc} */

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

@@ -37,6 +37,14 @@ public class FontTriplet implements Comparable, Serializable {
//This is only a cache
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.
* @param name font name
@@ -44,7 +52,7 @@ public class FontTriplet implements Comparable, Serializable {
* @param weight font weight (100, 200, 300...800, 900)
*/
public FontTriplet(String name, String style, int weight) {
this(name, style, weight, 0);
this(name, style, weight, Font.PRIORITY_DEFAULT);
}

/**
@@ -55,7 +63,7 @@ public class FontTriplet implements Comparable, Serializable {
* @param priority priority of this triplet/font mapping
*/
public FontTriplet(String name, String style, int weight, int priority) {
this.name = name;
this(name);
this.style = style;
this.weight = weight;
this.priority = priority;
@@ -120,6 +128,5 @@ public class FontTriplet implements Comparable, Serializable {
public String toString() {
return getKey();
}

}


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

@@ -59,25 +59,27 @@ public class FontUtil {

/**
* Removes all white space from a string (used primarily for font names)
* @param s the string
* @param str the string
* @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 */
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 */
private static final String[] LIGHT_WORDS = {"light"};
@@ -97,9 +99,11 @@ public class FontUtil {
* @return "normal" or "italic"
*/
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;
@@ -148,6 +152,4 @@ public class FontUtil {
}
return weight;
}
}

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

@@ -156,7 +156,7 @@ public class FontFileFinder extends DirectoryWalker implements FontFinder {
*
* @param dir directory to search
* @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 {
List results = new java.util.ArrayList();

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

@@ -94,9 +94,9 @@ public class FontInfoFinder {

//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
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)) {
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();
Iterator iter = familyNames.iterator();

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

@@ -0,0 +1,149 @@
/*
* 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

@@ -0,0 +1,65 @@
/*
* 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

@@ -0,0 +1,305 @@
/*
* 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

@@ -0,0 +1,61 @@
/*
* 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

@@ -0,0 +1,66 @@
/*
* 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

@@ -0,0 +1,83 @@
/*
* 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

@@ -0,0 +1,115 @@
/*
* 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

@@ -58,8 +58,10 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
/** True if this LayoutManager has handled all of its content. */
private boolean bFinished = false;
/** child LM and child LM iterator during getNextKnuthElement phase */
/** child LM during getNextKnuthElement phase */
protected LayoutManager curChildLM = null;
/** child LM iterator during getNextKnuthElement phase */
protected ListIterator childLMiter = null;
private int lastGeneratedPosition = -1;

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

@@ -45,7 +45,6 @@ public abstract class AbstractRendererConfigurator {
super();
this.userAgent = userAgent;
}

/**
* Returns the configuration subtree for a specific renderer.
@@ -61,16 +60,15 @@ public abstract class AbstractRendererConfigurator {
return null;
}
return getRendererConfig(userAgent, mimeType);
return getRendererConfig(mimeType);
}

/**
* 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
* @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();
if (cfg == null) {
if (log.isDebugEnabled()) {

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

@@ -25,7 +25,6 @@ import org.apache.fop.area.Trait;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet;
import org.w3c.dom.Document;

@@ -45,25 +44,32 @@ public abstract class PrintRenderer extends AbstractRenderer {
protected FontResolver fontResolver = null;

/** 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 {
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;
}

/**
@@ -73,8 +79,7 @@ public abstract class PrintRenderer extends AbstractRenderer {
*/
public void setupFontInfo(FontInfo inFontInfo) {
this.fontInfo = inFontInfo;
FontSetup.setup(fontInfo, fontList, fontResolver,
userAgent.getFactory().isBase14KerningEnabled());
userAgent.getFactory().getFontManager().setupRenderer(this);
}

/**
@@ -180,4 +185,11 @@ public abstract class PrintRenderer extends AbstractRenderer {
}
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

@@ -44,8 +44,8 @@ import org.apache.fop.apps.FopFactory;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.autodetect.FontFileFinder;
@@ -78,28 +78,30 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = getRendererConfig(renderer);
if (cfg == null) {
log.trace("no configuration found for " + renderer);
return;
}

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

FopFactory factory = userAgent.getFactory();
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,
fontCache);
if (fontCache != null && fontCache.hasChanged()) {
fontCache.save();
}
printRenderer.addFontList(fontInfoList);
printRenderer.addFontList(embedFontInfoList);
}

/**
@@ -113,10 +115,11 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
* @return a List of EmbedFontInfo objects.
* @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,
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);
if (fonts != null) {
@@ -204,12 +207,13 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
// font file (singular) configuration
Configuration[] font = fonts.getChildren("font");
for (int i = 0; i < font.length; i++) {
EmbedFontInfo fontInfo = getFontInfoFromConfiguration(
EmbedFontInfo embedFontInfo = getFontInfoFromConfiguration(
font[i], fontResolver, strict, fontCache);
if (fontInfo != null) {
fontInfoList.add(fontInfo);
if (embedFontInfo != null) {
fontInfoList.add(embedFontInfo);
}
}
if (log.isDebugEnabled()) {
log.debug("Finished font configuration in "
+ (System.currentTimeMillis() - start) + "ms");
@@ -221,11 +225,12 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
/**
* Iterates over font file list adding font info to list
* @param fontFileList font file list
* @param fontInfoList font info list
* @param embedFontInfoList a configured font info list
* @param resolver font resolver
*/
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();) {
URL fontUrl = (URL)iter.next();
// parse font to ascertain font info
@@ -242,7 +247,7 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
for (int i = 0, c = embedFontInfos.length; i < c; i++) {
EmbedFontInfo fontInfo = embedFontInfos[i];
if (fontInfo != null) {
fontInfoList.add(fontInfo);
embedFontInfoList.add(fontInfo);
}
}
}
@@ -256,6 +261,44 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
}
}

/**
* 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
*
@@ -263,18 +306,20 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
* @param fontResolver font resolver used to resolve font
* @param strict validate configuration strictly
* @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
*/
public static EmbedFontInfo getFontInfoFromConfiguration(
private static EmbedFontInfo getFontInfoFromConfiguration(
Configuration fontCfg, FontResolver fontResolver, boolean strict, FontCache fontCache)
throws FOPException {
String metricsUrl = fontCfg.getAttribute("metrics-url", null);
String embedUrl = fontCfg.getAttribute("embed-url", null);
String subFont = fontCfg.getAttribute("sub-font", 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;
}
if (strict) {
@@ -299,15 +344,13 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
}
}
}
boolean useKerning = fontCfg.getAttributeAsBoolean("kerning", true);
EmbedFontInfo fontInfo = null;
Configuration[] tripletCfg = fontCfg.getChildren("font-triplet");
// no font triplet info
if (tripletCfg.length == 0) {
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});
URL fontUrl;
try {
@@ -324,53 +367,36 @@ public class PrintRendererConfigurator extends AbstractRendererConfigurator
} else {
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

@@ -279,8 +279,8 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
public void setupFontInfo(FontInfo inFontInfo) {
this.fontInfo = inFontInfo;
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();
AFPFont bf = (AFPFont)afi.getAFPFont();
for (Iterator it2 = afi.getFontTriplets().iterator(); it2.hasNext();) {

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

@@ -0,0 +1,181 @@
/*
* 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

@@ -0,0 +1,111 @@
/*
* 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

@@ -1,353 +0,0 @@
/*
* 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

@@ -0,0 +1,138 @@
/*
* 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

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

/** {@inheritDoc} */

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

@@ -89,7 +89,6 @@ import org.apache.fop.render.RendererContext;
import org.apache.fop.render.RendererContextConstants;
import org.apache.fop.render.RendererEventProducer;
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.pcl.extensions.PCLElementMapping;
import org.apache.fop.traits.BorderProps;
@@ -202,11 +201,12 @@ public class PCLRenderer extends PrintRenderer {
fontInfo = inFontInfo;
BufferedImage fontImage = new BufferedImage(100, 100,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = fontImage.createGraphics();
Graphics2D graphics2D = fontImage.createGraphics();
//The next line is important to get accurate font metrics!
g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
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

@@ -98,7 +98,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder {
if (!isTextStroked()) {
FontInfo fontInfo = new FontInfo();
//TODO Do custom font configuration here somewhere/somehow
FontSetup.setup(fontInfo, null, null);
FontSetup.setup(fontInfo);
graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo));
}


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

@@ -71,7 +71,7 @@ public class NativeTextHandler implements PSTextHandler {
private void setupFontInfo() {
//Sets up a FontInfo with default fonts
fontInfo = new FontInfo();
FontSetup.setup(fontInfo, null, null);
FontSetup.setup(fontInfo);
}
/**

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

@@ -156,7 +156,7 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D {
if (fontInfo == null) {
//Default minimal fonts
FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, null, null);
FontSetup.setup(fontInfo);
setFontInfo(fontInfo);
}
}

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

@@ -26,6 +26,7 @@ import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.pdf.PDFDocument;
@@ -53,17 +54,20 @@ public class PDFDocumentGraphics2DConfigurator {
//Fonts
try {
FontResolver fontResolver = FontSetup.createMinimalFontResolver();
FontResolver fontResolver = FontManager.createMinimalFontResolver();
//TODO The following could be optimized by retaining the FontCache somewhere
FontCache fontCache = FontCache.load();
if (fontCache == null) {
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();
FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, fontList, fontResolver);
FontSetup.setup(fontInfo, embedFontInfoList, fontResolver);
graphics.setFontInfo(fontInfo);
} catch (FOPException e) {
throw new ConfigurationException("Error while setting up fonts", e);

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

@@ -959,7 +959,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
preparePainting();

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

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

+ 4
- 0
status.xml View File

@@ -57,6 +57,10 @@
<action context="Renderers" dev="AC" importance="high" type="add">
Added SVG support for AFP (GOCA).
</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">
PCL Renderer: Improved page format selection so it doesn't interfere with
duplex printing.

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

@@ -0,0 +1,33 @@
<?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

@@ -66,7 +66,7 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase {
final File baseDir = getBaseDir();
final String fontFOFilePath = getFontFOFilePath();
File foFile = new File(baseDir, fontFOFilePath);
final boolean dumpOutput = false;
final boolean dumpOutput = true;
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
convertFO(foFile, foUserAgent, dumpOutput);
}

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

@@ -0,0 +1,63 @@
/*
* 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

@@ -44,6 +44,7 @@ public class UserConfigTestSuite {
suite.addTest(new TestSuite(FontEmbedUrlMalformedTestCase.class));
suite.addTest(new TestSuite(FontsDirectoryRecursiveTestCase.class));
suite.addTest(new TestSuite(FontsAutoDetectTestCase.class));
suite.addTest(new TestSuite(FontsSubstitutionTestCase.class));
//$JUnit-END$
return suite;
}

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

@@ -95,8 +95,8 @@ public class LayoutEngineTester {
*/
public LayoutEngineTester(File areaTreeBackupDir) {
this.areaTreeBackupDir = areaTreeBackupDir;
fopFactory.setBase14KerningEnabled(false);
fopFactoryWithBase14Kerning.setBase14KerningEnabled(true);
fopFactory.getFontManager().setBase14KerningEnabled(false);
fopFactoryWithBase14Kerning.getFontManager().setBase14KerningEnabled(true);
}
private Templates getTestcase2FOStylesheet() throws TransformerConfigurationException {

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

@@ -101,7 +101,7 @@ public class BasePDFTestCase extends AbstractFOPTestCase {
}
}

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

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

@@ -44,9 +44,9 @@ public class PDFAConformanceTestCase extends BasePDFTestCase {
* @return an initialized FOUserAgent
* */
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;
}
/**
@@ -104,5 +104,5 @@ public class PDFAConformanceTestCase extends BasePDFTestCase {
//Good!
}
}
}

Loading…
Cancel
Save