You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ac...@apache.org on 2008/04/03 11:40:14 UTC
svn commit: r644243 - in /xmlgraphics/fop/branches/Temp_AFPGOCAResources: ./
src/documentation/content/xdocs/trunk/ src/foschema/
src/java/org/apache/fop/fonts/ src/java/org/apache/fop/fonts/autodetect/
src/java/org/apache/fop/fonts/truetype/ src/java/...
Author: acumiskey
Date: Thu Apr 3 02:40:10 2008
New Revision: 644243
URL: http://svn.apache.org/viewvc?rev=644243&view=rev
Log:
Merged revisions 644208,644213 via svnmerge from
https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk
........
r644208 | jeremias | 2008-04-03 09:05:14 +0100 (Thu, 03 Apr 2008) | 11 lines
Bugzilla #44737:
Added support for auto-configuring TrueType Collections. XML font metrics files for *.ttc fonts are not required anymore.
Submitted by: Jason Harrop <jason.at.plutext.org>
Changes to patch or in addition to the patch:
- Tab chars removed and Checkstyle issues fixed
- Some simplifications in the cache handling (CachedFontInfo is obsolete and less cache-private information is exposed to the outside).
- TTCs are fully detected and registered with FOP.
- TTCs can also be registered using a "font" element. The new "sub-font" attribute selected the sub-font in the TTC.
- Bug fixed in TTFFile: Font names were not decoded correctly (ex. font names in Chinese)
- Minimal docs.
........
r644213 | jeremias | 2008-04-03 09:13:50 +0100 (Thu, 03 Apr 2008) | 1 line
Oops. Fixed a last-minute change that broke the build.
........
Removed:
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/CachedFontInfo.java
Modified:
xmlgraphics/fop/branches/Temp_AFPGOCAResources/ (props changed)
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/documentation/content/xdocs/trunk/fonts.xml
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/foschema/fop-configuration.xsd
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/EmbedFontInfo.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontCache.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontLoader.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/LazyFont.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/FontFileReader.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFile.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/PrintRendererConfigurator.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/FontSetup.java
xmlgraphics/fop/branches/Temp_AFPGOCAResources/status.xml
Propchange: xmlgraphics/fop/branches/Temp_AFPGOCAResources/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Apr 3 02:40:10 2008
@@ -1 +1 @@
-/xmlgraphics/fop/trunk:1-643437
+/xmlgraphics/fop/trunk:1-644238
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/documentation/content/xdocs/trunk/fonts.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/documentation/content/xdocs/trunk/fonts.xml?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/documentation/content/xdocs/trunk/fonts.xml (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/documentation/content/xdocs/trunk/fonts.xml Thu Apr 3 02:40:10 2008
@@ -308,6 +308,11 @@
<source>java -cp build\fop.jar;lib\avalon-framework.jar;lib\commons-logging.jar;lib\commons-io.jar
org.apache.fop.fonts.apps.TTFReader -ttcname "MS Mincho"
msmincho.ttc msminch.xml</source>
+ <p>
+ Alternatively, the individual sub-fonts of a TrueType Collections can be selected
+ using the "sub-font" attribute on the "font" element. That means that generating
+ an XML font metrics file for TrueType collections is not necessary anymore.
+ </p>
</section>
<section id="register">
<title>Register Fonts with FOP</title>
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/foschema/fop-configuration.xsd
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/foschema/fop-configuration.xsd?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/foschema/fop-configuration.xsd (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/foschema/fop-configuration.xsd Thu Apr 3 02:40:10 2008
@@ -210,6 +210,7 @@
</xsd:sequence>
<xsd:attribute name="metrics-url" type="xsd:anyURI" use="optional"/>
<xsd:attribute name="embed-url" type="xsd:anyURI" use="optional"/>
+ <xsd:attribute name="sub-font" type="xsd:string" use="optional"/>
<xsd:attribute name="kerning" use="optional" default="no">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/EmbedFontInfo.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/EmbedFontInfo.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/EmbedFontInfo.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/EmbedFontInfo.java Thu Apr 3 02:40:10 2008
@@ -28,7 +28,7 @@
public class EmbedFontInfo implements Serializable {
/** Serialization Version UID */
- private static final long serialVersionUID = -9075848379822693399L;
+ private static final long serialVersionUID = 8755432068669997367L;
/** filename of the metrics file */
protected String metricsFile;
@@ -38,20 +38,27 @@
protected boolean kerning;
/** the list of associated font triplets */
protected List fontTriplets;
-
+
+ /** the PostScript name of the font */
+ protected String postScriptName = null;
+ /** the sub-fontname of the font (used for TrueType Collections, null otherwise) */
+ protected String subFontName = null;
+
/**
* Main constructor
* @param metricsFile Path to the xml file containing font metrics
* @param kerning True if kerning should be enabled
* @param fontTriplets List of font triplets to associate with this font
* @param embedFile Path to the embeddable font file (may be null)
+ * @param subFontName the sub-fontname used for TrueType Collections (null otherwise)
*/
public EmbedFontInfo(String metricsFile, boolean kerning,
- List fontTriplets, String embedFile) {
+ List fontTriplets, String embedFile, String subFontName) {
this.metricsFile = metricsFile;
this.embedFile = embedFile;
this.kerning = kerning;
this.fontTriplets = fontTriplets;
+ this.subFontName = subFontName;
}
/**
@@ -86,9 +93,35 @@
return fontTriplets;
}
+ /**
+ * Returns the sub-fontname name of the font. This is primarily used for TrueType Collections
+ * to select one of the sub-fonts. For all other fonts, this is always null.
+ * @return the sub-fontname (or null)
+ */
+ public String getSubFontName() {
+ return this.subFontName;
+ }
+
+ /**
+ * Returns the PostScript name of the font.
+ * @return the PostScript name
+ */
+ public String getPostScriptName() {
+ return postScriptName;
+ }
+
+ /**
+ * Sets the PostScript name of the font
+ * @param postScriptName the PostScript name
+ */
+ public void setPostScriptName(String postScriptName) {
+ this.postScriptName = postScriptName;
+ }
+
/** {@inheritDoc} */
public String toString() {
return "metrics-url=" + metricsFile + ",embed-url=" + embedFile
- + ", kerning=" + kerning + ", font-triplet=" + fontTriplets;
+ + ", kerning=" + kerning + ", font-triplet=" + fontTriplets
+ + (getSubFontName() != null ? ", sub-font=" + getSubFontName() : "");
}
}
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontCache.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontCache.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontCache.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontCache.java Thu Apr 3 02:40:10 2008
@@ -26,8 +26,12 @@
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
import java.util.Map;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -61,10 +65,11 @@
/** change lock */
private transient Object changeLock = new Object();
- /** master mapping of font url -> font info */
- private Map fontMap = new java.util.HashMap();
+ /** master mapping of font url -> font info. This needs to be
+ * a list, since a TTC file may contain more than 1 font. */
+ private Map fontfileMap = new java.util.HashMap(); //Map<String, CachedFontFile>
- /** mapping of font url -> file modified date */
+ /** mapping of font url -> file modified date (for all fonts that have failed to load) */
private Map failedFontMap = new java.util.HashMap();
/**
@@ -216,7 +221,7 @@
*/
public boolean containsFont(String embedUrl) {
if (embedUrl != null) {
- return fontMap.containsKey(embedUrl);
+ return fontfileMap.containsKey(embedUrl);
}
return false;
}
@@ -228,45 +233,100 @@
*/
public boolean containsFont(EmbedFontInfo fontInfo) {
if (fontInfo != null) {
- return fontMap.containsKey(getCacheKey(fontInfo));
+ return fontfileMap.containsKey(getCacheKey(fontInfo));
}
return false;
}
/**
- * adds a font info to cache
+ * Tries to identify a File instance from an array of URLs. If there's no file URL in the
+ * array, the method returns null.
+ * @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) {
+ File fontFile = null;
+ if (urlStr.startsWith("file:")) {
+ try {
+ URL url = new URL(urlStr);
+ fontFile = FileUtils.toFile(url);
+ } catch (MalformedURLException mfue) {
+ // do nothing
+ }
+ }
+ if (fontFile == null) {
+ fontFile = new File(urlStr);
+ }
+ if (fontFile.exists() && fontFile.canRead()) {
+ return fontFile;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a font info to cache
* @param fontInfo font info
*/
public void addFont(EmbedFontInfo fontInfo) {
String cacheKey = getCacheKey(fontInfo);
synchronized (changeLock) {
- if (!containsFont(cacheKey)) {
+ CachedFontFile cachedFontFile;
+ if (containsFont(cacheKey)) {
+ cachedFontFile = (CachedFontFile)fontfileMap.get(cacheKey);
+ if (!cachedFontFile.containsFont(fontInfo)) {
+ cachedFontFile.put(fontInfo);
+ }
+ } else {
+ // try and determine modified date
+ File fontFile = getFileFromUrls(new String[]
+ {fontInfo.getEmbedFile(), fontInfo.getMetricsFile()});
+ long lastModified = (fontFile != null ? fontFile.lastModified() : -1);
+ cachedFontFile = new CachedFontFile(lastModified);
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));
- }
+ cachedFontFile.put(fontInfo);
+ fontfileMap.put(cacheKey, cachedFontFile);
changed = true;
}
}
}
/**
- * returns a font from the cache
+ * Returns a font from the cache.
* @param embedUrl font info
- * @return boolean
+ * @return CachedFontFile object
*/
- public CachedFontInfo getFont(String embedUrl) {
+ public CachedFontFile getFontFile(String embedUrl) {
if (containsFont(embedUrl)) {
- return (CachedFontInfo)fontMap.get(embedUrl);
+ return (CachedFontFile)fontfileMap.get(embedUrl);
}
return null;
}
/**
+ * Returns the EmbedFontInfo instances belonging to a font file. If the font file was
+ * modified since it was cached the entry is removed and null is returned.
+ * @param embedUrl the font URL
+ * @param lastModified the last modified date/time of the font file
+ * @return the EmbedFontInfo instances or null if there's no cached entry or if it is outdated
+ */
+ public EmbedFontInfo[] getFontInfos(String embedUrl, long lastModified) {
+ CachedFontFile cff = getFontFile(embedUrl);
+ if (cff.lastModified() == lastModified) {
+ return cff.getEmbedFontInfos();
+ } else {
+ removeFont(embedUrl);
+ return null;
+ }
+ }
+
+ /**
* removes font from cache
* @param embedUrl embed url
*/
@@ -276,7 +336,7 @@
if (log.isTraceEnabled()) {
log.trace("Font removed from cache: " + embedUrl);
}
- fontMap.remove(embedUrl);
+ fontfileMap.remove(embedUrl);
changed = true;
}
}
@@ -326,9 +386,87 @@
if (log.isTraceEnabled()) {
log.trace("Font cache cleared.");
}
- fontMap.clear();
+ fontfileMap.clear();
failedFontMap.clear();
changed = true;
}
+ }
+
+ /**
+ * Retrieve the last modified date/time of a URL.
+ * @param url the URL
+ * @return the last modified date/time
+ */
+ public static long getLastModified(URL url) {
+ try {
+ URLConnection conn = url.openConnection();
+ try {
+ return conn.getLastModified();
+ } finally {
+ //An InputStream is created even if it's not accessed, but we need to close it.
+ IOUtils.closeQuietly(conn.getInputStream());
+ }
+ } catch (IOException e) {
+ // Should never happen, because URL must be local
+ log.debug("IOError: " + e.getMessage());
+ return 0;
+ }
+ }
+
+ private static class CachedFontFile implements Serializable {
+ /** file modify date (if available) */
+ private long lastModified = -1;
+
+ private Map filefontsMap = new java.util.HashMap(); //Map<String, EmbedFontInfo>
+
+ public CachedFontFile(long lastModified) {
+ setLastModified(lastModified);
+ }
+
+ void put(EmbedFontInfo efi) {
+ filefontsMap.put(efi.getPostScriptName(), efi);
+ }
+
+ public boolean containsFont(EmbedFontInfo efi) {
+ if (efi.getPostScriptName() != null) {
+ return filefontsMap.containsKey(efi.getPostScriptName());
+ }
+ return false;
+ }
+
+ public Map getFilefontsMap() {
+ return filefontsMap;
+ }
+
+ public EmbedFontInfo[] getEmbedFontInfos() {
+ return (EmbedFontInfo[])this.filefontsMap.values().toArray(
+ new EmbedFontInfo[this.filefontsMap.size()]);
+ }
+
+ /**
+ * 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
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return super.toString() + ", lastModified=" + lastModified;
+ }
+
}
}
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontLoader.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontLoader.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/FontLoader.java Thu Apr 3 02:40:10 2008
@@ -71,36 +71,39 @@
/**
* 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 subFontName the sub-fontname of a font (for TrueType Collections, null otherwise)
* @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)
+ public static CustomFont loadFont(File fontFile, String subFontName, FontResolver resolver)
throws IOException {
- return loadFont(fontFile.getAbsolutePath(), resolver);
+ return loadFont(fontFile.getAbsolutePath(), subFontName, resolver);
}
/**
* Loads a custom font from an URL. In the case of Type 1 fonts, the PFB file must be specified.
* @param fontUrl the URL representation of the font
+ * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise)
* @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(URL fontUrl, FontResolver resolver)
+ public static CustomFont loadFont(URL fontUrl, String subFontName, FontResolver resolver)
throws IOException {
- return loadFont(fontUrl.toExternalForm(), resolver);
+ return loadFont(fontUrl.toExternalForm(), subFontName, 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
+ * @param subFontName the sub-fontname of a font (for TrueType Collections, null otherwise)
* @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(String fontFileURI, FontResolver resolver)
+ public static CustomFont loadFont(String fontFileURI, String subFontName, FontResolver resolver)
throws IOException {
fontFileURI = fontFileURI.trim();
boolean type1 = isType1(fontFileURI);
@@ -108,7 +111,7 @@
if (type1) {
loader = new Type1FontLoader(fontFileURI, resolver);
} else {
- loader = new TTFFontLoader(fontFileURI, resolver);
+ loader = new TTFFontLoader(fontFileURI, subFontName, resolver);
}
return loader.getFont();
}
@@ -121,7 +124,7 @@
* @throws IOException In case of an I/O error
* @throws MalformedURLException If an invalid URL is built
*/
- protected static InputStream openFontUri(FontResolver resolver, String uri)
+ public static InputStream openFontUri(FontResolver resolver, String uri)
throws IOException, MalformedURLException {
InputStream in = null;
if (resolver != null) {
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/LazyFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/LazyFont.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/LazyFont.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/LazyFont.java Thu Apr 3 02:40:10 2008
@@ -44,6 +44,7 @@
private String metricsFileName = null;
private String fontEmbedPath = null;
private boolean useKerning = false;
+ private String subFontName = null;
private boolean isMetricsLoaded = false;
private Typeface realFont = null;
@@ -61,6 +62,7 @@
this.metricsFileName = fontInfo.getMetricsFile();
this.fontEmbedPath = fontInfo.getEmbedFile();
this.useKerning = fontInfo.getKerning();
+ this.subFontName = fontInfo.getSubFontName();
this.resolver = resolver;
}
@@ -123,7 +125,7 @@
if (fontEmbedPath == null) {
throw new RuntimeException("Cannot load font. No font URIs available.");
}
- realFont = FontLoader.loadFont(fontEmbedPath, resolver);
+ realFont = FontLoader.loadFont(fontEmbedPath, this.subFontName, resolver);
}
if (realFont instanceof FontDescriptor) {
realFontDescriptor = (FontDescriptor) realFont;
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontFileFinder.java Thu Apr 3 02:40:10 2008
@@ -72,14 +72,15 @@
}
/**
- * Font file filter. Currently searches for files with .ttf and .pfb extensions.
+ * Font file filter. Currently searches for files with .ttf, .ttc, .otf, and .pfb extensions.
* @return IOFileFilter font file filter
*/
protected static IOFileFilter getFileFilter() {
return FileFilterUtils.andFileFilter(
FileFilterUtils.fileFileFilter(),
- new WildcardFileFilter(new String[] {"*.ttf", "*.otf", "*.pfb"}, IOCase.INSENSITIVE)
- //TODO Add *.ttc when support for it has been added to the auto-detection mech.
+ new WildcardFileFilter(
+ new String[] {"*.ttf", "*.otf", "*.pfb", "*.ttc"},
+ IOCase.INSENSITIVE)
);
}
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java Thu Apr 3 02:40:10 2008
@@ -19,9 +19,8 @@
package org.apache.fop.fonts.autodetect;
-import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
-import java.net.URLConnection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
@@ -32,7 +31,6 @@
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;
@@ -41,6 +39,10 @@
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;
+import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.fonts.truetype.TTFFile;
+import org.apache.fop.fonts.truetype.TTFFontLoader;
/**
* Attempts to determine correct FontInfo
@@ -131,8 +133,13 @@
generateTripletsFromFont(customFont, fontTripletList);
String embedUrl;
embedUrl = fontUrl.toExternalForm();
+ String subFontName = null;
+ if (customFont instanceof MultiByteFont) {
+ subFontName = ((MultiByteFont)customFont).getTTCName();
+ }
EmbedFontInfo fontInfo = new EmbedFontInfo(null, customFont.isKerningEnabled(),
- fontTripletList, embedUrl);
+ fontTripletList, embedUrl, subFontName);
+ fontInfo.setPostScriptName(customFont.getFontName());
if (fontCache != null) {
fontCache.addFont(fontInfo);
}
@@ -145,35 +152,21 @@
* @param fontUrl font URL. Assumed to be local.
* @param resolver font resolver used to resolve font
* @param fontCache font cache (may be null)
- * @return newly created embed font info
+ * @return an array of newly created embed font info. Generally, this array
+ * will have only one entry, unless the fontUrl is a TrueType Collection
*/
- public EmbedFontInfo find(URL fontUrl, FontResolver resolver, FontCache fontCache) {
+ public EmbedFontInfo[] find(URL fontUrl, FontResolver resolver, FontCache fontCache) {
String embedUrl = null;
embedUrl = fontUrl.toExternalForm();
long fileLastModified = -1;
if (fontCache != null) {
- try {
- URLConnection conn = fontUrl.openConnection();
- try {
- fileLastModified = conn.getLastModified();
- } finally {
- //An InputStream is created even if it's not accessed, but we need to close it.
- IOUtils.closeQuietly(conn.getInputStream());
- }
- } catch (IOException e) {
- // Should never happen, because URL must be local
- log.debug("IOError: " + e.getMessage());
- fileLastModified = 0;
- }
+ fileLastModified = FontCache.getLastModified(fontUrl);
// 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);
+ EmbedFontInfo[] fontInfos = fontCache.getFontInfos(embedUrl, fileLastModified);
+ if (fontInfos != null) {
+ return fontInfos;
}
// is this a previously failed parsed font?
} else if (fontCache.isFailedFont(embedUrl, fileLastModified)) {
@@ -184,20 +177,81 @@
}
}
+
// try to determine triplet information from font file
CustomFont customFont = null;
- try {
- customFont = FontLoader.loadFont(fontUrl, 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 (fontUrl.toExternalForm().endsWith(".ttc")) {
+ // Get a list of the TTC Font names
+ List ttcNames = null; //List<String>
+ String fontFileURI = fontUrl.toExternalForm().trim();
+ TTFFontLoader ttfLoader = new TTFFontLoader(fontFileURI, resolver);
+ InputStream in = null;
+ try {
+ in = FontLoader.openFontUri(resolver, fontFileURI);
+ TTFFile ttf = new TTFFile();
+ FontFileReader reader = new FontFileReader(in);
+ ttcNames = ttf.getTTCnames(reader);
+ } catch (Exception e) {
+ log.error(e);
+ } finally {
+ IOUtils.closeQuietly(in);
}
- if (fontCache != null) {
- fontCache.registerFailedFont(embedUrl, fileLastModified);
+
+ List embedFontInfoList = new java.util.ArrayList(); //List<EmbedFontInfo>
+
+ // For each font name ...
+ //for (String fontName : ttcNames) {
+ Iterator ttcNamesIterator = ttcNames.iterator();
+ while (ttcNamesIterator.hasNext()) {
+ String fontName = (String)ttcNamesIterator.next();
+
+ if (log.isDebugEnabled()) {
+ log.debug("Loading " + fontName);
+ }
+ try {
+ ttfLoader = new TTFFontLoader(fontFileURI, fontName, resolver);
+ customFont = ttfLoader.getFont();
+ } 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);
+ }
+ continue;
+ }
+ EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache);
+ if (fi != null) {
+ embedFontInfoList.add(fi);
+ }
+ }
+ return (EmbedFontInfo[])embedFontInfoList.toArray(
+ new EmbedFontInfo[embedFontInfoList.size()]);
+ } else {
+ // The normal case
+ try {
+ customFont = FontLoader.loadFont(fontUrl, null, 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;
+ }
+ EmbedFontInfo fi = fontInfoFromCustomFont(fontUrl, customFont, fontCache);
+ if (fi != null) {
+ return new EmbedFontInfo[] {fi};
+ } else {
+ return null;
}
- return null;
}
- return fontInfoFromCustomFont(fontUrl, customFont, fontCache);
+
+
}
+
}
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/FontFileReader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/FontFileReader.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/FontFileReader.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/FontFileReader.java Thu Apr 3 02:40:10 2008
@@ -19,9 +19,9 @@
package org.apache.fop.fonts.truetype;
-import java.io.InputStream;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import org.apache.commons.io.IOUtils;
@@ -310,6 +310,26 @@
} else {
encoding = "ISO-8859-1";
}
+ return new String(tmp, encoding);
+ }
+
+ /**
+ * Read an ISO-8859-1 string of len bytes.
+ *
+ * @param len The length of the string to read
+ * @return A String
+ * @throws IOException If EOF is reached
+ */
+ public final String readTTFString(int len, int encodingID) throws IOException {
+ if ((len + current) > fsize) {
+ throw new java.io.EOFException("Reached EOF, file size=" + fsize);
+ }
+
+ byte[] tmp = new byte[len];
+ System.arraycopy(file, current, tmp, 0, len);
+ current += len;
+ final String encoding;
+ encoding = "UTF-16BE"; //Use this for all known encoding IDs for now
return new String(tmp, encoding);
}
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFile.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFile.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFile.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFile.java Thu Apr 3 02:40:10 2008
@@ -988,7 +988,10 @@
if (dirTabs.get("OS/2") != null) {
seekTab(in, "OS/2", 2 * 2);
this.usWeightClass = in.readTTFUShort();
+
+ // usWidthClass
in.skip(2);
+
int fsType = in.readTTFUShort();
if (fsType == 2) {
isEmbeddable = false;
@@ -1123,7 +1126,12 @@
if (((platformID == 1 || platformID == 3)
&& (encodingID == 0 || encodingID == 1))) {
in.seekSet(j + in.readTTFUShort());
- String txt = in.readTTFString(l);
+ String txt;
+ if (platformID == 3) {
+ txt = in.readTTFString(l, encodingID);
+ } else {
+ txt = in.readTTFString(l);
+ }
if (log.isDebugEnabled()) {
log.debug(platformID + " "
@@ -1147,7 +1155,7 @@
}
break;
case 4:
- if (fullName.length() == 0) {
+ if (fullName.length() == 0 || (platformID == 3 && languageID == 1033)) {
fullName = txt;
}
break;
@@ -1474,6 +1482,59 @@
}
}
+ /**
+ * Return TTC font names
+ * @param in FontFileReader to read from
+ * @return True if not collection or font name present, false otherwise
+ * @throws IOException In case of an I/O problem
+ */
+ public final List getTTCnames(FontFileReader in) throws IOException {
+ List fontNames = new java.util.ArrayList();
+
+ String tag = in.readTTFString(4);
+
+ if ("ttcf".equals(tag)) {
+ // This is a TrueType Collection
+ in.skip(4);
+
+ // Read directory offsets
+ int numDirectories = (int)in.readTTFULong();
+ long[] dirOffsets = new long[numDirectories];
+ for (int i = 0; i < numDirectories; i++) {
+ dirOffsets[i] = in.readTTFULong();
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("This is a TrueType collection file with "
+ + numDirectories + " fonts");
+ log.debug("Containing the following fonts: ");
+ }
+
+ for (int i = 0; (i < numDirectories); i++) {
+ in.seekSet(dirOffsets[i]);
+ readDirTabs(in);
+
+ readName(in);
+
+ log.debug(fullName);
+ fontNames.add(fullName);
+
+ // Reset names
+ notice = "";
+ fullName = "";
+ familyNames.clear();
+ postScriptName = "";
+ subFamilyName = "";
+ }
+
+ in.seekSet(0);
+ return fontNames;
+ } else {
+ log.error("Not a TTC!");
+ return null;
+ }
+ }
+
/*
* Helper classes, they are not very efficient, but that really
* doesn't matter...
@@ -1536,8 +1597,8 @@
* @throws IOException if unicodeIndex not found
*/
private Integer unicodeToGlyph(int unicodeIndex) throws IOException {
- final Integer result =
- (Integer) unicodeToGlyphMap.get(new Integer(unicodeIndex));
+ final Integer result
+ = (Integer) unicodeToGlyphMap.get(new Integer(unicodeIndex));
if (result == null) {
throw new IOException(
"Glyph index not found for unicode value " + unicodeIndex);
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java Thu Apr 3 02:40:10 2008
@@ -34,11 +34,12 @@
import org.apache.fop.fonts.MultiByteFont;
/**
- * Loads a font into memory directly from the original font file.
+ * Loads a TrueType font into memory directly from the original font file.
*/
public class TTFFontLoader extends FontLoader {
private MultiByteFont multiFont;
+ private String subFontName;
/**
* Default constructor
@@ -46,27 +47,50 @@
* @param resolver the FontResolver for font URI resolution
*/
public TTFFontLoader(String fontFileURI, FontResolver resolver) {
+ this(fontFileURI, null, resolver);
+ }
+
+ /**
+ * Additional constructor for TrueType Collections.
+ * @param fontFileURI the URI representing the font file
+ * @param subFontName the sub-fontname of a font in a TrueType Collection (or null for normal
+ * TrueType fonts)
+ * @param resolver the FontResolver for font URI resolution
+ */
+ public TTFFontLoader(String fontFileURI, String subFontName, FontResolver resolver) {
super(fontFileURI, resolver);
+ this.subFontName = subFontName;
}
/** {@inheritDoc} */
protected void read() throws IOException {
+ read(this.subFontName);
+ }
+
+ /**
+ * Reads a TrueType font.
+ * @param ttcFontName the TrueType sub-font name of TrueType Collection (may be null for
+ * normal TrueType fonts)
+ * @throws IOException if an I/O error occurs
+ */
+ private void read(String ttcFontName) throws IOException {
InputStream in = openFontUri(resolver, this.fontFileURI);
try {
TTFFile ttf = new TTFFile();
FontFileReader reader = new FontFileReader(in);
- boolean supported = ttf.readFont(reader, null);
+ boolean supported = ttf.readFont(reader, ttcFontName);
if (!supported) {
throw new IOException("TrueType font is not supported: " + fontFileURI);
}
- buildFont(ttf);
+ buildFont(ttf, ttcFontName);
loaded = true;
} finally {
IOUtils.closeQuietly(in);
}
}
-
- private void buildFont(TTFFile ttf) {
+
+
+ private void buildFont(TTFFile ttf, String ttcFontName) {
if (ttf.isCFF()) {
throw new UnsupportedOperationException(
"OpenType fonts with CFF data are not supported, yet");
@@ -79,7 +103,7 @@
returnFont.setFullName(ttf.getFullName());
returnFont.setFamilyNames(ttf.getFamilyNames());
returnFont.setFontSubFamilyName(ttf.getSubFamilyName());
- //multiFont.setTTCName(ttcName)
+ multiFont.setTTCName(ttcFontName);
returnFont.setCapHeight(ttf.getCapHeight());
returnFont.setXHeight(ttf.getXHeight());
returnFont.setAscender(ttf.getLowerCaseAscent());
@@ -91,7 +115,7 @@
returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle()));
returnFont.setMissingWidth(0);
returnFont.setWeight(ttf.getWeightClass());
-
+
multiFont.setCIDType(CIDFontType.CIDTYPE2);
int[] wx = ttf.getWidths();
multiFont.setWidthArray(wx);
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/PrintRendererConfigurator.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/PrintRendererConfigurator.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/PrintRendererConfigurator.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/PrintRendererConfigurator.java Thu Apr 3 02:40:10 2008
@@ -36,10 +36,11 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.util.ClasspathResource;
+
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;
@@ -50,7 +51,6 @@
import org.apache.fop.fonts.autodetect.FontFileFinder;
import org.apache.fop.fonts.autodetect.FontInfoFinder;
import org.apache.fop.util.LogUtil;
-import org.apache.xmlgraphics.util.ClasspathResource;
/**
* Base Print renderer configurator (mostly handles font configuration)
@@ -230,9 +230,20 @@
URL fontUrl = (URL)iter.next();
// parse font to ascertain font info
FontInfoFinder finder = new FontInfoFinder();
- EmbedFontInfo fontInfo = finder.find(fontUrl, resolver, fontCache);
- if (fontInfo != null) {
- fontInfoList.add(fontInfo);
+ //EmbedFontInfo fontInfo = finder.find(fontUrl, resolver, fontCache);
+
+ //List<EmbedFontInfo> embedFontInfoList = finder.find(fontUrl, resolver, fontCache);
+ EmbedFontInfo[] embedFontInfos = finder.find(fontUrl, resolver, fontCache);
+
+ if (embedFontInfos == null) {
+ return;
+ }
+
+ for (int i = 0, c = embedFontInfos.length; i < c; i++) {
+ EmbedFontInfo fontInfo = embedFontInfos[i];
+ if (fontInfo != null) {
+ fontInfoList.add(fontInfo);
+ }
}
}
}
@@ -257,9 +268,10 @@
*/
public static EmbedFontInfo getFontInfoFromConfiguration(
Configuration fontCfg, FontResolver fontResolver, boolean strict, FontCache fontCache)
- throws FOPException {
+ throws FOPException {
String metricsUrl = fontCfg.getAttribute("metrics-url", null);
String embedUrl = fontCfg.getAttribute("embed-url", null);
+ String subFont = fontCfg.getAttribute("sub-font", null);
if (metricsUrl == null && embedUrl == null) {
LogUtil.handleError(log, "Font configuration without metric-url or embed-url", strict);
@@ -296,7 +308,7 @@
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});
+ File fontFile = FontCache.getFileFromUrls(new String[] {embedUrl, metricsUrl});
URL fontUrl;
try {
fontUrl = fontFile.toURI().toURL();
@@ -307,7 +319,8 @@
}
if (fontFile != null) {
FontInfoFinder finder = new FontInfoFinder();
- return finder.find(fontUrl, fontResolver, fontCache);
+ EmbedFontInfo[] infos = finder.find(fontUrl, fontResolver, fontCache);
+ return infos[0]; //When subFont is set, only one font is returned
} else {
return null;
}
@@ -337,7 +350,7 @@
}
}
- fontInfo = new EmbedFontInfo(metricsUrl, useKerning, tripleList, embedUrl);
+ fontInfo = new EmbedFontInfo(metricsUrl, useKerning, tripleList, embedUrl, subFont);
if (fontCache != null) {
if (!fontCache.containsFont(fontInfo)) {
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/FontSetup.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/FontSetup.java?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/FontSetup.java (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/src/java/org/apache/fop/render/java2d/FontSetup.java Thu Apr 3 02:40:10 2008
@@ -304,7 +304,7 @@
Source fontSource = resolver.resolve(configFontInfo.getEmbedFile());
font = new CustomFontMetricsMapper(fontMetrics, fontSource);
} else {
- CustomFont fontMetrics = FontLoader.loadFont(fontFile, resolver);
+ CustomFont fontMetrics = FontLoader.loadFont(fontFile, null, resolver);
font = new CustomFontMetricsMapper(fontMetrics);
}
Modified: xmlgraphics/fop/branches/Temp_AFPGOCAResources/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_AFPGOCAResources/status.xml?rev=644243&r1=644242&r2=644243&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_AFPGOCAResources/status.xml (original)
+++ xmlgraphics/fop/branches/Temp_AFPGOCAResources/status.xml Thu Apr 3 02:40:10 2008
@@ -59,6 +59,10 @@
<action context="Renderers" dev="AC" importance="high" type="add">
Added de-duplication and externalization support for IOCA and GOCA data resource objects.
</action>
+ <action context="Fonts" dev="JM" type="add" fixes-bug="44737" due-to="Jason Harrop">
+ Added support for auto-configuring TrueType Collections. XML font metrics files for
+ *.ttc fonts are not required anymore.
+ </action>
<action context="Renderers" dev="JM" type="update">
When a JPEG image is embedded, an optionally embedded color profile is filtered out
as it's already embedded separately in the PDF file.
---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org