You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2015/06/27 02:18:22 UTC
svn commit: r1687878 [1/2] - in /pdfbox/trunk:
fontbox/src/main/java/org/apache/fontbox/
fontbox/src/main/java/org/apache/fontbox/cff/
fontbox/src/main/java/org/apache/fontbox/ttf/
fontbox/src/main/java/org/apache/fontbox/type1/ pdfbox/ pdfbox/src/main...
Author: jahewson
Date: Sat Jun 27 00:18:21 2015
New Revision: 1687878
URL: http://svn.apache.org/r1687878
Log:
PDFBOX-2842: Overhaul font substitution
Added:
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/EncodedFont.java (with props)
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/FontBoxFont.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDFontMapping.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontCache.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontFormat.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapper.java
- copied, changed from r1687667, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ExternalFonts.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapping.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDVectorFont.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/encoding/BuiltInEncoding.java (with props)
Removed:
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/Type1Equivalent.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ExternalFonts.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Equivalent.java
pdfbox/trunk/pdfbox/src/main/resources/org/apache/pdfbox/resources/otf/AdobeBlank.otf
Modified:
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFCIDFont.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFType1Font.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/IndexData.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OpenTypeFont.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java
pdfbox/trunk/pdfbox/pom.xml
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontProvider.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDSystemInfo.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType3Font.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/CIDType0Glyph2D.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/TTFGlyph2D.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/Type1Glyph2D.java
pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/Type1FontValidator.java
pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/container/Type1Container.java
pdfbox/trunk/preflight/src/main/java/org/apache/pdfbox/preflight/font/descriptor/Type1DescriptorHelper.java
Added: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/EncodedFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/EncodedFont.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/EncodedFont.java (added)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/EncodedFont.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package org.apache.fontbox;
+
+import java.io.IOException;
+import org.apache.fontbox.encoding.Encoding;
+
+/**
+ * A PostScript font which uses an encoding vector.
+ *
+ * @author John Hewson
+ */
+public interface EncodedFont
+{
+ /**
+ * Returns the PostScript Encoding vector for the font.
+ */
+ Encoding getEncoding() throws IOException;
+}
Propchange: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/EncodedFont.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/FontBoxFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/FontBoxFont.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/FontBoxFont.java (added)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/FontBoxFont.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package org.apache.fontbox;
+
+import java.awt.geom.GeneralPath;
+import java.io.IOException;
+import java.util.List;
+import org.apache.fontbox.util.BoundingBox;
+
+/**
+ * Common interface for all FontBox fonts.
+ *
+ * @author John Hewson
+ */
+public interface FontBoxFont
+{
+ /**
+ * The PostScript name of the font.
+ */
+ String getName() throws IOException;
+
+ /**
+ * Returns the font's bounding box in PostScript units.
+ */
+ BoundingBox getFontBBox() throws IOException;
+
+ /**
+ * Returns the FontMatrix in PostScript units.
+ */
+ List<Number> getFontMatrix() throws IOException;
+
+ /**
+ * Returns the path for the character with the given name.
+ *
+ * @return glyph path
+ * @throws IOException if the path could not be read
+ */
+ GeneralPath getPath(String name) throws IOException;
+
+ /**
+ * Returns the advance width for the character with the given name.
+ *
+ * @return glyph advance width
+ * @throws IOException if the path could not be read
+ */
+ float getWidth(String name) throws IOException;
+
+ /**
+ * Returns true if the font contains the given glyph.
+ *
+ * @param name PostScript glyph name
+ */
+ boolean hasGlyph(String name) throws IOException;
+}
Propchange: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/FontBoxFont.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFCIDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFCIDFont.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFCIDFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFCIDFont.java Sat Jun 27 00:18:21 2015
@@ -17,13 +17,13 @@
package org.apache.fontbox.cff;
-import org.apache.fontbox.type1.Type1CharStringReader;
-
+import java.awt.geom.GeneralPath;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.fontbox.type1.Type1CharStringReader;
/**
* A Type 0 CIDFont represented in a CFF file. Thread safe.
@@ -247,6 +247,39 @@ public class CFFCIDFont extends CFFFont
return (List<Number>)topDict.get("FontMatrix");
}
+ @Override
+ public GeneralPath getPath(String selector) throws IOException
+ {
+ int cid = selectorToCID(selector);
+ return getType2CharString(cid).getPath();
+ }
+
+ @Override
+ public float getWidth(String selector) throws IOException
+ {
+ int cid = selectorToCID(selector);
+ return getType2CharString(cid).getWidth();
+ }
+
+ @Override
+ public boolean hasGlyph(String selector) throws IOException
+ {
+ int cid = selectorToCID(selector);
+ return cid != 0;
+ }
+
+ /**
+ * Parses a CID selector of the form \ddddd.
+ */
+ private int selectorToCID(String selector)
+ {
+ if (!selector.startsWith("\\"))
+ {
+ throw new IllegalArgumentException("Invalid selector");
+ }
+ return Integer.parseInt(selector.substring(1));
+ }
+
/**
* Private implementation of Type1CharStringReader, because only CFFType1Font can
* expose this publicly, as CIDFonts only support this for legacy 'seac' commands.
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFFont.java Sat Jun 27 00:18:21 2015
@@ -16,11 +16,13 @@
*/
package org.apache.fontbox.cff;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import org.apache.fontbox.FontBoxFont;
import org.apache.fontbox.util.BoundingBox;
/**
@@ -29,7 +31,7 @@ import org.apache.fontbox.util.BoundingB
* @author Villu Ruusmann
* @author John Hewson
*/
-public abstract class CFFFont
+public abstract class CFFFont implements FontBoxFont
{
protected String fontName;
protected final Map<String, Object> topDict = new LinkedHashMap<String, Object>();
@@ -174,6 +176,14 @@ public abstract class CFFFont
return globalSubrIndex;
}
+ /**
+ * Returns the Type 2 charstring for the given CID.
+ *
+ * @param cidOrGid CID for CIFFont, or GID for Type 1 font
+ * @throws IOException if the charstring could not be read
+ */
+ public abstract Type2CharString getType2CharString(int cidOrGid) throws IOException;
+
@Override
public String toString()
{
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFType1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFType1Font.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFType1Font.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/CFFType1Font.java Sat Jun 27 00:18:21 2015
@@ -16,15 +16,14 @@
*/
package org.apache.fontbox.cff;
-import org.apache.fontbox.ttf.Type1Equivalent;
-import org.apache.fontbox.type1.Type1CharStringReader;
-
import java.awt.geom.GeneralPath;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.fontbox.EncodedFont;
+import org.apache.fontbox.type1.Type1CharStringReader;
/**
* A Type 1-equivalent font program represented in a CFF file. Thread safe.
@@ -32,7 +31,7 @@ import java.util.concurrent.ConcurrentHa
* @author Villu Ruusmann
* @author John Hewson
*/
-public class CFFType1Font extends CFFFont implements Type1Equivalent
+public class CFFType1Font extends CFFFont implements EncodedFont
{
private final Map<String, Object> privateDict = new LinkedHashMap<String, Object>();
private CFFEncoding encoding;
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/IndexData.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/IndexData.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/IndexData.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/cff/IndexData.java Sat Jun 27 00:18:21 2015
@@ -104,4 +104,4 @@ public class IndexData
{
data[index] = value;
}
-}
\ No newline at end of file
+}
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OpenTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OpenTypeFont.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OpenTypeFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OpenTypeFont.java Sat Jun 27 00:18:21 2015
@@ -17,6 +17,7 @@
package org.apache.fontbox.ttf;
+import java.awt.geom.GeneralPath;
import java.io.IOException;
/**
@@ -33,7 +34,6 @@ public class OpenTypeFont extends TrueTy
{
super(fontData);
}
-
/**
* Get the "cmap" table for this TTF.
*
@@ -41,12 +41,25 @@ public class OpenTypeFont extends TrueTy
*/
public synchronized CFFTable getCFF() throws IOException
{
- CFFTable cmap = (CFFTable)tables.get(CFFTable.TAG);
- if (cmap != null && !cmap.getInitialized())
+ CFFTable cff = (CFFTable)tables.get(CFFTable.TAG);
+ if (cff != null && !cff.getInitialized())
{
- readTable(cmap);
+ readTable(cff);
}
- return cmap;
+ return cff;
+ }
+
+ @Override
+ public synchronized GlyphTable getGlyph() throws IOException
+ {
+ throw new UnsupportedOperationException("OTF fonts do not have a glyf table");
+ }
+
+ @Override
+ public GeneralPath getPath(String name) throws IOException
+ {
+ int gid = nameToGID(name);
+ return getCFF().getFont().getType2CharString(gid).getPath();
}
/**
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TrueTypeFont.java Sat Jun 27 00:18:21 2015
@@ -19,13 +19,14 @@ package org.apache.fontbox.ttf;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.fontbox.encoding.Encoding;
+import org.apache.fontbox.FontBoxFont;
import org.apache.fontbox.util.BoundingBox;
/**
@@ -33,7 +34,7 @@ import org.apache.fontbox.util.BoundingB
*
* @author Ben Litchfield
*/
-public class TrueTypeFont implements Type1Equivalent, Closeable
+public class TrueTypeFont implements FontBoxFont, Closeable
{
private float version;
private int numberOfGlyphs = -1;
@@ -644,12 +645,6 @@ public class TrueTypeFont implements Typ
}
@Override
- public Encoding getEncoding()
- {
- return null;
- }
-
- @Override
public BoundingBox getFontBBox() throws IOException
{
short xMin = getHeader().getXMin();
@@ -661,6 +656,13 @@ public class TrueTypeFont implements Typ
}
@Override
+ public List<Number> getFontMatrix() throws IOException
+ {
+ float scale = 1000f / getUnitsPerEm();
+ return Arrays.<Number>asList(0.001f * scale, 0, 0, 0.001f * scale, 0, 0);
+ }
+
+ @Override
public String toString()
{
try
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/type1/Type1Font.java Sat Jun 27 00:18:21 2015
@@ -17,13 +17,6 @@
package org.apache.fontbox.type1;
-import org.apache.fontbox.cff.Type1CharString;
-import org.apache.fontbox.cff.Type1CharStringParser;
-import org.apache.fontbox.encoding.Encoding;
-import org.apache.fontbox.pfb.PfbParser;
-import org.apache.fontbox.ttf.Type1Equivalent;
-import org.apache.fontbox.util.BoundingBox;
-
import java.awt.geom.GeneralPath;
import java.io.IOException;
import java.io.InputStream;
@@ -33,13 +26,20 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.fontbox.FontBoxFont;
+import org.apache.fontbox.EncodedFont;
+import org.apache.fontbox.cff.Type1CharString;
+import org.apache.fontbox.cff.Type1CharStringParser;
+import org.apache.fontbox.encoding.Encoding;
+import org.apache.fontbox.pfb.PfbParser;
+import org.apache.fontbox.util.BoundingBox;
/**
* Represents an Adobe Type 1 (.pfb) font. Thread safe.
*
* @author John Hewson
*/
-public final class Type1Font implements Type1CharStringReader, Type1Equivalent
+public final class Type1Font implements Type1CharStringReader, EncodedFont, FontBoxFont
{
/**
* Constructs a new Type1Font object from a .pfb stream.
Modified: pdfbox/trunk/pdfbox/pom.xml
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/pom.xml?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/pom.xml (original)
+++ pdfbox/trunk/pdfbox/pom.xml Sat Jun 27 00:18:21 2015
@@ -97,7 +97,7 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <argLine>-Xmx128m</argLine>
+ <argLine>-Xmx768m</argLine>
<excludes>
<exclude>org/apache/pdfbox/TestAll.java</exclude>
<exclude>org/apache/pdfbox/rendering/TestPDFToImage.java</exclude>
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/cos/COSName.java Sat Jun 27 00:18:21 2015
@@ -453,7 +453,6 @@ public final class COSName extends COSBa
public static final COSName SOFT_LIGHT = new COSName("SoftLight");
public static final COSName SS = new COSName("SS");
public static final COSName ST = new COSName("St");
- public static final COSName STYLE = new COSName("Style");
public static final COSName STANDARD_ENCODING = new COSName("StandardEncoding");
public static final COSName STATE = new COSName("State");
public static final COSName STATE_MODEL = new COSName("StateModel");
@@ -466,6 +465,7 @@ public final class COSName extends COSBa
public static final COSName STRUCT_PARENT = new COSName("StructParent");
public static final COSName STRUCT_PARENTS = new COSName("StructParents");
public static final COSName STRUCT_TREE_ROOT = new COSName("StructTreeRoot");
+ public static final COSName STYLE = new COSName("Style");
public static final COSName SUB_FILTER = new COSName("SubFilter");
public static final COSName SUBJ = new COSName("Subj");
public static final COSName SUBJECT = new COSName("Subject");
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDFontMapping.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDFontMapping.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDFontMapping.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDFontMapping.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package org.apache.pdfbox.pdmodel.font;
+
+import org.apache.fontbox.FontBoxFont;
+import org.apache.fontbox.ttf.OpenTypeFont;
+
+/**
+ * A CIDFontMapping is a kind of FontMapping which allows for an additional TrueTypeFont substitute
+ * to be provided if a CID font is not available.
+ *
+ * @author John Hewson
+ */
+public final class CIDFontMapping extends FontMapping<OpenTypeFont>
+{
+ private final FontBoxFont ttf;
+
+ CIDFontMapping(OpenTypeFont font, FontBoxFont fontBoxFont, boolean isFallback)
+ {
+ super(font, isFallback);
+ this.ttf = fontBoxFont;
+ }
+
+ /**
+ * Returns a TrueType font when isCIDFont() is true, otherwise null.
+ */
+ public FontBoxFont getTrueTypeFont()
+ {
+ return ttf;
+ }
+
+ /**
+ * Returns true if this is a CID font.
+ */
+ public boolean isCIDFont()
+ {
+ return getFont() != null;
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDFontMapping.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java Sat Jun 27 00:18:21 2015
@@ -16,12 +16,21 @@
*/
package org.apache.pdfbox.pdmodel.font;
-import java.util.Set;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.FontBoxFont;
+import org.apache.fontbox.cff.CFFCIDFont;
import org.apache.fontbox.cff.CFFFont;
-import org.apache.fontbox.cff.CFFParser;
import org.apache.fontbox.ttf.NamingTable;
+import org.apache.fontbox.ttf.OTFParser;
+import org.apache.fontbox.ttf.OpenTypeFont;
import org.apache.fontbox.ttf.TTFParser;
import org.apache.fontbox.ttf.TrueTypeCollection;
import org.apache.fontbox.ttf.TrueTypeFont;
@@ -29,78 +38,132 @@ import org.apache.fontbox.type1.Type1Fon
import org.apache.fontbox.util.autodetect.FontFileFinder;
import org.apache.pdfbox.io.IOUtils;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
/**
- * External font provider which searches for fonts on the local filesystem.
+ * A FontProvider which searches for fonts on the local filesystem.
*
* @author John Hewson
*/
final class FileSystemFontProvider extends FontProvider
{
private static final Log LOG = LogFactory.getLog(FileSystemFontProvider.class);
+
+ private final List<FSFontInfo> fontInfoList = new ArrayList<FSFontInfo>();
+ private final FontCache cache;
+
+ private class FSFontInfo extends FontInfo
+ {
+ private final String postScriptName;
+ private final FontFormat format;
+ private final PDCIDSystemInfo cidSystemInfo;
+ private final File file;
- // cache of font files on the system (populated in constructor)
- private final Map<String, File> ttfFontFiles = new HashMap<String, File>();
- private final Map<String, File> cffFontFiles = new HashMap<String, File>();
- private final Map<String, File> type1FontFiles = new HashMap<String, File>();
-
- // cache of loaded fonts which are in use (populated on-the-fly)
- private final Map<String, TrueTypeFont> ttfFonts = new HashMap<String, TrueTypeFont>();
- private final Map<String, CFFFont> cffFonts = new HashMap<String, CFFFont>();
- private final Map<String, Type1Font> type1Fonts = new HashMap<String, Type1Font>();
+ private FSFontInfo(File file, FontFormat format, String postScriptName,
+ PDCIDSystemInfo cidSystemInfo)
+ {
+ this.file = file;
+ this.format = format;
+ this.postScriptName = postScriptName;
+ this.cidSystemInfo = cidSystemInfo;
+ }
+
+ @Override
+ public String getPostScriptName()
+ {
+ return postScriptName;
+ }
+
+ @Override
+ public FontFormat getFormat()
+ {
+ return format;
+ }
+
+ @Override
+ public PDCIDSystemInfo getCIDSystemInfo()
+ {
+ return cidSystemInfo;
+ }
+
+ @Override
+ public FontBoxFont getFont()
+ {
+ FontBoxFont cached = cache.getFont(this);
+ if (cached != null)
+ {
+ return cached;
+ }
+ else
+ {
+ FontBoxFont font;
+ switch (format)
+ {
+ case PFB: font = getType1Font(postScriptName, file); break;
+ case TTF: font = getTrueTypeFont(postScriptName, file); break;
+ case OTF: font = getOTFFont(postScriptName, file); break;
+ default: throw new RuntimeException("can't happen");
+ }
+ cache.addFont(this, font);
+ return font;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return super.toString() + " " + file;
+ }
+ }
/**
* Constructor.
*/
- FileSystemFontProvider()
+ FileSystemFontProvider(FontCache cache)
{
+ this.cache = cache;
+
if (LOG.isTraceEnabled())
{
LOG.trace("Will search the local system for fonts");
}
- int count = 0;
+ List<File> files = new ArrayList<File>();
FontFileFinder fontFileFinder = new FontFileFinder();
List<URI> fonts = fontFileFinder.find();
for (URI font : fonts)
{
- count++;
- File fontFile = new File(font);
+ files.add(new File(font));
+ }
+
+ if (LOG.isTraceEnabled())
+ {
+ LOG.trace("Found " + files.size() + " fonts on the local system");
+ }
+
+ // todo: loading all of these fonts is slow, can we cache this?
+ for (File file : files)
+ {
try
{
- if (fontFile.getPath().toLowerCase().endsWith(".ttf") ||
- fontFile.getPath().toLowerCase().endsWith(".otf"))
+ if (file.getPath().toLowerCase().endsWith(".ttf") ||
+ file.getPath().toLowerCase().endsWith(".otf"))
{
- addTrueTypeFont(fontFile);
+ addTrueTypeFont(file);
}
- else if (fontFile.getPath().toLowerCase().endsWith(".ttc") ||
- fontFile.getPath().toLowerCase().endsWith(".otc"))
+ else if (file.getPath().toLowerCase().endsWith(".ttc") ||
+ file.getPath().toLowerCase().endsWith(".otc"))
{
- addTrueTypeCollection(fontFile);
+ addTrueTypeCollection(file);
}
- else if (fontFile.getPath().toLowerCase().endsWith(".pfb"))
+ else if (file.getPath().toLowerCase().endsWith(".pfb"))
{
- addType1Font(fontFile);
+ addType1Font(file);
}
}
catch (IOException e)
{
- LOG.error("Error parsing font " + fontFile.getPath(), e);
+ LOG.error("Error parsing font " + file.getPath(), e);
}
}
-
- if (LOG.isTraceEnabled())
- {
- LOG.trace("Found " + count + " fonts on the local system");
- }
}
/**
@@ -133,17 +196,26 @@ final class FileSystemFontProvider exten
}
}
}
-
+
/**
* Adds an OTF or TTF font to the file cache. To reduce memory, the parsed font is not cached.
*/
private void addTrueTypeFont(File ttfFile) throws IOException
{
- TTFParser ttfParser = new TTFParser(false, true);
try
{
- TrueTypeFont ttf = ttfParser.parse(ttfFile);
- addTrueTypeFontImpl(ttf, ttfFile);
+ if (ttfFile.getPath().endsWith(".otf"))
+ {
+ OTFParser parser = new OTFParser(false, true);
+ OpenTypeFont otf = parser.parse(ttfFile);
+ addTrueTypeFontImpl(otf, ttfFile);
+ }
+ else
+ {
+ TTFParser parser = new TTFParser(false, true);
+ TrueTypeFont ttf = parser.parse(ttfFile);
+ addTrueTypeFontImpl(ttf, ttfFile);
+ }
}
catch (NullPointerException e) // TTF parser is buggy
{
@@ -154,7 +226,7 @@ final class FileSystemFontProvider exten
LOG.error("Could not load font file: " + ttfFile, e);
}
}
-
+
/**
* Adds an OTF or TTF font to the file cache. To reduce memory, the parsed font is not cached.
*/
@@ -168,9 +240,10 @@ final class FileSystemFontProvider exten
// ttf could still be null
if (ttf != null)
{
+ // todo: this is a performance bottleneck, we don't actually need to read this table
nameTable = ttf.getNaming();
}
-
+
if (nameTable == null)
{
LOG.warn("Missing 'name' table in font " + file);
@@ -178,26 +251,35 @@ final class FileSystemFontProvider exten
else
{
// read PostScript name, if any
- if (nameTable.getPostScriptName() != null)
+ if (ttf.getName() != null)
{
- String psName = nameTable.getPostScriptName();
-
String format;
- if (ttf.getTableMap().get("CFF ") != null)
+ if (ttf instanceof OpenTypeFont)
{
format = "OTF";
- cffFontFiles.putAll(toMap(getNames(ttf), file));
+ CFFFont cff = ((OpenTypeFont)ttf).getCFF().getFont();
+ PDCIDSystemInfo ros = null;
+ if (cff instanceof CFFCIDFont)
+ {
+ CFFCIDFont cidFont = (CFFCIDFont)cff;
+ String registry = cidFont.getRegistry();
+ String ordering = cidFont.getOrdering();
+ int supplement = cidFont.getSupplement();
+ ros = new PDCIDSystemInfo(registry, ordering, supplement);
+ }
+ fontInfoList.add(new FSFontInfo(file, FontFormat.OTF, ttf.getName(), ros));
}
else
{
format = "TTF";
- ttfFontFiles.putAll(toMap(getNames(ttf), file));
+ fontInfoList.add(new FSFontInfo(file, FontFormat.TTF, ttf.getName(), null));
}
if (LOG.isTraceEnabled())
{
- LOG.trace(format +": '" + psName + "' / '" + nameTable.getFontFamily() +
- "' / '" + nameTable.getFontSubFamily() + "'");
+ LOG.trace(format +": '" + ttf.getName() + "' / '" +
+ nameTable.getFontFamily() + "' / '" +
+ nameTable.getFontSubFamily() + "'");
}
}
else
@@ -206,6 +288,10 @@ final class FileSystemFontProvider exten
}
}
}
+ catch (IOException e)
+ {
+ LOG.error("Could not load font file: " + file, e);
+ }
finally
{
if (ttf != null)
@@ -224,56 +310,43 @@ final class FileSystemFontProvider exten
try
{
Type1Font type1 = Type1Font.createWithPFB(input);
-
- String psName = type1.getFontName();
- type1FontFiles.putAll(toMap(getNames(type1), pfbFile));
+ fontInfoList.add(new FSFontInfo(pfbFile, FontFormat.PFB, type1.getName(), null));
if (LOG.isTraceEnabled())
{
- LOG.trace("PFB: '" + psName + "' / '" + type1.getFamilyName() + "' / '" +
+ LOG.trace("PFB: '" + type1.getName() + "' / '" + type1.getFamilyName() + "' / '" +
type1.getWeight() + "'");
}
}
+ catch (IOException e)
+ {
+ LOG.error("Could not load font file: " + pfbFile, e);
+ }
finally
{
input.close();
}
}
-
- @Override
- public synchronized TrueTypeFont getTrueTypeFont(String postScriptName)
- {
- TrueTypeFont ttf = ttfFonts.get(postScriptName);
- if (ttf != null)
- {
- return ttf;
- }
- File file = ttfFontFiles.get(postScriptName);
- if (file != null)
+ private TrueTypeFont getTrueTypeFont(String postScriptName, File file)
+ {
+ try
{
- try
- {
- ttf = readTrueTypeFont(postScriptName, file);
+ TrueTypeFont ttf = readTrueTypeFont(postScriptName, file);
- for (String name : getNames(ttf))
- {
- ttfFonts.put(name, ttf);
- }
- if (LOG.isDebugEnabled())
- {
- LOG.debug("Loaded " + postScriptName + " from " + file);
- }
- return ttf;
- }
- catch (NullPointerException e) // TTF parser is buggy
+ if (LOG.isDebugEnabled())
{
- LOG.error("Could not load font file: " + file, e);
- }
- catch (IOException e)
- {
- LOG.error("Could not load font file: " + file, e);
+ LOG.debug("Loaded " + postScriptName + " from " + file);
}
+ return ttf;
+ }
+ catch (NullPointerException e) // TTF parser is buggy
+ {
+ LOG.error("Could not load font file: " + file, e);
+ }
+ catch (IOException e)
+ {
+ LOG.error("Could not load font file: " + file, e);
}
return null;
}
@@ -298,129 +371,72 @@ final class FileSystemFontProvider exten
return ttfParser.parse(file);
}
}
-
- @Override
- public synchronized CFFFont getCFFFont(String postScriptName)
+
+ private OpenTypeFont getOTFFont(String postScriptName, File file)
{
- CFFFont cff = cffFonts.get(postScriptName);
- if (cff != null)
+ try
{
- return cff;
- }
+ // todo JH: we don't yet support loading CFF fonts from OTC collectionsâ¨
+ OTFParser parser = new OTFParser(false, true);
+ OpenTypeFont otf = parser.parse(file);
- File file = cffFontFiles.get(postScriptName);
- if (file != null)
- {
- InputStream input = null;
- try
+ if (LOG.isDebugEnabled())
{
- // todo JH: we don't yet support loading CFF fonts from OTC collectionsâ¨
- input = new FileInputStream(file);
- byte[] bytes = IOUtils.toByteArray(input);
- CFFParser cffParser = new CFFParser();
- cff = cffParser.parse(bytes).get(0);
- for (String name : getNames(cff))
- {
- cffFonts.put(name, cff);
- }
- if (LOG.isDebugEnabled())
- {
- LOG.debug("Loaded " + postScriptName + " from " + file);
- }
- return cff;
- }
- catch (IOException e)
- {
- LOG.error("Could not load font file: " + file, e);
- }
- finally
- {
- IOUtils.closeQuietly(input);
+ LOG.debug("Loaded " + postScriptName + " from " + file);
}
+ return otf;
+ }
+ catch (IOException e)
+ {
+ LOG.error("Could not load font file: " + file, e);
}
return null;
}
- @Override
- public synchronized Type1Font getType1Font(String postScriptName)
+ private Type1Font getType1Font(String postScriptName, File file)
{
- Type1Font type1 = type1Fonts.get(postScriptName);
- if (type1 != null)
+ InputStream input = null;
+ try
{
- return type1;
- }
+ input = new FileInputStream(file);
+ Type1Font type1 = Type1Font.createWithPFB(input);
- File file = type1FontFiles.get(postScriptName);
- if (file != null)
- {
- InputStream input = null;
- try
+ if (LOG.isDebugEnabled())
{
- input = new FileInputStream(file);
- type1 = Type1Font.createWithPFB(input);
- for (String name : getNames(type1))
- {
- type1Fonts.put(name, type1);
- }
- if (LOG.isDebugEnabled())
- {
- LOG.debug("Loaded " + postScriptName + " from " + file);
- }
- return type1;
- }
- catch (IOException e)
- {
- LOG.error("Could not load font file: " + file, e);
- }
- finally
- {
- IOUtils.closeQuietly(input);
+ LOG.debug("Loaded " + postScriptName + " from " + file);
}
+ return type1;
}
- return null;
- }
-
- /**
- * Returns a map containing the given file for each string key.
- */
- private Map<String, File> toMap(Set<String> names, File file)
- {
- Map<String, File> map = new HashMap<String, File>();
- for (String name : names)
+ catch (IOException e)
+ {
+ LOG.error("Could not load font file: " + file, e);
+ }
+ finally
{
- map.put(name, file);
+ IOUtils.closeQuietly(input);
}
- return map;
+ return null;
}
@Override
public String toDebugString()
{
StringBuilder sb = new StringBuilder();
- for (Map.Entry<String, File> entry : ttfFontFiles.entrySet())
+ for (FSFontInfo info : fontInfoList)
{
- sb.append("TTF: ");
- sb.append(entry.getKey());
+ sb.append(info.getFormat());
sb.append(": ");
- sb.append(entry.getValue().getPath());
- sb.append('\n');
- }
- for (Map.Entry<String, File> entry : cffFontFiles.entrySet())
- {
- sb.append("OTF: ");
- sb.append(entry.getKey());
- sb.append(": ");
- sb.append(entry.getValue().getPath());
- sb.append('\n');
- }
- for (Map.Entry<String, File> entry : type1FontFiles.entrySet())
- {
- sb.append("PFB: ");
- sb.append(entry.getKey());
+ sb.append(info.getPostScriptName());
sb.append(": ");
- sb.append(entry.getValue().getPath());
+ sb.append(info.file.getPath());
sb.append('\n');
}
return sb.toString();
}
+
+ @Override
+ public List<? extends FontInfo> getFontInfo()
+ {
+ return fontInfoList;
+ }
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontCache.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontCache.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontCache.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontCache.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package org.apache.pdfbox.pdmodel.font;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.fontbox.FontBoxFont;
+
+/**
+ * A cache for system fonts. This allows PDFBox to manage caching for a {@link FontProvider}.
+ * PDFBox is free to purge this cache at will.
+ *
+ * @author John Hewson
+ */
+public final class FontCache
+{
+ private final Map<FontInfo, FontBoxFont> cache = new ConcurrentHashMap<FontInfo, FontBoxFont>();
+
+ /**
+ * Adds the given FontBox font to the cache.
+ */
+ public void addFont(FontInfo info, FontBoxFont font)
+ {
+ cache.put(info, font);
+ }
+
+ /**
+ * Returns the FontBox font associated with the given FontInfo.
+ */
+ public FontBoxFont getFont(FontInfo info)
+ {
+ return cache.get(info);
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontFormat.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontFormat.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontFormat.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontFormat.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package org.apache.pdfbox.pdmodel.font;
+
+/**
+ * Font file format.
+ *
+ * @author John Hewson
+ */
+public enum FontFormat
+{
+ /**
+ * TrueType font.
+ */
+ TTF,
+
+ /**
+ * OpenType font.
+ */
+ OTF,
+
+ /**
+ * Type 1 (binary) font.
+ */
+ PFB
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontFormat.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+package org.apache.pdfbox.pdmodel.font;
+
+import org.apache.fontbox.FontBoxFont;
+
+/**
+ * Information about a font on the system.
+ *
+ * @author John Hewson
+ */
+public abstract class FontInfo
+{
+ /**
+ * Returns the PostScript name of the font.
+ */
+ public abstract String getPostScriptName();
+
+ /**
+ * Returns the font's format.
+ */
+ public abstract FontFormat getFormat();
+
+ /**
+ * Returns the CIDSystemInfo associated with the font, if any.
+ */
+ public abstract PDCIDSystemInfo getCIDSystemInfo();
+
+ /**
+ * Returns a new FontBox font instance for the font. Implementors of this method must not
+ * cache the return value of this method unless doing so via the current {@link FontCache}.
+ */
+ public abstract FontBoxFont getFont();
+
+ @Override
+ public String toString()
+ {
+ return getPostScriptName() + " (" + getFormat() + ")";
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapper.java (from r1687667, pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ExternalFonts.java)
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapper.java?p2=pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapper.java&p1=pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ExternalFonts.java&r1=1687667&r2=1687878&rev=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/ExternalFonts.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapper.java Sat Jun 27 00:18:21 2015
@@ -23,68 +23,48 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fontbox.cff.CFFCIDFont;
+import org.apache.fontbox.FontBoxFont;
import org.apache.fontbox.cff.CFFFont;
-import org.apache.fontbox.cff.CFFParser;
import org.apache.fontbox.cff.CFFType1Font;
+import org.apache.fontbox.ttf.OpenTypeFont;
import org.apache.fontbox.ttf.TTFParser;
-import org.apache.fontbox.ttf.Type1Equivalent;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.fontbox.type1.Type1Font;
-import org.apache.pdfbox.io.IOUtils;
/**
- * External font service, locates non-embedded fonts via a pluggable FontProvider.
+ * Font mapper, locates non-embedded fonts via a pluggable FontProvider.
*
* @author John Hewson
*/
-public final class ExternalFonts
+public final class FontMapper
{
- private ExternalFonts() {}
-
- // lazy thread safe singleton
- private static class DefaultFontProvider
- {
- private static final FontProvider INSTANCE = new FileSystemFontProvider();
- }
+ private FontMapper() {}
- private static final Log log = LogFactory.getLog(ExternalFonts.class);
+ private static final FontCache fontCache = new FontCache(); // todo: static cache isn't ideal
+ private static final Log log = LogFactory.getLog(FontMapper.class);
private static FontProvider fontProvider;
+ private static Map<String, FontInfo> fontInfoByName;
/** fallback fonts, used as as a last resort */
- private static final TrueTypeFont ttfFallbackFont;
- private static final CFFCIDFont cidFallbackFont;
+ private static final TrueTypeFont lastResortFont;
static
{
try
{
- // ttf
String ttfName = "org/apache/pdfbox/resources/ttf/LiberationSans-Regular.ttf";
- URL url = ExternalFonts.class.getClassLoader().getResource(ttfName);
+ URL url = FontMapper.class.getClassLoader().getResource(ttfName);
if (url == null)
{
throw new IOException("Error loading resource: " + ttfName);
}
InputStream ttfStream = url.openStream();
TTFParser ttfParser = new TTFParser();
- ttfFallbackFont = ttfParser.parse(ttfStream);
-
- // cff
- String cffName = "org/apache/pdfbox/resources/otf/AdobeBlank.otf";
- url = ExternalFonts.class.getClassLoader().getResource(cffName);
- if (url == null)
- {
- throw new IOException("Error loading resource: " + ttfName);
- }
- InputStream cffStream = url.openStream();
- byte[] bytes = IOUtils.toByteArray(cffStream);
- CFFParser cffParser = new CFFParser();
- cidFallbackFont = (CFFCIDFont)cffParser.parse(bytes).get(0);
+ lastResortFont = ttfParser.parse(ttfStream);
}
catch (IOException e)
{
@@ -92,26 +72,52 @@ public final class ExternalFonts
}
}
+ // lazy thread safe singleton
+ private static class DefaultFontProvider
+ {
+ private static final FontProvider INSTANCE = new FileSystemFontProvider(fontCache);
+ }
+
/**
* Sets the font service provider.
*/
- public static void setProvider(FontProvider fontProvider)
+ public synchronized static void setProvider(FontProvider fontProvider)
{
- ExternalFonts.fontProvider = fontProvider;
+ FontMapper.fontProvider = fontProvider;
+ fontInfoByName = createFontInfoByName(fontProvider.getFontInfo());
}
/**
* Returns the font service provider. Defaults to using FileSystemFontProvider.
*/
- public static FontProvider getProvider()
+ public synchronized static FontProvider getProvider()
{
if (fontProvider == null)
{
- fontProvider = DefaultFontProvider.INSTANCE;
+ setProvider(DefaultFontProvider.INSTANCE);
}
return fontProvider;
}
+ /**
+ * Returns the font cache associated with this FontMapper. This method is needed by
+ * FontProvider subclasses.
+ */
+ public static FontCache getFontCache()
+ {
+ return fontCache;
+ }
+
+ private static Map<String, FontInfo> createFontInfoByName(List<? extends FontInfo> fontInfoList)
+ {
+ Map<String, FontInfo> map = new LinkedHashMap<String, FontInfo>();
+ for (FontInfo info : fontInfoList)
+ {
+ map.put(info.getPostScriptName(), info);
+ }
+ return map;
+ }
+
/** Map of PostScript name substitutes, in priority order. */
private static final Map<String, List<String>> substitutes = new HashMap<String, List<String>>();
static
@@ -156,13 +162,7 @@ public final class ExternalFonts
"NimbusRomNo9L-MediItal"));
substitutes.put("Symbol", Arrays.asList("Symbol", "SymbolMT", "StandardSymL"));
substitutes.put("ZapfDingbats", Arrays.asList("ZapfDingbatsITC", "Dingbats", "MS-Gothic"));
-
- // extra substitute mechanism for CJK CIDFonts when all we know is the ROS
- substitutes.put("$Adobe-CNS1", Arrays.asList("AdobeMingStd-Light"));
- substitutes.put("$Adobe-Japan1", Arrays.asList("KozMinPr6N-Regular"));
- substitutes.put("$Adobe-Korea1", Arrays.asList("AdobeGothicStd-Bold"));
- substitutes.put("$Adobe-GB1", Arrays.asList("AdobeHeitiStd-Regular"));
-
+
// Acrobat also uses alternative names for Standard 14 fonts, which we map to those above
// these include names such as "Arial" and "TimesNewRoman"
for (String baseName : Standard14Fonts.getNames())
@@ -215,73 +215,6 @@ public final class ExternalFonts
}
/**
- * Windows name (ArialNarrow,Bold) to PostScript name (ArialNarrow-Bold)
- */
- private static String windowsToPs(String windowsName)
- {
- return windowsName.replaceAll(",", "-");
- }
-
- /**
- * Finds a CFF CID-Keyed font with the given PostScript name, or a suitable substitute, or null.
- *
- * @param registryOrdering the CID system registry and ordering e.g. "Adobe-Japan1", if any
- * @param fontDescriptor the font descriptor, if any
- */
- public static CFFCIDFont getCFFCIDFontFallback(String registryOrdering,
- PDFontDescriptor fontDescriptor)
- {
- // try ROS substitutes
- // todo: this is a fairly primitive mechanism and could be improved
- if (registryOrdering != null)
- {
- for (String substituteName : getSubstitutes("$" + registryOrdering))
- {
- CFFFont cff = getProvider().getCFFFont(substituteName);
- if (cff instanceof CFFCIDFont)
- {
- return (CFFCIDFont) cff;
- }
- }
- }
- return cidFallbackFont;
- }
-
- /**
- * Returns the fallback font, used for rendering when no other fonts are available,
- * we attempt to find a good fallback based on the font descriptor.
- */
- public static Type1Equivalent getType1FallbackFont(PDFontDescriptor fontDescriptor)
- {
- String fontName = getFallbackFontName(fontDescriptor);
- Type1Equivalent type1Equivalent = getType1EquivalentFont(fontName);
- if (type1Equivalent == null)
- {
- // only systems with no fonts should reach this point, so we return a basic fallback
- log.error("No fallback font for '" + fontName + "'");
- return ttfFallbackFont;
- }
- return type1Equivalent;
- }
-
- /**
- * Returns the fallback font, used for rendering when no other fonts are available,
- * we attempt to find a good fallback based on the font descriptor.
- */
- public static TrueTypeFont getTrueTypeFallbackFont(PDFontDescriptor fontDescriptor)
- {
- String fontName = getFallbackFontName(fontDescriptor);
- TrueTypeFont ttf = getTrueTypeFont(fontName);
- if (ttf == null)
- {
- // we have to return something here as TTFs aren't strictly required on the system
- log.error("No TTF fallback font for '" + fontName + "'");
- return ttfFallbackFont;
- }
- return ttf;
- }
-
- /**
* Attempts to find a good fallback based on the font descriptor.
*/
private static String getFallbackFontName(PDFontDescriptor fontDescriptor)
@@ -365,138 +298,203 @@ public final class ExternalFonts
/**
* Finds a TrueType font with the given PostScript name, or a suitable substitute, or null.
*
- * @param postScriptName PostScript font name
+ * @param fontDescriptor FontDescriptor
*/
- public static TrueTypeFont getTrueTypeFont(String postScriptName)
+ public static FontMapping<TrueTypeFont> getTrueTypeFont(PDFontDescriptor fontDescriptor)
{
- // first ask the font provider for the font
- TrueTypeFont ttf = getProvider().getTrueTypeFont(postScriptName);
- if (ttf == null)
+ TrueTypeFont ttf = (TrueTypeFont)findFont(FontFormat.TTF, fontDescriptor.getFontName());
+ if (ttf != null)
+ {
+ return new FontMapping<TrueTypeFont>(ttf, false);
+ }
+ else
{
- // then try substitutes
- for (String substituteName : getSubstitutes(postScriptName))
+ // fallback - todo: i.e. fuzzy match
+ String fontName = getFallbackFontName(fontDescriptor);
+ ttf = (TrueTypeFont) findFont(FontFormat.TTF, fontName);
+ if (ttf == null)
{
- ttf = getProvider().getTrueTypeFont(substituteName);
- if (ttf != null)
- {
- return ttf;
- }
+ // we have to return something here as TTFs aren't strictly required on the system
+ log.error("Using last-resort fallback for TTF font '" + fontName + "'");
+ ttf = lastResortFont;
}
- // then Windows name
- ttf = getProvider().getTrueTypeFont(windowsToPs(postScriptName));
+ return new FontMapping<TrueTypeFont>(ttf, true);
}
- return ttf;
}
/**
- * Finds a TrueType font with the given PostScript name, or a suitable substitute, or null.
+ * Finds a font with the given PostScript name, or a suitable substitute, or null. This allows
+ * any font to be substituted with a PFB, TTF or OTF.
*
- * @param postScriptName PostScript font name
+ * @param fontDescriptor the FontDescriptor of the font to find
*/
- public static Type1Font getType1Font(String postScriptName)
+ public static FontMapping<FontBoxFont> getFontBoxFont(PDFontDescriptor fontDescriptor)
{
- // first ask the font provider for the font
- Type1Font t1 = getProvider().getType1Font(postScriptName);
- if (t1 == null)
+ FontBoxFont font = findFontBoxFont(fontDescriptor.getFontName());
+ if (font != null)
{
- // then try substitutes
- for (String substituteName : getSubstitutes(postScriptName))
+ return new FontMapping<FontBoxFont>(font, false);
+ }
+ else
+ {
+ // fallback - todo: i.e. fuzzy match
+ String fontName = getFallbackFontName(fontDescriptor);
+ font = findFontBoxFont(fontName);
+ if (font == null)
{
- t1 = getProvider().getType1Font(substituteName);
- if (t1 != null)
- {
- return t1;
- }
+ // we have to return something here as TTFs aren't strictly required on the system
+ log.error("Using last-resort fallback for font '" + fontName + "'");
+ font = lastResortFont;
}
- // then Windows name
- t1 = getProvider().getType1Font(windowsToPs(postScriptName));
+ return new FontMapping<FontBoxFont>(font, true);
}
- return t1;
}
/**
- * Finds a CFF Type 1 font with the given PostScript name, or a suitable substitute, or null.
+ * Finds a font with the given PostScript name, or a suitable substitute, or null.
*
* @param postScriptName PostScript font name
*/
- public static CFFType1Font getCFFType1Font(String postScriptName)
+ private static FontBoxFont findFontBoxFont(String postScriptName)
{
- CFFFont cff = getCFFFont(postScriptName);
+ Type1Font t1 = (Type1Font)findFont(FontFormat.PFB, postScriptName);
+ if (t1 != null)
+ {
+ return t1;
+ }
+
+ CFFFont cff = (CFFFont)findFont(FontFormat.OTF, postScriptName);
if (cff instanceof CFFType1Font)
{
- return (CFFType1Font)cff;
+ return cff;
+ }
+
+ TrueTypeFont ttf = (TrueTypeFont)findFont(FontFormat.TTF, postScriptName);
+ if (ttf != null)
+ {
+ return ttf;
}
+
return null;
}
/**
- * Finds a CFF CID-Keyed font with the given PostScript name, or a suitable substitute, or null.
+ * Finds a font with the given PostScript name, or a suitable substitute, or null.
*
* @param postScriptName PostScript font name
*/
- public static CFFCIDFont getCFFCIDFont(String postScriptName)
+ private static FontBoxFont findFont(FontFormat format, String postScriptName)
{
- CFFFont cff = getCFFFont(postScriptName);
- if (cff instanceof CFFCIDFont)
+ // make sure the font provider is initialized
+ if (fontProvider == null)
+ {
+ getProvider();
+ }
+
+ // first try to match the PostScript name
+ FontInfo info = getFont(format, postScriptName);
+ if (info != null)
+ {
+ return info.getFont();
+ }
+
+ // remove hyphens (e.g. Arial-Black -> ArialBlack)
+ info = getFont(format, postScriptName.replaceAll("-", ""));
+ if (info != null)
+ {
+ return info.getFont();
+ }
+
+ // then try named substitutes
+ for (String substituteName : getSubstitutes(postScriptName))
{
- return (CFFCIDFont)cff;
+ info = getFont(format, substituteName);
+ if (info != null)
+ {
+ return info.getFont();
+ }
+ }
+
+ // then try converting Windows names e.g. (ArialNarrow,Bold) -> (ArialNarrow-Bold)
+ info = getFont(format, postScriptName.replaceAll(",", "-"));
+ if (info != null)
+ {
+ return info.getFont();
}
+
+ // no matches
return null;
}
/**
- * Finds a CFF font with the given PostScript name, or a suitable substitute, or null.
- *
- * @param postScriptName PostScript font name
+ * Finds the named font with the given format.
*/
- private static CFFFont getCFFFont(String postScriptName)
+ private static FontInfo getFont(FontFormat format, String postScriptName)
{
- // first ask the font provider for the font
- CFFFont cff = getProvider().getCFFFont(postScriptName);
- if (cff == null)
+ // strip subset tag (happens when we substitute a corrupt embedded font, see PDFBOX-2642)
+ if (postScriptName.contains("+"))
{
- // then try substitutes
- for (String substituteName : getSubstitutes(postScriptName))
- {
- cff = getProvider().getCFFFont(substituteName);
- if (cff != null)
- {
- return cff;
- }
- }
-
- // then Windows name
- cff = getProvider().getCFFFont(windowsToPs(postScriptName));
+ postScriptName = postScriptName.substring(postScriptName.indexOf("+") + 1);
+ }
+
+ // look up the PostScript name
+ FontInfo info = fontInfoByName.get(postScriptName);
+ if (info != null && info.getFormat() == format)
+ {
+ return info;
}
- return cff;
+ return null;
}
-
+
/**
- * Finds a Type 1-equivalent font with the given PostScript name, or a suitable substitute,
- * or null. This allows a Type 1 font to be substituted with a PFB, TTF or OTF.
- *
- * @param postScriptName PostScript font name
+ * Finds a CFF CID-Keyed font with the given PostScript name, or a suitable substitute, or null.
+ * This method can also map CJK fonts via their CIDSystemInfo (ROS).
+ *
+ * @param fontDescriptor FontDescriptor
+ * @param cidSystemInfo the CID system info, e.g. "Adobe-Japan1", if any.
*/
- public static Type1Equivalent getType1EquivalentFont(String postScriptName)
+ public static CIDFontMapping getCIDFont(PDFontDescriptor fontDescriptor,
+ PDCIDSystemInfo cidSystemInfo)
{
- Type1Font t1 = getType1Font(postScriptName);
- if (t1 != null)
+ // try name match or substitute with OTF
+ OpenTypeFont otf1 = (OpenTypeFont)findFont(FontFormat.OTF, fontDescriptor.getFontName());
+ if (otf1 != null)
{
- return t1;
+ return new CIDFontMapping(otf1, null, false);
}
- CFFType1Font cff = getCFFType1Font(postScriptName);
- if (cff != null)
+ // try name match or substitute with TTF
+ TrueTypeFont ttf = (TrueTypeFont)findFont(FontFormat.TTF, fontDescriptor.getFontName());
+ if (ttf != null)
{
- return cff;
+ return new CIDFontMapping(null, ttf, false);
}
- TrueTypeFont ttf = getTrueTypeFont(postScriptName);
- if (ttf != null)
+ if (cidSystemInfo != null)
{
- return ttf;
+ // "In Acrobat 3.0.1 and later, Type 0 fonts that use a CMap whose CIDSystemInfo
+ // dictionary defines the Adobe-GB1, Adobe-CNS1 Adobe-Japan1, or Adobe-Korea1 character
+ // collection can also be substituted." - Adobe Supplement to the ISO 32000
+
+ String collection = cidSystemInfo.getRegistry() + "-" + cidSystemInfo.getOrdering();
+
+ if (collection.equals("Adobe-GB1") || collection.equals("Adobe-CNS1") ||
+ collection.equals("Adobe-Japan1") || collection.equals("Adobe-Korea1"))
+ {
+ // try automatic substitutes via character collection
+ for (FontInfo info : fontInfoByName.values())
+ {
+ if (info.getCIDSystemInfo() != null &&
+ info.getCIDSystemInfo().getRegistry().equals(cidSystemInfo.getRegistry()) &&
+ info.getCIDSystemInfo().getOrdering().equals(cidSystemInfo.getOrdering()))
+ {
+ return new CIDFontMapping((OpenTypeFont)info.getFont(), null, true);
+ }
+ }
+ }
}
- return null;
+ // last-resort fallback
+ return new CIDFontMapping(null, lastResortFont, true);
}
}
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapping.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapping.java?rev=1687878&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapping.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapping.java Sat Jun 27 00:18:21 2015
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+package org.apache.pdfbox.pdmodel.font;
+
+import org.apache.fontbox.FontBoxFont;
+
+/**
+ * A font mapping from a PDF font to a FontBox font.
+ *
+ * @author John Hewson
+ */
+public class FontMapping<T extends FontBoxFont>
+{
+ private final T font;
+ private final boolean isFallback;
+
+ FontMapping(T font, boolean isFallback)
+ {
+ this.font = font;
+ this.isFallback = isFallback;
+ }
+
+ /**
+ * Returns the mapped, FontBox font. This is never null.
+ */
+ public T getFont()
+ {
+ return font;
+ }
+
+ /**
+ * Returns true if the mapped font is a fallback, i.e. a substitute based on basic font style,
+ * such as bold/italic, rather than font name.
+ */
+ public boolean isFallback()
+ {
+ return isFallback;
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontMapping.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontProvider.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontProvider.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontProvider.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontProvider.java Sat Jun 27 00:18:21 2015
@@ -16,93 +16,23 @@
*/
package org.apache.pdfbox.pdmodel.font;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import org.apache.fontbox.cff.CFFFont;
-import org.apache.fontbox.ttf.TrueTypeFont;
-import org.apache.fontbox.type1.Type1Font;
+import java.util.List;
/**
- * External font service provider interface. Implementations are expected to be thread safe.
+ * External font service provider interface.
*
* @author John Hewson
*/
public abstract class FontProvider
{
/**
- * Returns a TrueType which corresponds to the given PostScript name. If there is no
- * suitable font, then this method will return null.
- *
- * @param postScriptName PostScript font name
- */
- public abstract TrueTypeFont getTrueTypeFont(String postScriptName);
-
- /**
- * Returns a CFF font which corresponds to the given PostScript name. If there is no
- * suitable font, then this method will return null.
- *
- * @param postScriptName PostScript font name
- */
- public abstract CFFFont getCFFFont(String postScriptName);
-
- /**
- * Returns a Type 1 which corresponds to the given PostScript name. If there is no
- * suitable font, then this method will return null.
- *
- * @param postScriptName PostScript font name
- */
- public abstract Type1Font getType1Font(String postScriptName);
-
- /**
* Returns a string containing debugging information. This will be written to the log if no
* suitable fonts are found and no fallback fonts are available. May be null.
*/
public abstract String toDebugString();
/**
- * Returns the font names for a given font. This allows substitution based on the PostScript
- * name of the external font, instead of just the BaseName in the PDF.
+ * Returns a list of information about fonts on the system.
*/
- protected final Set<String> getNames(TrueTypeFont font) throws IOException
- {
- return getPostScriptNames(font.getName());
- // could add format-specific names here if needed
- }
-
- /**
- * Returns the font names for a given font. This allows substitution based on the PostScript
- * name of the external font, instead of just the BaseName in the PDF.
- */
- protected final Set<String> getNames(Type1Font font) throws IOException
- {
- return getPostScriptNames(font.getName());
- // could add format-specific names here if needed
- }
-
- /**
- * Returns the font names for a given font. This allows substitution based on the PostScript
- * name of the external font, instead of just the BaseName in the PDF.
- */
- protected final Set<String> getNames(CFFFont font) throws IOException
- {
- return getPostScriptNames(font.getName());
- // could add format-specific names here if needed
- }
-
- /**
- * Returns a list of alternative names for the given PostScript name.
- */
- private Set<String> getPostScriptNames(String postScriptName) throws IOException
- {
- Set<String> names = new HashSet<String>();
-
- // built-in PostScript name
- names.add(postScriptName);
-
- // remove hyphens (e.g. Arial-Black -> ArialBlack)
- names.add(postScriptName.replaceAll("-", ""));
-
- return names;
- }
+ public abstract List<? extends FontInfo> getFontInfo();
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFont.java Sat Jun 27 00:18:21 2015
@@ -38,7 +38,7 @@ import org.apache.pdfbox.util.Vector;
*
* @author Ben Litchfield
*/
-public abstract class PDCIDFont implements COSObjectable, PDFontLike
+public abstract class PDCIDFont implements COSObjectable, PDFontLike, PDVectorFont
{
protected final PDType0Font parent;
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java?rev=1687878&r1=1687877&r2=1687878&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType0.java Sat Jun 27 00:18:21 2015
@@ -17,6 +17,7 @@
package org.apache.pdfbox.pdmodel.font;
import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.HashMap;
@@ -24,6 +25,7 @@ import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.FontBoxFont;
import org.apache.fontbox.cff.CFFCIDFont;
import org.apache.fontbox.cff.CFFFont;
import org.apache.fontbox.cff.CFFParser;
@@ -31,7 +33,6 @@ import org.apache.fontbox.cff.CFFType1Fo
import org.apache.fontbox.cff.Type2CharString;
import org.apache.fontbox.util.BoundingBox;
import org.apache.pdfbox.cos.COSDictionary;
-import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.util.Matrix;
@@ -47,7 +48,7 @@ public class PDCIDFontType0 extends PDCI
private static final Log LOG = LogFactory.getLog(PDCIDFontType0.class);
private final CFFCIDFont cidFont; // Top DICT that uses CIDFont operators
- private final CFFType1Font t1Font; // Top DICT that does not use CIDFont operators
+ private final FontBoxFont t1Font; // Top DICT that does not use CIDFont operators
private final Map<Integer, Float> glyphHeights = new HashMap<Integer, Float>();
private final boolean isEmbedded;
@@ -81,8 +82,8 @@ public class PDCIDFontType0 extends PDCI
CFFFont cffFont = null;
if (bytes != null && bytes.length > 0 && (bytes[0] & 0xff) == '%')
{
- // todo: PDFBOX-2642 contains a Type1 PFB font in a CIDFont, but we can't handle it yet
- LOG.error("Unsupported: Type1 font instead of CFF in " + fd.getFontName());
+ // PDFBOX-2642 contains a corrupt PFB font instead of a CFF
+ LOG.warn("Found PFB but expected embedded CFF font " + fd.getFontName());
fontIsDamaged = true;
}
else if (bytes != null)
@@ -110,53 +111,30 @@ public class PDCIDFontType0 extends PDCI
else
{
cidFont = null;
- t1Font = (CFFType1Font)cffFont;
+ t1Font = cffFont;
}
isEmbedded = true;
isDamaged = false;
}
else
{
- // substitute
- CFFCIDFont cidSub = ExternalFonts.getCFFCIDFont(getBaseFont());
- if (cidSub != null)
+ // find font or substitute
+ CIDFontMapping mapping = FontMapper.getCIDFont(getFontDescriptor(), getCIDSystemInfo());
+
+ if (mapping.isCIDFont())
{
- cidFont = cidSub;
+ cidFont = (CFFCIDFont)mapping.getFont().getCFF().getFont();
t1Font = null;
}
else
{
- COSDictionary cidSystemInfo = (COSDictionary)
- dict.getDictionaryObject(COSName.CIDSYSTEMINFO);
-
- String registryOrdering = null;
- if (cidSystemInfo != null)
- {
- String registry = cidSystemInfo.getNameAsString(COSName.REGISTRY);
- String ordering = cidSystemInfo.getNameAsString(COSName.ORDERING);
- if (registry != null && ordering != null)
- {
- registryOrdering = registry + "-" + ordering;
- }
- }
-
- cidSub = ExternalFonts.getCFFCIDFontFallback(registryOrdering, getFontDescriptor());
- cidFont = cidSub;
- t1Font = null;
+ cidFont = null;
+ t1Font = mapping.getTrueTypeFont();
+ }
- if (cidSub.getName().equals("AdobeBlank"))
- {
- // this error often indicates that the user needs to install the Adobe Reader
- // Asian and Extended Language Pack
- if (!fontIsDamaged)
- {
- LOG.error("Missing CID-keyed font " + getBaseFont());
- }
- }
- else
- {
- LOG.warn("Using fallback for CID-keyed font " + getBaseFont());
- }
+ if (mapping.isFallback())
+ {
+ LOG.warn("Using fallback for CID-keyed font " + getBaseFont());
}
isEmbedded = false;
isDamaged = fontIsDamaged;
@@ -164,7 +142,7 @@ public class PDCIDFontType0 extends PDCI
fontMatrixTransform = getFontMatrix().createAffineTransform();
fontMatrixTransform.scale(1000, 1000);
}
-
+
@Override
public Matrix getFontMatrix()
{
@@ -177,7 +155,14 @@ public class PDCIDFontType0 extends PDCI
}
else
{
- numbers = t1Font.getFontMatrix();
+ try
+ {
+ numbers = t1Font.getFontMatrix();
+ }
+ catch (IOException e)
+ {
+ return new Matrix(0.001f, 0, 0, 0.001f, 0, 0);
+ }
}
if (numbers != null && numbers.size() == 6)
@@ -203,12 +188,19 @@ public class PDCIDFontType0 extends PDCI
}
else
{
- return t1Font.getFontBBox();
+ try
+ {
+ return t1Font.getFontBBox();
+ }
+ catch (IOException e)
+ {
+ return new BoundingBox();
+ }
}
}
/**
- * Returns the embedded CFF CIDFont.
+ * Returns the embedded CFF CIDFont, or null if the substitute is not a CFF font.
*/
public CFFFont getCFFFont()
{
@@ -216,14 +208,19 @@ public class PDCIDFontType0 extends PDCI
{
return cidFont;
}
+ else if (t1Font instanceof CFFType1Font)
+ {
+ return (CFFType1Font)t1Font;
+ }
else
{
- return t1Font;
+ return null;
}
}
/**
- * Returns the Type 2 charstring for the given CID.
+ * Returns the Type 2 charstring for the given CID, or null if the substituted font does not
+ * contain Type 2 charstrings.
*
* @param cid CID
* @throws IOException if the charstring could not be read
@@ -234,9 +231,65 @@ public class PDCIDFontType0 extends PDCI
{
return cidFont.getType2CharString(cid);
}
+ else if (t1Font instanceof CFFType1Font)
+ {
+ return ((CFFType1Font)t1Font).getType2CharString(cid);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the name of the glyph with the given character code. This is done by looking up the
+ * code in the parent font's ToUnicode map and generating a glyph name from that.
+ */
+ private String getGlyphName(int code) throws IOException
+ {
+ String unicodes = parent.toUnicode(code);
+ if (unicodes == null)
+ {
+ return ".notdef";
+ }
+ return String.format("uni%04X", unicodes.codePointAt(0));
+ }
+
+ @Override
+ public GeneralPath getPath(int code) throws IOException
+ {
+ int cid = codeToCID(code);
+ Type2CharString charstring = getType2CharString(cid);
+ if (charstring != null)
+ {
+ return charstring.getPath();
+ }
+ else if (isEmbedded && t1Font instanceof CFFType1Font)
+ {
+ return ((CFFType1Font)t1Font).getType2CharString(cid).getPath();
+ }
else
{
- return t1Font.getType2CharString(cid);
+ return t1Font.getPath(getGlyphName(code));
+ }
+ }
+
+ @Override
+ public boolean hasGlyph(int code) throws IOException
+ {
+ int cid = codeToCID(code);
+ Type2CharString charstring = getType2CharString(cid);
+ if (charstring != null)
+ {
+ return charstring.getGID() != 0;
+ }
+ else if (isEmbedded && t1Font instanceof CFFType1Font)
+ {
+ return ((CFFType1Font)t1Font).getType2CharString(cid).getGID() != 0;
+ }
+ else
+ {
+ return t1Font.hasGlyph(getGlyphName(code));
}
}
@@ -281,8 +334,20 @@ public class PDCIDFontType0 extends PDCI
public float getWidthFromFont(int code) throws IOException
{
int cid = codeToCID(code);
- int width = getType2CharString(cid).getWidth();
-
+ float width;
+ if (cidFont != null)
+ {
+ width = getType2CharString(cid).getWidth();
+ }
+ else if (isEmbedded && t1Font instanceof CFFType1Font)
+ {
+ width = ((CFFType1Font)t1Font).getType2CharString(cid).getWidth();
+ }
+ else
+ {
+ width = t1Font.getWidth(getGlyphName(code));
+ }
+
Point2D p = new Point2D.Float(width, 0);
fontMatrixTransform.transform(p, p);
return (float)p.getX();