Skip to content

Commit 9dc46ab

Browse files
committed
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
1 parent ed2ea5e commit 9dc46ab

File tree

111 files changed

+4024
-1462
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+4024
-1462
lines changed

fop.bat

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,16 @@ set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\serializer-2.7.0.jar
6262
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\batik-all-1.6.jar
6363
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\xmlgraphics-commons-1.2svn.jar
6464
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\avalon-framework-4.2.0.jar
65-
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.1.jar
65+
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-io-1.3.1.jar
6666
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\commons-logging-1.0.4.jar
6767
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\jimi-1.0.jar
6868
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\jai_core.jar
6969
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\jai_codec.jar
7070
set LOCALCLASSPATH=%LOCALCLASSPATH%;%LIBDIR%\fop-hyph.jar
7171
set LOCALCLASSPATH=%LOCALCLASSPATH%;%FOP_HYPHENATION_PATH%
7272

73+
set JAVAOPTS=-Denv.windir=%WINDIR%
74+
7375
if "%JAVA_HOME%" == "" goto noJavaHome
7476
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
7577
if "%JAVACMD%" == "" set JAVACMD=%JAVA_HOME%\bin\java
@@ -80,5 +82,4 @@ if "%JAVACMD%" == "" set JAVACMD=java
8082

8183
:runFop
8284
rem ECHO "%JAVACMD%"
83-
"%JAVACMD%" %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
84-
85+
"%JAVACMD%" %JAVAOPTS% %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%

fop.cmd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ set LIBDIR=%LOCAL_FOP_HOME%lib
5858
set LOCALCLASSPATH=%FOP_HYPHENATION_PATH%
5959
for %%l in (%LOCAL_FOP_HOME%build\*.jar %LIBDIR%\*.jar) do set LOCALCLASSPATH=!LOCALCLASSPATH!;%%l
6060

61+
set JAVAOPTS=-Denv.windir=%WINDIR%
62+
6163
if "%JAVA_HOME%" == "" goto noJavaHome
6264
if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
6365
if "%JAVACMD%" == "" set JAVACMD=%JAVA_HOME%\bin\java
@@ -68,6 +70,6 @@ if "%JAVACMD%" == "" set JAVACMD=java
6870

6971
:runFop
7072
rem echo "%JAVACMD%" %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
71-
"%JAVACMD%" %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
73+
"%JAVACMD%" %JAVAOPTS% %LOGCHOICE% %LOGLEVEL% -cp "%LOCALCLASSPATH%" org.apache.fop.cli.Main %FOP_CMD_LINE_ARGS%
7274

7375
ENDLOCAL

lib/commons-io-1.1.jar

-60.1 KB
Binary file not shown.

lib/commons-io-1.3.1.jar

81.7 KB
Binary file not shown.

lib/commons-io.NOTICE.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
Apache Jakarta Commons IO
2+
Copyright 2001-2007 The Apache Software Foundation
3+
14
This product includes software developed by
25
The Apache Software Foundation (http://www.apache.org/).
36

src/documentation/content/xdocs/trunk/configuration.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,24 @@
151151
default-page-settings element to specify the two values.</td>
152152
<td>"height" 11 inches, "width" 8.26 inches</td>
153153
</tr>
154+
<tr>
155+
<td>use-cache</td>
156+
<td>boolean (true, false)</td>
157+
<td>All fonts information that has been gathered as a result of "directory"
158+
or "auto-detect" font configurations will be cached for future rendering runs.
159+
This setting should improve performance on systems where
160+
fonts have been configured using the "directory" or "auto-detect" tag mechanisms.
161+
By default this option is switched on.</td>
162+
<td>true</td>
163+
</tr>
164+
<tr>
165+
<td>cache-file</td>
166+
<td>String</td>
167+
<td>This options specifies the file/directory path of the fop cache file.
168+
This option can also be specified on the command-line using the -cache option.
169+
This file is currently only used to cache font triplet information for future reference.</td>
170+
<td>${base}/conf/fop.cache</td>
171+
</tr>
154172
<tr>
155173
<td>renderers</td>
156174
<td>(see text below)</td>

src/documentation/content/xdocs/trunk/fonts.xml

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<authors>
2525
<person name="Jeremias Märki" email=""/>
2626
<person name="Tore Engvig" email=""/>
27+
<person name="Adrian Cumiskey" email=""/>
2728
</authors>
2829
</header>
2930
<body>
@@ -129,8 +130,7 @@
129130
More information about fonts can be found at:</p>
130131
<ul>
131132
<li><a href="http://partners.adobe.com/asn/developer/type/ftypes.html">Adobe font types</a></li>
132-
<li><a href="http://partners.adobe.com/asn/developer/technotes/fonts.html">Adobe Font Technote</a>
133-
</li>
133+
<li><a href="http://partners.adobe.com/asn/developer/technotes/fonts.html">Adobe Font Technote</a></li>
134134
</ul>
135135
<section id="type1-metrics">
136136
<title>Type 1 Font Metrics</title>
@@ -236,19 +236,39 @@ It will display all of the font names and exit with an Exception.</p>
236236
<section id="register">
237237
<title>Register Fonts with FOP</title>
238238
<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>
239-
<source><![CDATA[<font metrics-url="file:///C:/myfonts/FTL_____.xml" kerning="yes"
239+
<source><![CDATA[
240+
<fonts>
241+
<!-- register a particular font -->
242+
<font metrics-url="file:///C:/myfonts/FTL_____.xml" kerning="yes"
240243
embed-url="file:///C:/myfonts/FTL_____.pfb">
241-
<font-triplet name="FrutigerLight" style="normal" weight="normal"/>
242-
</font>]]></source>
244+
<font-triplet name="FrutigerLight" style="normal" weight="normal"/>
245+
</font>
246+
247+
<!-- register all the fonts found in a directory -->
248+
<directory>C:\MyFonts1</directory>
249+
250+
<!-- register all the fonts found in a directory
251+
and all of its sub directories (use with care) -->
252+
<directory recursive="true">C:\MyFonts2</directory>
253+
254+
<!-- automatically detect operating system installed fonts -->
255+
<auto-detect/>
256+
</fonts>]]></source>
243257
<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>
244258
<ul>
245259
<li>
246260
URLs are used to access the font metric and font files.
247261
Relative URLs are resolved relative to the font-base property (or base) if available.
248262
See <a href="configuration.html">FOP: Configuration</a> for more information.
249263
</li>
250-
<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>
251-
<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>
264+
<li>Either an "embed-url" or a "metrics-url" must be specified for font tag configurations.</li>
265+
<li>The font "kerning" attribute is optional. Kerning is currently not used at all.</li>
266+
<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>
267+
<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>
268+
<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>
269+
<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>
270+
<li>Fonts registered with "font" tag configurations override fonts found by means of "directory" tag definitions.</li>
271+
<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>
252272
<li>
253273
If relative URLs are specified, they are evaluated relative to the value of the
254274
"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
281301
See <a href="#ttf-encoding">Table of TTF Encoding Options</a> for more details.</p>
282302
</section>
283303
<section id="embedding-base14">
284-
<title>Explicitely embedding the base 14 fonts</title>
304+
<title>Explicitly embedding the base 14 fonts</title>
285305
<p>
286306
There are cases where you might want to force the embedding of one or more of the base 14 fonts that
287307
can normally be considered available on the target platform (viewer, printer). One of these cases is

src/java/org/apache/fop/apps/FOURIResolver.java

Lines changed: 104 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.net.URLConnection;
3030

3131
import javax.xml.transform.Source;
32+
import javax.xml.transform.TransformerException;
3233
import javax.xml.transform.stream.StreamSource;
3334

3435
// commons logging
@@ -47,8 +48,41 @@
4748
public class FOURIResolver
4849
implements javax.xml.transform.URIResolver {
4950

51+
// log
5052
private Log log = LogFactory.getLog("FOP");
53+
54+
// true if exceptions are to be thrown if the URIs cannot be resolved.
55+
private boolean throwExceptions = false;
56+
57+
/**
58+
* Default constructor
59+
*/
60+
public FOURIResolver() {
61+
this(false);
62+
}
5163

64+
/**
65+
* Additional constructor
66+
* @param throwExceptions true if exceptions are to be thrown if the URIs cannot be
67+
* resolved.
68+
*/
69+
public FOURIResolver(boolean throwExceptions) {
70+
this.throwExceptions = throwExceptions;
71+
}
72+
73+
/**
74+
* Handles resolve exceptions appropriately.
75+
* @param errorStr error string
76+
* @param strict strict user config
77+
*/
78+
private void handleException(Exception e, String errorStr, boolean strict)
79+
throws TransformerException {
80+
if (strict) {
81+
throw new TransformerException(errorStr, e);
82+
}
83+
log.error(e.getMessage());
84+
}
85+
5286
/**
5387
* Called by the processor through {@link FOUserAgent} when it encounters an
5488
* uri in an external-graphic element.
@@ -70,31 +104,25 @@ public class FOURIResolver
70104
* @throws javax.xml.transform.TransformerException Never thrown by this implementation.
71105
* @see javax.xml.transform.URIResolver#resolve(String, String)
72106
*/
73-
public Source resolve(String href, String base)
74-
throws javax.xml.transform.TransformerException {
75-
76-
//data URLs can be quite long so don't try to build a File (can lead to problems)
107+
public Source resolve(String href, String base) throws TransformerException {
108+
// data URLs can be quite long so don't try to build a File (can lead to problems)
77109
if (href.startsWith("data:")) {
78110
return parseDataURI(href);
79111
}
80-
112+
81113
URL absoluteURL = null;
82-
File f = new File(href);
83-
if (f.exists()) {
114+
File file = new File(href);
115+
if (file.canRead() && file.isFile()) {
84116
try {
85-
absoluteURL = f.toURL();
117+
absoluteURL = file.toURL();
86118
} catch (MalformedURLException mfue) {
87-
log.error("Could not convert filename to URL: " + mfue.getMessage());
119+
handleException(mfue,
120+
"Could not convert filename '" + href + "' to URL", throwExceptions);
88121
}
89122
} else {
90-
URL baseURL = null;
91-
try {
92-
baseURL = toBaseURL(base);
93-
} catch (MalformedURLException mfue) {
94-
log.error("Error with base URL \"" + base + "\"): " + mfue.getMessage());
95-
}
96-
if (baseURL == null) {
97-
// We don't have a valid baseURL just use the URL as given
123+
// no base provided
124+
if (base == null) {
125+
// We don't have a valid file protocol based URL
98126
try {
99127
absoluteURL = new URL(href);
100128
} catch (MalformedURLException mue) {
@@ -103,64 +131,78 @@ public Source resolve(String href, String base)
103131
// the href contains only a path then file: is assumed
104132
absoluteURL = new URL("file:" + href);
105133
} catch (MalformedURLException mfue) {
106-
log.error("Error with URL '" + href + "': " + mue.getMessage());
107-
return null;
134+
handleException(mfue,
135+
"Error with URL '" + href + "'", throwExceptions);
108136
}
109137
}
138+
139+
// try and resolve from context of base
110140
} else {
141+
URL baseURL = null;
111142
try {
112-
/*
113-
This piece of code is based on the following statement in
114-
RFC2396 section 5.2:
115-
116-
3) If the scheme component is defined, indicating that the reference
117-
starts with a scheme name, then the reference is interpreted as an
118-
absolute URI and we are done. Otherwise, the reference URI's
119-
scheme is inherited from the base URI's scheme component.
120-
121-
Due to a loophole in prior specifications [RFC1630], some parsers
122-
allow the scheme name to be present in a relative URI if it is the
123-
same as the base URI scheme. Unfortunately, this can conflict
124-
with the correct parsing of non-hierarchical URI. For backwards
125-
compatibility, an implementation may work around such references
126-
by removing the scheme if it matches that of the base URI and the
127-
scheme is known to always use the <hier_part> syntax.
128-
129-
The URL class does not implement this work around, so we do.
130-
*/
143+
baseURL = new URL(base);
144+
} catch (MalformedURLException mfue) {
145+
handleException(mfue, "Error with base URL '" + base + "'", throwExceptions);
146+
}
131147

132-
String scheme = baseURL.getProtocol() + ":";
133-
if (href.startsWith(scheme)) {
134-
href = href.substring(scheme.length());
135-
if ("file:".equals(scheme)) {
136-
int colonPos = href.indexOf(':');
137-
int slashPos = href.indexOf('/');
138-
if (slashPos >= 0 && colonPos >= 0 && colonPos < slashPos) {
139-
href = "/" + href; //Absolute file URL doesn't have a leading slash
140-
}
148+
/*
149+
* This piece of code is based on the following statement in
150+
* RFC2396 section 5.2:
151+
*
152+
* 3) If the scheme component is defined, indicating that the
153+
* reference starts with a scheme name, then the reference is
154+
* interpreted as an absolute URI and we are done. Otherwise,
155+
* the reference URI's scheme is inherited from the base URI's
156+
* scheme component.
157+
*
158+
* Due to a loophole in prior specifications [RFC1630], some
159+
* parsers allow the scheme name to be present in a relative URI
160+
* if it is the same as the base URI scheme. Unfortunately, this
161+
* can conflict with the correct parsing of non-hierarchical
162+
* URI. For backwards compatibility, an implementation may work
163+
* around such references by removing the scheme if it matches
164+
* that of the base URI and the scheme is known to always use
165+
* the <hier_part> syntax.
166+
*
167+
* The URL class does not implement this work around, so we do.
168+
*/
169+
String scheme = baseURL.getProtocol() + ":";
170+
if (href.startsWith(scheme)) {
171+
href = href.substring(scheme.length());
172+
if ("file:".equals(scheme)) {
173+
int colonPos = href.indexOf(':');
174+
int slashPos = href.indexOf('/');
175+
if (slashPos >= 0 && colonPos >= 0 && colonPos < slashPos) {
176+
href = "/" + href; // Absolute file URL doesn't
177+
// have a leading slash
141178
}
142179
}
180+
}
181+
try {
143182
absoluteURL = new URL(baseURL, href);
144183
} catch (MalformedURLException mfue) {
145-
log.error("Error with URL '" + href + "': " + mfue.getMessage());
146-
return null;
184+
handleException(mfue,
185+
"Error with URL; base '" + base + "' " + "href '" + href + "'",
186+
throwExceptions);
147187
}
148188
}
149189
}
150190

151-
String effURL = absoluteURL.toExternalForm();
152-
try {
153-
URLConnection connection = absoluteURL.openConnection();
154-
connection.setAllowUserInteraction(false);
155-
connection.setDoInput(true);
156-
updateURLConnection(connection, href);
157-
connection.connect();
158-
return new StreamSource(connection.getInputStream(), effURL);
159-
} catch (FileNotFoundException fnfe) {
160-
//Note: This is on "debug" level since the caller is supposed to handle this
161-
log.debug("File not found: " + effURL);
162-
} catch (java.io.IOException ioe) {
163-
log.error("Error with opening URL '" + effURL + "': " + ioe.getMessage());
191+
if (absoluteURL != null) {
192+
String effURL = absoluteURL.toExternalForm();
193+
try {
194+
URLConnection connection = absoluteURL.openConnection();
195+
connection.setAllowUserInteraction(false);
196+
connection.setDoInput(true);
197+
updateURLConnection(connection, href);
198+
connection.connect();
199+
return new StreamSource(connection.getInputStream(), effURL);
200+
} catch (FileNotFoundException fnfe) {
201+
//Note: This is on "debug" level since the caller is supposed to handle this
202+
log.debug("File not found: " + effURL);
203+
} catch (java.io.IOException ioe) {
204+
log.error("Error with opening URL '" + effURL + "': " + ioe.getMessage());
205+
}
164206
}
165207
return null;
166208
}
@@ -200,29 +242,6 @@ protected void applyHttpBasicAuthentication(URLConnection connection,
200242
}
201243
}
202244

203-
/**
204-
* Returns the base URL as a java.net.URL.
205-
* If the base URL is not set a default URL pointing to the
206-
* current directory is returned.
207-
* @param baseURL the base URL
208-
* @returns the base URL as java.net.URL
209-
*/
210-
private URL toBaseURL(String base) throws MalformedURLException {
211-
if (base == null) {
212-
return new java.io.File("").toURL();
213-
}
214-
if (!base.endsWith("/")) {
215-
// The behavior described by RFC 3986 regarding resolution of relative
216-
// references may be misleading for normal users:
217-
// file://path/to/resources + myResource.res -> file://path/to/myResource.res
218-
// file://path/to/resources/ + myResource.res -> file://path/to/resources/myResource.res
219-
// We assume that even when the ending slash is missing, users have the second
220-
// example in mind
221-
base += "/";
222-
}
223-
return new URL(base);
224-
}
225-
226245
/**
227246
* Parses inline data URIs as generated by MS Word's XML export and FO stylesheet.
228247
* @see <a href="http://www.ietf.org/rfc/rfc2397">RFC 2397</a>

0 commit comments

Comments
 (0)