git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@474387 13f79535-47bb-0310-9956-ffa450edef68tags/fop-0_93
@@ -31,7 +31,7 @@ public abstract class CustomFont extends Typeface | |||
private String fontName = null; | |||
private String embedFileName = null; | |||
private String embedResourceName = null; | |||
protected String embedResourceName = null; | |||
private FontResolver resolver = null; | |||
private int capHeight = 0; |
@@ -0,0 +1,106 @@ | |||
/* | |||
* 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.IOException; | |||
import java.io.InputStream; | |||
import java.net.MalformedURLException; | |||
import java.net.URL; | |||
import javax.xml.transform.Source; | |||
import javax.xml.transform.stream.StreamSource; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.fop.fonts.truetype.TTFFontLoader; | |||
import org.apache.fop.fonts.type1.Type1FontLoader; | |||
/** | |||
* Base class for font loaders. | |||
*/ | |||
public abstract class FontLoader { | |||
/** | |||
* 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 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) | |||
throws IOException { | |||
FontLoader loader; | |||
fontFileURI = fontFileURI.trim(); | |||
String name = fontFileURI.toLowerCase(); | |||
String effURI; | |||
boolean type1 = false; | |||
if (name.endsWith(".pfb")) { | |||
type1 = true; | |||
effURI = name.substring(0, fontFileURI.length() - 4) + ".pfm"; | |||
} else { | |||
effURI = fontFileURI; | |||
} | |||
InputStream in = openFontFile(resolver, effURI); | |||
try { | |||
if (type1) { | |||
loader = new Type1FontLoader(fontFileURI, in, resolver); | |||
} else { | |||
loader = new TTFFontLoader(fontFileURI, in, resolver); | |||
} | |||
return loader.getFont(); | |||
} finally { | |||
IOUtils.closeQuietly(in); | |||
} | |||
} | |||
private static InputStream openFontFile(FontResolver resolver, String uri) | |||
throws IOException, MalformedURLException { | |||
InputStream in = null; | |||
if (resolver != null) { | |||
Source source = resolver.resolve(uri); | |||
if (source == null) { | |||
String err = "Cannot load font: failed to create Source for font file " | |||
+ uri; | |||
throw new IOException(err); | |||
} | |||
if (source instanceof StreamSource) { | |||
in = ((StreamSource) source).getInputStream(); | |||
} | |||
if (in == null && source.getSystemId() != null) { | |||
in = new java.net.URL(source.getSystemId()).openStream(); | |||
} | |||
if (in == null) { | |||
String err = "Cannot load font: failed to create InputStream from" | |||
+ " Source for font file " + uri; | |||
throw new IOException(err); | |||
} | |||
} else { | |||
in = new URL(uri).openStream(); | |||
} | |||
return in; | |||
} | |||
/** | |||
* @return the font loaded by this loader | |||
*/ | |||
public abstract CustomFont getFont(); | |||
} |
@@ -209,30 +209,28 @@ public class FontSetup { | |||
EmbedFontInfo configFontInfo = (EmbedFontInfo) fontInfoList.get(i); | |||
String metricsFile = configFontInfo.getMetricsFile(); | |||
if (metricsFile != null) { | |||
internalName = "F" + num; | |||
num++; | |||
/* | |||
reader = new FontReader(metricsFile); | |||
reader.useKerning(configFontInfo.getKerning()); | |||
reader.setFontEmbedPath(configFontInfo.getEmbedFile()); | |||
fontInfo.addMetrics(internalName, reader.getFont()); | |||
*/ | |||
LazyFont font = new LazyFont(configFontInfo.getEmbedFile(), | |||
metricsFile, | |||
configFontInfo.getKerning(), | |||
resolver); | |||
fontInfo.addMetrics(internalName, font); | |||
internalName = "F" + num; | |||
num++; | |||
/* | |||
reader = new FontReader(metricsFile); | |||
reader.useKerning(configFontInfo.getKerning()); | |||
reader.setFontEmbedPath(configFontInfo.getEmbedFile()); | |||
fontInfo.addMetrics(internalName, reader.getFont()); | |||
*/ | |||
LazyFont font = new LazyFont(configFontInfo.getEmbedFile(), | |||
metricsFile, | |||
configFontInfo.getKerning(), | |||
resolver); | |||
fontInfo.addMetrics(internalName, font); | |||
List triplets = configFontInfo.getFontTriplets(); | |||
for (int c = 0; c < triplets.size(); c++) { | |||
FontTriplet triplet = (FontTriplet) triplets.get(c); | |||
List triplets = configFontInfo.getFontTriplets(); | |||
for (int c = 0; c < triplets.size(); c++) { | |||
FontTriplet triplet = (FontTriplet) triplets.get(c); | |||
if (log.isDebugEnabled()) { | |||
log.debug("Registering: " + triplet + " under " + internalName); | |||
} | |||
fontInfo.addFontProperties(internalName, triplet); | |||
if (log.isDebugEnabled()) { | |||
log.debug("Registering: " + triplet + " under " + internalName); | |||
} | |||
fontInfo.addFontProperties(internalName, triplet); | |||
} | |||
} | |||
} | |||
@@ -270,7 +268,7 @@ public class FontSetup { | |||
} | |||
EmbedFontInfo efi; | |||
efi = new EmbedFontInfo(font[i].getAttribute("metrics-url"), | |||
efi = new EmbedFontInfo(font[i].getAttribute("metrics-url", null), | |||
font[i].getAttributeAsBoolean("kerning", false), | |||
tripleList, font[i].getAttribute("embed-url", null)); | |||
@@ -65,52 +65,58 @@ public class LazyFont extends Typeface implements FontDescriptor { | |||
private void load(boolean fail) { | |||
if (!isMetricsLoaded) { | |||
try { | |||
/**@todo Possible thread problem here */ | |||
FontReader reader = null; | |||
if (resolver != null) { | |||
Source source = resolver.resolve(metricsFileName); | |||
if (source == null) { | |||
String err = "Cannot load font: failed to create Source from metrics file " | |||
+ metricsFileName; | |||
if (fail) { | |||
throw new RuntimeException(err); | |||
} else { | |||
log.error(err); | |||
if (metricsFileName != null) { | |||
/**@todo Possible thread problem here */ | |||
FontReader reader = null; | |||
if (resolver != null) { | |||
Source source = resolver.resolve(metricsFileName); | |||
if (source == null) { | |||
String err = "Cannot load font: failed to create Source from metrics file " | |||
+ metricsFileName; | |||
if (fail) { | |||
throw new RuntimeException(err); | |||
} else { | |||
log.error(err); | |||
} | |||
return; | |||
} | |||
return; | |||
} | |||
InputStream in = null; | |||
if (source instanceof StreamSource) { | |||
in = ((StreamSource) source).getInputStream(); | |||
} | |||
if (in == null && source.getSystemId() != null) { | |||
in = new java.net.URL(source.getSystemId()).openStream(); | |||
} | |||
if (in == null) { | |||
String err = "Cannot load font: failed to create InputStream from" | |||
+ " Source for metrics file " + metricsFileName; | |||
if (fail) { | |||
throw new RuntimeException(err); | |||
} else { | |||
log.error(err); | |||
InputStream in = null; | |||
if (source instanceof StreamSource) { | |||
in = ((StreamSource) source).getInputStream(); | |||
} | |||
return; | |||
if (in == null && source.getSystemId() != null) { | |||
in = new java.net.URL(source.getSystemId()).openStream(); | |||
} | |||
if (in == null) { | |||
String err = "Cannot load font: failed to create InputStream from" | |||
+ " Source for metrics file " + metricsFileName; | |||
if (fail) { | |||
throw new RuntimeException(err); | |||
} else { | |||
log.error(err); | |||
} | |||
return; | |||
} | |||
InputSource src = new InputSource(in); | |||
src.setSystemId(source.getSystemId()); | |||
reader = new FontReader(src); | |||
} else { | |||
reader | |||
= new FontReader(new InputSource(new URL(metricsFileName).openStream())); | |||
} | |||
InputSource src = new InputSource(in); | |||
src.setSystemId(source.getSystemId()); | |||
reader = new FontReader(src); | |||
reader.setKerningEnabled(useKerning); | |||
reader.setFontEmbedPath(fontEmbedPath); | |||
reader.setResolver(resolver); | |||
realFont = reader.getFont(); | |||
} else { | |||
reader | |||
= new FontReader(new InputSource(new URL(metricsFileName).openStream())); | |||
if (fontEmbedPath == null) { | |||
throw new RuntimeException("Cannot load font. No font URIs available."); | |||
} | |||
realFont = FontLoader.loadFont(fontEmbedPath, resolver); | |||
} | |||
reader.setKerningEnabled(useKerning); | |||
reader.setFontEmbedPath(fontEmbedPath); | |||
reader.setResolver(resolver); | |||
realFont = reader.getFont(); | |||
if (realFont instanceof FontDescriptor) { | |||
realFontDescriptor = (FontDescriptor) realFont; | |||
} | |||
// log.debug("Metrics " + metricsFileName + " loaded."); | |||
} catch (FOPException fopex) { | |||
log.error("Failed to read font metrics file " + metricsFileName, fopex); | |||
if (fail) { |
@@ -33,8 +33,6 @@ public class MultiByteFont extends CIDFont { | |||
private String ttcName = null; | |||
private String encoding = "Identity-H"; | |||
private String embedResourceName = null; | |||
private int defaultWidth = 0; | |||
private CIDFontType cidType = CIDFontType.CIDTYPE2; | |||
@@ -0,0 +1,125 @@ | |||
/* | |||
* 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.truetype; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
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; | |||
/** | |||
* Loads a font into memory directly from the original font file. | |||
*/ | |||
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(); | |||
FontFileReader reader = new FontFileReader(in); | |||
boolean supported = ttf.readFont(reader, null); | |||
if (!supported) { | |||
throw new IOException("Could not load TrueType font: " + fontFileURI); | |||
} | |||
multiFont = new MultiByteFont(); | |||
multiFont.setResolver(this.resolver); | |||
returnFont = multiFont; | |||
read(); | |||
} | |||
private void read() throws IOException { | |||
returnFont.setFontName(ttf.getFamilyName()); | |||
//multiFont.setTTCName(ttcName) | |||
returnFont.setCapHeight(ttf.getCapHeight()); | |||
returnFont.setXHeight(ttf.getXHeight()); | |||
returnFont.setAscender(ttf.getLowerCaseAscent()); | |||
returnFont.setDescender(ttf.getLowerCaseDescent()); | |||
returnFont.setFontBBox(ttf.getFontBBox()); | |||
//returnFont.setFirstChar(ttf.getFirstChar();) | |||
returnFont.setFlags(ttf.getFlags()); | |||
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); | |||
List entries = ttf.getCMaps(); | |||
BFEntry[] bfentries = new BFEntry[entries.size()]; | |||
int pos = 0; | |||
Iterator iter = ttf.getCMaps().listIterator(); | |||
while (iter.hasNext()) { | |||
TTFCmapEntry ce = (TTFCmapEntry)iter.next(); | |||
bfentries[pos] = new BFEntry(ce.getUnicodeStart(), ce.getUnicodeEnd(), | |||
ce.getGlyphStartIndex()); | |||
pos++; | |||
} | |||
multiFont.setBFEntries(bfentries); | |||
copyKerning(ttf, true); | |||
multiFont.setEmbedFileName(this.fontFileURI); | |||
} | |||
private void copyKerning(TTFFile ttf, boolean isCid) { | |||
// Get kerning | |||
Iterator iter; | |||
if (isCid) { | |||
iter = ttf.getKerning().keySet().iterator(); | |||
} else { | |||
iter = ttf.getAnsiKerning().keySet().iterator(); | |||
} | |||
while (iter.hasNext()) { | |||
Integer kpx1 = (Integer)iter.next(); | |||
Map h2; | |||
if (isCid) { | |||
h2 = (Map)ttf.getKerning().get(kpx1); | |||
} else { | |||
h2 = (Map)ttf.getAnsiKerning().get(kpx1); | |||
} | |||
returnFont.putKerningEntry(kpx1, h2); | |||
} | |||
} | |||
/** @see org.apache.fop.fonts.FontLoader#getFont() */ | |||
public CustomFont getFont() { | |||
return this.returnFont; | |||
} | |||
} |
@@ -0,0 +1,88 @@ | |||
/* | |||
* 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.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; | |||
import org.apache.fop.fonts.SingleByteFont; | |||
/** | |||
* Loads a Type 1 font into memory directly from the original font file. | |||
*/ | |||
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. | |||
* @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 | |||
* @throws IOException In case of an I/O error | |||
*/ | |||
public Type1FontLoader(String fontFileURI, InputStream in, FontResolver resolver) | |||
throws IOException { | |||
this.fontFileURI = fontFileURI; | |||
this.resolver = resolver; | |||
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()); | |||
returnFont.setAscender(pfm.getLowerCaseAscent()); | |||
returnFont.setDescender(pfm.getLowerCaseDescent()); | |||
returnFont.setFontBBox(pfm.getFontBBox()); | |||
returnFont.setFirstChar(pfm.getFirstChar()); | |||
returnFont.setLastChar(pfm.getFirstChar()); | |||
returnFont.setFlags(pfm.getFlags()); | |||
returnFont.setStemV(pfm.getStemV()); | |||
returnFont.setItalicAngle(pfm.getItalicAngle()); | |||
returnFont.setMissingWidth(0); | |||
for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { | |||
singleFont.setWidth(i, pfm.getCharWidth(i)); | |||
} | |||
singleFont.setEmbedFileName(this.fontFileURI); | |||
} | |||
/** @see org.apache.fop.fonts.FontLoader#getFont() */ | |||
public CustomFont getFont() { | |||
return this.returnFont; | |||
} | |||
} |
@@ -28,6 +28,10 @@ | |||
<changes> | |||
<release version="FOP Trunk"> | |||
<action context="Code" dev="JM" type="add"> | |||
Added initial support for loading fonts without a pre-created XML font metric | |||
file. | |||
</action> | |||
<action context="Code" dev="JM" type="add" fixes-bug="40729" due-to="Peter Coppens"> | |||
Support for the rgb-icc() function and for a proprietary cmyk() function (for device CMYK | |||
colors only through the PDF renderer so far). |