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);
+
}
/*