瀏覽代碼

Added initial support for loading fonts without a pre-created XML font metrics file.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@474387 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-0_93
Jeremias Maerki 17 年之前
父節點
當前提交
652b3cbc55

+ 1
- 1
src/java/org/apache/fop/fonts/CustomFont.java 查看文件

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

+ 106
- 0
src/java/org/apache/fop/fonts/FontLoader.java 查看文件

@@ -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();
}

+ 20
- 22
src/java/org/apache/fop/fonts/FontSetup.java 查看文件

@@ -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));


+ 44
- 38
src/java/org/apache/fop/fonts/LazyFont.java 查看文件

@@ -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) {

+ 0
- 2
src/java/org/apache/fop/fonts/MultiByteFont.java 查看文件

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


+ 125
- 0
src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java 查看文件

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

+ 88
- 0
src/java/org/apache/fop/fonts/type1/Type1FontLoader.java 查看文件

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

+ 4
- 0
status.xml 查看文件

@@ -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).

Loading…
取消
儲存