diff options
author | Jeremias Maerki <jeremias@apache.org> | 2006-11-13 16:28:13 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2006-11-13 16:28:13 +0000 |
commit | 652b3cbc5586d794a41bee4d2c824539e18b3cfc (patch) | |
tree | b1f28123ec5b116e8ee68934af49680dd8c35d1d | |
parent | d6f78f8cc3de4b43e36dff19fef56778149ca96d (diff) | |
download | xmlgraphics-fop-652b3cbc5586d794a41bee4d2c824539e18b3cfc.tar.gz xmlgraphics-fop-652b3cbc5586d794a41bee4d2c824539e18b3cfc.zip |
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
-rw-r--r-- | src/java/org/apache/fop/fonts/CustomFont.java | 2 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontLoader.java | 106 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/FontSetup.java | 42 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/LazyFont.java | 82 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/MultiByteFont.java | 2 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java | 125 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/type1/Type1FontLoader.java | 88 | ||||
-rw-r--r-- | status.xml | 4 |
8 files changed, 388 insertions, 63 deletions
diff --git a/src/java/org/apache/fop/fonts/CustomFont.java b/src/java/org/apache/fop/fonts/CustomFont.java index 8f21a449d..5d7221c13 100644 --- a/src/java/org/apache/fop/fonts/CustomFont.java +++ b/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; diff --git a/src/java/org/apache/fop/fonts/FontLoader.java b/src/java/org/apache/fop/fonts/FontLoader.java new file mode 100644 index 000000000..4377f9fab --- /dev/null +++ b/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();
+
+
+}
diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index 4c9e3b768..3362ce334 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/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)); diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java index 4d0b57cee..658c0cf1e 100644 --- a/src/java/org/apache/fop/fonts/LazyFont.java +++ b/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) { diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java index bcb295741..2dd3846ed 100644 --- a/src/java/org/apache/fop/fonts/MultiByteFont.java +++ b/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; diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java new file mode 100644 index 000000000..53be6a8d0 --- /dev/null +++ b/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;
+ }
+
+}
diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java new file mode 100644 index 000000000..ef0d45767 --- /dev/null +++ b/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;
+ }
+
+}
diff --git a/status.xml b/status.xml index 5a3bcc431..e931f104e 100644 --- a/status.xml +++ b/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). |