Browse Source

Bugzilla #41831:

- Add support font auto-detection (easier font configuration) including a font cache to speed up the auto-detection process.
- Refactoring of the configuration code: All Avalon configuration stuff is extracted into separate "Configurator" classes.
- Refactoring of the FOURIResolver.
Submitted by: Adrian Cumiskey <fop-dev.at.cumiskey.com>

Changes to the patch by jeremias during the review:
- Font cache simplified (Java object serialization instead of XML), functionality fixed and moved to the fonts.package.
- Relocated default cache file location to user directory.
- Fixed the font configuration for PDFDocumentGraphics2D/PDFTranscoder that got lost with the patch.
- Fixed a problem with having a non-file URL as font base URL.
- Simplified RendererContextInfo stuff to make it easier to understand.
- Fixed handling of Type 1 fonts in auto-detection.
- Reduced verbosity of font-related log output.
- Updated Jakarta Commons IO to version 1.3.1 (the patch depends on it)
- Various javadocs improvements

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@542237 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_94
Jeremias Maerki 17 years ago
parent
commit
8c1aba3f97
100 changed files with 3833 additions and 1413 deletions
  1. 4
    3
      fop.bat
  2. 3
    1
      fop.cmd
  3. BIN
      lib/commons-io-1.1.jar
  4. BIN
      lib/commons-io-1.3.1.jar
  5. 3
    0
      lib/commons-io.NOTICE.txt
  6. 18
    0
      src/documentation/content/xdocs/trunk/configuration.xml
  7. 28
    8
      src/documentation/content/xdocs/trunk/fonts.xml
  8. 104
    85
      src/java/org/apache/fop/apps/FOURIResolver.java
  9. 29
    14
      src/java/org/apache/fop/apps/FOUserAgent.java
  10. 136
    228
      src/java/org/apache/fop/apps/FopFactory.java
  11. 241
    0
      src/java/org/apache/fop/apps/FopFactoryConfigurator.java
  12. 1
    1
      src/java/org/apache/fop/area/AreaTreeParser.java
  13. 3
    3
      src/java/org/apache/fop/cli/CommandLineOptions.java
  14. 117
    0
      src/java/org/apache/fop/fonts/CachedFontInfo.java
  15. 25
    2
      src/java/org/apache/fop/fonts/CustomFont.java
  16. 21
    8
      src/java/org/apache/fop/fonts/EmbedFontInfo.java
  17. 15
    5
      src/java/org/apache/fop/fonts/Font.java
  18. 330
    0
      src/java/org/apache/fop/fonts/FontCache.java
  19. 5
    6
      src/java/org/apache/fop/fonts/FontInfo.java
  20. 90
    10
      src/java/org/apache/fop/fonts/FontLoader.java
  21. 64
    201
      src/java/org/apache/fop/fonts/FontSetup.java
  22. 20
    0
      src/java/org/apache/fop/fonts/FontUtil.java
  23. 12
    6
      src/java/org/apache/fop/fonts/LazyFont.java
  24. 2
    21
      src/java/org/apache/fop/fonts/MultiByteFont.java
  25. 3
    18
      src/java/org/apache/fop/fonts/apps/TTFReader.java
  26. 158
    0
      src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
  27. 38
    0
      src/java/org/apache/fop/fonts/autodetect/FontFinder.java
  28. 171
    0
      src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
  29. 39
    0
      src/java/org/apache/fop/fonts/autodetect/MacFontDirFinder.java
  30. 55
    0
      src/java/org/apache/fop/fonts/autodetect/NativeFontDirFinder.java
  31. 39
    0
      src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java
  32. 108
    0
      src/java/org/apache/fop/fonts/autodetect/WindowsFontDirFinder.java
  33. 23
    0
      src/java/org/apache/fop/fonts/autodetect/package.html
  34. 8
    0
      src/java/org/apache/fop/fonts/truetype/TTFFile.java
  35. 23
    25
      src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
  36. 6
    17
      src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
  37. 1
    63
      src/java/org/apache/fop/pdf/PDFFilterList.java
  38. 4
    56
      src/java/org/apache/fop/render/AbstractRenderer.java
  39. 91
    0
      src/java/org/apache/fop/render/AbstractRendererConfigurator.java
  40. 12
    3
      src/java/org/apache/fop/render/AbstractRendererMaker.java
  41. 19
    0
      src/java/org/apache/fop/render/PrintRenderer.java
  42. 332
    0
      src/java/org/apache/fop/render/PrintRendererConfigurator.java
  43. 34
    0
      src/java/org/apache/fop/render/RendererConfigurator.java
  44. 1
    9
      src/java/org/apache/fop/render/RendererContext.java
  45. 3
    15
      src/java/org/apache/fop/render/RendererFactory.java
  46. 92
    0
      src/java/org/apache/fop/render/XMLHandlerConfigurator.java
  47. 17
    194
      src/java/org/apache/fop/render/afp/AFPRenderer.java
  48. 241
    0
      src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
  49. 7
    1
      src/java/org/apache/fop/render/afp/AFPRendererMaker.java
  50. 3
    2
      src/java/org/apache/fop/render/awt/AWTRenderer.java
  51. 11
    30
      src/java/org/apache/fop/render/bitmap/TIFFRenderer.java
  52. 72
    0
      src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java
  53. 8
    3
      src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java
  54. 59
    59
      src/java/org/apache/fop/render/java2d/FontSetup.java
  55. 7
    18
      src/java/org/apache/fop/render/java2d/Java2DRenderer.java
  56. 57
    0
      src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java
  57. 6
    27
      src/java/org/apache/fop/render/pcl/PCLRenderer.java
  58. 74
    0
      src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java
  59. 10
    5
      src/java/org/apache/fop/render/pcl/PCLRendererMaker.java
  60. 16
    36
      src/java/org/apache/fop/render/pdf/PDFRenderer.java
  61. 134
    0
      src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java
  62. 8
    3
      src/java/org/apache/fop/render/pdf/PDFRendererMaker.java
  63. 9
    3
      src/java/org/apache/fop/render/print/PrintRendererMaker.java
  64. 1
    1
      src/java/org/apache/fop/render/ps/NativeTextHandler.java
  65. 0
    21
      src/java/org/apache/fop/render/ps/PSRenderer.java
  66. 56
    0
      src/java/org/apache/fop/render/ps/PSRendererConfigurator.java
  67. 8
    4
      src/java/org/apache/fop/render/ps/PSRendererMaker.java
  68. 4
    4
      src/java/org/apache/fop/render/ps/PSTextPainter.java
  69. 0
    8
      src/java/org/apache/fop/render/txt/TXTRenderer.java
  70. 53
    0
      src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java
  71. 8
    4
      src/java/org/apache/fop/render/txt/TXTRendererMaker.java
  72. 0
    19
      src/java/org/apache/fop/render/xml/XMLRenderer.java
  73. 9
    3
      src/java/org/apache/fop/render/xml/XMLRendererMaker.java
  74. 0
    16
      src/java/org/apache/fop/svg/PDFContext.java
  75. 37
    51
      src/java/org/apache/fop/svg/PDFDocumentGraphics2D.java
  76. 66
    0
      src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.java
  77. 1
    1
      src/java/org/apache/fop/svg/PDFGraphics2D.java
  78. 4
    1
      src/java/org/apache/fop/svg/PDFTextElementBridge.java
  79. 4
    4
      src/java/org/apache/fop/svg/PDFTextPainter.java
  80. 15
    5
      src/java/org/apache/fop/svg/PDFTranscoder.java
  81. 57
    0
      src/java/org/apache/fop/util/LogUtil.java
  82. 0
    9
      src/sandbox/org/apache/fop/render/svg/SVGRenderer.java
  83. 3
    0
      status.xml
  84. 4
    1
      test/config/test_font_attributes_missing.xconf
  85. 3
    0
      test/config/test_font_embedurl_bad.xconf
  86. 3
    0
      test/config/test_font_embedurl_malformed.xconf
  87. 3
    0
      test/config/test_font_metricsurl_bad.xconf
  88. 3
    0
      test/config/test_font_metricsurl_malformed.xconf
  89. 3
    0
      test/config/test_font_tripletattribute_missing.xconf
  90. 3
    0
      test/config/test_fontbase_bad.xconf
  91. 22
    0
      test/config/test_fonts_autodetect.xconf
  92. 22
    0
      test/config/test_fonts_directory_bad.xconf
  93. 22
    0
      test/config/test_fonts_directory_recursive.xconf
  94. 45
    0
      test/java/org/apache/fop/config/BaseConstructiveUserConfigTestCase.java
  95. 45
    0
      test/java/org/apache/fop/config/BaseDestructiveUserConfigTestCase.java
  96. 37
    38
      test/java/org/apache/fop/config/BaseUserConfigTestCase.java
  97. 9
    10
      test/java/org/apache/fop/config/FontAttributesMissingTestCase.java
  98. 6
    13
      test/java/org/apache/fop/config/FontBaseBadTestCase.java
  99. 7
    11
      test/java/org/apache/fop/config/FontEmbedUrlBadTestCase.java
  100. 0
    0
      test/java/org/apache/fop/config/FontEmbedUrlMalformedTestCase.java

+ 4
- 3
fop.bat View File

@@ -62,7 +62,7 @@ set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\serializer-2.7.0.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\batik-all-1.6.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.2svn.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\avalon-framework-4.2.0.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.1.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.3.1.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-logging-1.0.4.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\jimi-1.0.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\jai_core.jar
@@ -70,6 +70,8 @@ set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\jai_codec.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\fop-hyph.jar
set LOCALCLASSPATH=%LOCALCLASSPATH%;%FOP_HYPHENATION_PATH%
set JAVAOPTS=-Denv.windir=%WINDIR%
if "%JAVA_HOME%" == "" goto noJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
if "%JAVACMD%" == "" set JAVACMD=%JAVA_HOME%\bin\java
@@ -80,5 +82,4 @@ if "%JAVACMD%" == "" set JAVACMD=java
:runFop
rem ECHO "%JAVACMD%"
"%JAVACMD%" %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
"%JAVACMD%" %JAVAOPTS% %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%

+ 3
- 1
fop.cmd View File

@@ -58,6 +58,8 @@ set LIBDIR=%LOCAL_FOP_HOME%lib
set LOCALCLASSPATH=%FOP_HYPHENATION_PATH%
for %%l in (%LOCAL_FOP_HOME%build\*.jar %LIBDIR%\*.jar) do set LOCALCLASSPATH=!LOCALCLASSPATH!;%%l
set JAVAOPTS=-Denv.windir=%WINDIR%
if "%JAVA_HOME%" == "" goto noJavaHome
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
if "%JAVACMD%" == "" set JAVACMD=%JAVA_HOME%\bin\java
@@ -68,6 +70,6 @@ if "%JAVACMD%" == "" set JAVACMD=java
:runFop
rem echo "%JAVACMD%" %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
"%JAVACMD%" %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
"%JAVACMD%" %JAVAOPTS% %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
ENDLOCAL

BIN
lib/commons-io-1.1.jar View File


BIN
lib/commons-io-1.3.1.jar View File


+ 3
- 0
lib/commons-io.NOTICE.txt View File

@@ -1,3 +1,6 @@
Apache Jakarta Commons IO
Copyright 2001-2007 The Apache Software Foundation

This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).


+ 18
- 0
src/documentation/content/xdocs/trunk/configuration.xml View File

@@ -151,6 +151,24 @@
default-page-settings element to specify the two values.</td>
<td>"height" 11 inches, "width" 8.26 inches</td>
</tr>
<tr>
<td>use-cache</td>
<td>boolean (true, false)</td>
<td>All fonts information that has been gathered as a result of "directory"
or "auto-detect" font configurations will be cached for future rendering runs.
This setting should improve performance on systems where
fonts have been configured using the "directory" or "auto-detect" tag mechanisms.
By default this option is switched on.</td>
<td>true</td>
</tr>
<tr>
<td>cache-file</td>
<td>String</td>
<td>This options specifies the file/directory path of the fop cache file.
This option can also be specified on the command-line using the -cache option.
This file is currently only used to cache font triplet information for future reference.</td>
<td>${base}/conf/fop.cache</td>
</tr>
<tr>
<td>renderers</td>
<td>(see text below)</td>

+ 28
- 8
src/documentation/content/xdocs/trunk/fonts.xml View File

@@ -24,6 +24,7 @@
<authors>
<person name="Jeremias Märki" email=""/>
<person name="Tore Engvig" email=""/>
<person name="Adrian Cumiskey" email=""/>
</authors>
</header>
<body>
@@ -129,8 +130,7 @@
More information about fonts can be found at:</p>
<ul>
<li><a href="http://partners.adobe.com/asn/developer/type/ftypes.html">Adobe font types</a></li>
<li><a href="http://partners.adobe.com/asn/developer/technotes/fonts.html">Adobe Font Technote</a>
</li>
<li><a href="http://partners.adobe.com/asn/developer/technotes/fonts.html">Adobe Font Technote</a></li>
</ul>
<section id="type1-metrics">
<title>Type 1 Font Metrics</title>
@@ -236,10 +236,24 @@ It will display all of the font names and exit with an Exception.</p>
<section id="register">
<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[<font metrics-url="file:///C:/myfonts/FTL_____.xml" kerning="yes"
<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>]]></source>
<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
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>
<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. Otherwise, FOP has no way of finding your custom font information.</note>
<ul>
<li>
@@ -247,8 +261,14 @@ It will display all of the font names and exit with an Exception.</p>
Relative URLs are resolved relative to the font-base property (or base) if available.
See <a href="configuration.html">FOP: Configuration</a> for more information.
</li>
<li>The "kerning" and "embed-url" attributes are optional. Kerning is currently not used at all. If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.</li>
<li>When setting the embed-url attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.</li>
<li>Either an "embed-url" or a "metrics-url" must be specified for font tag configurations.</li>
<li>The font "kerning" attribute is optional. Kerning is currently not used at all.</li>
<li>If embedding is off, the output will position the text correctly (from the metrics file), but it will not be displayed or printed correctly unless the viewer has the applicable font available to their local system.</li>
<li>When setting the "embed-url" attribute for Type 1 fonts, be sure to specify the PFB (actual font data), not PFM (font metrics) file that you used to generate the XML font metrics file.</li>
<li>The fonts "directory" tag can be used to register fonts contained within a single or list of directory paths. The "recursive" attribute can be specified to recursively add fonts from all sub directories.</li>
<li>The fonts "auto-detect" tag can be used to automatically register fonts that are found to be installed on the native operating system.</li>
<li>Fonts registered with "font" tag configurations override fonts found by means of "directory" tag definitions.</li>
<li>Fonts found as a result of a "directory" tag configuration override fonts found as a result of the "auto-detect" tag being specified.</li>
<li>
If relative URLs are specified, they are evaluated relative to the value of the
"font-base" setting. If there is no "font-base" setting, the fonts are evaluated
@@ -281,7 +301,7 @@ Characters will be WinAnsi encoded (as specified in the PDF spec), so you lose t
See <a href="#ttf-encoding">Table of TTF Encoding Options</a> for more details.</p>
</section>
<section id="embedding-base14">
<title>Explicitely embedding the base 14 fonts</title>
<title>Explicitly embedding the base 14 fonts</title>
<p>
There are cases where you might want to force the embedding of one or more of the base 14 fonts that
can normally be considered available on the target platform (viewer, printer). One of these cases is

+ 104
- 85
src/java/org/apache/fop/apps/FOURIResolver.java View File

@@ -29,6 +29,7 @@ import java.net.URL;
import java.net.URLConnection;

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

// commons logging
@@ -47,8 +48,41 @@ import org.apache.xmlgraphics.util.io.Base64EncodeStream;
public class FOURIResolver
implements javax.xml.transform.URIResolver {
// log
private Log log = LogFactory.getLog("FOP");

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

/**
* Default constructor
*/
public FOURIResolver() {
this(false);
}
/**
* Additional constructor
* @param throwExceptions true if exceptions are to be thrown if the URIs cannot be
* resolved.
*/
public FOURIResolver(boolean throwExceptions) {
this.throwExceptions = throwExceptions;
}
/**
* Handles resolve exceptions appropriately.
* @param errorStr error string
* @param strict strict user config
*/
private void handleException(Exception e, String errorStr, boolean strict)
throws TransformerException {
if (strict) {
throw new TransformerException(errorStr, e);
}
log.error(e.getMessage());
}

/**
* Called by the processor through {@link FOUserAgent} when it encounters an
* uri in an external-graphic element.
@@ -70,31 +104,25 @@ public class FOURIResolver
* @throws javax.xml.transform.TransformerException Never thrown by this implementation.
* @see javax.xml.transform.URIResolver#resolve(String, String)
*/
public Source resolve(String href, String base)
throws javax.xml.transform.TransformerException {
//data URLs can be quite long so don't try to build a File (can lead to problems)
public Source resolve(String href, String base) throws TransformerException {
// data URLs can be quite long so don't try to build a File (can lead to problems)
if (href.startsWith("data:")) {
return parseDataURI(href);
}
URL absoluteURL = null;
File f = new File(href);
if (f.exists()) {
File file = new File(href);
if (file.canRead() && file.isFile()) {
try {
absoluteURL = f.toURL();
absoluteURL = file.toURL();
} catch (MalformedURLException mfue) {
log.error("Could not convert filename to URL: " + mfue.getMessage());
handleException(mfue,
"Could not convert filename '" + href + "' to URL", throwExceptions);
}
} else {
URL baseURL = null;
try {
baseURL = toBaseURL(base);
} catch (MalformedURLException mfue) {
log.error("Error with base URL \"" + base + "\"): " + mfue.getMessage());
}
if (baseURL == null) {
// We don't have a valid baseURL just use the URL as given
// no base provided
if (base == null) {
// We don't have a valid file protocol based URL
try {
absoluteURL = new URL(href);
} catch (MalformedURLException mue) {
@@ -103,64 +131,78 @@ public class FOURIResolver
// the href contains only a path then file: is assumed
absoluteURL = new URL("file:" + href);
} catch (MalformedURLException mfue) {
log.error("Error with URL '" + href + "': " + mue.getMessage());
return null;
handleException(mfue,
"Error with URL '" + href + "'", throwExceptions);
}
}

// try and resolve from context of base
} else {
URL baseURL = null;
try {
/*
This piece of code is based on the following statement in
RFC2396 section 5.2:

3) If the scheme component is defined, indicating that the reference
starts with a scheme name, then the reference is interpreted as an
absolute URI and we are done. Otherwise, the reference URI's
scheme is inherited from the base URI's scheme component.

Due to a loophole in prior specifications [RFC1630], some parsers
allow the scheme name to be present in a relative URI if it is the
same as the base URI scheme. Unfortunately, this can conflict
with the correct parsing of non-hierarchical URI. For backwards
compatibility, an implementation may work around such references
by removing the scheme if it matches that of the base URI and the
scheme is known to always use the <hier_part> syntax.

The URL class does not implement this work around, so we do.
*/
baseURL = new URL(base);
} catch (MalformedURLException mfue) {
handleException(mfue, "Error with base URL '" + base + "'", throwExceptions);
}

String scheme = baseURL.getProtocol() + ":";
if (href.startsWith(scheme)) {
href = href.substring(scheme.length());
if ("file:".equals(scheme)) {
int colonPos = href.indexOf(':');
int slashPos = href.indexOf('/');
if (slashPos >= 0 && colonPos >= 0 && colonPos < slashPos) {
href = "/" + href; //Absolute file URL doesn't have a leading slash
}
/*
* This piece of code is based on the following statement in
* RFC2396 section 5.2:
*
* 3) If the scheme component is defined, indicating that the
* reference starts with a scheme name, then the reference is
* interpreted as an absolute URI and we are done. Otherwise,
* the reference URI's scheme is inherited from the base URI's
* scheme component.
*
* Due to a loophole in prior specifications [RFC1630], some
* parsers allow the scheme name to be present in a relative URI
* if it is the same as the base URI scheme. Unfortunately, this
* can conflict with the correct parsing of non-hierarchical
* URI. For backwards compatibility, an implementation may work
* around such references by removing the scheme if it matches
* that of the base URI and the scheme is known to always use
* the <hier_part> syntax.
*
* The URL class does not implement this work around, so we do.
*/
String scheme = baseURL.getProtocol() + ":";
if (href.startsWith(scheme)) {
href = href.substring(scheme.length());
if ("file:".equals(scheme)) {
int colonPos = href.indexOf(':');
int slashPos = href.indexOf('/');
if (slashPos >= 0 && colonPos >= 0 && colonPos < slashPos) {
href = "/" + href; // Absolute file URL doesn't
// have a leading slash
}
}
}
try {
absoluteURL = new URL(baseURL, href);
} catch (MalformedURLException mfue) {
log.error("Error with URL '" + href + "': " + mfue.getMessage());
return null;
handleException(mfue,
"Error with URL; base '" + base + "' " + "href '" + href + "'",
throwExceptions);
}
}
}
String effURL = absoluteURL.toExternalForm();
try {
URLConnection connection = absoluteURL.openConnection();
connection.setAllowUserInteraction(false);
connection.setDoInput(true);
updateURLConnection(connection, href);
connection.connect();
return new StreamSource(connection.getInputStream(), effURL);
} catch (FileNotFoundException fnfe) {
//Note: This is on "debug" level since the caller is supposed to handle this
log.debug("File not found: " + effURL);
} catch (java.io.IOException ioe) {
log.error("Error with opening URL '" + effURL + "': " + ioe.getMessage());
if (absoluteURL != null) {
String effURL = absoluteURL.toExternalForm();
try {
URLConnection connection = absoluteURL.openConnection();
connection.setAllowUserInteraction(false);
connection.setDoInput(true);
updateURLConnection(connection, href);
connection.connect();
return new StreamSource(connection.getInputStream(), effURL);
} catch (FileNotFoundException fnfe) {
//Note: This is on "debug" level since the caller is supposed to handle this
log.debug("File not found: " + effURL);
} catch (java.io.IOException ioe) {
log.error("Error with opening URL '" + effURL + "': " + ioe.getMessage());
}
}
return null;
}
@@ -200,29 +242,6 @@ public class FOURIResolver
}
}
/**
* Returns the base URL as a java.net.URL.
* If the base URL is not set a default URL pointing to the
* current directory is returned.
* @param baseURL the base URL
* @returns the base URL as java.net.URL
*/
private URL toBaseURL(String base) throws MalformedURLException {
if (base == null) {
return new java.io.File("").toURL();
}
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 += "/";
}
return new URL(base);
}

/**
* Parses inline data URIs as generated by MS Word's XML export and FO stylesheet.
* @see <a href="http://www.ietf.org/rfc/rfc2397">RFC 2397</a>

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

@@ -63,19 +63,25 @@ import org.apache.fop.render.pdf.PDFRenderer;
public class FOUserAgent {

/** Defines the default target resolution (72dpi) for FOP */
public static final float DEFAULT_TARGET_RESOLUTION = FopFactory.DEFAULT_TARGET_RESOLUTION;
public static final float DEFAULT_TARGET_RESOLUTION = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION;

private static Log log = LogFactory.getLog("FOP");

private FopFactory factory;
/** The base URL for all URL resolutions, especially for external-graphics */
private String baseURL;
/**
* The base URL for all URL resolutions, especially for
* external-graphics.
*/
private String base = null;

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

/** A user settable URI Resolver */
private URIResolver uriResolver = null;
private float targetResolution = DEFAULT_TARGET_RESOLUTION;
private float targetResolution = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION;
private Map rendererOptions = new java.util.HashMap();
private File outputFile = null;
private Renderer rendererOverride = null;
@@ -105,7 +111,6 @@ public class FOUserAgent {
/**
* Default constructor
* @throws FOPException
* @see org.apache.fop.apps.FopFactory
* @deprecated Provided for compatibility only. Please use the methods from
* FopFactory to construct FOUserAgent instances!
@@ -126,6 +131,7 @@ public class FOUserAgent {
}
this.factory = factory;
setBaseURL(factory.getBaseURL());
setFontBaseURL(factory.getFontBaseURL());
setTargetResolution(factory.getTargetResolution());
}
@@ -277,10 +283,18 @@ public class FOUserAgent {
/**
* Sets the base URL.
* @param baseURL base URL
* @param baseUrl base URL
*/
public void setBaseURL(String baseURL) {
this.baseURL = baseURL;
public void setBaseURL(String baseUrl) {
this.base = baseUrl;
}

/**
* sets font base URL
* @param fontBaseUrl font base URL
*/
public void setFontBaseURL(String fontBaseUrl) {
this.fontBase = fontBaseUrl;
}

/**
@@ -288,7 +302,7 @@ public class FOUserAgent {
* @return the base URL
*/
public String getBaseURL() {
return this.baseURL;
return this.base;
}

/**
@@ -410,8 +424,10 @@ public class FOUserAgent {
*/
public void setTargetResolution(float dpi) {
this.targetResolution = dpi;
log.info("target-resolution set to: " + targetResolution
+ "dpi (px2mm=" + getTargetPixelUnitToMillimeter() + ")");
if (log.isDebugEnabled()) {
log.debug("target-resolution set to: " + targetResolution
+ "dpi (px2mm=" + getTargetPixelUnitToMillimeter() + ")");
}
}

/**
@@ -429,8 +445,7 @@ public class FOUserAgent {

/** @return the font base URL */
public String getFontBaseURL() {
String fontBaseURL = getFactory().getFontBaseURL();
return fontBaseURL != null ? fontBaseURL : getBaseURL();
return fontBase != null ? fontBase : getBaseURL();
}

/**

+ 136
- 228
src/java/org/apache/fop/apps/FopFactory.java View File

@@ -26,6 +26,7 @@ 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.Map;
@@ -39,14 +40,13 @@ import javax.xml.transform.stream.StreamSource;
import org.xml.sax.SAXException;

import org.apache.avalon.framework.configuration.Configuration;
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.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.hyphenation.HyphenationTreeResolver;
import org.apache.fop.image.ImageFactory;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
@@ -62,27 +62,6 @@ import org.apache.fop.util.ContentHandlerFactoryRegistry;
*/
public class FopFactory {
/** Defines the default target resolution (72dpi) for FOP */
public static final float DEFAULT_TARGET_RESOLUTION = 72.0f; //dpi

/** Defines the default source resolution (72dpi) for FOP */
private static final float DEFAULT_SOURCE_RESOLUTION = 72.0f; //dpi

/** Defines the default page-height */
private static final String DEFAULT_PAGE_HEIGHT = "11in";
/** Defines the default page-width */
private static final String DEFAULT_PAGE_WIDTH = "8.26in";
/** Defines if FOP should use strict validation for FO and user config */
private static final boolean DEFAULT_STRICT_FO_VALIDATION = true;

/** Defines if FOP should validate the user config strictly */
private static final boolean DEFAULT_STRICT_USERCONFIG_VALIDATION = true;
/** Defines if FOP should use an alternative rule to determine text indents */
private static final boolean DEFAULT_BREAK_INDENT_INHERITANCE = false;

/** logger instance */
private static Log log = LogFactory.getLog(FopFactory.class);
@@ -100,7 +79,7 @@ public class FopFactory {
= new ContentHandlerFactoryRegistry();
/** Our default resolver if none is set */
private URIResolver foURIResolver = new FOURIResolver();
private URIResolver foURIResolver = null;
/** A user settable URI Resolver */
private URIResolver uriResolver = null;
@@ -108,22 +87,23 @@ public class FopFactory {
/** The resolver for user-supplied hyphenation patterns */
private HyphenationTreeResolver hyphResolver;
/** Image factory for creating fop image objects */
private ImageFactory imageFactory = new ImageFactory();

/** user configuration */
private Configuration userConfig = null;
/** Configuration layer used to configure fop */
private FopFactoryConfigurator config = null;
/**
* The base URL for all URL resolutions, especially for
* external-graphics.
*/
private String baseURL;
private String base = null;

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

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

/**
* FOP has the ability, for some FO's, to continue processing even if the
@@ -131,32 +111,36 @@ public class FopFactory {
* behavior for FOP. However, this flag, if set, provides the user the
* ability for FOP to halt on all content model violations if desired.
*/
private boolean strictFOValidation = DEFAULT_STRICT_FO_VALIDATION;
private boolean strictFOValidation = FopFactoryConfigurator.DEFAULT_STRICT_FO_VALIDATION;

/**
* FOP will validate the contents of the user configuration strictly
* (e.g. base-urls and font urls/paths).
*/
private boolean strictUserConfigValidation = DEFAULT_STRICT_USERCONFIG_VALIDATION;
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 = DEFAULT_SOURCE_RESOLUTION;
private float sourceResolution = FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION;

/** Target resolution in dpi */
private float targetResolution = DEFAULT_TARGET_RESOLUTION;
private float targetResolution = FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION;

/** Page height */
private String pageHeight = DEFAULT_PAGE_HEIGHT;
private String pageHeight = FopFactoryConfigurator.DEFAULT_PAGE_HEIGHT;
/** Page width */
private String pageWidth = DEFAULT_PAGE_WIDTH;
private String pageWidth = FopFactoryConfigurator.DEFAULT_PAGE_WIDTH;

/** @see #setBreakIndentInheritanceOnReferenceAreaBoundary(boolean) */
private boolean breakIndentInheritanceOnReferenceAreaBoundary
= DEFAULT_BREAK_INDENT_INHERITANCE;
= FopFactoryConfigurator.DEFAULT_BREAK_INDENT_INHERITANCE;

/** Optional overriding LayoutManagerMaker */
private LayoutManagerMaker lmMakerOverride = null;
@@ -165,14 +149,17 @@ public class FopFactory {
/** Map with cached ICC based ColorSpace objects. */
private Map colorSpaceMap = null;
/**
* Main constructor.
*/
protected FopFactory() {
this.config = new FopFactoryConfigurator(this);
this.elementMappingRegistry = new ElementMappingRegistry(this);
this.foURIResolver = new FOURIResolver(validateUserConfigStrictly());
// Use a synchronized Map - I am not really sure this is needed, but better safe than sorry.
this.colorSpaceMap = Collections.synchronizedMap(new java.util.HashMap());
setUseCache(FopFactoryConfigurator.DEFAULT_USE_CACHE);
}
/**
@@ -335,12 +322,43 @@ public class FopFactory {
return this.lmMakerOverride;
}

/**
* cleans the base url
* @param base
* @return
* @throws MalformedURLException
* @throws URISyntaxException
*/
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 baseURL base URL
* @param base base URL
* @throws MalformedURLException
* @throws URISyntaxException
*/
void setBaseURL(String baseURL) {
this.baseURL = baseURL;
public void setBaseURL(String base) throws MalformedURLException {
this.base = checkBaseURL(base);
}

/**
@@ -348,42 +366,46 @@ public class FopFactory {
* @return the base URL
*/
public String getBaseURL() {
return this.baseURL;
return this.base;
}
/**
* Sets the font base URL.
* @param fontBaseURL font base URL
* @param fontBase font base URL
* @throws MalformedURLException
* @throws URISyntaxException
*/
public void setFontBaseURL(String fontBaseURL) {
this.fontBaseURL = fontBaseURL;
public void setFontBaseURL(String fontBase) throws MalformedURLException {
this.fontBase = checkBaseURL(fontBase);
}

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

/** @return the hyphen base URL */
public String getHyphenBaseURL() {
return hyphenBaseURL;
return this.hyphenBase;
}

/**
* Sets the hyphen base URL.
* @param hyphenBaseURL hythen base URL
*/
public void setHyphenBaseURL(final String hyphenBaseURL) {
if (hyphenBaseURL != null) {
* @param hyphenBase hythen base URL
* @throws MalformedURLException
* @throws URISyntaxException
* */
public void setHyphenBaseURL(final String hyphenBase) throws MalformedURLException {
if (hyphenBase != null) {
this.hyphResolver = new HyphenationTreeResolver() {
public Source resolve(String href) {
return resolveURI(href, hyphenBaseURL);
return resolveURI(href, hyphenBase);
}
};
}
this.hyphenBaseURL = hyphenBaseURL;
this.hyphenBase = checkBaseURL(hyphenBase);
}
/**
* Sets the URI Resolver. It is used for resolving factory-level URIs like hyphenation
* patterns and as backup for URI resolution performed during a rendering run.
@@ -483,8 +505,10 @@ public class FopFactory {
*/
public void setSourceResolution(float dpi) {
this.sourceResolution = dpi;
log.info("source-resolution set to: " + sourceResolution
+ "dpi (px2mm=" + getSourcePixelUnitToMillimeter() + ")");
if (log.isDebugEnabled()) {
log.debug("source-resolution set to: " + sourceResolution
+ "dpi (px2mm=" + getSourcePixelUnitToMillimeter() + ")");
}
}

/** @return the resolution for resolution-dependant output */
@@ -538,7 +562,9 @@ public class FopFactory {
*/
public void setPageHeight(String pageHeight) {
this.pageHeight = pageHeight;
log.info("Default page-height set to: " + pageHeight);
if (log.isDebugEnabled()) {
log.debug("Default page-height set to: " + pageHeight);
}
}
/**
@@ -559,7 +585,9 @@ public class FopFactory {
*/
public void setPageWidth(String pageWidth) {
this.pageWidth = pageWidth;
log.info("Default page-width set to: " + pageWidth);
if (log.isDebugEnabled()) {
log.debug("Default page-width set to: " + pageWidth);
}
}
/**
@@ -595,7 +623,7 @@ public class FopFactory {
public Set getIgnoredNamespace() {
return Collections.unmodifiableSet(this.ignoredNamespaces);
}
//------------------------------------------- Configuration stuff
/**
@@ -605,14 +633,9 @@ public class FopFactory {
* @throws SAXException if a parsing error occurs
*/
public void setUserConfig(File userConfigFile) throws SAXException, IOException {
try {
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
setUserConfig(cfgBuilder.buildFromFile(userConfigFile));
} catch (ConfigurationException e) {
throw new FOPException(e);
}
config.setUserConfig(userConfigFile);
}

/**
* Set the user configuration from an URI.
* @param uri the URI to the configuration file
@@ -620,12 +643,7 @@ public class FopFactory {
* @throws SAXException if a parsing error occurs
*/
public void setUserConfig(String uri) throws SAXException, IOException {
try {
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
setUserConfig(cfgBuilder.build(uri));
} catch (ConfigurationException e) {
throw new FOPException(e);
}
config.setUserConfig(uri);
}
/**
@@ -634,12 +652,7 @@ public class FopFactory {
* @throws FOPException if a configuration problem occurs
*/
public void setUserConfig(Configuration userConfig) throws FOPException {
this.userConfig = userConfig;
try {
configure(userConfig);
} catch (ConfigurationException e) {
throw new FOPException(e);
}
config.setUserConfig(userConfig);
}

/**
@@ -647,162 +660,54 @@ public class FopFactory {
* @return the user configuration
*/
public Configuration getUserConfig() {
return userConfig;
return config.getUserConfig();
}

/**
* Returns the configuration subtree for a specific renderer.
* @param mimeType MIME type of the renderer
* @return the requested configuration subtree, null if there's no configuration
* Is the user configuration to be validated?
* @param strictUserConfigValidation strict user config validation
*/
public Configuration getUserRendererConfig(String mimeType) {
if (userConfig == null || mimeType == null) {
return null;
}
Configuration userRendererConfig = null;

Configuration[] cfgs
= userConfig.getChild("renderers").getChildren("renderer");
for (int i = 0; i < cfgs.length; ++i) {
Configuration child = cfgs[i];
try {
if (child.getAttribute("mime").equals(mimeType)) {
userRendererConfig = child;
break;
}
} catch (ConfigurationException e) {
// silently pass over configurations without mime type
}
}
log.debug((userRendererConfig == null ? "No u" : "U")
+ "ser configuration found for MIME type " + mimeType);
return userRendererConfig;
public void setStrictUserConfigValidation(boolean strictUserConfigValidation) {
this.strictUserConfigValidation = strictUserConfigValidation;
}

/**
* Initializes user agent settings from the user configuration
* file, if present: baseURL, resolution, default page size,...
*
* @throws ConfigurationException when there is an entry that
* misses the required attribute
* Configures the FopFactory.
* @param cfg Avalon Configuration Object
* @see org.apache.avalon.framework.configuration.Configurable
*/
public void configure(Configuration cfg) throws ConfigurationException {
log.info("Initializing FopFactory Configuration");
if (cfg.getChild("strict-configuration", false) != null) {
this.strictUserConfigValidation
= cfg.getChild("strict-configuration").getValueAsBoolean();
}
if (cfg.getChild("strict-validation", false) != null) {
this.strictFOValidation = cfg.getChild("strict-validation").getValueAsBoolean();
}
if (cfg.getChild("base", false) != null) {
try {
setBaseURL(getBaseURLfromConfig(cfg, "base"));
} catch (ConfigurationException e) {
if (strictUserConfigValidation) {
throw e;
}
log.error(e.getMessage());
}
}
if (cfg.getChild("font-base", false) != null) {
try {
setFontBaseURL(getBaseURLfromConfig(cfg, "font-base"));
} catch (ConfigurationException e) {
if (strictUserConfigValidation) {
throw e;
}
log.error(e.getMessage());
}
}
if (cfg.getChild("hyphenation-base", false) != null) {
try {
setHyphenBaseURL(getBaseURLfromConfig(cfg, "hyphenation-base"));
} catch (ConfigurationException e) {
if (strictUserConfigValidation) {
throw e;
}
log.error(e.getMessage());
}
}
if (cfg.getChild("source-resolution", false) != null) {
setSourceResolution(
cfg.getChild("source-resolution").getValueAsFloat(DEFAULT_SOURCE_RESOLUTION));
}
if (cfg.getChild("target-resolution", false) != null) {
setTargetResolution(
cfg.getChild("target-resolution").getValueAsFloat(DEFAULT_TARGET_RESOLUTION));
}
if (cfg.getChild("break-indent-inheritance", false) != null) {
setBreakIndentInheritanceOnReferenceAreaBoundary(
cfg.getChild("break-indent-inheritance").getValueAsBoolean());
}
Configuration pageConfig = cfg.getChild("default-page-settings");
if (pageConfig.getAttribute("height", null) != null) {
setPageHeight(pageConfig.getAttribute("height", DEFAULT_PAGE_HEIGHT));
}
if (pageConfig.getAttribute("width", null) != null) {
setPageWidth(pageConfig.getAttribute("width", DEFAULT_PAGE_WIDTH));
}
* Is the user configuration to be validated?
* @return if the user configuration should be validated
*/
public boolean validateUserConfigStrictly() {
return this.strictUserConfigValidation;
}

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

/**
* Retrieves and verifies a base URL.
* @param cfg The Configuration object to retrieve the base URL from
* @param name the element name for the base URL
* @return the requested base URL or null if not available
* @throws ConfigurationException
*/
public static String getBaseURLfromConfig(Configuration cfg, String name)
throws ConfigurationException {
if (cfg.getChild(name, false) != null) {
try {
String cfgBasePath = cfg.getChild(name).getValue(null);
if (cfgBasePath != null) {
// Is the path a dirname?
File dir = new File(cfgBasePath);
// if (!dir.exists()) {
// throw new ConfigurationException("Base URL '" + name
// + "' references non-existent resource '"
// + cfgBasePath + "'");
// } else if (dir.isDirectory()) {
if (dir.isDirectory()) {
// Yes, convert it into a URL
cfgBasePath = dir.toURL().toExternalForm();
}
// Otherwise, this is already a URL
}
log.info(name + " set to: " + cfgBasePath);
return cfgBasePath;
} catch (MalformedURLException mue) {
throw new ConfigurationException("Base URL '" + name
+ "' in user config is malformed!");
* 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;
}
return null;
}

/**
* Is the user configuration to be validated?
* @param strictUserConfigValidation strict user config validation
* Cache results of font triplet detection/auto-config?
* @return whether this factory is uses the cache
*/
public void setStrictUserConfigValidation(boolean strictUserConfigValidation) {
this.strictUserConfigValidation = strictUserConfigValidation;
public boolean useCache() {
return (this.fontCache != null);
}

/**
* Is the user configuration to be validated?
* @return if the user configuration should be validated
*/
public boolean validateUserConfigStrictly() {
return this.strictUserConfigValidation;
public FontCache getFontCache() {
return this.fontCache;
}
//------------------------------------------- URI resolution

/**
@@ -810,26 +715,29 @@ public class FopFactory {
* Will use the configured resolver and if not successful fall back
* to the default resolver.
* @param uri URI to access
* @param base the base URI to resolve against
* @param baseUri the base URI to resolve against
* @return A {@link javax.xml.transform.Source} object, or null if the URI
* cannot be resolved.
* @see org.apache.fop.apps.FOURIResolver
*/
public Source resolveURI(String uri, String base) {
public Source resolveURI(String uri, String baseUri) {
Source source = null;
//RFC 2397 data URLs don't need to be resolved, just decode them.
boolean bypassURIResolution = uri.startsWith("data:");
if (!bypassURIResolution && uriResolver != null) {
try {
source = uriResolver.resolve(uri, base);
source = uriResolver.resolve(uri, baseUri);
} catch (TransformerException te) {
log.error("Attempt to resolve URI '" + uri + "' failed: ", te);
if (validateUserConfigStrictly()) {
return null;
}
}
}
if (source == null) {
// URI Resolver not configured or returned null, use default resolver
try {
source = foURIResolver.resolve(uri, base);
source = foURIResolver.resolve(uri, baseUri);
} catch (TransformerException te) {
log.error("Attempt to resolve URI '" + uri + "' failed: ", te);
}
@@ -846,18 +754,18 @@ public class FopFactory {
* The FOP URI resolver is used to try and locate the ICC file.
* If that fails null is returned.
*
* @param base a base URI to resolve relative URIs
* @param baseUri a base URI to resolve relative URIs
* @param iccProfileSrc ICC Profile source to return a ColorSpace for
* @return ICC ColorSpace object or null if ColorSpace could not be created
*/
public ColorSpace getColorSpace(String base, String iccProfileSrc) {
public ColorSpace getColorSpace(String baseUri, String iccProfileSrc) {
ColorSpace colorSpace = null;
if (!this.colorSpaceMap.containsKey(base + iccProfileSrc)) {
if (!this.colorSpaceMap.containsKey(baseUri + iccProfileSrc)) {
try {
ICC_Profile iccProfile = null;
// First attempt to use the FOP URI resolver to locate the ICC
// profile
Source src = this.resolveURI(iccProfileSrc, base);
Source src = this.resolveURI(iccProfileSrc, baseUri);
if (src != null && src instanceof StreamSource) {
// FOP URI resolver found ICC profile - create ICC profile
// from the Source
@@ -882,16 +790,16 @@ public class FopFactory {

if (colorSpace != null) {
// Put in cache (not when VM resolved it as we can't control
this.colorSpaceMap.put(base + iccProfileSrc, colorSpace);
this.colorSpaceMap.put(baseUri + iccProfileSrc, colorSpace);
} else {
// TODO To avoid an excessive amount of warnings perhaps
// register a null ColorMap in the colorSpaceMap
log.warn("Color profile '" + iccProfileSrc + "' not found.");
}
} else {
colorSpace = (ColorSpace) this.colorSpaceMap.get(base
colorSpace = (ColorSpace) this.colorSpaceMap.get(baseUri
+ iccProfileSrc);
}
return colorSpace;
}
}
}

+ 241
- 0
src/java/org/apache/fop/apps/FopFactoryConfigurator.java View File

@@ -0,0 +1,241 @@
/*
* 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.apps;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;

import org.apache.avalon.framework.configuration.Configuration;
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.util.LogUtil;
import org.xml.sax.SAXException;

/**
* FopFactory configurator
*/
public class FopFactoryConfigurator {

/** Defines if FOP should use an alternative rule to determine text indents */
public static final boolean DEFAULT_BREAK_INDENT_INHERITANCE = false;
/** Defines if FOP should validate the user config strictly */
public static final boolean DEFAULT_STRICT_USERCONFIG_VALIDATION = true;
/** Defines if FOP should use strict validation for FO and user config */
public static final boolean DEFAULT_STRICT_FO_VALIDATION = true;
/** Defines the default page-width */
public static final String DEFAULT_PAGE_WIDTH = "8.26in";
/** Defines the default page-height */
public static final String DEFAULT_PAGE_HEIGHT = "11in";
/** Defines the default source resolution (72dpi) for FOP */
public static final float DEFAULT_SOURCE_RESOLUTION = 72.0f; //dpi
/** 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);

/** Fop factory */
private FopFactory factory = null;

/** Fop factory configuration */
private Configuration cfg = null;

/**
* Default constructor
* @param factory fop factory
*/
public FopFactoryConfigurator(FopFactory factory) {
super();
this.factory = factory;
}
/**
* Initializes user agent settings from the user configuration
* file, if present: baseURL, resolution, default page size,...
* @param factory fop factory
* @throws FOPException fop exception
*/
public void configure(FopFactory factory) throws FOPException {
if (log.isDebugEnabled()) {
log.debug("Initializing FopFactory Configuration");
}

// strict configuration
if (cfg.getChild("strict-configuration", false) != null) {
try {
factory.setStrictUserConfigValidation(
cfg.getChild("strict-configuration").getValueAsBoolean());
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, false);
}
}
boolean strict = factory.validateUserConfigStrictly();
// strict fo validation
if (cfg.getChild("strict-validation", false) != null) {
try {
factory.setStrictValidation(
cfg.getChild("strict-validation").getValueAsBoolean());
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, strict);
}
}

// base definitions for relative path resolution
if (cfg.getChild("base", false) != null) {
try {
factory.setBaseURL(
cfg.getChild("base").getValue(null));
} catch (MalformedURLException mfue) {
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(
cfg.getChild("hyphenation-base").getValue(null));
} catch (MalformedURLException mfue) {
LogUtil.handleException(log, mfue, strict);
}
}
// renderer options
if (cfg.getChild("source-resolution", false) != null) {
factory.setSourceResolution(
cfg.getChild("source-resolution").getValueAsFloat(
FopFactoryConfigurator.DEFAULT_SOURCE_RESOLUTION));
if (log.isDebugEnabled()) {
log.debug("source-resolution set to: " + factory.getSourceResolution()
+ "dpi (px2mm=" + factory.getSourcePixelUnitToMillimeter() + ")");
}
}
if (cfg.getChild("target-resolution", false) != null) {
factory.setTargetResolution(
cfg.getChild("target-resolution").getValueAsFloat(
FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION));
if (log.isDebugEnabled()) {
log.debug("target-resolution set to: " + factory.getTargetResolution()
+ "dpi (px2mm=" + factory.getTargetPixelUnitToMillimeter()
+ ")");
}
}
if (cfg.getChild("break-indent-inheritance", false) != null) {
try {
factory.setBreakIndentInheritanceOnReferenceAreaBoundary(
cfg.getChild("break-indent-inheritance").getValueAsBoolean());
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, strict);
}
}
Configuration pageConfig = cfg.getChild("default-page-settings");
if (pageConfig.getAttribute("height", null) != null) {
factory.setPageHeight(
pageConfig.getAttribute("height", FopFactoryConfigurator.DEFAULT_PAGE_HEIGHT));
if (log.isInfoEnabled()) {
log.info("Default page-height set to: " + factory.getPageHeight());
}
}
if (pageConfig.getAttribute("width", null) != null) {
factory.setPageWidth(
pageConfig.getAttribute("width", FopFactoryConfigurator.DEFAULT_PAGE_WIDTH));
if (log.isInfoEnabled()) {
log.info("Default page-width set to: " + factory.getPageWidth());
}
}

// 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);
}
}
}
/**
* Set the user configuration.
* @param userConfigFile the configuration file
* @throws IOException if an I/O error occurs
* @throws SAXException if a parsing error occurs
*/
public void setUserConfig(File userConfigFile) throws SAXException, IOException {
try {
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
setUserConfig(cfgBuilder.buildFromFile(userConfigFile));
} catch (ConfigurationException e) {
throw new FOPException(e);
}
}
/**
* Set the user configuration from an URI.
* @param uri the URI to the configuration file
* @throws IOException if an I/O error occurs
* @throws SAXException if a parsing error occurs
*/
public void setUserConfig(String uri) throws SAXException, IOException {
try {
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
setUserConfig(cfgBuilder.build(uri));
} catch (ConfigurationException e) {
throw new FOPException(e);
}
}
/**
* Set the user configuration.
* @param cfg avalon configuration
* @throws FOPException if a configuration problem occurs
*/
public void setUserConfig(Configuration cfg) throws FOPException {
this.cfg = cfg;
configure(this.factory);
}
/**
* Get the avalon user configuration.
* @return the user configuration
*/
public Configuration getUserConfig() {
return this.cfg;
}
}

+ 1
- 1
src/java/org/apache/fop/area/AreaTreeParser.java View File

@@ -1060,7 +1060,7 @@ public class AreaTreeParser {
if (fontName != null) {
String fontStyle = attributes.getValue("font-style");
int fontWeight = getAttributeAsInteger(
attributes, "font-weight", Font.NORMAL);
attributes, "font-weight", Font.WEIGHT_NORMAL);
area.addTrait(trait,
FontInfo.createFontKey(fontName, fontStyle, fontWeight));
}

+ 3
- 3
src/java/org/apache/fop/cli/CommandLineOptions.java View File

@@ -143,7 +143,7 @@ public class CommandLineOptions {
dumpConfiguration();
}
checkSettings();
createUserConfig();
setUserConfig();
//Factory config is set up, now we can create the user agent
foUserAgent = factory.newFOUserAgent();
@@ -772,11 +772,11 @@ public class CommandLineOptions {
} // end checkSettings

/**
* Create the user configuration.
* Sets the user configuration.
* @throws FOPException if creating the user configuration fails
* @throws IOException
*/
private void createUserConfig() throws FOPException, IOException {
private void setUserConfig() throws FOPException, IOException {
if (userConfigFile == null) {
return;
}

+ 117
- 0
src/java/org/apache/fop/fonts/CachedFontInfo.java View File

@@ -0,0 +1,117 @@
/*
* 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.io.File;
import java.util.List;

import org.apache.xml.utils.URI;
import org.apache.xml.utils.URI.MalformedURIException;

/**
* Font info stored in the cache
*/
public class CachedFontInfo extends EmbedFontInfo {

/** Serialization Version UID */
private static final long serialVersionUID = 240028291961081894L;
/** file modify date (if available) */
private long lastModified = -1;

/**
* Returns a file given a list of urls
* @param urls array of possible font urls
* @return file font file
*/
public static File getFileFromUrls(String[] urls) {
for (int i = 0; i < urls.length; i++) {
String urlStr = urls[i];
if (urlStr != null) {
if (urlStr.startsWith("file:")) {
URI uri;
try {
uri = new URI(urlStr);
urlStr = uri.getPath();
} catch (MalformedURIException e) {
// do nothing
}
}
File fontFile = new File(urlStr);
if (fontFile.exists() && fontFile.canRead()) {
return fontFile;
}
}
}
return null;
}

/**
* Default constructor
* @param metricsFile metrics file
* @param kerning kerning
* @param fontTriplets font triplets
* @param embedFile embed file
* @param lastModified timestamp that this font was last modified
*/
public CachedFontInfo(String metricsFile, boolean kerning, List fontTriplets,
String embedFile, long lastModified) {
super(metricsFile, kerning, fontTriplets, embedFile);
this.lastModified = lastModified;
}

/**
* Constructor
* @param fontInfo an existing embed font info
*/
public CachedFontInfo(EmbedFontInfo fontInfo) {
super(fontInfo.metricsFile, fontInfo.kerning, fontInfo.fontTriplets, fontInfo.embedFile);
// try and determine modified date
File fontFile = getFileFromUrls(new String[] {embedFile, metricsFile});
if (fontFile != null ) {
this.lastModified = fontFile.lastModified();
}
}

/**
* Gets the modified timestamp for font file (not always available)
* @return modified timestamp
*/
public long lastModified() {
return this.lastModified;
}

/**
* Gets the modified timestamp for font file
* (used for the purposes of font info caching)
* @param lastModified modified font file timestamp
*/
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}
/**
* @return string representation of this object
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + ", lastModified=" + lastModified;
}
}

+ 25
- 2
src/java/org/apache/fop/fonts/CustomFont.java View File

@@ -30,8 +30,9 @@ public abstract class CustomFont extends Typeface
implements FontDescriptor, MutableFont {

private String fontName = null;
private String fontSubName = null;
private String embedFileName = null;
protected String embedResourceName = null;
private String embedResourceName = null;
private FontResolver resolver = null;
private int capHeight = 0;
@@ -51,7 +52,6 @@ public abstract class CustomFont extends Typeface

private boolean useKerning = true;


/**
* @see org.apache.fop.fonts.FontMetrics#getFontName()
*/
@@ -59,6 +59,21 @@ public abstract class CustomFont extends Typeface
return fontName;
}

/**
* @see org.apache.fop.fonts.FontMetrics#getStrippedFontName()
*/
public String getStrippedFontName() {
return FontUtil.stripWhiteSpace(fontName);
}

/**
* Returns font's subfamily name.
* @return the font's subfamily name
*/
public String getFontSubName() {
return fontSubName;
}

/**
* Returns an URI representing an embeddable font file. The URI will often
* be a filename or an URL.
@@ -238,6 +253,14 @@ public abstract class CustomFont extends Typeface
this.fontName = name;
}

/**
* Sets the font's subfamily name.
* @param subFamilyName the subfamily name of the font
*/
public void setFontSubFamilyName(String subFamilyName) {
this.fontSubName = subFamilyName;
}
/**
* @see org.apache.fop.fonts.MutableFont#setEmbedFileName(String)
*/

+ 21
- 8
src/java/org/apache/fop/fonts/EmbedFontInfo.java View File

@@ -19,17 +19,26 @@
package org.apache.fop.fonts;

import java.io.Serializable;
import java.util.List;

/**
* FontInfo contains meta information on fonts (where is the metrics file etc.)
*/
public class EmbedFontInfo {
public class EmbedFontInfo implements Serializable {
private String metricsFile, embedFile;
private boolean kerning;
private List fontTriplets;

/** Serialization Version UID */
private static final long serialVersionUID = -9075848379822693399L;
/** filename of the metrics file */
protected String metricsFile;
/** filename of the main font file */
protected String embedFile;
/** false, to disable kerning */
protected boolean kerning;
/** the list of associated font triplets */
protected List fontTriplets;
/**
* Main constructor
* @param metricsFile Path to the xml file containing font metrics
@@ -44,7 +53,7 @@ public class EmbedFontInfo {
this.kerning = kerning;
this.fontTriplets = fontTriplets;
}
/**
* Returns the path to the metrics file
* @return the metrics file path
@@ -76,6 +85,10 @@ public class EmbedFontInfo {
public List getFontTriplets() {
return fontTriplets;
}

/** @see java.lang.Object#toString() */
public String toString() {
return "metrics-url=" + metricsFile + ",embed-url=" + embedFile
+ ", kerning=" + kerning + ", font-triplet=" + fontTriplets;
}
}


+ 15
- 5
src/java/org/apache/fop/fonts/Font.java View File

@@ -27,12 +27,22 @@ import java.util.Map;
*/
public class Font {

/** Default fallback key */
public static final FontTriplet DEFAULT_FONT = new FontTriplet("any", "normal", 400);
/** Normal font weight */
public static final int NORMAL = 400;
/** Bold font weight */
public static final int BOLD = 700;
public static final int WEIGHT_BOLD = 700;

/** Normal font weight */
public static final int WEIGHT_NORMAL = 400;

/** Normal font style */
public static final String STYLE_NORMAL = "normal";

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

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


private String fontName;
private FontTriplet triplet;

+ 330
- 0
src/java/org/apache/fop/fonts/FontCache.java View File

@@ -0,0 +1,330 @@
/*
* 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.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.FOPException;
import org.apache.fop.util.LogUtil;

/**
* Fop cache (currently only used for font info caching)
*/
public final class FontCache implements Serializable {
/** Serialization Version UID */
private static final long serialVersionUID = 605232520271754717L;

/** logging instance */
private static Log log = LogFactory.getLog(FontCache.class);

/** FOP's user directory name */
private static final String FOP_USER_DIR = ".fop";

/** 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;
/** change lock */
private transient Object changeLock = new Object();
/** master mapping of font url -> font info */
private Map fontMap = new java.util.HashMap();

/** mapping of font url -> file modified date */
private Map failedFontMap = new java.util.HashMap();

/**
* Default constructor
*/
public FontCache() {
//nop
}

private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.changeLock = new Object(); //Initialize transient field
}

private static File getUserHome() {
String s = System.getProperty("user.home");
if (s != null) {
File userDir = new File(s);
if (userDir.exists()) {
return userDir;
}
}
return null;
}
/**
* Returns the default font cache file.
* @param forWriting true if the user directory should be created
* @return the default font cache file
*/
public static File getDefaultCacheFile(boolean forWriting) {
File userHome = getUserHome();
if (userHome != null) {
File fopUserDir = new File(userHome, FOP_USER_DIR);
if (forWriting) {
fopUserDir.mkdir();
}
return new File(fopUserDir, DEFAULT_CACHE_FILENAME);
}
return new File(FOP_USER_DIR);
}
/**
* Reads the default font cache file and returns its contents.
* @return the font cache deserialized from the file (or null if no cache file exists or if
* it could not be read)
*/
public static FontCache load() {
return loadFrom(getDefaultCacheFile(false));
}
/**
* Reads a font cache file and returns its contents.
* @param cacheFile the cache file
* @return the font cache deserialized from the file (or null if no cache file exists or if
* it could not be read)
*/
public static FontCache loadFrom(File cacheFile) {
if (cacheFile.exists()) {
try {
if (log.isTraceEnabled()) {
log.trace("Loading font cache from " + cacheFile.getCanonicalPath());
}
InputStream in = new java.io.FileInputStream(cacheFile);
in = new java.io.BufferedInputStream(in);
ObjectInputStream oin = new ObjectInputStream(in);
try {
return (FontCache)oin.readObject();
} finally {
IOUtils.closeQuietly(oin);
}
} catch (ClassNotFoundException e) {
//We don't really care about the exception since it's just a cache file
log.warn("Could not read font cache. Discarding font cache file. Reason: "
+ e.getMessage());
} catch (IOException ioe) {
//We don't really care about the exception since it's just a cache file
log.warn("I/O exception while reading font cache (" + ioe.getMessage()
+ "). Discarding font cache file.");
}
}
return null;
}
/**
* Writes the font cache to disk.
* @throws FOPException fop exception
*/
public void save() throws FOPException {
saveTo(getDefaultCacheFile(true));
}
/**
* Writes the font cache to disk.
* @param cacheFile the file to write to
* @throws FOPException fop exception
*/
public void saveTo(File cacheFile) throws FOPException {
synchronized (changeLock) {
if (changed) {
try {
if (log.isTraceEnabled()) {
log.trace("Writing font cache to " + cacheFile.getCanonicalPath());
}
OutputStream out = new java.io.FileOutputStream(cacheFile);
out = new java.io.BufferedOutputStream(out);
ObjectOutputStream oout = new ObjectOutputStream(out);
try {
oout.writeObject(this);
} finally {
IOUtils.closeQuietly(oout);
}
} catch (IOException ioe) {
LogUtil.handleException(log, ioe, true);
}
changed = false;
log.trace("Cache file written.");
}
}
}

/**
* creates a key given a font info for the font mapping
* @param fontInfo font info
* @return font cache key
*/
protected static String getCacheKey(EmbedFontInfo fontInfo) {
if (fontInfo != null) {
String embedFile = fontInfo.getEmbedFile();
String metricsFile = fontInfo.getMetricsFile();
return (embedFile != null) ? embedFile : metricsFile;
}
return null;
}

/**
* cache has been updated since it was read
* @return if this cache has changed
*/
public boolean hasChanged() {
return this.changed;
}
/**
* is this font in the cache?
* @param embedUrl font info
* @return boolean
*/
public boolean containsFont(String embedUrl) {
if (embedUrl != null) {
return fontMap.containsKey(embedUrl);
}
return false;
}

/**
* is this font info in the cache?
* @param fontInfo font info
* @return font
*/
public boolean containsFont(EmbedFontInfo fontInfo) {
if (fontInfo != null) {
return fontMap.containsKey(getCacheKey(fontInfo));
}
return false;
}

/**
* adds a font info to cache
* @param fontInfo font info
*/
public void addFont(EmbedFontInfo fontInfo) {
String cacheKey = getCacheKey(fontInfo);
synchronized (changeLock) {
if (!containsFont(cacheKey)) {
if (log.isTraceEnabled()) {
log.trace("Font added to cache: " + cacheKey);
}
if (fontInfo instanceof CachedFontInfo) {
fontMap.put(cacheKey, fontInfo);
} else {
fontMap.put(cacheKey, new CachedFontInfo(fontInfo));
}
changed = true;
}
}
}

/**
* returns a font from the cache
* @param embedUrl font info
* @return boolean
*/
public CachedFontInfo getFont(String embedUrl) {
if (containsFont(embedUrl)) {
return (CachedFontInfo)fontMap.get(embedUrl);
}
return null;
}
/**
* removes font from cache
* @param embedUrl embed url
*/
public void removeFont(String embedUrl) {
synchronized (changeLock) {
if (containsFont(embedUrl)) {
if (log.isTraceEnabled()) {
log.trace("Font removed from cache: " + embedUrl);
}
fontMap.remove(embedUrl);
changed = true;
}
}
}
/**
* has this font previously failed to load?
* @param embedUrl embed url
* @param lastModified last modified
* @return whether this is a failed font
*/
public boolean isFailedFont(String embedUrl, long lastModified) {
if (failedFontMap.containsKey(embedUrl)) {
synchronized (changeLock) {
long failedLastModified = ((Long)failedFontMap.get(embedUrl)).longValue();
if (lastModified != failedLastModified) {
// this font has been changed so lets remove it
// from failed font map for now
failedFontMap.remove(embedUrl);
changed = true;
}
}
return true;
}
return false;
}

/**
* 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));
changed = true;
}
}
}

/**
* Clears font cache
*/
public void clear() {
synchronized (changeLock) {
if (log.isTraceEnabled()) {
log.trace("Font cache cleared.");
}
fontMap.clear();
failedFontMap.clear();
changed = true;
}
}
}

+ 5
- 6
src/java/org/apache/fop/fonts/FontInfo.java View File

@@ -130,6 +130,9 @@ public class FontInfo {
*/
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;
// first try given parameters
@@ -146,13 +149,13 @@ public class FontInfo {
// only if the font may be substituted
// fallback 1: try the same font-family and weight with default style
if (f == null) {
key = createFontKey(family, "normal", weight);
key = createFontKey(family, Font.STYLE_NORMAL, weight);
f = getInternalFontKey(key);
}
// fallback 2: try the same font-family with default style and weight
if (f == null) {
key = createFontKey(family, "normal", 400);
key = createFontKey(family, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL);
f = getInternalFontKey(key);
}
@@ -426,8 +429,4 @@ public class FontInfo {
return 0;
}
}
}




+ 90
- 10
src/java/org/apache/fop/fonts/FontLoader.java View File

@@ -19,6 +19,7 @@
package org.apache.fop.fonts;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
@@ -28,6 +29,8 @@ import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.truetype.TTFFontLoader;
import org.apache.fop.fonts.type1.Type1FontLoader;
@@ -36,6 +39,51 @@ import org.apache.fop.fonts.type1.Type1FontLoader;
*/
public abstract class FontLoader {
/**
* logging instance
*/
protected static Log log = LogFactory.getLog(FontLoader.class);
/** URI representing the font file */
protected String fontFileURI = null;
/** the InputStream to load the font from */
protected InputStream in = null;
/** the FontResolver to use for font URI resolution */
protected FontResolver resolver = null;
/** the loaded font */
protected CustomFont returnFont = null;
/** true if the font has been loaded */
protected boolean loaded = false;
/**
* Default constructor.
* @param fontFileURI the URI to the PFB file of a Type 1 font
* @param in the InputStream reading the PFM file of a Type 1 font
* @param resolver the font resolver used to resolve URIs
*/
public FontLoader(String fontFileURI, InputStream in, FontResolver resolver) {
this.fontFileURI = fontFileURI;
this.in = in;
this.resolver = resolver;
}
private static boolean isType1(String fontURI) {
return fontURI.toLowerCase().endsWith(".pfb");
}
/**
* Loads a custom font from a File. In the case of Type 1 fonts, the PFB file must be specified.
* @param fontFile the File representation of the font
* @param resolver the font resolver to use when resolving URIs
* @return the newly loaded font
* @throws IOException In case of an I/O error
*/
public static CustomFont loadFont(File fontFile, FontResolver resolver)
throws IOException {
return loadFont(fontFile.getAbsolutePath(), resolver);
}
/**
* Loads a custom font from a URI. In the case of Type 1 fonts, the PFB file must be specified.
* @param fontFileURI the URI to the font
@@ -45,21 +93,38 @@ public abstract class FontLoader {
*/
public static CustomFont loadFont(String fontFileURI, FontResolver resolver)
throws IOException {
FontLoader loader;
fontFileURI = fontFileURI.trim();
String name = fontFileURI.toLowerCase();
String effURI;
boolean type1 = false;
if (name.endsWith(".pfb")) {
type1 = true;
boolean type1 = isType1(fontFileURI);
if (type1) {
effURI = name.substring(0, fontFileURI.length() - 4) + ".pfm";
} else {
effURI = fontFileURI;
}
if (log.isDebugEnabled()) {
log.debug("opening " + effURI);
}
InputStream in = openFontFile(resolver, effURI);
return loadFontFromInputStream(fontFileURI, resolver, type1, in);
}
/**
* Loads and returns a font given an input stream.
* @param fontFileURI font file uri
* @param resolver font resolver
* @param isType1 is it a type1 font?
* @param in input stream
* @return the loaded font.
* @throws IOException In case of an I/O error
*/
protected static CustomFont loadFontFromInputStream(
String fontFileURI, FontResolver resolver, boolean isType1,
InputStream in)
throws IOException {
FontLoader loader;
try {
if (type1) {
if (isType1) {
loader = new Type1FontLoader(fontFileURI, in, resolver);
} else {
loader = new TTFFontLoader(fontFileURI, in, resolver);
@@ -70,6 +135,14 @@ public abstract class FontLoader {
}
}
/**
* Opens a font file and returns an input stream.
* @param resolver the FontResolver to use for font URI resolution
* @param uri the URI representing the font
* @return the InputStream to read the font from.
* @throws IOException In case of an I/O error
* @throws MalformedURLException If an invalid URL is built
*/
private static InputStream openFontFile(FontResolver resolver, String uri)
throws IOException, MalformedURLException {
InputStream in = null;
@@ -96,11 +169,18 @@ public abstract class FontLoader {
}
return in;
}
/**
* @return the font loaded by this loader
* Reads/parses the font data.
* @throws IOException In case of an I/O error
*/
public abstract CustomFont getFont();
protected abstract void read() throws IOException;
/** @see org.apache.fop.fonts.FontLoader#getFont() */
public CustomFont getFont() throws IOException {
if (!loaded) {
read();
}
return this.returnFont;
}
}

+ 64
- 201
src/java/org/apache/fop/fonts/FontSetup.java View File

@@ -34,16 +34,11 @@ import org.apache.fop.fonts.base14.CourierOblique;
import org.apache.fop.fonts.base14.CourierBoldOblique;
import org.apache.fop.fonts.base14.Symbol;
import org.apache.fop.fonts.base14.ZapfDingbats;
import org.apache.fop.render.PrintRenderer;

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

// Avalon
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;

// Java
import java.util.List;

@@ -62,8 +57,8 @@ public class FontSetup {
/**
* logging instance
*/
protected static Log log = LogFactory.getLog("org.apache.fop.fonts");
protected static Log log = LogFactory.getLog(FontSetup.class);
/**
* Sets up the font info object.
*
@@ -113,52 +108,52 @@ public class FontSetup {
// fontInfo.addMetrics("F17", new BauerBodoniBoldItalic());

/* any is treated as serif */
fontInfo.addFontProperties("F5", "any", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "any", "italic", Font.NORMAL);
fontInfo.addFontProperties("F6", "any", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F7", "any", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "any", "italic", Font.BOLD);
fontInfo.addFontProperties("F8", "any", "oblique", Font.BOLD);
fontInfo.addFontProperties("F1", "sans-serif", "normal", Font.NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "italic", Font.NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", "normal", Font.BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "oblique", Font.BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "italic", Font.BOLD);
fontInfo.addFontProperties("F5", "serif", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "serif", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "serif", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "serif", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "serif", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "serif", "italic", Font.BOLD);
fontInfo.addFontProperties("F9", "monospace", "normal", Font.NORMAL);
fontInfo.addFontProperties("F10", "monospace", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F10", "monospace", "italic", Font.NORMAL);
fontInfo.addFontProperties("F11", "monospace", "normal", Font.BOLD);
fontInfo.addFontProperties("F12", "monospace", "oblique", Font.BOLD);
fontInfo.addFontProperties("F12", "monospace", "italic", Font.BOLD);
fontInfo.addFontProperties("F1", "Helvetica", "normal", Font.NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "italic", Font.NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", "normal", Font.BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "oblique", Font.BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "italic", Font.BOLD);
fontInfo.addFontProperties("F5", "Times", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "Times", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "Times", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "Times", "italic", Font.BOLD);
fontInfo.addFontProperties("F9", "Courier", "normal", Font.NORMAL);
fontInfo.addFontProperties("F10", "Courier", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F10", "Courier", "italic", Font.NORMAL);
fontInfo.addFontProperties("F11", "Courier", "normal", Font.BOLD);
fontInfo.addFontProperties("F12", "Courier", "oblique", Font.BOLD);
fontInfo.addFontProperties("F12", "Courier", "italic", Font.BOLD);
fontInfo.addFontProperties("F13", "Symbol", "normal", Font.NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", Font.NORMAL);
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);
@@ -166,20 +161,20 @@ public class FontSetup {
// fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD);

/* for compatibility with PassiveTex */
fontInfo.addFontProperties("F5", "Times-Roman", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "italic", Font.BOLD);
fontInfo.addFontProperties("F5", "Times Roman", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.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", "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.NORMAL);
"normal", Font.WEIGHT_NORMAL);

/* Add configured fonts */
addConfiguredFonts(fontInfo, embedList, 15, resolver);
@@ -218,10 +213,7 @@ public class FontSetup {
reader.setFontEmbedPath(configFontInfo.getEmbedFile());
fontInfo.addMetrics(internalName, reader.getFont());
*/
LazyFont font = new LazyFont(configFontInfo.getEmbedFile(),
metricsFile,
configFontInfo.getKerning(),
resolver);
LazyFont font = new LazyFont(configFontInfo, resolver);
fontInfo.addMetrics(internalName, font);

List triplets = configFontInfo.getFontTriplets();
@@ -237,7 +229,7 @@ public class FontSetup {
}

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

/** @see org.apache.fop.fonts.FontResolver#resolve(java.lang.String) */
@@ -245,135 +237,6 @@ public class FontSetup {
//Minimal functionality here
return new StreamSource(href);
}
};
}
/**
* Builds a list of EmbedFontInfo objects for use with the setup() method.
*
* @param cfg Configuration object
* @param renderer calling Renderer object
* @return List the newly created list of fonts
* @throws ConfigurationException if something's wrong with the config data
*/
public static List buildFontListFromConfiguration(Configuration cfg, PrintRenderer renderer)
throws ConfigurationException {
List fontList = new java.util.ArrayList();
FontResolver fontResolver = (renderer != null ? renderer.getFontResolver() : null);
if (fontResolver == null) {
//Ensure that we have minimal font resolution capabilities
fontResolver = FontSetup.createMinimalFontResolver();
}
boolean strict = false;
if (renderer != null) {
strict = renderer.getUserAgent().getFactory().validateUserConfigStrictly();
}
Configuration[] fonts = cfg.getChildren("fonts");
for (int f = 0; f < fonts.length; f++) {
Configuration[] font = fonts[f].getChildren("font");
for (int i = 0; i < font.length; i++) {
String metricsUrl = font[i].getAttribute("metrics-url", null);
String embedUrl = font[i].getAttribute("embed-url", null);
if (metricsUrl == null && embedUrl == null) {
if (strict) {
throw new ConfigurationException(
"Font configuration without metric-url or embed-url");
}
log.error("Font configuration without metric-url or embed-url");
continue;
}
if (metricsUrl != null && fontResolver.resolve(metricsUrl) == null) {
if (strict) {
throw new ConfigurationException("Failed to resolve font metric-url '"
+ metricsUrl + "'");
}
log.error("Failed to resolve font metric-url '" + metricsUrl + "'");
continue;
}
if (embedUrl != null && fontResolver.resolve(embedUrl) == null) {
if (strict) {
throw new ConfigurationException("Failed to resolve font with embed-url '"
+ embedUrl + "'");
}
log.error("Failed to resolve font with embed-url '" + embedUrl + "'");
continue;
}
boolean useKerning = font[i].getAttributeAsBoolean("kerning", false);
Configuration[] triple = font[i].getChildren("font-triplet");
List tripleList = new java.util.ArrayList();
for (int j = 0; j < triple.length; j++) {
String name = triple[j].getAttribute("name");
if (name == null) {
if (strict) {
throw new ConfigurationException("font-triplet without name");
}
log.error("font-triplet without name");
continue;
}
String weightStr = triple[j].getAttribute("weight");
if (weightStr == null) {
if (strict) {
throw new ConfigurationException("font-triplet without weight");
}
log.error("font-triplet without weight");
continue;
}
int weight = FontUtil.parseCSS2FontWeight(weightStr);
String style = triple[j].getAttribute("style");
if (style == null) {
if (strict) {
throw new ConfigurationException("font-triplet without style");
}
log.error("font-triplet without style");
continue;
}
tripleList.add(FontInfo.createFontKey(name,
style, weight));
}
EmbedFontInfo configFontInfo = new EmbedFontInfo(metricsUrl,
useKerning, tripleList, embedUrl);
if (log.isDebugEnabled()) {
log.debug("Adding font " + configFontInfo.getEmbedFile()
+ ", metric file " + configFontInfo.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());
}
}
fontList.add(configFontInfo);
}
}
return fontList;
}

/**
* Builds a list of EmbedFontInfo objects for use with the setup() method.
*
* @param cfg Configuration object
* @return List the newly created list of fonts
* @throws ConfigurationException if something's wrong with the config data
*/
public static List buildFontListFromConfiguration(Configuration cfg)
throws ConfigurationException {
return buildFontListFromConfiguration(cfg, null);
}
}
}

+ 20
- 0
src/java/org/apache/fop/fonts/FontUtil.java View File

@@ -57,4 +57,24 @@ public class FontUtil {
return weight;
}

/**
* Removes all white space from a string (used primarily for font names)
* @param s 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);
}
}
return sb.toString();
}

}

+ 12
- 6
src/java/org/apache/fop/fonts/LazyFont.java View File

@@ -54,14 +54,21 @@ public class LazyFont extends Typeface implements FontDescriptor {
* @param useKerning True, if kerning should be enabled
* @param resolver the font resolver to handle font URIs
*/
public LazyFont(String fontEmbedPath, String metricsFileName
, boolean useKerning, FontResolver resolver) {
this.metricsFileName = metricsFileName;
this.fontEmbedPath = fontEmbedPath;
this.useKerning = useKerning;
public LazyFont(EmbedFontInfo fontInfo, FontResolver resolver) {
this.metricsFileName = fontInfo.getMetricsFile();
this.fontEmbedPath = fontInfo.getEmbedFile();
this.useKerning = fontInfo.getKerning();
this.resolver = resolver;
}

/**
* String representation of LazyFont
*/
public String toString() {
return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + ", kerning=" + useKerning );
}
private void load(boolean fail) {
if (!isMetricsLoaded) {
try {
@@ -327,6 +334,5 @@ public class LazyFont extends Typeface implements FontDescriptor {
load(true);
return realFontDescriptor.isEmbeddable();
}

}


+ 2
- 21
src/java/org/apache/fop/fonts/MultiByteFont.java View File

@@ -108,28 +108,9 @@ public class MultiByteFont extends CIDFont {
public void setCIDType(CIDFontType cidType) {
this.cidType = cidType;
}

/**
* Removes all white space from a string (used primarily for font names)
* @param s 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);
}
}
return sb.toString();
}
private String getPrefixedFontName() {
return namePrefix + stripWhiteSpace(super.getFontName());
return namePrefix + FontUtil.stripWhiteSpace(super.getFontName());
}
/**
@@ -147,7 +128,7 @@ public class MultiByteFont extends CIDFont {
* @see org.apache.fop.fonts.FontDescriptor#isEmbeddable()
*/
public boolean isEmbeddable() {
return !(getEmbedFileName() == null && embedResourceName == null);
return !(getEmbedFileName() == null && getEmbedResourceName() == null);
}

/**

+ 3
- 18
src/java/org/apache/fop/fonts/apps/TTFReader.java View File

@@ -27,6 +27,7 @@ import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.LogFactory;
import org.apache.fop.Version;
import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.truetype.FontFileReader;
import org.apache.fop.fonts.truetype.TTFCmapEntry;
import org.apache.fop.fonts.truetype.TTFFile;
@@ -258,10 +259,10 @@ public class TTFReader extends AbstractFontReader {
// "Perpetua-Bold", but the TrueType spec says that in the ttf file
// it should be "Perpetua,Bold".

String s = stripWhiteSpace(ttf.getPostScriptName());
String s = FontUtil.stripWhiteSpace(ttf.getPostScriptName());

if (fontName != null) {
el.appendChild(doc.createTextNode(stripWhiteSpace(fontName)));
el.appendChild(doc.createTextNode(FontUtil.stripWhiteSpace(fontName)));
} else {
el.appendChild(doc.createTextNode(s));
}
@@ -450,22 +451,6 @@ public class TTFReader extends AbstractFontReader {
}


private String stripWhiteSpace(String s) {
char[] ch = new char[s.length()];
s.getChars(0, s.length(), ch, 0);
StringBuffer stb = new StringBuffer();
for (int i = 0; i < ch.length; i++) {
if (ch[i] != ' '
&& ch[i] != '\r'
&& ch[i] != '\n'
&& ch[i] != '\t') {
stb.append(ch[i]);
}
}

return stb.toString();
}
/**
* Bugzilla 40739, check that attr has a metrics-version attribute
* compatible with ours.

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

@@ -0,0 +1,158 @@
/*
* 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.autodetect;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Helps to autodetect/locate available operating system fonts.
*/
public class FontFileFinder extends DirectoryWalker implements FontFinder {

/** logging instance */
private final Log log = LogFactory.getLog(FontFileFinder.class);

/** default depth limit of recursion when searching for font files **/
public static final int DEFAULT_DEPTH_LIMIT = -1;
/**
* Default constructor
*/
public FontFileFinder() {
super(getDirectoryFilter(), getFileFilter(), DEFAULT_DEPTH_LIMIT);
}

/**
* Constructor
* @param depthLimit recursion depth limit
*/
public FontFileFinder(int depthLimit) {
super(getDirectoryFilter(), getFileFilter(), depthLimit);
}
/**
* Font directory filter. Currently ignores hidden directories.
* @return IOFileFilter font directory filter
*/
protected static IOFileFilter getDirectoryFilter() {
return FileFilterUtils.andFileFilter(
FileFilterUtils.directoryFileFilter(),
FileFilterUtils.notFileFilter(FileFilterUtils.prefixFileFilter("."))
);
}
/**
* Font file filter. Currently searches for files with .ttf and .pfb extensions.
* @return IOFileFilter font file filter
*/
protected static IOFileFilter getFileFilter() {
return FileFilterUtils.andFileFilter(
FileFilterUtils.fileFileFilter(),
FileFilterUtils.orFileFilter(
FileFilterUtils.suffixFileFilter(".ttf"),
FileFilterUtils.suffixFileFilter(".pfb")
)
);
}
/**
* @param directory directory to handle
* @param depth recursion depth
* @param results collection
* @return whether directory should be handled
* @see org.apache.commons.io.DirectoryWalker#handleDirectory(File, int, Collection)
*/
protected boolean handleDirectory(File directory, int depth, Collection results) {
return true;
}

/**
* @param file file to handle
* @param depth recursion depth
* @param results collection
* @see org.apache.commons.io.DirectoryWalker#handleFile(File, int, Collection)
*/
protected void handleFile(File file, int depth, Collection results) {
results.add(file);
}
/**
* @param directory the directory being processed
* @param depth the current directory level
* @param results the colleciton of results objects
* @see org.apache.commons.io.DirectoryWalker.handleDirectoryEnd
*/
protected void handleDirectoryEnd(File directory, int depth, Collection results) {
if (log.isDebugEnabled()) {
log.debug(directory + ": found " + results.size() + " font"
+ ((results.size() == 1) ? "" : "s"));
}
}
/**
* Automagically finds a list of font files on local system
*
* @return list of font files
* @throws IOException io exception
* @see org.apache.fop.fonts.autodetect.FontFinder#find()
*/
public List find() throws IOException {
final FontFinder fontDirFinder;
final String osName = System.getProperty("os.name");
if (osName.startsWith("Windows")) {
fontDirFinder = new WindowsFontDirFinder();
} else {
if (osName.startsWith("Mac")) {
fontDirFinder = new MacFontDirFinder();
} else {
fontDirFinder = new UnixFontDirFinder();
}
}
List fontDirs = fontDirFinder.find();
List results = new java.util.ArrayList();
for (Iterator iter = fontDirs.iterator(); iter.hasNext();) {
super.walk((File)iter.next(), results);
}
return results;
}

/**
* Searches a given directory for font files
*
* @param dir directory to search
* @return list of font files
* @throws IOException io exception
*/
public List find(String dir) throws IOException {
List results = new java.util.ArrayList();
super.walk(new File(dir), results);
return results;
}
}

+ 38
- 0
src/java/org/apache/fop/fonts/autodetect/FontFinder.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.autodetect;

import java.io.IOException;
import java.util.List;

/**
* Implementers provide find method for searching native operating system
* for available fonts.
*/
public interface FontFinder {
/**
* Finds a list of font files.
* @return list of font files
* @throws IOException In case of an I/O problem
*/
List find() throws IOException;
}

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

@@ -0,0 +1,171 @@
/*
* 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.autodetect;

import java.io.File;
import java.net.MalformedURLException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.CachedFontInfo;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;

/**
* Attempts to determine correct FontInfo
*/
public class FontInfoFinder {
/** logging instance */
private Log log = LogFactory.getLog(FontInfoFinder.class);

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

/** font constituent names which identify a font as being of "bold" weight */
private static final String[] BOLD_WORDS = {"bold", "black", "heavy", "ultra", "super"};

/**
* Attempts to determine FontTriplet from a given CustomFont.
* It seems to be fairly accurate but will probably require some tweaking over time
*
* @param customFont CustomFont
* @return newly created font triplet
*/
private FontTriplet tripletFromFont(CustomFont customFont) {
// default style and weight triplet vales (fallback)
String name = customFont.getStrippedFontName();
String subName = customFont.getFontSubName();
String searchName = name.toLowerCase();
if (subName != null) {
searchName += subName.toLowerCase();
}
// style
String style = Font.STYLE_NORMAL;
if (customFont.getItalicAngle() > 0) {
style = Font.STYLE_ITALIC;
} else {
for (int i = 0; i < ITALIC_WORDS.length; i++) {
if (searchName.indexOf(ITALIC_WORDS[i]) != -1) {
style = Font.STYLE_ITALIC;
break;
}
}
}
// weight
int weight = Font.WEIGHT_NORMAL;
for (int i = 0; i < BOLD_WORDS.length; i++) {
if (searchName.indexOf(BOLD_WORDS[i]) != -1) {
weight = Font.WEIGHT_BOLD;
break;
}
}
return new FontTriplet(name, style, weight);
}
/**
* Attempts to determine FontInfo from a given custom font
* @param fontFile the font file
* @param customFont the custom font
* @param fontCache font cache (may be null)
* @return
*/
private EmbedFontInfo fontInfoFromCustomFont(
File fontFile, CustomFont customFont, FontCache fontCache) {
FontTriplet fontTriplet = tripletFromFont(customFont);
List fontTripletList = new java.util.ArrayList();
fontTripletList.add(fontTriplet);
String embedUrl;
try {
embedUrl = fontFile.toURL().toExternalForm();
} catch (MalformedURLException e) {
embedUrl = fontFile.getAbsolutePath();
}
EmbedFontInfo fontInfo = new EmbedFontInfo(null, customFont.isKerningEnabled(),
fontTripletList, embedUrl);
if (fontCache != null) {
fontCache.addFont(fontInfo);
}
return fontInfo;
}
/**
* Attempts to determine EmbedFontInfo from a given font file.
*
* @param fontFile font file
* @param resolver font resolver used to resolve font
* @param fontCache font cache (may be null)
* @return newly created embed font info
*/
public EmbedFontInfo find(File fontFile, FontResolver resolver, FontCache fontCache) {
String embedUrl = null;
try {
embedUrl = fontFile.toURL().toExternalForm();
} catch (MalformedURLException mfue) {
// should never happen
log.error("Failed to convert '" + fontFile + "' to URL: " + mfue.getMessage() );
}
long fileLastModified = -1;
if (fontCache != null) {
fileLastModified = fontFile.lastModified();
// firstly try and fetch it from cache before loading/parsing the font file
if (fontCache.containsFont(embedUrl)) {
CachedFontInfo fontInfo = fontCache.getFont(embedUrl);
if (fontInfo.lastModified() == fileLastModified) {
return fontInfo;
} else {
// out of date cache item
fontCache.removeFont(embedUrl);
}
// is this a previously failed parsed font?
} else if (fontCache.isFailedFont(embedUrl, fileLastModified)) {
if (log.isDebugEnabled()) {
log.debug("Skipping font file that failed to load previously: " + embedUrl);
}
return null;
}
}
// try to determine triplet information from font file
CustomFont customFont = null;
try {
customFont = FontLoader.loadFont(fontFile, resolver);
} catch (Exception e) {
//TODO Too verbose (it's an error but we don't care if some fonts can't be loaded)
if (log.isErrorEnabled()) {
log.error("Unable to load font file: " + embedUrl + ". Reason: " + e.getMessage());
}
if (fontCache != null) {
fontCache.registerFailedFont(embedUrl, fileLastModified);
}
return null;
}
return fontInfoFromCustomFont(fontFile, customFont, fontCache);
}
}

+ 39
- 0
src/java/org/apache/fop/fonts/autodetect/MacFontDirFinder.java View File

@@ -0,0 +1,39 @@
/*
* 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.autodetect;

/**
* Mac font directory finder
*/
public class MacFontDirFinder extends NativeFontDirFinder {

/**
* Some guesses at possible unix font directory locations
* @return a array of possible font directory locations
*/
protected String[] getSearchableDirectories() {
return new String[] {
System.getProperty("user.home") + "/Library/Fonts/", // user
"/Library/Fonts/", // local
"/System/Library/Fonts/", // system
"/Network/Library/Fonts/" // network
};
}
}

+ 55
- 0
src/java/org/apache/fop/fonts/autodetect/NativeFontDirFinder.java View File

@@ -0,0 +1,55 @@
/*
* 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.autodetect;

import java.io.File;
import java.util.List;

/**
* Native font finder base class
*/
public abstract class NativeFontDirFinder implements FontFinder {
/**
* Generic method used by Mac and Unix font finders.
* @return list of natively existing font directories
* @see FontFinder#find()
*/
public List find() {
List fontDirList = new java.util.ArrayList();
String[] searchableDirectories = getSearchableDirectories();
if (searchableDirectories != null) {
for (int i = 0; i < searchableDirectories.length; i++) {
File fontDir = new File(searchableDirectories[i]);
if (fontDir.exists() && fontDir.canRead()) {
fontDirList.add(fontDir);
}
}
}
return fontDirList;
}
/**
* Returns an array of directories to search for fonts in.
* @return an array of directories
*/
protected abstract String[] getSearchableDirectories();
}

+ 39
- 0
src/java/org/apache/fop/fonts/autodetect/UnixFontDirFinder.java View File

@@ -0,0 +1,39 @@
/*
* 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.autodetect;

/**
* Unix font directory finder
*/
public class UnixFontDirFinder extends NativeFontDirFinder {

/**
* Some guesses at possible unix font directory locations
* @return a list of possible font locations
*/
protected String[] getSearchableDirectories() {
return new String[] {
System.getProperty("user.home") + "/.fonts", // user
"/usr/local/fonts", // local
"/usr/share/fonts", // system
"/usr/X11R6/lib/X11/fonts" // X
};
}
}

+ 108
- 0
src/java/org/apache/fop/fonts/autodetect/WindowsFontDirFinder.java View File

@@ -0,0 +1,108 @@
/*
* 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.autodetect;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

/**
* FontFinder for native Windows platforms
*/
public class WindowsFontDirFinder implements FontFinder {
/**
* Attempts to read windir environment variable on windows
* (disclaimer: This is a bit dirty but seems to work nicely)
*/
private String getWinDir(String osName) throws IOException {
Process process = null;
Runtime runtime = Runtime.getRuntime();
if (osName.startsWith("Windows 9")) {
process = runtime.exec("command.com /c echo %windir%");
} else {
process = runtime.exec("cmd.exe /c echo %windir%");
}
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
return bufferedReader.readLine();
}

/**
* @see FontFinder#find()
* @return a list of detected font files
*/
public List find() {
List fontDirList = new java.util.ArrayList();
String windir = null;
try {
windir = System.getProperty("env.windir");
} catch (SecurityException e) {
// should continue if this fails
}
String osName = System.getProperty("os.name");
if (windir == null) {
try {
windir = getWinDir(osName);
} catch (IOException e) {
// should continue if this fails
}
}
File osFontsDir = null, psFontsDir = null;
if (windir != null) {
// remove any trailing '/'
if (windir.endsWith("/")) {
windir = windir.substring(0, windir.length() - 1);
}
osFontsDir = new File(windir + File.separator + "FONTS");
if (osFontsDir.exists() && osFontsDir.canRead()) {
fontDirList.add(osFontsDir);
}
psFontsDir = new File(windir.substring(0, 2) + File.separator + "PSFONTS");
if (psFontsDir.exists() && psFontsDir.canRead()) {
fontDirList.add(psFontsDir);
}
} else {
String windowsDirName = osName.endsWith("NT") ? "WINNT" : "WINDOWS";
// look for true type font folder
for (char driveLetter = 'C'; driveLetter <= 'E'; driveLetter++) {
osFontsDir = new File(
driveLetter + ":"
+ File.separator + windowsDirName
+ File.separator + "FONTS");
if (osFontsDir.exists() && osFontsDir.canRead()) {
fontDirList.add(osFontsDir);
break;
}
}
// look for type 1 font folder
for (char driveLetter = 'C'; driveLetter <= 'E'; driveLetter++) {
psFontsDir = new File(driveLetter + ":" + File.separator + "PSFONTS");
if (psFontsDir.exists() && psFontsDir.canRead()) {
fontDirList.add(psFontsDir);
break;
}
}
}
return fontDirList;
}
}

+ 23
- 0
src/java/org/apache/fop/fonts/autodetect/package.html View File

@@ -0,0 +1,23 @@
<!--
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: $ -->
<HTML>
<TITLE>org.apache.fop.fonts.autodetect Package</TITLE>
<BODY>
<P>A collection of classes that aid in the autodetection of installed system fonts.</P>
</BODY>
</HTML>

+ 8
- 0
src/java/org/apache/fop/fonts/truetype/TTFFile.java View File

@@ -566,6 +566,14 @@ public class TTFFile {
return familyName;
}

/**
* Returns the font sub family name of the font.
* @return String The sub family name
*/
public String getSubFamilyName() {
return subFamilyName;
}

/**
* Returns the name of the character set used.
* @return String The caracter set

+ 23
- 25
src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java View File

@@ -27,7 +27,6 @@ import java.util.Map;
import org.apache.fop.fonts.BFEntry;
import org.apache.fop.fonts.CIDFontType;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.MultiByteFont;
@@ -37,18 +36,23 @@ import org.apache.fop.fonts.MultiByteFont;
*/
public class TTFFontLoader extends FontLoader {
private String fontFileURI;
private TTFFile ttf;
private MultiByteFont multiFont;
private CustomFont returnFont;
private FontResolver resolver;
public TTFFontLoader(String fontFileURI, InputStream in, FontResolver resolver)
throws IOException {
this.fontFileURI = fontFileURI;
this.resolver = resolver;
this.ttf = new TTFFile();
/**
* Default constructor
* @param fontFileURI the URI representing the font file
* @param in the InputStream to load the font from
* @param resolver the FontResolver for font URI resolution
*/
public TTFFontLoader(String fontFileURI, InputStream in, FontResolver resolver) {
super(fontFileURI, in, resolver);
}
/**
* @see FontLoader#read()
*/
protected void read() throws IOException {
TTFFile ttf = new TTFFile();
FontFileReader reader = new FontFileReader(in);
boolean supported = ttf.readFont(reader, null);
if (!supported) {
@@ -61,11 +65,9 @@ public class TTFFontLoader extends FontLoader {
multiFont = new MultiByteFont();
multiFont.setResolver(this.resolver);
returnFont = multiFont;
read();
}
private void read() throws IOException {
returnFont.setFontName(ttf.getFamilyName());
returnFont.setFontSubFamilyName(ttf.getSubFamilyName());
//multiFont.setTTCName(ttcName)
returnFont.setCapHeight(ttf.getCapHeight());
returnFont.setXHeight(ttf.getXHeight());
@@ -77,6 +79,7 @@ public class TTFFontLoader extends FontLoader {
returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF
returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle()));
returnFont.setMissingWidth(0);
multiFont.setCIDType(CIDFontType.CIDTYPE2);
int[] wx = ttf.getWidths();
multiFont.setWidthArray(wx);
@@ -93,9 +96,12 @@ public class TTFFontLoader extends FontLoader {
multiFont.setBFEntries(bfentries);
copyKerning(ttf, true);
multiFont.setEmbedFileName(this.fontFileURI);
loaded = true;
}
/**
* Copy kerning information.
*/
private void copyKerning(TTFFile ttf, boolean isCid) {
// Get kerning
@@ -115,15 +121,7 @@ public class TTFFontLoader extends FontLoader {
} else {
h2 = (Map)ttf.getAnsiKerning().get(kpx1);
}
returnFont.putKerningEntry(kpx1, h2);
}
}
/** @see org.apache.fop.fonts.FontLoader#getFont() */
public CustomFont getFont() {
return this.returnFont;
}
}
}

+ 6
- 17
src/java/org/apache/fop/fonts/type1/Type1FontLoader.java View File

@@ -22,7 +22,6 @@ package org.apache.fop.fonts.type1;
import java.io.IOException;
import java.io.InputStream;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontType;
@@ -33,11 +32,8 @@ import org.apache.fop.fonts.SingleByteFont;
*/
public class Type1FontLoader extends FontLoader {
private String fontFileURI;
private PFMFile pfm;
private SingleByteFont singleFont;
private CustomFont returnFont;
private FontResolver resolver;
/**
* Constructs a new Type 1 font loader.
@@ -48,19 +44,19 @@ public class Type1FontLoader extends FontLoader {
*/
public Type1FontLoader(String fontFileURI, InputStream in, FontResolver resolver)
throws IOException {
this.fontFileURI = fontFileURI;
this.resolver = resolver;
super(fontFileURI, in, resolver);
}
/**
* @see FontLoader#read()
*/
protected void read() throws IOException {
pfm = new PFMFile();
pfm.load(in);
singleFont = new SingleByteFont();
singleFont.setFontType(FontType.TYPE1);
singleFont.setResolver(this.resolver);
returnFont = singleFont;
read();
}
private void read() throws IOException {
returnFont.setFontName(pfm.getPostscriptName());
returnFont.setCapHeight(pfm.getCapHeight());
returnFont.setXHeight(pfm.getXHeight());
@@ -77,12 +73,5 @@ public class Type1FontLoader extends FontLoader {
singleFont.setWidth(i, pfm.getCharWidth(i));
}
singleFont.setEmbedFileName(this.fontFileURI);
}
/** @see org.apache.fop.fonts.FontLoader#getFont() */
public CustomFont getFont() {
return this.returnFont;
}
}

+ 1
- 63
src/java/org/apache/fop/pdf/PDFFilterList.java View File

@@ -24,14 +24,6 @@ import java.io.OutputStream;
import java.util.List;
import java.util.Map;

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

// Avalon
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* This class represents a list of PDF filters to be applied when serializing
* the output of a PDF object.
@@ -56,12 +48,7 @@ public class PDFFilterList {
private List filters = new java.util.ArrayList();

private boolean ignoreASCIIFilters = false;
/**
* logging instance
*/
protected static Log logger = LogFactory.getLog("org.apache.fop.render");
/**
* Default constructor.
* <p>
@@ -290,53 +277,4 @@ public class PDFFilterList {
}
return out;
}

/**
* Builds a filter map from an Avalon Configuration object.
* @param cfg the Configuration object
* @return Map the newly built filter map
* @throws ConfigurationException if a filter list is defined twice
*/
public static Map buildFilterMapFromConfiguration(Configuration cfg)
throws ConfigurationException {
Map filterMap = new java.util.HashMap();
Configuration[] filterLists = cfg.getChildren("filterList");
for (int i = 0; i < filterLists.length; i++) {
Configuration filters = filterLists[i];
String type = filters.getAttribute("type", null);
Configuration[] filt = filters.getChildren("value");
List filterList = new java.util.ArrayList();
for (int j = 0; j < filt.length; j++) {
String name = filt[j].getValue();
filterList.add(name);
}
if (type == null) {
type = PDFFilterList.DEFAULT_FILTER;
}

if (!filterList.isEmpty() && logger.isDebugEnabled()) {
StringBuffer debug = new StringBuffer("Adding PDF filter");
if (filterList.size() != 1) {
debug.append("s");
}
debug.append(" for type ").append(type).append(": ");
for (int j = 0; j < filterList.size(); j++) {
if (j != 0) {
debug.append(", ");
}
debug.append(filterList.get(j));
}
logger.debug(debug.toString());
}
if (filterMap.get(type) != null) {
throw new ConfigurationException("A filterList of type '"
+ type + "' has already been defined");
}
filterMap.put(type, filterList);
}
return filterMap;
}

}

+ 4
- 56
src/java/org/apache/fop/render/AbstractRenderer.java View File

@@ -69,18 +69,13 @@ import org.apache.fop.fonts.FontInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// Avalon
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;

/**
* Abstract base class for all renderers. The Abstract renderer does all the
* top level processing of the area tree and adds some abstract methods to
* handle viewports. This keeps track of the current block and inline position.
*/
public abstract class AbstractRenderer
implements Renderer, Configurable, Constants {
implements Renderer, Constants {

/** logging instance */
protected static Log log = LogFactory.getLog("org.apache.fop.render");
@@ -117,12 +112,6 @@ public abstract class AbstractRenderer
private Set warnedXMLHandlers;
/**
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration conf) throws ConfigurationException {
}

/**
* @see org.apache.fop.render.Renderer#setupFontInfo(FontInfo)
*/
@@ -804,39 +793,6 @@ public abstract class AbstractRenderer
// Some renderers (ex. Text) don't support foreign objects.
}

/**
* Returns the configuration subtree for a specific renderer.
* @param cfg the renderer configuration
* @param namespace the namespace (i.e. the XMLHandler) for which the configuration should
* be returned
* @return the requested configuration subtree, null if there's no configuration
*/
public static Configuration getHandlerConfig(Configuration cfg, String namespace) {

if (cfg == null || namespace == null) {
return null;
}

Configuration handlerConfig = null;

Configuration[] children = cfg.getChildren("xml-handler");
for (int i = 0; i < children.length; ++i) {
try {
if (children[i].getAttribute("namespace").equals(namespace)) {
handlerConfig = children[i];
break;
}
} catch (ConfigurationException e) {
// silently pass over configurations without namespace
}
}
if (log.isDebugEnabled()) {
log.debug((handlerConfig == null ? "No" : "")
+ "XML handler configuration found for namespace " + namespace);
}
return handlerConfig;
}

/**
* Render the xml document with the given xml namespace.
* The Render Context is by the handle to render into the current
@@ -851,15 +807,9 @@ public abstract class AbstractRenderer
this, namespace);
if (handler != null) {
try {
//Optional XML handler configuration
Configuration cfg = userAgent.getFactory().getUserRendererConfig(getMimeType());
if (cfg != null) {
cfg = getHandlerConfig(cfg, namespace);
if (cfg != null) {
ctx.setProperty(RendererContextConstants.HANDLER_CONFIGURATION, cfg);
}
}
XMLHandlerConfigurator configurator
= new XMLHandlerConfigurator(userAgent);
configurator.configure(ctx, namespace);
handler.handleXML(ctx, doc, namespace);
} catch (Throwable t) {
// could not handle document
@@ -887,6 +837,4 @@ public abstract class AbstractRenderer
public String getMimeType() {
return null;
}

}


+ 91
- 0
src/java/org/apache/fop/render/AbstractRendererConfigurator.java View File

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

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.FOUserAgent;

/**
* Abstract base classes for renderer-related configurator classes. This class basically just
* provides an accessor to the specific renderer configuration object.
*/
public abstract class AbstractRendererConfigurator {

/** logger instance */
protected static Log log = LogFactory.getLog(AbstractRendererConfigurator.class);

/** fop factory configuration */
protected FOUserAgent userAgent = null;
/**
* Default constructor
* @param userAgent user agent
*/
public AbstractRendererConfigurator(FOUserAgent userAgent) {
super();
this.userAgent = userAgent;
}

/**
* Returns the configuration subtree for a specific renderer.
* @param renderer the renderer
* @return the requested configuration subtree, null if there's no configuration
*/
protected Configuration getRendererConfig(Renderer renderer) {
Configuration cfg = userAgent.getFactory().getUserConfig();
if (cfg == null) {
if (log.isDebugEnabled()) {
log.debug("userconfig is null");
}
return null;
}
String mimeType = renderer.getMimeType();
if (mimeType == null) {
if (log.isInfoEnabled()) {
log.info("renderer mimeType is null");
}
return null;
}
Configuration userRendererConfig = null;
Configuration[] cfgs
= cfg.getChild("renderers").getChildren("renderer");
for (int i = 0; i < cfgs.length; ++i) {
Configuration child = cfgs[i];
try {
if (child.getAttribute("mime").equals(mimeType)) {
userRendererConfig = child;
break;
}
} catch (ConfigurationException e) {
// silently pass over configurations without mime type
}
}
log.debug((userRendererConfig == null ? "No u" : "U")
+ "ser configuration found for MIME type " + mimeType);
return userRendererConfig;
}
}

+ 12
- 3
src/java/org/apache/fop/render/AbstractRendererMaker.java View File

@@ -29,10 +29,10 @@ public abstract class AbstractRendererMaker {
/**
* Instantiates a new renderer.
* @param ua the user agent
* @param userAgent the user agent
* @return the newly instantiated renderer
*/
public abstract Renderer makeRenderer(FOUserAgent ua);
public abstract Renderer makeRenderer(FOUserAgent userAgent);
/**
* @return Indicates whether this renderer requires an OutputStream to work with.
@@ -44,6 +44,16 @@ public abstract class AbstractRendererMaker {
*/
public abstract String[] getSupportedMimeTypes();
/**
* Returns a renderer config object that can be used to
* configure the renderer.
* @param userAgent user agent
* @return a config object that can be used to configure the renderer
*/
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return null;
}
/**
* Indicates whether a specific MIME type is supported by this renderer.
* @param mimeType the MIME type (ex. "application/pdf")
@@ -58,5 +68,4 @@ public abstract class AbstractRendererMaker {
}
return false;
}
}

+ 19
- 0
src/java/org/apache/fop/render/PrintRenderer.java View File

@@ -46,7 +46,26 @@ public abstract class PrintRenderer extends AbstractRenderer {

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

/**
* Set up the font info
*

+ 332
- 0
src/java/org/apache/fop/render/PrintRendererConfigurator.java View File

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

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

import javax.xml.transform.stream.StreamSource;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.fonts.CachedFontInfo;
import org.apache.fop.fonts.EmbedFontInfo;
import org.apache.fop.fonts.FontCache;
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.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.autodetect.FontFileFinder;
import org.apache.fop.fonts.autodetect.FontInfoFinder;
import org.apache.fop.util.LogUtil;

/**
* Base Print renderer configurator (mostly handles font configuration)
*/
public class PrintRendererConfigurator extends AbstractRendererConfigurator
implements RendererConfigurator {

/** have we already autodetected system fonts? */
private static boolean autodetectedFonts = false;

/** logger instance */
protected static Log log = LogFactory.getLog(PrintRendererConfigurator.class);

/**
* Default constructor
* @param userAgent user agent
*/
public PrintRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Builds a list of EmbedFontInfo objects for use with the setup() method.
*
* @param renderer print renderer
* @throws FOPException if something's wrong with the config data
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = getRendererConfig(renderer);
if (cfg == null) {
return;
}

PrintRenderer printRenderer = (PrintRenderer)renderer;
FontResolver fontResolver = printRenderer.getFontResolver();
if (fontResolver == null) {
//Ensure that we have minimal font resolution capabilities
fontResolver = FontSetup.createMinimalFontResolver();
}

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

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

/**
* Builds a list of EmbedFontInfo objects for use with the setup() method.
*
* @param cfg Configuration object
* @param fontBaseURL the base URL to resolve relative font URLs with
* @param fontResolver the FontResolver to use
* @param strict true if an Exception should be thrown if an error is found.
* @param fontCache the font cache (or null if it is disabled)
* @return a List of EmbedFontInfo objects.
* @throws FOPException If an error occurs while processing the configuration
*/
public static List buildFontListFromConfiguration(Configuration cfg,
String fontBaseURL, FontResolver fontResolver,
boolean strict, FontCache fontCache) throws FOPException {
List fontInfoList = new java.util.ArrayList();

Configuration fonts = cfg.getChild("fonts");
if (fonts != null) {
long start = 0;
if (log.isDebugEnabled()) {
log.debug("Starting font configuration...");
start = System.currentTimeMillis();
}
// native o/s search (autodetect) configuration
boolean autodetectFonts = (fonts.getChild("auto-detect", false) != null);
if (!autodetectedFonts && autodetectFonts) {
// search in font base if it is defined and
// is a directory but don't recurse
FontFileFinder fontFileFinder = new FontFileFinder();
if (fontBaseURL != null) {
try {
File fontBase = FileUtils.toFile(new URL(fontBaseURL));
if (fontBase != null) {
//Can only use the font base URL if it's a file URL
addFontInfoListFromFileList(
fontFileFinder.find(fontBase.getAbsolutePath()),
fontInfoList,
fontResolver,
fontCache
);
}
} catch (IOException e) {
LogUtil.handleException(log, e, strict);
}
}

// native o/s font directory finder
try {
addFontInfoListFromFileList(
fontFileFinder.find(),
fontInfoList,
fontResolver,
fontCache
);
} catch (IOException e) {
LogUtil.handleException(log, e, strict);
}
autodetectedFonts = true;
}

// directory (multiple font) configuration
Configuration[] directories = fonts.getChildren("directory");
for (int i = 0; i < directories.length; i++) {
boolean recursive = directories[i].getAttributeAsBoolean("recursive", false);
String directory = null;
try {
directory = directories[i].getValue();
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, strict);
continue;
}
if (directory == null) {
LogUtil.handleException(log,
new FOPException("directory defined without value"), strict);
continue;
}
FontFileFinder fontFileFinder = new FontFileFinder(recursive ? -1 : 1);
try {
addFontInfoListFromFileList(
fontFileFinder.find(directory),
fontInfoList,
fontResolver,
fontCache
);
} catch (IOException e) {
LogUtil.handleException(log, e, strict);
}
}
// font file (singular) configuration
Configuration[] font = fonts.getChildren("font");
for (int i = 0; i < font.length; i++) {
EmbedFontInfo fontInfo = getFontInfoFromConfiguration(
font[i], fontResolver, strict, fontCache);
if (fontInfo != null) {
fontInfoList.add(fontInfo);
}
}
if (log.isDebugEnabled()) {
log.debug("Finished font configuration in "
+ (System.currentTimeMillis() - start) + "ms");
}
}
return fontInfoList;
}

/**
* Iterates over font file list adding font info to list
* @param fontFileList font file list
* @param fontInfoList font info list
* @param resolver font resolver
*/
private static void addFontInfoListFromFileList(
List fontFileList, List fontInfoList, FontResolver resolver, FontCache fontCache) {
for (Iterator iter = fontFileList.iterator(); iter.hasNext();) {
File fontFile = (File)iter.next();
// parse font to ascertain font info
FontInfoFinder finder = new FontInfoFinder();
EmbedFontInfo fontInfo = finder.find(fontFile, resolver, fontCache);
if (fontInfo != null) {
fontInfoList.add(fontInfo);
}
}
}
/**
* Returns a font info from a font node Configuration definition
*
* @param fontCfg Configuration object (font node)
* @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
* @throws FOPException if something's wrong with the config data
*/
public 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);

if (metricsUrl == null && embedUrl == null) {
LogUtil.handleError(log, "Font configuration without metric-url or embed-url", strict);
return null;
}
if (embedUrl != null) {
StreamSource source = (StreamSource)fontResolver.resolve(embedUrl);
if (source == null) {
LogUtil.handleError(log,
"Failed to resolve font with embed-url '" + embedUrl + "'", strict);
return null;
}
embedUrl = source.getSystemId(); // absolute path/url
}
if (metricsUrl != null) {
StreamSource source = (StreamSource)fontResolver.resolve(metricsUrl);
if (source == null) {
LogUtil.handleError(log,
"Failed to resolve font with metric-url '" + metricsUrl + "'", strict);
return null;
}
metricsUrl = source.getSystemId(); // absolute path/url
}
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 = CachedFontInfo.getFileFromUrls(new String[] {embedUrl, metricsUrl});
if (fontFile != null) {
FontInfoFinder finder = new FontInfoFinder();
return finder.find(fontFile, fontResolver, fontCache);
} 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);
if (fontCache != null) {
if (!fontCache.containsFont(fontInfo)) {
fontCache.addFont(fontInfo);
}
}

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;
}
}

+ 34
- 0
src/java/org/apache/fop/render/RendererConfigurator.java View File

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

import org.apache.fop.apps.FOPException;

/**
* Renderer configurator interface
*/
public interface RendererConfigurator {
/**
* Configures a renderer
* @param renderer renderer
* @throws FOPException fop exception
*/
void configure(Renderer renderer) throws FOPException;
}

+ 1
- 9
src/java/org/apache/fop/render/RendererContext.java View File

@@ -23,7 +23,6 @@ package org.apache.fop.render;
import java.util.Map;

//FOP
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOUserAgent;

/**
@@ -156,17 +155,10 @@ public class RendererContext {
return ((Integer)context.getProperty(RendererContextConstants.HEIGHT)).intValue();
}

/** @return the handler configuration */
public Configuration getHandlerConfiguration() {
return (Configuration)context.getProperty(
RendererContextConstants.HANDLER_CONFIGURATION);
}

/** @return the foreign attributes */
public Map getForeignAttributes() {
return (Map)context.getProperty(RendererContextConstants.FOREIGN_ATTRIBUTES);
}
}
}
}


+ 3
- 15
src/java/org/apache/fop/render/RendererFactory.java View File

@@ -25,9 +25,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@@ -185,18 +182,9 @@ public class RendererFactory {
}
Renderer rend = maker.makeRenderer(userAgent);
rend.setUserAgent(userAgent);
String mimeType = rend.getMimeType(); //Always use main MIME type for this
Configuration userRendererConfig = null;
if (mimeType != null) {
userRendererConfig
= userAgent.getFactory().getUserRendererConfig(mimeType);
}
if (userRendererConfig != null) {
try {
ContainerUtil.configure(rend, userRendererConfig);
} catch (ConfigurationException e) {
throw new FOPException(e);
}
RendererConfigurator configurator = maker.getConfigurator(userAgent);
if (configurator != null) {
configurator.configure(rend);
}
return rend;
}

+ 92
- 0
src/java/org/apache/fop/render/XMLHandlerConfigurator.java View File

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

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.apps.FOUserAgent;

/**
* Configurator for XMLHandler objects.
*/
public class XMLHandlerConfigurator extends AbstractRendererConfigurator {

/** logger instance */
protected static Log log = LogFactory.getLog(XMLHandlerConfigurator.class);
/**
* Default constructor
* @param userAgent the user agent
*/
public XMLHandlerConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Returns the configuration subtree for a specific renderer.
* @param cfg the renderer configuration
* @param namespace the namespace (i.e. the XMLHandler) for which the configuration should
* be returned
* @return the requested configuration subtree, null if there's no configuration
*/
private Configuration getHandlerConfig(Configuration cfg, String namespace) {
if (cfg == null || namespace == null) {
return null;
}
Configuration handlerConfig = null;

Configuration[] children = cfg.getChildren("xml-handler");
for (int i = 0; i < children.length; ++i) {
try {
if (children[i].getAttribute("namespace").equals(namespace)) {
handlerConfig = children[i];
break;
}
} catch (ConfigurationException e) {
// silently pass over configurations without namespace
}
}
if (log.isDebugEnabled()) {
log.debug((handlerConfig == null ? "No" : "")
+ "XML handler configuration found for namespace " + namespace);
}
return handlerConfig;
}

/**
* Configures renderer context by setting the handler configuration on it.
* @param context the RendererContext (contains the user agent)
* @param ns the Namespace of the foreign object
* @throws FOPException if configuring the target objects fails
*/
public void configure(RendererContext context, String ns) throws FOPException {
//Optional XML handler configuration
Configuration cfg = getRendererConfig(context.getRenderer());
if (cfg != null) {
cfg = getHandlerConfig(cfg, ns);
if (cfg != null) {
context.setProperty(RendererContextConstants.HANDLER_CONFIGURATION, cfg);
}
}
}
}

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

@@ -33,8 +33,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
@@ -57,8 +55,6 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.fonts.base14.Courier;
import org.apache.fop.fonts.base14.Helvetica;
import org.apache.fop.fonts.base14.TimesRoman;
@@ -76,7 +72,6 @@ import org.apache.fop.render.afp.fonts.AFPFont;
import org.apache.fop.render.afp.fonts.CharacterSet;
import org.apache.fop.render.afp.fonts.FopCharacterSet;
import org.apache.fop.render.afp.fonts.OutlineFont;
import org.apache.fop.render.afp.fonts.RasterFont;
import org.apache.fop.render.afp.modca.AFPConstants;
import org.apache.fop.render.afp.modca.AFPDataStream;
import org.apache.fop.render.afp.modca.ImageObject;
@@ -302,195 +297,6 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
}
}

/**
*/
private AFPFontInfo buildFont(Configuration fontCfg, String _path)
throws ConfigurationException {

Configuration[] triple = fontCfg.getChildren("font-triplet");
List tripleList = new java.util.ArrayList();
if (triple.length == 0) {
log.error("Mandatory font configuration element '<font-triplet...' is missing");
return null;
}
for (int j = 0; j < triple.length; j++) {
int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight"));
tripleList.add(new FontTriplet(triple[j].getAttribute("name"),
triple[j].getAttribute("style"),
weight));
}

//build the fonts
Configuration afpFontCfg = fontCfg.getChild("afp-font");
if (afpFontCfg == null) {
log.error("Mandatory font configuration element '<afp-font...' is missing");
return null;
}
String path = afpFontCfg.getAttribute("path", _path);
String type = afpFontCfg.getAttribute("type");
if (type == null) {
log.error("Mandatory afp-font configuration attribute 'type=' is missing");
return null;
}
String codepage = afpFontCfg.getAttribute("codepage");
if (codepage == null) {
log.error("Mandatory afp-font configuration attribute 'code=' is missing");
return null;
}
String encoding = afpFontCfg.getAttribute("encoding");
if (encoding == null) {
log.error("Mandatory afp-font configuration attribute 'encoding=' is missing");
return null;
}

if ("raster".equalsIgnoreCase(type)) {

String name = afpFontCfg.getAttribute("name", "Unknown");

// Create a new font object
RasterFont font = new RasterFont(name);

Configuration[] rasters = afpFontCfg.getChildren("afp-raster-font");
if (rasters.length == 0) {
log.error("Mandatory font configuration elements '<afp-raster-font...' are missing");
return null;
}
for (int j = 0; j < rasters.length; j++) {
Configuration rasterCfg = rasters[j];

String characterset = rasterCfg.getAttribute("characterset");
if (characterset == null) {
log.error("Mandatory afp-raster-font configuration attribute 'characterset=' is missing");
return null;
}
int size = rasterCfg.getAttributeAsInteger("size");
String base14 = rasterCfg.getAttribute("base14-font", null);

if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
+ base14);
try {
Typeface tf = (Typeface)clazz.newInstance();
font.addCharacterSet(size, new FopCharacterSet(
codepage, encoding, characterset, size, tf));
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
+ " could not be instantiated";
log.error(msg);
}
} catch (ClassNotFoundException cnfe) {
String msg = "The base 14 font class for " + characterset
+ " could not be found";
log.error(msg);
}
} else {
font.addCharacterSet(size, new CharacterSet(
codepage, encoding, characterset, path));
}
}
return new AFPFontInfo(font, tripleList);

} else if ("outline".equalsIgnoreCase(type)) {

String characterset = afpFontCfg.getAttribute("characterset");
if (characterset == null) {
log.error("Mandatory afp-font configuration attribute 'characterset=' is missing");
return null;
}
String name = afpFontCfg.getAttribute("name", characterset);

CharacterSet characterSet = null;

String base14 = afpFontCfg.getAttribute("base14-font", null);

if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
+ base14);
try {
Typeface tf = (Typeface)clazz.newInstance();
characterSet = new FopCharacterSet(
codepage, encoding, characterset, 1, tf);
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
+ " could not be instantiated";
log.error(msg);
}
} catch (ClassNotFoundException cnfe) {
String msg = "The base 14 font class for " + characterset
+ " could not be found";
log.error(msg);
}
} else {
characterSet = new CharacterSet(codepage, encoding, characterset, path);
}
// Create a new font object
OutlineFont font = new OutlineFont(name, characterSet);
return new AFPFontInfo(font, tripleList);
} else {
log.error("No or incorrect type attribute");
}
return null;
}

/**
* Builds a list of AFPFontInfo objects for use with the setup() method.
* @param cfg Configuration object
* @return List the newly created list of fonts
* @throws ConfigurationException if something's wrong with the config data
*/
public List buildFontListFromConfiguration(Configuration cfg)
throws ConfigurationException {
List fontList = new java.util.ArrayList();
Configuration[] font = cfg.getChild("fonts").getChildren("font");
for (int i = 0; i < font.length; i++) {
AFPFontInfo afi = buildFont(font[i], null);
if (afi != null) {
if (log.isDebugEnabled()) {
log.debug("Adding font " + afi.getAFPFont().getFontName());
for (int j = 0; j < afi.getFontTriplets().size(); ++j) {
FontTriplet triplet = (FontTriplet) afi.getFontTriplets().get(j);
log.debug("Font triplet "
+ triplet.getName() + ", "
+ triplet.getStyle() + ", "
+ triplet.getWeight());
}
}

fontList.add(afi);
}
}
return fontList;
}

/**
* Configure the AFP renderer.
* Get the configuration to be used for fonts etc.
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
//Font configuration
this.fontList = buildFontListFromConfiguration(cfg);
Configuration images = cfg.getChild("images");
if (!"color".equalsIgnoreCase(images.getAttribute("mode", "b+w"))) {
bitsPerPixel = images.getAttributeAsInteger("bits-per-pixel", 8);
switch (bitsPerPixel) {
case 1:
case 4:
case 8:
break;
default:
log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
bitsPerPixel = 8;
break;
}
} else {
colorImages = true;
}

}

/**
* @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
*/
@@ -1765,5 +1571,22 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
}
}

public void setBitsPerPixel(int bitsPerPixel) {
this.bitsPerPixel = bitsPerPixel;
switch (bitsPerPixel) {
case 1:
case 4:
case 8:
break;
default:
log.warn("Invalid bits_per_pixel value, must be 1, 4 or 8.");
bitsPerPixel = 8;
break;
}
}

public void setColorImages(boolean colorImages) {
this.colorImages = colorImages;
}
}


+ 241
- 0
src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java View File

@@ -0,0 +1,241 @@
/*
* 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.afp;

import java.util.List;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.afp.fonts.AFPFontInfo;
import org.apache.fop.render.afp.fonts.CharacterSet;
import org.apache.fop.render.afp.fonts.FopCharacterSet;
import org.apache.fop.render.afp.fonts.OutlineFont;
import org.apache.fop.render.afp.fonts.RasterFont;
import org.apache.fop.util.LogUtil;

/**
* AFP Renderer configurator
*/
public class AFPRendererConfigurator extends PrintRendererConfigurator {

/**
* Default constructor
* @param userAgent user agent
*/
public AFPRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

private AFPFontInfo buildFont(Configuration fontCfg, String fontPath)
throws ConfigurationException {

Configuration[] triple = fontCfg.getChildren("font-triplet");
List tripleList = new java.util.ArrayList();
if (triple.length == 0) {
log.error("Mandatory font configuration element '<font-triplet...' is missing");
return null;
}
for (int j = 0; j < triple.length; j++) {
int weight = FontUtil.parseCSS2FontWeight(triple[j].getAttribute("weight"));
tripleList.add(new FontTriplet(triple[j].getAttribute("name"),
triple[j].getAttribute("style"),
weight));
}

//build the fonts
Configuration afpFontCfg = fontCfg.getChild("afp-font");
if (afpFontCfg == null) {
log.error("Mandatory font configuration element '<afp-font...' is missing");
return null;
}
String path = afpFontCfg.getAttribute("path", fontPath);
String type = afpFontCfg.getAttribute("type");
if (type == null) {
log.error("Mandatory afp-font configuration attribute 'type=' is missing");
return null;
}
String codepage = afpFontCfg.getAttribute("codepage");
if (codepage == null) {
log.error("Mandatory afp-font configuration attribute 'code=' is missing");
return null;
}
String encoding = afpFontCfg.getAttribute("encoding");
if (encoding == null) {
log.error("Mandatory afp-font configuration attribute 'encoding=' is missing");
return null;
}

if ("raster".equalsIgnoreCase(type)) {

String name = afpFontCfg.getAttribute("name", "Unknown");

// Create a new font object
RasterFont font = new RasterFont(name);

Configuration[] rasters = afpFontCfg.getChildren("afp-raster-font");
if (rasters.length == 0) {
log.error(
"Mandatory font configuration elements '<afp-raster-font...' are missing");
return null;
}
for (int j = 0; j < rasters.length; j++) {
Configuration rasterCfg = rasters[j];

String characterset = rasterCfg.getAttribute("characterset");
if (characterset == null) {
log.error(
"Mandatory afp-raster-font configuration attribute 'characterset=' is missing");
return null;
}
int size = rasterCfg.getAttributeAsInteger("size");
String base14 = rasterCfg.getAttribute("base14-font", null);

if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
+ base14);
try {
Typeface tf = (Typeface)clazz.newInstance();
font.addCharacterSet(size, new FopCharacterSet(
codepage, encoding, characterset, size, tf));
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
+ " could not be instantiated";
log.error(msg);
}
} catch (ClassNotFoundException cnfe) {
String msg = "The base 14 font class for " + characterset
+ " could not be found";
log.error(msg);
}
} else {
font.addCharacterSet(size, new CharacterSet(
codepage, encoding, characterset, path));
}
}
return new AFPFontInfo(font, tripleList);

} else if ("outline".equalsIgnoreCase(type)) {

String characterset = afpFontCfg.getAttribute("characterset");
if (characterset == null) {
log.error("Mandatory afp-font configuration attribute 'characterset=' is missing");
return null;
}
String name = afpFontCfg.getAttribute("name", characterset);

CharacterSet characterSet = null;

String base14 = afpFontCfg.getAttribute("base14-font", null);

if (base14 != null) {
try {
Class clazz = Class.forName("org.apache.fop.fonts.base14."
+ base14);
try {
Typeface tf = (Typeface)clazz.newInstance();
characterSet = new FopCharacterSet(
codepage, encoding, characterset, 1, tf);
} catch (Exception ie) {
String msg = "The base 14 font class " + clazz.getName()
+ " could not be instantiated";
log.error(msg);
}
} catch (ClassNotFoundException cnfe) {
String msg = "The base 14 font class for " + characterset
+ " could not be found";
log.error(msg);
}
} else {
characterSet = new CharacterSet(codepage, encoding, characterset, path);
}
// Create a new font object
OutlineFont font = new OutlineFont(name, characterSet);
return new AFPFontInfo(font, tripleList);
} else {
log.error("No or incorrect type attribute");
}
return null;
}
/**
* Builds a list of AFPFontInfo objects for use with the setup() method.
* @param cfg Configuration object
* @return List the newly created list of fonts
* @throws ConfigurationException if something's wrong with the config data
*/
private List buildFontListFromConfiguration(Configuration cfg)
throws ConfigurationException {
List fontList = new java.util.ArrayList();
Configuration[] font = cfg.getChild("fonts").getChildren("font");
for (int i = 0; i < font.length; i++) {
AFPFontInfo afi = buildFont(font[i], null);
if (afi != null) {
if (log.isDebugEnabled()) {
log.debug("Adding font " + afi.getAFPFont().getFontName());
for (int j = 0; j < afi.getFontTriplets().size(); ++j) {
FontTriplet triplet = (FontTriplet) afi.getFontTriplets().get(j);
log.debug(" Font triplet "
+ triplet.getName() + ", "
+ triplet.getStyle() + ", "
+ triplet.getWeight());
}
}

fontList.add(afi);
}
}
return fontList;
}

/**
* Configure the AFP renderer.
* @param renderer AFP renderer
* @throws FOPException fop exception
* @see org.apache.fop.render.PrintRendererConfigurator#configure(Renderer)
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
AFPRenderer afpRenderer = (AFPRenderer)renderer;
try {
List fontList = buildFontListFromConfiguration(cfg);
afpRenderer.setFontList(fontList);
} catch (ConfigurationException e) {
LogUtil.handleException(log, e,
userAgent.getFactory().validateUserConfigStrictly());
}
Configuration images = cfg.getChild("images");
if (!"color".equalsIgnoreCase(images.getAttribute("mode", "b+w"))) {
afpRenderer.setBitsPerPixel(images.getAttributeAsInteger("bits-per-pixel", 8));
} else {
afpRenderer.setColorImages(true);
}
}
}
}

+ 7
- 1
src/java/org/apache/fop/render/afp/AFPRendererMaker.java View File

@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;

/**
* RendererMaker for the AFP Renderer.
@@ -35,10 +36,15 @@ public class AFPRendererMaker extends AbstractRendererMaker {


/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
public Renderer makeRenderer(FOUserAgent userAgent) {
return new AFPRenderer();
}

/** @see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new AFPRendererConfigurator(userAgent);
}

/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;

+ 3
- 2
src/java/org/apache/fop/render/awt/AWTRenderer.java View File

@@ -38,6 +38,7 @@ import java.io.IOException;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactoryConfigurator;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.Area;
import org.apache.fop.area.PageViewport;
@@ -149,10 +150,10 @@ public class AWTRenderer extends Java2DRenderer implements Pageable {
pageWidth = (int) Math.round(bounds.getWidth() / 1000f);
pageHeight = (int) Math.round(bounds.getHeight() / 1000f);
double scaleX = scaleFactor
* (25.4 / FOUserAgent.DEFAULT_TARGET_RESOLUTION)
* (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)
/ userAgent.getTargetPixelUnitToMillimeter();
double scaleY = scaleFactor
* (25.4 / FOUserAgent.DEFAULT_TARGET_RESOLUTION)
* (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)
/ userAgent.getTargetPixelUnitToMillimeter();
int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5);
int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5);

+ 11
- 30
src/java/org/apache/fop/render/bitmap/TIFFRenderer.java View File

@@ -32,9 +32,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;

import org.apache.commons.logging.Log;

import org.apache.xmlgraphics.image.GraphicsUtil;
@@ -77,12 +74,12 @@ public class TIFFRenderer extends Java2DRenderer {

//private static final String COMPRESSION_NONE = "NONE";
//private static final String COMPRESSION_JPEG = "JPEG";
private static final String COMPRESSION_PACKBITS = "PackBits";
public static final String COMPRESSION_PACKBITS = "PackBits";
//private static final String COMPRESSION_DEFLATE = "Deflate";
//private static final String COMPRESSION_LZW = "LZW";
//private static final String COMPRESSION_ZLIB = "ZLib";
private static final String COMPRESSION_CCITT_T6 = "CCITT T.6"; //CCITT Group 4
private static final String COMPRESSION_CCITT_T4 = "CCITT T.4"; //CCITT Group 3
public static final String COMPRESSION_CCITT_T6 = "CCITT T.6"; //CCITT Group 4
public static final String COMPRESSION_CCITT_T4 = "CCITT T.4"; //CCITT Group 3
/** ImageWriter parameters */
private ImageWriterParams writerParams;
@@ -115,30 +112,6 @@ public class TIFFRenderer extends Java2DRenderer {
writerParams.setResolution(dpi);
}

/**
* Configure the TIFF renderer. Get the configuration to be used for
* compression
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
super.configure(cfg);

//set compression
String name = cfg.getChild("compression").getValue(COMPRESSION_PACKBITS);
//Some compression formats need a special image format:
if (name.equalsIgnoreCase(COMPRESSION_CCITT_T6)) {
bufferedImageType = BufferedImage.TYPE_BYTE_BINARY;
} else if (name.equalsIgnoreCase(COMPRESSION_CCITT_T4)) {
bufferedImageType = BufferedImage.TYPE_BYTE_BINARY;
} else {
bufferedImageType = BufferedImage.TYPE_INT_ARGB;
}
if (!"NONE".equalsIgnoreCase(name)) {
writerParams.setCompressionMethod(name);
}
log.info("TIFF compression set to " + name);
}

/** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
public void startRenderer(OutputStream outputStream) throws IOException {
this.outputStream = outputStream;
@@ -253,4 +226,12 @@ public class TIFFRenderer extends Java2DRenderer {
"Method 'remove' is not supported.");
}
}

public void setBufferedImageType(int bufferedImageType) {
this.bufferedImageType = bufferedImageType;
}

public ImageWriterParams getWriterParams() {
return writerParams;
}
}

+ 72
- 0
src/java/org/apache/fop/render/bitmap/TIFFRendererConfigurator.java View File

@@ -0,0 +1,72 @@
/*
* 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.bitmap;

import java.awt.image.BufferedImage;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;

/**
* TIFF Renderer configurator
*/
public class TIFFRendererConfigurator extends PrintRendererConfigurator {

/**
* Default constructor
* @param userAgent user agent
*/
public TIFFRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Configure the TIFF renderer. Get the configuration to be used for
* compression
* @param renderer tiff renderer
* @throws FOPException fop exception
* @see org.apache.fop.render.PrintRendererConfigurator#configure(Renderer)
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
TIFFRenderer tiffRenderer = (TIFFRenderer)renderer;
//set compression
String name = cfg.getChild("compression").getValue(TIFFRenderer.COMPRESSION_PACKBITS);
//Some compression formats need a special image format:
if (name.equalsIgnoreCase(TIFFRenderer.COMPRESSION_CCITT_T6)) {
tiffRenderer.setBufferedImageType(BufferedImage.TYPE_BYTE_BINARY);
} else if (name.equalsIgnoreCase(TIFFRenderer.COMPRESSION_CCITT_T4)) {
tiffRenderer.setBufferedImageType(BufferedImage.TYPE_BYTE_BINARY);
} else {
tiffRenderer.setBufferedImageType(BufferedImage.TYPE_INT_ARGB);
}
if (!"NONE".equalsIgnoreCase(name)) {
tiffRenderer.getWriterParams().setCompressionMethod(name);
}
if (log.isInfoEnabled()) {
log.info("TIFF compression set to " + name);
}
}
}
}

+ 8
- 3
src/java/org/apache/fop/render/bitmap/TIFFRendererMaker.java View File

@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the TIFF Renderer.
@@ -31,12 +32,16 @@ public class TIFFRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {MimeConstants.MIME_TIFF};
/** @see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/** @see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new TIFFRenderer();
}
/** @see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new TIFFRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;

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

@@ -139,52 +139,52 @@ public class FontSetup {
// fontInfo.addMetrics("F17", new BauerBodoniBoldItalic());

/* any is treated as serif */
fontInfo.addFontProperties("F5", "any", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "any", "italic", Font.NORMAL);
fontInfo.addFontProperties("F6", "any", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F7", "any", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "any", "italic", Font.BOLD);
fontInfo.addFontProperties("F8", "any", "oblique", Font.BOLD);
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.NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F2", "sans-serif", "italic", Font.NORMAL);
fontInfo.addFontProperties("F3", "sans-serif", "normal", Font.BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "oblique", Font.BOLD);
fontInfo.addFontProperties("F4", "sans-serif", "italic", Font.BOLD);
fontInfo.addFontProperties("F5", "serif", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "serif", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "serif", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "serif", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "serif", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "serif", "italic", Font.BOLD);
fontInfo.addFontProperties("F9", "monospace", "normal", Font.NORMAL);
fontInfo.addFontProperties("F10", "monospace", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F10", "monospace", "italic", Font.NORMAL);
fontInfo.addFontProperties("F11", "monospace", "normal", Font.BOLD);
fontInfo.addFontProperties("F12", "monospace", "oblique", Font.BOLD);
fontInfo.addFontProperties("F12", "monospace", "italic", Font.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.NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F2", "Helvetica", "italic", Font.NORMAL);
fontInfo.addFontProperties("F3", "Helvetica", "normal", Font.BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "oblique", Font.BOLD);
fontInfo.addFontProperties("F4", "Helvetica", "italic", Font.BOLD);
fontInfo.addFontProperties("F5", "Times", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "Times", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "Times", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "Times", "italic", Font.BOLD);
fontInfo.addFontProperties("F9", "Courier", "normal", Font.NORMAL);
fontInfo.addFontProperties("F10", "Courier", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F10", "Courier", "italic", Font.NORMAL);
fontInfo.addFontProperties("F11", "Courier", "normal", Font.BOLD);
fontInfo.addFontProperties("F12", "Courier", "oblique", Font.BOLD);
fontInfo.addFontProperties("F12", "Courier", "italic", Font.BOLD);
fontInfo.addFontProperties("F13", "Symbol", "normal", Font.NORMAL);
fontInfo.addFontProperties("F14", "ZapfDingbats", "normal", Font.NORMAL);
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);
@@ -192,20 +192,20 @@ public class FontSetup {
// fontInfo.addFontProperties("F17", "BauerBodoni", "italic", FontInfo.BOLD);

/* for compatibility with PassiveTex */
fontInfo.addFontProperties("F5", "Times-Roman", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times-Roman", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "Times-Roman", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "Times-Roman", "italic", Font.BOLD);
fontInfo.addFontProperties("F5", "Times Roman", "normal", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "oblique", Font.NORMAL);
fontInfo.addFontProperties("F6", "Times Roman", "italic", Font.NORMAL);
fontInfo.addFontProperties("F7", "Times Roman", "normal", Font.BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "oblique", Font.BOLD);
fontInfo.addFontProperties("F8", "Times Roman", "italic", Font.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", "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.NORMAL);
"normal", Font.WEIGHT_NORMAL);
configureInstalledAWTFonts(fontInfo, graphics, LAST_PREDEFINED_FONT_NUMBER + 1);
}
@@ -252,9 +252,9 @@ public class FontSetup {
FontMetricsMapper metric = new FontMetricsMapper(family, fontStyle, graphics);
fontInfo.addMetrics(fontKey, metric);
int weight = Font.NORMAL;
int weight = Font.WEIGHT_NORMAL;
if ((fontStyle & java.awt.Font.BOLD) != 0) {
weight = Font.BOLD;
weight = Font.WEIGHT_BOLD;
}
String style = "normal";
if ((fontStyle & java.awt.Font.ITALIC) != 0) {

+ 7
- 18
src/java/org/apache/fop/render/java2d/Java2DRenderer.java View File

@@ -53,10 +53,9 @@ import java.util.Stack;

import org.w3c.dom.Document;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.FopFactoryConfigurator;
import org.apache.fop.area.CTM;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.Trait;
@@ -73,7 +72,6 @@ import org.apache.fop.fonts.Typeface;
import org.apache.fop.image.FopImage;
import org.apache.fop.image.ImageFactory;
import org.apache.fop.image.XMLImage;
import org.apache.fop.pdf.PDFAMode;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
@@ -150,19 +148,6 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
public Java2DRenderer() {
}

/**
* @see org.apache.fop.render.AbstractRenderer#configure(
* org.apache.avalon.framework.configuration.Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
super.configure(cfg);

String s = cfg.getChild(JAVA2D_TRANSPARENT_PAGE_BACKGROUND, true).getValue(null);
if (s != null) {
this.transparentPageBackground = "true".equalsIgnoreCase(s);
}
}

/**
* @see org.apache.fop.render.Renderer#setUserAgent(org.apache.fop.apps.FOUserAgent)
*/
@@ -305,10 +290,10 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
+ pageHeight + ")");

double scaleX = scaleFactor
* (25.4 / FOUserAgent.DEFAULT_TARGET_RESOLUTION)
* (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)
/ userAgent.getTargetPixelUnitToMillimeter();
double scaleY = scaleFactor
* (25.4 / FOUserAgent.DEFAULT_TARGET_RESOLUTION)
* (25.4 / FopFactoryConfigurator.DEFAULT_TARGET_RESOLUTION)
/ userAgent.getTargetPixelUnitToMillimeter();
int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5);
int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5);
@@ -1023,4 +1008,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
//not necessary in Java2D
}

public void setTransparentPageBackground(boolean transparentPageBackground) {
this.transparentPageBackground = transparentPageBackground;
}

}

+ 57
- 0
src/java/org/apache/fop/render/java2d/Java2DRendererConfigurator.java View File

@@ -0,0 +1,57 @@
/*
* 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 org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;

/**
* Configurerer for Java 2D renderer
*/
public class Java2DRendererConfigurator extends PrintRendererConfigurator {

/**
* Default constructor
* @param userAgent user agent
*/
public Java2DRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Configure the Java 2D renderer.
* @param renderer java 2d renderer
* @throws FOPException fop exception
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
Java2DRenderer java2dRenderer = (Java2DRenderer)renderer;
String value = cfg.getChild(
Java2DRenderer.JAVA2D_TRANSPARENT_PAGE_BACKGROUND, true).getValue(null);
if (value != null) {
java2dRenderer.setTransparentPageBackground("true".equalsIgnoreCase(value));
}
}
}
}

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

@@ -53,8 +53,6 @@ import org.w3c.dom.Document;
import org.apache.xmlgraphics.java2d.GraphicContext;

// FOP
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;
@@ -143,31 +141,8 @@ public class PCLRenderer extends PrintRenderer {
public PCLRenderer() {
}

/**
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
super.configure(cfg);
String rendering = cfg.getChild("rendering").getValue(null);
if ("quality".equalsIgnoreCase(rendering)) {
this.qualityBeforeSpeed = true;
} else if ("speed".equalsIgnoreCase(rendering)) {
this.qualityBeforeSpeed = false;
} else if (rendering != null) {
throw new ConfigurationException(
"Valid values for 'rendering' are 'quality' and 'speed'. Value found: "
+ rendering);
}
String textRendering = cfg.getChild("text-rendering").getValue(null);
if ("bitmap".equalsIgnoreCase(textRendering)) {
this.allTextAsBitmaps = true;
} else if ("auto".equalsIgnoreCase(textRendering)) {
this.allTextAsBitmaps = false;
} else if (textRendering != null) {
throw new ConfigurationException(
"Valid values for 'text-rendering' are 'auto' and 'bitmap'. Value found: "
+ textRendering);
}
public void setQualityBeforeSpeed(boolean qualityBeforeSpeed) {
this.qualityBeforeSpeed = qualityBeforeSpeed;
}

/**
@@ -1499,6 +1474,10 @@ public class PCLRenderer extends PrintRenderer {
handleIOTrouble(ioe);
}
}

public void setAllTextAsBitmaps(boolean allTextAsBitmaps) {
this.allTextAsBitmaps = allTextAsBitmaps;
}

+ 74
- 0
src/java/org/apache/fop/render/pcl/PCLRendererConfigurator.java View File

@@ -0,0 +1,74 @@
/*
* 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.pcl;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;

/**
* PCL Renderer configurator
*/
public class PCLRendererConfigurator extends PrintRendererConfigurator {
/**
* Default constructor
* @param userAgent user agent
*/
public PCLRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Configure the TIFF renderer. Get the configuration to be used for
* compression
* @param renderer PCL renderer
* @throws FOPException fop exception
* @see org.apache.fop.render.PrintRendererConfigurator#configure(Renderer)
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
PCLRenderer pclRenderer = (PCLRenderer)renderer;
String rendering = cfg.getChild("rendering").getValue(null);
if ("quality".equalsIgnoreCase(rendering)) {
pclRenderer.setQualityBeforeSpeed(true);
} else if ("speed".equalsIgnoreCase(rendering)) {
pclRenderer.setQualityBeforeSpeed(false);
} else if (rendering != null) {
throw new FOPException(
"Valid values for 'rendering' are 'quality' and 'speed'. Value found: "
+ rendering);
}
String textRendering = cfg.getChild("text-rendering").getValue(null);
if ("bitmap".equalsIgnoreCase(textRendering)) {
pclRenderer.setAllTextAsBitmaps(true);
} else if ("auto".equalsIgnoreCase(textRendering)) {
pclRenderer.setAllTextAsBitmaps(false);
} else if (textRendering != null) {
throw new FOPException(
"Valid values for 'text-rendering' are 'auto' and 'bitmap'. Value found: "
+ textRendering);
}
}
}
}

+ 10
- 5
src/java/org/apache/fop/render/pcl/PCLRendererMaker.java View File

@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the PCL Renderer.
@@ -31,14 +32,19 @@ public class PCLRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {
MimeConstants.MIME_PCL,
MimeConstants.MIME_PCL_ALT};
MimeConstants.MIME_PCL_ALT
};
/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/**@see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new PCLRenderer();
}
/** @see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new PCLRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;
@@ -48,5 +54,4 @@ public class PCLRendererMaker extends AbstractRendererMaker {
public String[] getSupportedMimeTypes() {
return MIMES;
}
}

+ 16
- 36
src/java/org/apache/fop/render/pdf/PDFRenderer.java View File

@@ -41,8 +41,6 @@ import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;

// Avalon
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.io.IOUtils;

// FOP
@@ -69,7 +67,6 @@ import org.apache.fop.area.inline.WordArea;
import org.apache.fop.area.inline.SpaceArea;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.image.FopImage;
import org.apache.fop.image.ImageFactory;
import org.apache.fop.image.XMLImage;
@@ -86,7 +83,6 @@ import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFGoTo;
import org.apache.fop.pdf.PDFICCBasedColorSpace;
import org.apache.fop.pdf.PDFICCStream;
import org.apache.fop.pdf.PDFGoTo;
import org.apache.fop.pdf.PDFInfo;
import org.apache.fop.pdf.PDFLink;
import org.apache.fop.pdf.PDFMetadata;
@@ -266,38 +262,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
public PDFRenderer() {
}

/**
* Configure the PDF renderer.
* Get the configuration to be used for pdf stream filters,
* fonts etc.
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
//PDF filters
this.filterMap = PDFFilterList.buildFilterMapFromConfiguration(cfg);

//Font configuration
List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg, this);
if (this.fontList == null) {
this.fontList = cfgFonts;
} else {
this.fontList.addAll(cfgFonts);
}
String s = cfg.getChild(PDF_A_MODE, true).getValue(null);
if (s != null) {
this.pdfAMode = PDFAMode.valueOf(s);
}
s = cfg.getChild(PDF_X_MODE, true).getValue(null);
if (s != null) {
this.pdfXMode = PDFXMode.valueOf(s);
}
s = cfg.getChild(KEY_OUTPUT_PROFILE, true).getValue(null);
if (s != null) {
this.outputProfileURI = s;
}
}

private boolean booleanValueOf(Object obj) {
if (obj instanceof Boolean) {
return ((Boolean)obj).booleanValue();
@@ -1891,5 +1855,21 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
public String getMimeType() {
return MIME_TYPE;
}
public void setAMode(PDFAMode mode) {
this.pdfAMode = mode;
}

public void setXMode(PDFXMode mode) {
this.pdfXMode = mode;
}

public void setOutputProfileURI(String outputProfileURI) {
this.outputProfileURI = outputProfileURI;
}

public void setFilterMap(Map filterMap) {
this.filterMap = filterMap;
}
}


+ 134
- 0
src/java/org/apache/fop/render/pdf/PDFRendererConfigurator.java View File

@@ -0,0 +1,134 @@
/*
* 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.pdf;

import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.pdf.PDFAMode;
import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFXMode;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;
import org.apache.fop.util.LogUtil;

/**
* PDF renderer configurator
*/
public class PDFRendererConfigurator extends PrintRendererConfigurator {

/**
* Default constructor
* @param userAgent user agent
*/
public PDFRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Configure the PDF renderer.
* Get the configuration to be used for pdf stream filters,
* fonts etc.
* @param renderer pdf renderer
* @throws FOPException fop exception
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
PDFRenderer pdfRenderer = (PDFRenderer)renderer;
//PDF filters
try {
Map filterMap = buildFilterMapFromConfiguration(cfg);
if (filterMap != null) {
pdfRenderer.setFilterMap(filterMap);
}
} catch (ConfigurationException e) {
LogUtil.handleException(log, e, false);
}
super.configure(renderer);
String s = cfg.getChild(PDFRenderer.PDF_A_MODE, true).getValue(null);
if (s != null) {
pdfRenderer.setAMode(PDFAMode.valueOf(s));
}
s = cfg.getChild(PDFRenderer.PDF_X_MODE, true).getValue(null);
if (s != null) {
pdfRenderer.setXMode(PDFXMode.valueOf(s));
}
s = cfg.getChild(PDFRenderer.KEY_OUTPUT_PROFILE, true).getValue(null);
if (s != null) {
pdfRenderer.setOutputProfileURI(s);
}
}
}

/**
* Builds a filter map from an Avalon Configuration object.
* @param cfg the Configuration object
* @return Map the newly built filter map
* @throws ConfigurationException if a filter list is defined twice
*/
public static Map buildFilterMapFromConfiguration(Configuration cfg)
throws ConfigurationException {
Map filterMap = new java.util.HashMap();
Configuration[] filterLists = cfg.getChildren("filterList");
for (int i = 0; i < filterLists.length; i++) {
Configuration filters = filterLists[i];
String type = filters.getAttribute("type", null);
Configuration[] filt = filters.getChildren("value");
List filterList = new java.util.ArrayList();
for (int j = 0; j < filt.length; j++) {
String name = filt[j].getValue();
filterList.add(name);
}
if (type == null) {
type = PDFFilterList.DEFAULT_FILTER;
}
if (!filterList.isEmpty() && log.isDebugEnabled()) {
StringBuffer debug = new StringBuffer("Adding PDF filter");
if (filterList.size() != 1) {
debug.append("s");
}
debug.append(" for type ").append(type).append(": ");
for (int j = 0; j < filterList.size(); j++) {
if (j != 0) {
debug.append(", ");
}
debug.append(filterList.get(j));
}
log.debug(debug.toString());
}
if (filterMap.get(type) != null) {
throw new ConfigurationException("A filterList of type '"
+ type + "' has already been defined");
}
filterMap.put(type, filterList);
}
return filterMap;
}
}

+ 8
- 3
src/java/org/apache/fop/render/pdf/PDFRendererMaker.java View File

@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the PDF Renderer.
@@ -31,12 +32,16 @@ public class PDFRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {MimeConstants.MIME_PDF};
/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/** @see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new PDFRenderer();
}
/** @see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new PDFRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;

+ 9
- 3
src/java/org/apache/fop/render/print/PrintRendererMaker.java View File

@@ -22,7 +22,9 @@ package org.apache.fop.render.print;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the Print Renderer.
@@ -31,12 +33,16 @@ public class PrintRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_PRINT};
/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/**@see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new PrintRenderer();
}
/** @see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new PrintRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return false;

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

@@ -159,7 +159,7 @@ public class NativeTextHandler implements TextHandler {
}
int fontSize = 1000 * f.getSize();
String style = f.isItalic() ? "italic" : "normal";
int weight = f.isBold() ? Font.BOLD : Font.NORMAL;
int weight = f.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;
FontTriplet triplet = fontInfo.findAdjustWeight(fontFamily, style, weight);
if (triplet == null) {

+ 0
- 21
src/java/org/apache/fop/render/ps/PSRenderer.java View File

@@ -35,8 +35,6 @@ import java.util.Map;
import javax.xml.transform.Source;

// FOP
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -61,7 +59,6 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.image.EPSImage;
@@ -145,24 +142,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer implements ImageAda
/** This is a map of PSResource instances of all forms (key: uri) */
private Map formResources;
/**
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
super.configure(cfg);
this.autoRotateLandscape = cfg.getChild(AUTO_ROTATE_LANDSCAPE).getValueAsBoolean(false);
this.languageLevel = cfg.getChild(LANGUAGE_LEVEL).getValueAsInteger(this.languageLevel);
this.twoPassGeneration = cfg.getChild(OPTIMIZE_RESOURCES).getValueAsBoolean(false);

//Font configuration
List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg, this);
if (this.fontList == null) {
this.fontList = cfgFonts;
} else {
this.fontList.addAll(cfgFonts);
}
}

/**
* @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
*/

+ 56
- 0
src/java/org/apache/fop/render/ps/PSRendererConfigurator.java View File

@@ -0,0 +1,56 @@
/*
* 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.ps;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;

/**
* Postscript renderer config
*/
public class PSRendererConfigurator extends PrintRendererConfigurator {

/**
* Default constructor
* @param userAgent user agent
*/
public PSRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Configure the PS renderer.
* @param renderer postscript renderer
* @throws FOPException fop exception
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
super.configure(renderer);

PSRenderer psRenderer = (PSRenderer)renderer;
psRenderer.setAutoRotateLandscape(
cfg.getChild("auto-rotate-landscape").getValueAsBoolean(false));
}
}
}

+ 8
- 4
src/java/org/apache/fop/render/ps/PSRendererMaker.java View File

@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the PostScript Renderer.
@@ -31,12 +32,16 @@ public class PSRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {MimeConstants.MIME_POSTSCRIPT};
/** @see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/** @see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new PSRenderer();
}
/** @see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new PSRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;
@@ -46,5 +51,4 @@ public class PSRendererMaker extends AbstractRendererMaker {
public String[] getSupportedMimeTypes() {
return MIMES;
}
}

+ 4
- 4
src/java/org/apache/fop/render/ps/PSTextPainter.java View File

@@ -367,8 +367,8 @@ public class PSTextPainter implements TextPainter {
private int getWeight(AttributedCharacterIterator aci) {
Float taWeight = (Float)aci.getAttribute(TextAttribute.WEIGHT);
return ((taWeight != null) && (taWeight.floatValue() > 1.0))
? Font.BOLD
: Font.NORMAL;
? Font.WEIGHT_BOLD
: Font.WEIGHT_NORMAL;
}

private Font makeFont(AttributedCharacterIterator aci) {
@@ -402,7 +402,7 @@ public class PSTextPainter implements TextPainter {
}
}
}
FontTriplet triplet = fontInfo.fontLookup("any", style, Font.NORMAL);
FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
int fsize = (int)(fontSize.floatValue() * 1000);
return fontInfo.getFontInstance(triplet, fsize);
}
@@ -411,7 +411,7 @@ public class PSTextPainter implements TextPainter {
final String style = getStyle(aci);
final int weight = getWeight(aci);
int fStyle = java.awt.Font.PLAIN;
if (weight == Font.BOLD) {
if (weight == Font.WEIGHT_BOLD) {
fStyle |= java.awt.Font.BOLD;
}
if ("italic".equals(style)) {

+ 0
- 8
src/java/org/apache/fop/render/txt/TXTRenderer.java View File

@@ -27,8 +27,6 @@ import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.area.Area;
import org.apache.fop.area.CTM;
@@ -115,12 +113,6 @@ public class TXTRenderer extends AbstractPathOrientedRenderer {
public String getMimeType() {
return "text/plain";
}

/** @see org.apache.fop.render.AbstractRenderer */
public void configure(Configuration conf) throws ConfigurationException {
super.configure(conf);
this.encoding = conf.getChild("encoding", true).getValue(null);
}
/**
* Sets the encoding of the target file.

+ 53
- 0
src/java/org/apache/fop/render/txt/TXTRendererConfigurator.java View File

@@ -0,0 +1,53 @@
/*
* 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.txt;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;

/**
* TXT Renderer configurator
*/
public class TXTRendererConfigurator extends PrintRendererConfigurator {

/**
* Default constructor
* @param userAgent user agent
*/
public TXTRendererConfigurator(FOUserAgent userAgent) {
super(userAgent);
}

/**
* Configure the PS renderer.
* @param renderer TXT renderer
* @throws FOPException fop exception
*/
public void configure(Renderer renderer) throws FOPException {
Configuration cfg = super.getRendererConfig(renderer);
if (cfg != null) {
TXTRenderer txtRenderer = (TXTRenderer)renderer;
txtRenderer.setEncoding(cfg.getChild("encoding", true).getValue(null));
}
}
}

+ 8
- 4
src/java/org/apache/fop/render/txt/TXTRendererMaker.java View File

@@ -23,6 +23,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the Plain Text Renderer.
@@ -31,12 +32,16 @@ public class TXTRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {MimeConstants.MIME_PLAIN_TEXT};
/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/**@see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new TXTRenderer();
}
/**@see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new TXTRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;
@@ -46,5 +51,4 @@ public class TXTRendererMaker extends AbstractRendererMaker {
public String[] getSupportedMimeTypes() {
return MIMES;
}
}

+ 0
- 19
src/java/org/apache/fop/render/xml/XMLRenderer.java View File

@@ -41,8 +41,6 @@ import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.util.QName;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
@@ -83,7 +81,6 @@ import org.apache.fop.area.inline.WordArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.render.PrintRenderer;
import org.apache.fop.render.Renderer;
@@ -139,22 +136,6 @@ public class XMLRenderer extends PrintRenderer {
context = new RendererContext(this, XML_MIME_TYPE);
}

/**
* Configure the XML renderer.
* Get the configuration to be used for fonts etc.
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
super.configure(cfg);
//Font configuration
List cfgFonts = FontSetup.buildFontListFromConfiguration(cfg, this);
if (this.fontList == null) {
this.fontList = cfgFonts;
} else {
this.fontList.addAll(cfgFonts);
}
}

/**
* @see org.apache.fop.render.Renderer#setUserAgent(FOUserAgent)
*/

+ 9
- 3
src/java/org/apache/fop/render/xml/XMLRendererMaker.java View File

@@ -22,7 +22,9 @@ package org.apache.fop.render.xml;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.render.AbstractRendererMaker;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.Renderer;
import org.apache.fop.render.RendererConfigurator;
/**
* RendererMaker for the Area Tree XML Renderer.
@@ -31,12 +33,16 @@ public class XMLRendererMaker extends AbstractRendererMaker {
private static final String[] MIMES = new String[] {MimeConstants.MIME_FOP_AREA_TREE};
/**@see org.apache.fop.render.AbstractRendererMaker */
public Renderer makeRenderer(FOUserAgent ua) {
/**@see org.apache.fop.render.AbstractRendererMaker#makeRenderer(FOUserAgent) */
public Renderer makeRenderer(FOUserAgent userAgent) {
return new XMLRenderer();
}
/**@see org.apache.fop.render.AbstractRendererMaker#getConfigurator(FOUserAgent) */
public RendererConfigurator getConfigurator(FOUserAgent userAgent) {
return new PrintRendererConfigurator(userAgent);
}
/** @see org.apache.fop.render.AbstractRendererMaker#needsOutputStream() */
public boolean needsOutputStream() {
return true;

+ 0
- 16
src/java/org/apache/fop/svg/PDFContext.java View File

@@ -19,8 +19,6 @@

package org.apache.fop.svg;

import java.util.List;

import org.apache.fop.pdf.PDFPage;

/**
@@ -30,24 +28,10 @@ import org.apache.fop.pdf.PDFPage;
public class PDFContext {

private PDFPage currentPage;
private List fontList;

/** number of pages generated */
private int pagecount;
/**
* Sets the font list as creates by the FontSetup class.
* @param list the font list
*/
public void setFontList(List list) {
this.fontList = list;
}

/** @return the font list */
public List getFontList() {
return this.fontList;
}

/** @return true if a page is set up for painting. */
public boolean isPagePending() {
return this.currentPage != null;

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

@@ -19,6 +19,7 @@

package org.apache.fop.svg;

import org.apache.fop.Version;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFFilterList;
import org.apache.fop.pdf.PDFPage;
@@ -28,13 +29,8 @@ import org.apache.fop.pdf.PDFNumber;
import org.apache.fop.pdf.PDFResources;
import org.apache.fop.pdf.PDFColor;
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.fonts.FontInfo;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.fonts.FontSetup;

import java.awt.Graphics;
import java.awt.Font;
@@ -56,8 +52,7 @@ import java.io.StringWriter;
* @version $Id$
* @see org.apache.fop.svg.PDFGraphics2D
*/
public class PDFDocumentGraphics2D extends PDFGraphics2D
implements Configurable, Initializable {
public class PDFDocumentGraphics2D extends PDFGraphics2D {

private PDFContext pdfContext;

@@ -89,9 +84,6 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
*/
protected AffineTransform initialTransform;

//Avalon component
private Configuration cfg;

/**
* Create a new PDFDocumentGraphics2D.
* This is used to create a new pdf document, the height,
@@ -106,19 +98,9 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
public PDFDocumentGraphics2D(boolean textAsShapes) {
super(textAsShapes);

this.pdfDoc = new PDFDocument("Apache FOP Version " + Version.getVersion()
+ ": PDFDocumentGraphics2D");
this.pdfContext = new PDFContext();
if (!textAsShapes) {
fontInfo = new FontInfo();
FontSetup.setup(fontInfo, null, null);
//FontState fontState = new FontState("Helvetica", "normal",
// FontInfo.NORMAL, 12, 0);
}
try {
initialize();
} catch (Exception e) {
//Should never happen
throw new CascadingRuntimeException("Internal error", e);
}
}

/**
@@ -153,33 +135,6 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
this(false);
}

/**
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
this.cfg = cfg;
this.pdfContext.setFontList(FontSetup.buildFontListFromConfiguration(cfg));
}

/**
* @see org.apache.avalon.framework.activity.Initializable#initialize()
*/
public void initialize() throws Exception {
if (this.fontInfo == null || this.cfg != null) {
fontInfo = new FontInfo();
FontSetup.setup(fontInfo, this.pdfContext.getFontList(), null);
//FontState fontState = new FontState("Helvetica", "normal",
// FontInfo.NORMAL, 12, 0);
}

this.pdfDoc = new PDFDocument("Apache FOP: SVG to PDF Transcoder");

if (this.cfg != null) {
this.pdfDoc.setFilterMap(
PDFFilterList.buildFilterMapFromConfiguration(cfg));
}
}

/**
* Setup the document.
* @param stream the output stream to write the document
@@ -196,6 +151,18 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
setOutputStream(stream);
}

/**
* Setup a default FontInfo instance if none has been setup before.
*/
public void setupDefaultFontInfo() {
if (fontInfo == null) {
//Default minimal fonts
FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, null, null);
setFontInfo(fontInfo);
}
}
/**
* Set the device resolution for rendering. Will take effect at the
* start of the next page.
@@ -212,6 +179,14 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
return deviceDPI;
}

/**
* Sets the font info for this PDF document.
* @param fontInfo the font info object with all the fonts
*/
public void setFontInfo(FontInfo fontInfo) {
this.fontInfo = fontInfo;
}
/**
* Get the font info for this pdf document.
* @return the font information
@@ -228,6 +203,14 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
return this.pdfDoc;
}

/**
* Return the PDFContext for this instance.
* @return the PDFContext
*/
public PDFContext getPDFContext() {
return this.pdfContext;
}
/**
* Set the dimensions of the svg document that will be drawn.
* This is useful if the dimensions of the svg document are different
@@ -295,6 +278,10 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
if (pdfContext.isPagePending()) {
return;
}
//Setup default font info if no more font configuration has been done by the user.
if (!this.textAsShapes && getFontInfo() == null) {
setupDefaultFontInfo();
}
try {
startPage();
} catch (IOException ioe) {
@@ -389,7 +376,6 @@ public class PDFDocumentGraphics2D extends PDFGraphics2D
public PDFDocumentGraphics2D(PDFDocumentGraphics2D g) {
super(g);
this.pdfContext = g.pdfContext;
this.cfg = g.cfg;
this.width = g.width;
this.height = g.height;
this.svgWidth = g.svgWidth;

+ 66
- 0
src/java/org/apache/fop/svg/PDFDocumentGraphics2DConfigurator.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.svg;

import java.util.List;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.fop.apps.FOPException;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontSetup;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.render.PrintRendererConfigurator;
import org.apache.fop.render.pdf.PDFRendererConfigurator;

/**
* Configurator class for PDFDocumentGraphics2D.
*/
public class PDFDocumentGraphics2DConfigurator {

/**
* Configures a PDFDocumentGraphics2D instance using an Avalon Configuration object.
* @param graphics the PDFDocumentGraphics2D instance
* @param cfg the configuration
* @throws ConfigurationException if an error occurs while configuring the object
*/
public void configure(PDFDocumentGraphics2D graphics, Configuration cfg)
throws ConfigurationException {
PDFDocument pdfDoc = graphics.getPDFDocument();
//Filter map
pdfDoc.setFilterMap(
PDFRendererConfigurator.buildFilterMapFromConfiguration(cfg));
//Fonts
try {
FontResolver fontResolver = FontSetup.createMinimalFontResolver();
List fontList = PrintRendererConfigurator.buildFontListFromConfiguration(
cfg, null, fontResolver, false, null);
FontInfo fontInfo = new FontInfo();
FontSetup.setup(fontInfo, fontList, 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

@@ -1429,7 +1429,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
}
float siz = gFont.getSize2D();
String style = gFont.isItalic() ? "italic" : "normal";
int weight = gFont.isBold() ? Font.BOLD : Font.NORMAL;
int weight = gFont.isBold() ? Font.WEIGHT_BOLD : Font.WEIGHT_NORMAL;
FontTriplet triplet = fontInfo.fontLookup(n, style, weight);
fontState = fontInfo.getFontInstance(triplet, (int)(siz * 1000 + 0.5));
} else {

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

@@ -22,7 +22,6 @@ package org.apache.fop.svg;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.bridge.SVGTextElementBridge;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.TextUtilities;
import org.apache.batik.gvt.GraphicsNode;

import org.apache.fop.fonts.FontInfo;
@@ -82,12 +81,16 @@ public class PDFTextElementBridge extends SVGTextElementBridge {
* easily rendered using normal drawString on the PDFGraphics2D
*/
private boolean isSimple(BridgeContext ctx, Element element, GraphicsNode node) {
/* I cannot find any reference that 36pt is the maximum font size in PDF. Tests show
* no such restriction (jeremias, 28.5.2007)
*
// Font size, in user space units.
float fs = TextUtilities.convertFontSize(element).floatValue();
// PDF cannot display fonts over 36pt
if (fs > 36) {
return false;
}
*/

Element nodeElement;
for (Node n = element.getFirstChild();

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

@@ -160,8 +160,8 @@ public class PDFTextPainter implements TextPainter {
String style = ((posture != null) && (posture.floatValue() > 0.0))
? "italic" : "normal";
int weight = ((taWeight != null)
&& (taWeight.floatValue() > 1.0)) ? Font.BOLD
: Font.NORMAL;
&& (taWeight.floatValue() > 1.0)) ? Font.WEIGHT_BOLD
: Font.WEIGHT_NORMAL;

Font fontState = null;
FontInfo fi = fontInfo;
@@ -187,7 +187,7 @@ public class PDFTextPainter implements TextPainter {
}
}
if (!found) {
FontTriplet triplet = fontInfo.fontLookup("any", style, Font.NORMAL);
FontTriplet triplet = fontInfo.fontLookup("any", style, Font.WEIGHT_NORMAL);
int fsize = (int)(size.floatValue() * 1000);
fontState = fontInfo.getFontInstance(triplet, fsize);
} else {
@@ -196,7 +196,7 @@ public class PDFTextPainter implements TextPainter {
}
}
int fStyle = java.awt.Font.PLAIN;
if (weight == Font.BOLD) {
if (weight == Font.WEIGHT_BOLD) {
if (style.equals("italic")) {
fStyle = java.awt.Font.BOLD | java.awt.Font.ITALIC;
} else {

+ 15
- 5
src/java/org/apache/fop/svg/PDFTranscoder.java View File

@@ -25,7 +25,6 @@ import java.io.IOException;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.container.ContainerUtil;
import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.UnitProcessor;
import org.apache.batik.bridge.UserAgent;
@@ -35,6 +34,9 @@ import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.TranscodingHints;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.transcoder.keys.FloatKey;
import org.apache.fop.Version;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontSetup;
import org.w3c.dom.Document;
import org.w3c.dom.svg.SVGLength;

@@ -120,12 +122,16 @@ public class PDFTranscoder extends AbstractFOPTranscoder
throws TranscoderException {

graphics = new PDFDocumentGraphics2D();
graphics.getPDFDocument().getInfo().setProducer("Apache FOP Version "
+ Version.getVersion()
+ ": PDF Transcoder for Batik");
try {
if (this.cfg != null) {
ContainerUtil.configure(graphics, this.cfg);
PDFDocumentGraphics2DConfigurator configurator
= new PDFDocumentGraphics2DConfigurator();
configurator.configure(graphics, this.cfg);
}
ContainerUtil.initialize(graphics);
} catch (Exception e) {
throw new TranscoderException(
"Error while setting up PDFDocumentGraphics2D", e);
@@ -133,7 +139,9 @@ public class PDFTranscoder extends AbstractFOPTranscoder

super.transcode(document, uri, output);

getLogger().trace("document size: " + width + " x " + height);
if (getLogger().isTraceEnabled()) {
getLogger().trace("document size: " + width + " x " + height);
}
// prepare the image to be painted
UnitProcessor.Context uctx = UnitProcessor.createContext(ctx,
@@ -144,7 +152,9 @@ public class PDFTranscoder extends AbstractFOPTranscoder
float heightInPt = UnitProcessor.userSpaceToSVG(height, SVGLength.SVG_LENGTHTYPE_PT,
UnitProcessor.HORIZONTAL_LENGTH, uctx);
int h = (int)(heightInPt + 0.5);
getLogger().trace("document size: " + w + "pt x " + h + "pt");
if (getLogger().isTraceEnabled()) {
getLogger().trace("document size: " + w + "pt x " + h + "pt");
}

// prepare the image to be painted
//int w = (int)(width + 0.5);

+ 57
- 0
src/java/org/apache/fop/util/LogUtil.java View File

@@ -0,0 +1,57 @@
/*
* 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.util;

import org.apache.commons.logging.Log;
import org.apache.fop.apps.FOPException;

/**
* Convenience Logging utility methods used in FOP
*/
public class LogUtil {

/**
* Convenience method that handles any error appropriately
* @param log log
* @param errorStr error string
* @param strict validate strictly
* @throws FOPException fop exception
*/
public static void handleError(Log log, String errorStr, boolean strict) throws FOPException {
handleException(log, new FOPException(errorStr), strict);
}

/**
* Convenience method that handles any error appropriately
* @param log log
* @param e exception
* @param strict validate strictly
* @throws FOPException fop exception
*/
public static void handleException(Log log, Exception e, boolean strict) throws FOPException {
if (strict) {
if (e instanceof FOPException) {
throw (FOPException)e;
}
throw new FOPException(e);
}
log.error(e.getMessage());
}
}

+ 0
- 9
src/sandbox/org/apache/fop/render/svg/SVGRenderer.java View File

@@ -26,8 +26,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.batik.svggen.SVGGeneratorContext;
import org.apache.batik.svggen.SVGGraphics2D;
@@ -78,13 +76,6 @@ public class SVGRenderer extends Java2DRenderer {
public SVGRenderer() {
}

/**
* @see org.apache.fop.render.AbstractRenderer#configure(
* org.apache.avalon.framework.configuration.Configuration)
*/
public void configure(Configuration cfg) throws ConfigurationException {
}

/** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
public void startRenderer(OutputStream outputStream) throws IOException {
this.firstOutputStream = outputStream;

+ 3
- 0
status.xml View File

@@ -28,6 +28,9 @@

<changes>
<release version="FOP Trunk">
<action context="Code" dev="JM" type="add" fixes-bug="41831" due-to="Adrian Cumiskey">
Add support for font auto-detection (easier font configuration).
</action>
<action context="Code" dev="JM" type="update" fixes-bug="42406" due-to="Hussein Shafie">
Use source resolution setting for bitmap images which don't provide their own
resolution.

test/config/test_fontattributes_missing.xconf → test/config/test_font_attributes_missing.xconf View File

@@ -3,12 +3,15 @@
<!-- 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>
<renderers>
<renderer mime="application/pdf">
<fonts>

test/config/test_embedurl_bad.xconf → test/config/test_font_embedurl_bad.xconf View File

@@ -3,6 +3,9 @@
<!-- 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>


test/config/test_embedurl_malformed.xconf → test/config/test_font_embedurl_malformed.xconf View File

@@ -3,6 +3,9 @@
<!-- 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>


test/config/test_metricsurl_bad.xconf → test/config/test_font_metricsurl_bad.xconf View File

@@ -3,6 +3,9 @@
<!-- 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>


test/config/test_metricsurl_malformed.xconf → test/config/test_font_metricsurl_malformed.xconf View File

@@ -3,6 +3,9 @@
<!-- 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>


test/config/test_fonttripletattribute_missing.xconf → test/config/test_font_tripletattribute_missing.xconf View File

@@ -3,6 +3,9 @@
<!-- 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>


+ 3
- 0
test/config/test_fontbase_bad.xconf View File

@@ -3,6 +3,9 @@
<!-- 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>


+ 22
- 0
test/config/test_fonts_autodetect.xconf View File

@@ -0,0 +1,22 @@
<?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>
<renderers>
<renderer mime="application/pdf">
<fonts>
<auto-detect/>
</fonts>
</renderer>
</renderers>
</fop>

+ 22
- 0
test/config/test_fonts_directory_bad.xconf View File

@@ -0,0 +1,22 @@
<?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>
<renderers>
<renderer mime="application/pdf">
<fonts>
<directory>doesnotexist</directory>
</fonts>
</renderer>
</renderers>
</fop>

+ 22
- 0
test/config/test_fonts_directory_recursive.xconf View File

@@ -0,0 +1,22 @@
<?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>
<renderers>
<renderer mime="application/pdf">
<fonts>
<directory recursive="true">test/resources/fonts</directory>
</fonts>
</renderer>
</renderers>
</fop>

+ 45
- 0
test/java/org/apache/fop/config/BaseConstructiveUserConfigTestCase.java View File

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

public abstract class BaseConstructiveUserConfigTestCase extends BaseUserConfigTestCase {

/**
* @see junit.framework.TestCase#TestCase(String)
*/
public BaseConstructiveUserConfigTestCase(String name) {
super(name);
}

/**
* Test using a standard FOP font
* @throws Exception checkstyle wants a comment here, even a silly one
*/
public void testUserConfig() throws Exception {
try {
initConfig();
convertFO();
} catch (Exception e) {
// this should *not* happen!
e.printStackTrace();
fail(e.getMessage());
}
}
}

+ 45
- 0
test/java/org/apache/fop/config/BaseDestructiveUserConfigTestCase.java View File

@@ -0,0 +1,45 @@
/*
* 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 org.apache.fop.apps.FOPException;

public abstract class BaseDestructiveUserConfigTestCase extends BaseUserConfigTestCase {

/**
* @see junit.framework.TestCase#TestCase(String)
*/
public BaseDestructiveUserConfigTestCase(String name) {
super(name);
}

public void testUserConfig() throws Exception {
try {
initConfig();
convertFO();
fail( getName() + ": Expected Configuration Exception" );
} catch (FOPException e) {
// this *should* happen!
} catch (Exception e) {
e.printStackTrace();
fail( getName() + ": Expected FOPException but got: " + e.getMessage() );
}
}
}

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

@@ -15,7 +15,7 @@
* limitations under the License.
*/

/* $Id$ */
/* $Id: $ */

package org.apache.fop.config;

@@ -28,7 +28,6 @@ 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.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.render.pdf.BasePDFTestCase;
import org.xml.sax.SAXException;
@@ -39,7 +38,7 @@ import org.xml.sax.SAXException;
*/
public abstract class BaseUserConfigTestCase extends BasePDFTestCase {

protected static DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
protected DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();

/** logging instance */
protected Log log = LogFactory.getLog(BaseUserConfigTestCase.class);
@@ -59,28 +58,19 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase {
// do nothing
}

/**
* Test using a standard FOP font
* @throws Exception checkstyle wants a comment here, even a silly one
*/
public void testUserConfig() throws Exception {
try {
fopFactory.setUserConfig(getUserConfig());
final File baseDir = getBaseDir();
final String fontFOFilePath = getFontFOFilePath();
File foFile = new File(baseDir, fontFOFilePath);
final boolean dumpOutput = false;
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
convertFO(foFile, foUserAgent, dumpOutput);
fail( getName() + ": Expected Configuration Exception" );
} catch (FOPException e) {
// this *should* happen!
} catch (Exception e) {
fail( getName() + ": Expected FOPException but got: " + e.getMessage() );
}
protected void initConfig() throws Exception {
fopFactory.setUserConfig(getUserConfig());
}


protected void convertFO() throws Exception {
final File baseDir = getBaseDir();
final String fontFOFilePath = getFontFOFilePath();
File foFile = new File(baseDir, fontFOFilePath);
final boolean dumpOutput = false;
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
convertFO(foFile, foUserAgent, dumpOutput);
}
/**
* get test FOP config File
* @return fo test filepath
@@ -96,11 +86,31 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase {
* @throws SAXException
* @throws ConfigurationException
*/
protected Configuration getUserConfig(String configString)
throws ConfigurationException, SAXException, IOException {
protected Configuration getUserConfig(String configString) throws ConfigurationException, SAXException, IOException {
return cfgBuilder.build(new ByteArrayInputStream(configString.getBytes()));
}

/** get base config directory */
protected String getBaseConfigDir() {
return "test/config";
}

/**
* @return user config File
*/
abstract protected String getUserConfigFilename();

/*
* @see junit.framework.TestCase#getName()
*/
public String getName() {
return getUserConfigFilename();
}

protected File getUserConfigFile() {
return new File(getBaseConfigDir() + File.separator + getUserConfigFilename());
}

/**
* get test FOP Configuration
* @return fo test filepath
@@ -108,18 +118,7 @@ public abstract class BaseUserConfigTestCase extends BasePDFTestCase {
* @throws SAXException
* @throws ConfigurationException
*/
protected Configuration getUserConfig()
throws ConfigurationException, SAXException, IOException {
protected Configuration getUserConfig() throws ConfigurationException, SAXException, IOException {
return cfgBuilder.buildFromFile(getUserConfigFile());
}
/** get base config directory */
protected String getBaseConfigDir() {
return "test/config";
}
/**
* @return user config File
*/
protected abstract File getUserConfigFile();
}
}

+ 9
- 10
test/java/org/apache/fop/config/FontAttributesMissingTestCase.java View File

@@ -19,20 +19,19 @@

package org.apache.fop.config;

import java.io.File;
// this font is without a metrics-url or an embed-url
public class FontAttributesMissingTestCase extends BaseUserConfigTestCase {
/*
* this font is without a metrics-url or an embed-url
*/
public class FontAttributesMissingTestCase extends BaseDestructiveUserConfigTestCase {

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

protected File getUserConfigFile() {
return new File( getBaseConfigDir() + "/test_fontattributes_missing.xconf");
}
public String getName() {
return "test_fontattributes_missing.xconf";
/**
* @see org.apache.fop.config.BaseUserConfigTestCase#getUserConfigFilename()
*/
public String getUserConfigFilename() {
return "test_font_attributes_missing.xconf";
}
}

+ 6
- 13
test/java/org/apache/fop/config/FontBaseBadTestCase.java View File

@@ -19,10 +19,10 @@

package org.apache.fop.config;

import java.io.File;
// this font base does not exist and a relative font path is used
public class FontBaseBadTestCase extends BaseUserConfigTestCase {
/*
* this font base does not exist and a relative font path is used
*/
public class FontBaseBadTestCase extends BaseDestructiveUserConfigTestCase {

public FontBaseBadTestCase(String name) {
super(name);
@@ -34,16 +34,9 @@ public class FontBaseBadTestCase extends BaseUserConfigTestCase {
}

/**
* @see org.apache.fop.config.BaseUserConfigTestCase#getUserConfigFile()
*/
protected File getUserConfigFile() {
return new File( getBaseConfigDir() + "/test_fontbase_bad.xconf");
}
/**
* @return configuration filename
* @see org.apache.fop.config.BaseUserConfigTestCase#getUserConfigFilename()
*/
public String getName() {
public String getUserConfigFilename() {
return "test_fontbase_bad.xconf";
}
}

test/java/org/apache/fop/config/EmbedUrlBadTestCase.java → test/java/org/apache/fop/config/FontEmbedUrlBadTestCase.java View File

@@ -19,23 +19,19 @@

package org.apache.fop.config;

import java.io.File;

//
/**
* this font has an embed-url that does not exist on filesystem.
*/
public class EmbedUrlBadTestCase extends BaseUserConfigTestCase {
public class FontEmbedUrlBadTestCase extends BaseDestructiveUserConfigTestCase {

public EmbedUrlBadTestCase(String name) {
public FontEmbedUrlBadTestCase(String name) {
super(name);
}

protected File getUserConfigFile() {
return new File( getBaseConfigDir() + "/test_embedurl_bad.xconf");
}
public String getName() {
return "test_embedurl_bad.xconf";
/**
* @see org.apache.fop.config.BaseUserConfigTestCase#getUserConfigFilename()
*/
public String getUserConfigFilename() {
return "test_font_embedurl_bad.xconf";
}
}

test/java/org/apache/fop/config/EmbedUrlMalformedTestCase.java → test/java/org/apache/fop/config/FontEmbedUrlMalformedTestCase.java View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save