]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Added initial support for loading fonts without a pre-created XML font metrics file.
authorJeremias Maerki <jeremias@apache.org>
Mon, 13 Nov 2006 16:28:13 +0000 (16:28 +0000)
committerJeremias Maerki <jeremias@apache.org>
Mon, 13 Nov 2006 16:28:13 +0000 (16:28 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@474387 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/fonts/CustomFont.java
src/java/org/apache/fop/fonts/FontLoader.java [new file with mode: 0644]
src/java/org/apache/fop/fonts/FontSetup.java
src/java/org/apache/fop/fonts/LazyFont.java
src/java/org/apache/fop/fonts/MultiByteFont.java
src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java [new file with mode: 0644]
src/java/org/apache/fop/fonts/type1/Type1FontLoader.java [new file with mode: 0644]
status.xml

index 8f21a449da3624e420b0c8ffb92be423b8d107ba..5d7221c13dc7d37e78ed7135d9ca979470fe9b05 100644 (file)
@@ -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 (file)
index 0000000..4377f9f
--- /dev/null
@@ -0,0 +1,106 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ * \r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+package org.apache.fop.fonts;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.net.MalformedURLException;\r
+import java.net.URL;\r
+\r
+import javax.xml.transform.Source;\r
+import javax.xml.transform.stream.StreamSource;\r
+\r
+import org.apache.commons.io.IOUtils;\r
+import org.apache.fop.fonts.truetype.TTFFontLoader;\r
+import org.apache.fop.fonts.type1.Type1FontLoader;\r
+\r
+/**\r
+ * Base class for font loaders.\r
+ */\r
+public abstract class FontLoader {\r
+\r
+    /**\r
+     * Loads a custom font from a URI. In the case of Type 1 fonts, the PFB file must be specified.\r
+     * @param fontFileURI the URI to the font\r
+     * @param resolver the font resolver to use when resolving URIs\r
+     * @return the newly loaded font\r
+     * @throws IOException In case of an I/O error\r
+     */\r
+    public static CustomFont loadFont(String fontFileURI, FontResolver resolver)\r
+                throws IOException {\r
+        FontLoader loader;\r
+        fontFileURI = fontFileURI.trim();\r
+        String name = fontFileURI.toLowerCase();\r
+        String effURI;\r
+        boolean type1 = false;\r
+        if (name.endsWith(".pfb")) {\r
+            type1 = true;\r
+            effURI = name.substring(0, fontFileURI.length() - 4) + ".pfm";\r
+        } else {\r
+            effURI = fontFileURI;\r
+        }\r
+        \r
+        InputStream in = openFontFile(resolver, effURI);\r
+        try {\r
+            if (type1) {\r
+                loader = new Type1FontLoader(fontFileURI, in, resolver);\r
+            } else {\r
+                loader = new TTFFontLoader(fontFileURI, in, resolver);\r
+            }\r
+            return loader.getFont();\r
+        } finally {\r
+            IOUtils.closeQuietly(in);\r
+        }\r
+    }\r
+\r
+    private static InputStream openFontFile(FontResolver resolver, String uri) \r
+                    throws IOException, MalformedURLException {\r
+        InputStream in = null;\r
+        if (resolver != null) {\r
+            Source source = resolver.resolve(uri);\r
+            if (source == null) {\r
+                String err = "Cannot load font: failed to create Source for font file " \r
+                    + uri; \r
+                throw new IOException(err);\r
+            }\r
+            if (source instanceof StreamSource) {\r
+                in = ((StreamSource) source).getInputStream();\r
+            }\r
+            if (in == null && source.getSystemId() != null) {\r
+                in = new java.net.URL(source.getSystemId()).openStream();\r
+            }\r
+            if (in == null) {\r
+                String err = "Cannot load font: failed to create InputStream from"\r
+                    + " Source for font file " + uri; \r
+                throw new IOException(err);\r
+            }\r
+        } else {\r
+            in = new URL(uri).openStream();\r
+        }\r
+        return in;\r
+    }\r
+    \r
+    /**\r
+     * @return the font loaded by this loader\r
+     */\r
+    public abstract CustomFont getFont();\r
+\r
+    \r
+}\r
index 4c9e3b768c0d483f812f227a2b08ba004baa5d9c..3362ce334147347da08181e93a9f6b09105b6529 100644 (file)
@@ -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));
 
index 4d0b57cee9097045392f3e779c4527defeaeebd2..658c0cf1e837c318da0e3d4484cca8495e55c3ac 100644 (file)
@@ -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) {
index bcb2957412b2b10bcfde74c3f2abbdff15f80c16..2dd3846ed9ab5ab1fa8153c5ba970e2e0b5c7cbe 100644 (file)
@@ -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 (file)
index 0000000..53be6a8
--- /dev/null
@@ -0,0 +1,125 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ * \r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+package org.apache.fop.fonts.truetype;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.apache.fop.fonts.BFEntry;\r
+import org.apache.fop.fonts.CIDFontType;\r
+import org.apache.fop.fonts.CustomFont;\r
+import org.apache.fop.fonts.FontLoader;\r
+import org.apache.fop.fonts.FontResolver;\r
+import org.apache.fop.fonts.MultiByteFont;\r
+\r
+/**\r
+ * Loads a font into memory directly from the original font file.\r
+ */\r
+public class TTFFontLoader extends FontLoader {\r
+\r
+    private String fontFileURI;\r
+    private TTFFile ttf;\r
+    private MultiByteFont multiFont;\r
+    private CustomFont returnFont;\r
+    private FontResolver resolver;\r
+    \r
+    public TTFFontLoader(String fontFileURI, InputStream in, FontResolver resolver) \r
+                throws IOException {\r
+        this.fontFileURI = fontFileURI;\r
+        this.resolver = resolver;\r
+\r
+        this.ttf = new TTFFile();\r
+        FontFileReader reader = new FontFileReader(in);\r
+        boolean supported = ttf.readFont(reader, null);\r
+        if (!supported) {\r
+            throw new IOException("Could not load TrueType font: " + fontFileURI);\r
+        }\r
+        multiFont = new MultiByteFont();\r
+        multiFont.setResolver(this.resolver);\r
+        returnFont = multiFont;\r
+        read();        \r
+    }\r
+    \r
+    private void read() throws IOException {\r
+        returnFont.setFontName(ttf.getFamilyName());\r
+        //multiFont.setTTCName(ttcName)\r
+        returnFont.setCapHeight(ttf.getCapHeight());\r
+        returnFont.setXHeight(ttf.getXHeight());\r
+        returnFont.setAscender(ttf.getLowerCaseAscent());\r
+        returnFont.setDescender(ttf.getLowerCaseDescent());\r
+        returnFont.setFontBBox(ttf.getFontBBox());\r
+        //returnFont.setFirstChar(ttf.getFirstChar();)\r
+        returnFont.setFlags(ttf.getFlags());\r
+        returnFont.setStemV(Integer.parseInt(ttf.getStemV())); //not used for TTF\r
+        returnFont.setItalicAngle(Integer.parseInt(ttf.getItalicAngle()));\r
+        returnFont.setMissingWidth(0);\r
+        multiFont.setCIDType(CIDFontType.CIDTYPE2);\r
+        int[] wx = ttf.getWidths();\r
+        multiFont.setWidthArray(wx);\r
+        List entries = ttf.getCMaps();\r
+        BFEntry[] bfentries = new BFEntry[entries.size()];\r
+        int pos = 0;\r
+        Iterator iter = ttf.getCMaps().listIterator();\r
+        while (iter.hasNext()) {\r
+            TTFCmapEntry ce = (TTFCmapEntry)iter.next();\r
+            bfentries[pos] = new BFEntry(ce.getUnicodeStart(), ce.getUnicodeEnd(),\r
+                    ce.getGlyphStartIndex());\r
+            pos++;\r
+        }\r
+        multiFont.setBFEntries(bfentries);\r
+        copyKerning(ttf, true);\r
+        multiFont.setEmbedFileName(this.fontFileURI);\r
+        \r
+    }\r
+    \r
+    private void copyKerning(TTFFile ttf, boolean isCid) {\r
+        \r
+        // Get kerning\r
+        Iterator iter;\r
+        if (isCid) {\r
+            iter = ttf.getKerning().keySet().iterator();\r
+        } else {\r
+            iter = ttf.getAnsiKerning().keySet().iterator();\r
+        }\r
+\r
+        while (iter.hasNext()) {\r
+            Integer kpx1 = (Integer)iter.next();\r
+\r
+            Map h2;\r
+            if (isCid) {\r
+                h2 = (Map)ttf.getKerning().get(kpx1);\r
+            } else {\r
+                h2 = (Map)ttf.getAnsiKerning().get(kpx1);\r
+            }\r
+\r
+            returnFont.putKerningEntry(kpx1, h2);\r
+        }\r
+    }\r
+    \r
+    \r
+    /** @see org.apache.fop.fonts.FontLoader#getFont() */\r
+    public CustomFont getFont() {\r
+        return this.returnFont;\r
+    }\r
+    \r
+}\r
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 (file)
index 0000000..ef0d457
--- /dev/null
@@ -0,0 +1,88 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ * \r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/* $Id$ */\r
+\r
+package org.apache.fop.fonts.type1;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+import org.apache.fop.fonts.CustomFont;\r
+import org.apache.fop.fonts.FontLoader;\r
+import org.apache.fop.fonts.FontResolver;\r
+import org.apache.fop.fonts.FontType;\r
+import org.apache.fop.fonts.SingleByteFont;\r
+\r
+/**\r
+ * Loads a Type 1 font into memory directly from the original font file.\r
+ */\r
+public class Type1FontLoader extends FontLoader {\r
+\r
+    private String fontFileURI;\r
+    private PFMFile pfm;\r
+    private SingleByteFont singleFont;\r
+    private CustomFont returnFont;\r
+    private FontResolver resolver;\r
+    \r
+    /**\r
+     * Constructs a new Type 1 font loader.\r
+     * @param fontFileURI the URI to the PFB file of a Type 1 font\r
+     * @param in the InputStream reading the PFM file of a Type 1 font\r
+     * @param resolver the font resolver used to resolve URIs\r
+     * @throws IOException In case of an I/O error\r
+     */\r
+    public Type1FontLoader(String fontFileURI, InputStream in, FontResolver resolver) \r
+                throws IOException {\r
+        this.fontFileURI = fontFileURI;\r
+        this.resolver = resolver;\r
+\r
+        pfm = new PFMFile();\r
+        pfm.load(in);\r
+        singleFont = new SingleByteFont();\r
+        singleFont.setFontType(FontType.TYPE1);\r
+        singleFont.setResolver(this.resolver);\r
+        returnFont = singleFont;\r
+        read();        \r
+    }\r
+    \r
+    private void read() throws IOException {\r
+        returnFont.setFontName(pfm.getPostscriptName());\r
+        returnFont.setCapHeight(pfm.getCapHeight());\r
+        returnFont.setXHeight(pfm.getXHeight());\r
+        returnFont.setAscender(pfm.getLowerCaseAscent());\r
+        returnFont.setDescender(pfm.getLowerCaseDescent());\r
+        returnFont.setFontBBox(pfm.getFontBBox());\r
+        returnFont.setFirstChar(pfm.getFirstChar());\r
+        returnFont.setLastChar(pfm.getFirstChar());\r
+        returnFont.setFlags(pfm.getFlags());\r
+        returnFont.setStemV(pfm.getStemV());\r
+        returnFont.setItalicAngle(pfm.getItalicAngle());\r
+        returnFont.setMissingWidth(0);\r
+        for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) {\r
+            singleFont.setWidth(i, pfm.getCharWidth(i));\r
+        }\r
+        singleFont.setEmbedFileName(this.fontFileURI);\r
+        \r
+    }\r
+    \r
+    /** @see org.apache.fop.fonts.FontLoader#getFont() */\r
+    public CustomFont getFont() {\r
+        return this.returnFont;\r
+    }\r
+    \r
+}\r
index 5a3bcc431cd59b1a2a8f12ffbbfadd4fa31e64fb..e931f104e18072eaabe717a6105fcbd9911830a1 100644 (file)
 
   <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).