Over the years I've kept an eye on the lists. Every year it seems like someone's interested, and someone's willing. Right now I guess I don't know if anyone is actively working on /proper/ CFF support. So hopefully I'm not stepping on anyone's toes.

I've attached a patch with a quick, dirty, and naive hack. For OTF/CFF fonts, it embeds the CFF table wholesale in the PDF as a FontFile3 with the proper Subset fields. This gets you WinAnsi characters only. Pretty sure there's no kerning in there either. But it's a start. I guess I'll be looking into what it'll take to get a proper encoding map all setup.

My ultimate desire with FOP is to see access alternate glyphs. I'm using FF's Zwo (yeah, yeah, next time just buy the TrueType version — but even Quark /kinda/ works with these things) and would like to access the salt and/or ss01 glyphs.

- alex
Index: src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java
===================================================================
--- src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java   (revision 
1076664)
+++ src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java   (working copy)
@@ -108,12 +108,8 @@
 
 
     private void buildFont(TTFFile ttf, String ttcFontName) {
-        if (ttf.isCFF()) {
-            throw new UnsupportedOperationException(
-                    "OpenType fonts with CFF data are not supported, yet");
-        }
 
-        boolean isCid = this.embedded;
+        boolean isCid = !ttf.isCFF() && this.embedded;
         if (this.encodingMode == EncodingMode.SINGLE_BYTE) {
             isCid = false;
         }
@@ -159,7 +155,11 @@
             }
             multiFont.setBFEntries(bfentries);
         } else {
-            singleFont.setFontType(FontType.TRUETYPE);
+            if (ttf.isCFF()) {
+                singleFont.setFontType(FontType.TYPE3);
+            } else {
+                singleFont.setFontType(FontType.TRUETYPE);
+            }
             singleFont.setEncoding(ttf.getCharSetName());
             returnFont.setFirstChar(ttf.getFirstChar());
             returnFont.setLastChar(ttf.getLastChar());
Index: src/java/org/apache/fop/fonts/truetype/TTFFile.java
===================================================================
--- src/java/org/apache/fop/fonts/truetype/TTFFile.java (revision 1076664)
+++ src/java/org/apache/fop/fonts/truetype/TTFFile.java (working copy)
@@ -545,6 +545,7 @@
             readIndexToLocation(in);
             readGlyf(in);
         }
+
         readName(in);
         boolean pcltFound = readPCLT(in);
         // Read cmap table and fill in ansiwidths
@@ -1690,6 +1691,22 @@
         return result;
     }
 
+    public byte[] getCFFTable(FontFileReader in) throws IOException {
+        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("CFF ");
+        if (entry != null) {
+            byte[] output = new byte[(int)entry.getLength()];
+            
+            seekTab(in, "CFF ", 0);
+
+            System.arraycopy(in.getBytes(in.getCurrentPos(), 
(int)entry.getLength()),
+                             0, output, 0, (int)entry.getLength());
+            return output;
+        } else {
+            log.warn("Couldn't find a CFF table in this CFF font?");
+            return null;
+        }
+    }
+
     /**
      * Static main method to get info about a TrueType font.
      * @param args The command line arguments
Index: src/java/org/apache/fop/pdf/PDFFontDescriptor.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFFontDescriptor.java  (revision 1076664)
+++ src/java/org/apache/fop/pdf/PDFFontDescriptor.java  (working copy)
@@ -103,6 +103,8 @@
     public void setFontFile(FontType subtype, AbstractPDFStream fontfile) {
         if (subtype == FontType.TYPE1) {
             put("FontFile", fontfile);
+        } else if (subtype == FontType.TYPE3) {
+            put("FontFile3", fontfile);
         } else {
             put("FontFile2", fontfile);
         }
@@ -118,6 +120,9 @@
         if (stream == null) {
             stream = (AbstractPDFStream)get("FontFile3");
         }
+        if (stream == null) {
+            log.error("Failed to find font file");
+        }
         return stream;
     }
 
Index: src/java/org/apache/fop/pdf/PDFT3Stream.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFT3Stream.java        (revision 0)
+++ src/java/org/apache/fop/pdf/PDFT3Stream.java        (revision 0)
@@ -0,0 +1,89 @@
+/*
+ * 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: PDFTTFStream.java 744851 2009-02-16 08:09:29Z jeremias $ */
+
+package org.apache.fop.pdf;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Special PDFStream for embeddable TrueType fonts.
+ */
+public class PDFT3Stream extends AbstractPDFFontStream {
+
+    private int origLength;
+    private byte[] ttfData;
+
+    /**
+     * Main constructor
+     * @param len original length
+     */
+    public PDFT3Stream(int len) {
+        super();
+        origLength = len;
+    }
+
+    /** {@inheritDoc} */
+    protected int getSizeHint() throws IOException {
+        if (this.ttfData != null) {
+            return ttfData.length;
+        } else {
+            return 0; //no hint available
+        }
+    }
+
+    /**
+     * Overload the base object method so we don't have to copy
+     * byte arrays around so much
+     * {@inheritDoc}
+     */
+    protected int output(java.io.OutputStream stream)
+            throws java.io.IOException {
+        if (log.isDebugEnabled()) {
+            log.debug("Writing " + origLength + " bytes of TTF font data");
+        }
+
+        int length = super.output(stream);
+        log.debug("Embedded OpenType CFF font");
+        return length;
+    }
+
+    /** {@inheritDoc} */
+    protected void outputRawStreamData(OutputStream out) throws IOException {
+        out.write(this.ttfData);
+    }
+
+    /** {@inheritDoc} */
+    protected void populateStreamDict(Object lengthEntry) {
+        put("Subtype", new PDFName("Type1"));
+        super.populateStreamDict(lengthEntry);
+    }
+
+    /**
+     * Sets the TrueType font data.
+     * @param data the font payload
+     * @param size size of the payload
+     * @throws IOException in case of an I/O problem
+     */
+    public void setData(byte[] data, int size) throws IOException {
+        this.ttfData = new byte[size];
+        System.arraycopy(data, 0, this.ttfData, 0, size);
+    }
+
+}
Index: src/java/org/apache/fop/pdf/PDFFont.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFFont.java    (revision 1076664)
+++ src/java/org/apache/fop/pdf/PDFFont.java    (working copy)
@@ -113,8 +113,7 @@
             return new PDFFontType1(fontname, basefont,
                                     encoding);
         } else if (subtype == FontType.TYPE3) {
-            //return new PDFFontType3(number, fontname, basefont, encoding);
-            return null; //NYI
+            return new PDFFontType3(fontname, basefont, encoding);
         } else if (subtype == FontType.TRUETYPE) {
             return new PDFFontTrueType(fontname, basefont,
                                        encoding);
@@ -152,7 +151,7 @@
         } else if (fontType == FontType.MMTYPE1) {
             return new PDFName(fontType.getName());
         } else if (fontType == FontType.TYPE3) {
-            return new PDFName(fontType.getName());
+            return new PDFName("Type1C");
         } else if (fontType == FontType.TRUETYPE) {
             return new PDFName(fontType.getName());
         } else {
Index: src/java/org/apache/fop/pdf/PDFFactory.java
===================================================================
--- src/java/org/apache/fop/pdf/PDFFactory.java (revision 1076664)
+++ src/java/org/apache/fop/pdf/PDFFactory.java (working copy)
@@ -60,6 +60,7 @@
 import org.apache.fop.fonts.SingleByteFont;
 import org.apache.fop.fonts.Typeface;
 import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.fonts.truetype.TTFFile;
 import org.apache.fop.fonts.truetype.TTFSubSetFile;
 import org.apache.fop.fonts.type1.PFBData;
 import org.apache.fop.fonts.type1.PFBParser;
@@ -1687,10 +1688,22 @@
                         PFBData pfb = parser.parsePFB(in);
                         embeddedFont = new PDFT1Stream();
                         ((PDFT1Stream)embeddedFont).setData(pfb);
+                    } else if (desc.getFontType() == FontType.TYPE3) {
+                        FontFileReader reader = new FontFileReader(in);
+                        TTFFile ttfile = new TTFFile();
+                        ttfile.readFont(reader);
+
+                        byte[] cffTable = ttfile.getCFFTable(reader);
+
+                        embeddedFont = new PDFT3Stream(cffTable.length);
+                        ((PDFT3Stream)embeddedFont).setData(cffTable, 
cffTable.length);
                     } else {
+                        log.debug("Unknown TTF?");
+
                         byte[] file = IOUtils.toByteArray(in);
                         embeddedFont = new PDFTTFStream(file.length);
                         ((PDFTTFStream)embeddedFont).setData(file, 
file.length);
+
                     }
 
                     /*

Reply via email to