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 2016/08/10 16:06:07 UTC
svn commit: r1755774 - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox: pdmodel/font/
rendering/
Author: jahewson
Date: Wed Aug 10 16:06:07 2016
New Revision: 1755774
URL: http://svn.apache.org/viewvc?rev=1755774&view=rev
Log:
PDFBOX-3459: Move Glyph2D functionality into PDFont subclasses
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/GlyphCache.java (with props)
Removed:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/CIDType0Glyph2D.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/Glyph2D.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
Modified:
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/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/PDVectorFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
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=1755774&r1=1755773&r2=1755774&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 Wed Aug 10 16:06:07 2016
@@ -57,10 +57,9 @@ public class PDCIDFontType0 extends PDCI
private final Map<Integer, Float> glyphHeights = new HashMap<Integer, Float>();
private final boolean isEmbedded;
private final boolean isDamaged;
-
+ private final AffineTransform fontMatrixTransform;
private Float avgWidth = null;
private Matrix fontMatrix;
- private final AffineTransform fontMatrixTransform;
private BoundingBox fontBBox;
/**
@@ -190,16 +189,6 @@ public class PDCIDFontType0 extends PDCI
return fontMatrix;
}
- private class ByteSource implements CFFParser.ByteSource
- {
- @Override
- public byte[] getBytes() throws IOException
- {
- PDStream ff3Stream = getFontDescriptor().getFontFile3();
- return IOUtils.toByteArray(ff3Stream.createInputStream());
- }
- }
-
@Override
public BoundingBox getBoundingBox()
{
@@ -328,6 +317,12 @@ public class PDCIDFontType0 extends PDCI
}
@Override
+ public GeneralPath getNormalizedPath(int code) throws IOException
+ {
+ return getPath(code);
+ }
+
+ @Override
public boolean hasGlyph(int code) throws IOException
{
int cid = codeToCID(code);
@@ -448,4 +443,14 @@ public class PDCIDFontType0 extends PDCI
// todo: not implemented, highly suspect
return 500;
}
+
+ private class ByteSource implements CFFParser.ByteSource
+ {
+ @Override
+ public byte[] getBytes() throws IOException
+ {
+ PDStream ff3Stream = getFontDescriptor().getFontFile3();
+ return IOUtils.toByteArray(ff3Stream.createInputStream());
+ }
+ }
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java Wed Aug 10 16:06:07 2016
@@ -16,6 +16,7 @@
*/
package org.apache.pdfbox.pdmodel.font;
+import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.io.IOException;
import java.io.InputStream;
@@ -447,6 +448,36 @@ public class PDCIDFontType2 extends PDCI
}
}
+ @Override
+ public GeneralPath getNormalizedPath(int code) throws IOException
+ {
+ boolean hasScaling = ttf.getUnitsPerEm() != 1000;
+ float scale = 1000f / ttf.getUnitsPerEm();
+ int gid = codeToGID(code);
+
+ GeneralPath path = getPath(code);
+
+ // Acrobat only draws GID 0 for embedded CIDFonts, see PDFBOX-2372
+ if (gid == 0 && !isEmbedded())
+ {
+ path = null;
+ }
+
+ if (path == null)
+ {
+ // empty glyph (e.g. space, newline)
+ return new GeneralPath();
+ }
+ else
+ {
+ if (hasScaling)
+ {
+ path.transform(AffineTransform.getScaleInstance(scale, scale));
+ }
+ return path;
+ }
+ }
+
@Override
public boolean hasGlyph(int code) throws IOException
{
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java Wed Aug 10 16:06:07 2016
@@ -16,6 +16,7 @@
*/
package org.apache.pdfbox.pdmodel.font;
+import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.io.File;
import java.io.FileInputStream;
@@ -75,6 +76,86 @@ public class PDTrueTypeFont extends PDSi
}
}
+ private final TrueTypeFont ttf;
+ private final boolean isEmbedded;
+ private final boolean isDamaged;
+ private CmapSubtable cmapWinUnicode = null;
+ private CmapSubtable cmapWinSymbol = null;
+ private CmapSubtable cmapMacRoman = null;
+ private boolean cmapInitialized = false;
+ private Map<Integer, Integer> gidToCode; // for embedding
+ private BoundingBox fontBBox;
+
+ /**
+ * Creates a new TrueType font from a Font dictionary.
+ *
+ * @param fontDictionary The font dictionary according to the PDF specification.
+ */
+ public PDTrueTypeFont(COSDictionary fontDictionary) throws IOException
+ {
+ super(fontDictionary);
+
+ TrueTypeFont ttfFont = null;
+ boolean fontIsDamaged = false;
+ if (getFontDescriptor() != null)
+ {
+ PDFontDescriptor fd = super.getFontDescriptor();
+ PDStream ff2Stream = fd.getFontFile2();
+ if (ff2Stream != null)
+ {
+ try
+ {
+ // embedded
+ TTFParser ttfParser = new TTFParser(true);
+ ttfFont = ttfParser.parse(ff2Stream.createInputStream());
+ }
+ catch (NullPointerException e) // TTF parser is buggy
+ {
+ LOG.warn("Could not read embedded TTF for font " + getBaseFont(), e);
+ fontIsDamaged = true;
+ }
+ catch (IOException e)
+ {
+ LOG.warn("Could not read embedded TTF for font " + getBaseFont(), e);
+ fontIsDamaged = true;
+ }
+ }
+ }
+ isEmbedded = ttfFont != null;
+ isDamaged = fontIsDamaged;
+
+ // substitute
+ if (ttfFont == null)
+ {
+ FontMapping<TrueTypeFont> mapping = FontMappers.instance()
+ .getTrueTypeFont(getBaseFont(),
+ getFontDescriptor());
+ ttfFont = mapping.getFont();
+
+ if (mapping.isFallback())
+ {
+ LOG.warn("Using fallback font '" + ttfFont + "' for '" + getBaseFont() + "'");
+ }
+ }
+ ttf = ttfFont;
+ readEncoding();
+ }
+ /**
+ * Creates a new TrueType font for embedding.
+ */
+ private PDTrueTypeFont(PDDocument document, InputStream ttfStream, Encoding encoding)
+ throws IOException
+ {
+ PDTrueTypeFontEmbedder embedder = new PDTrueTypeFontEmbedder(document, dict, ttfStream,
+ encoding);
+ this.encoding = encoding;
+ ttf = embedder.getTrueTypeFont();
+ setFontDescriptor(embedder.getFontDescriptor());
+ isEmbedded = true;
+ isDamaged = false;
+ glyphList = GlyphList.getAdobeGlyphList();
+ }
+
/**
* Loads a TTF to be embedded into a document as a simple font.
*
@@ -110,7 +191,7 @@ public class PDTrueTypeFont extends PDSi
{
return new PDTrueTypeFont(doc, input, encoding);
}
-
+
/**
* Loads a TTF to be embedded into a document as a simple font. Only supports WinAnsiEncoding.
*
@@ -143,72 +224,6 @@ public class PDTrueTypeFont extends PDSi
return new PDTrueTypeFont(doc, input, WinAnsiEncoding.INSTANCE);
}
- private CmapSubtable cmapWinUnicode = null;
- private CmapSubtable cmapWinSymbol = null;
- private CmapSubtable cmapMacRoman = null;
- private boolean cmapInitialized = false;
- private Map<Integer, Integer> gidToCode; // for embedding
-
- private final TrueTypeFont ttf;
- private final boolean isEmbedded;
- private final boolean isDamaged;
- private BoundingBox fontBBox;
-
- /**
- * Creates a new TrueType font from a Font dictionary.
- *
- * @param fontDictionary The font dictionary according to the PDF specification.
- */
- public PDTrueTypeFont(COSDictionary fontDictionary) throws IOException
- {
- super(fontDictionary);
-
- TrueTypeFont ttfFont = null;
- boolean fontIsDamaged = false;
- if (getFontDescriptor() != null)
- {
- PDFontDescriptor fd = super.getFontDescriptor();
- PDStream ff2Stream = fd.getFontFile2();
- if (ff2Stream != null)
- {
- try
- {
- // embedded
- TTFParser ttfParser = new TTFParser(true);
- ttfFont = ttfParser.parse(ff2Stream.createInputStream());
- }
- catch (NullPointerException e) // TTF parser is buggy
- {
- LOG.warn("Could not read embedded TTF for font " + getBaseFont(), e);
- fontIsDamaged = true;
- }
- catch (IOException e)
- {
- LOG.warn("Could not read embedded TTF for font " + getBaseFont(), e);
- fontIsDamaged = true;
- }
- }
- }
- isEmbedded = ttfFont != null;
- isDamaged = fontIsDamaged;
-
- // substitute
- if (ttfFont == null)
- {
- FontMapping<TrueTypeFont> mapping = FontMappers.instance()
- .getTrueTypeFont(getBaseFont(),
- getFontDescriptor());
- ttfFont = mapping.getFont();
-
- if (mapping.isFallback())
- {
- LOG.warn("Using fallback font '" + ttfFont + "' for '" + getBaseFont() + "'");
- }
- }
- ttf = ttfFont;
- readEncoding();
- }
-
/**
* Returns the PostScript name of the font.
*/
@@ -271,22 +286,6 @@ public class PDTrueTypeFont extends PDSi
}
}
- /**
- * Creates a new TrueType font for embedding.
- */
- private PDTrueTypeFont(PDDocument document, InputStream ttfStream, Encoding encoding)
- throws IOException
- {
- PDTrueTypeFontEmbedder embedder = new PDTrueTypeFontEmbedder(document, dict, ttfStream,
- encoding);
- this.encoding = encoding;
- ttf = embedder.getTrueTypeFont();
- setFontDescriptor(embedder.getFontDescriptor());
- isEmbedded = true;
- isDamaged = false;
- glyphList = GlyphList.getAdobeGlyphList();
- }
-
@Override
public int readCode(InputStream in) throws IOException
{
@@ -494,10 +493,40 @@ public class PDTrueTypeFont extends PDSi
}
@Override
+ public GeneralPath getNormalizedPath(int code) throws IOException
+ {
+ boolean hasScaling = ttf.getUnitsPerEm() != 1000;
+ float scale = 1000f / ttf.getUnitsPerEm();
+ int gid = codeToGID(code);
+
+ GeneralPath path = getPath(code);
+
+ // Acrobat only draws GID 0 for embedded or "Standard 14" fonts, see PDFBOX-2372
+ if (gid == 0 && !isEmbedded() && !isStandard14())
+ {
+ path = null;
+ }
+
+ if (path == null)
+ {
+ // empty glyph (e.g. space, newline)
+ return new GeneralPath();
+ }
+ else
+ {
+ if (hasScaling)
+ {
+ path.transform(AffineTransform.getScaleInstance(scale, scale));
+ }
+ return path;
+ }
+ }
+
+ @Override
public boolean hasGlyph(String name) throws IOException
{
int gid = ttf.nameToGID(name);
- return gid != 0;
+ return !(gid == 0 || gid >= ttf.getMaximumProfile().getNumGlyphs());
}
@Override
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java Wed Aug 10 16:06:07 2016
@@ -46,13 +46,47 @@ public class PDType0Font extends PDFont
private static final Log LOG = LogFactory.getLog(PDType0Font.class);
private final PDCIDFont descendantFont;
+ private final Set<Integer> noUnicode = new HashSet<Integer>();
private CMap cMap, cMapUCS2;
private boolean isCMapPredefined;
private boolean isDescendantCJK;
private PDCIDFontType2Embedder embedder;
- private final Set<Integer> noUnicode = new HashSet<Integer>();
/**
+ * Constructor for reading a Type0 font from a PDF file.
+ *
+ * @param fontDictionary The font dictionary according to the PDF specification.
+ * @throws IOException if the descendant font is missing.
+ */
+ public PDType0Font(COSDictionary fontDictionary) throws IOException
+ {
+ super(fontDictionary);
+ COSArray descendantFonts = (COSArray)dict.getDictionaryObject(COSName.DESCENDANT_FONTS);
+ COSDictionary descendantFontDictionary = (COSDictionary) descendantFonts.getObject(0);
+
+ if (descendantFontDictionary == null)
+ {
+ throw new IOException("Missing descendant font dictionary");
+ }
+
+ descendantFont = PDFontFactory.createDescendantFont(descendantFontDictionary, this);
+ readEncoding();
+ fetchCMapUCS2();
+ }
+
+ /**
+ * Private. Creates a new TrueType font for embedding.
+ */
+ private PDType0Font(PDDocument document, TrueTypeFont ttf, boolean embedSubset)
+ throws IOException
+ {
+ embedder = new PDCIDFontType2Embedder(document, dict, ttf, embedSubset, this);
+ descendantFont = embedder.getCIDFont();
+ readEncoding();
+ fetchCMapUCS2();
+ }
+
+ /**
* Loads a TTF to be embedded into a document as a Type 0 font.
*
* @param doc The PDF document that will hold the embedded font.
@@ -108,40 +142,6 @@ public class PDType0Font extends PDFont
return new PDType0Font(doc, ttf, embedSubset);
}
- /**
- * Constructor for reading a Type0 font from a PDF file.
- *
- * @param fontDictionary The font dictionary according to the PDF specification.
- * @throws IOException if the descendant font is missing.
- */
- public PDType0Font(COSDictionary fontDictionary) throws IOException
- {
- super(fontDictionary);
- COSArray descendantFonts = (COSArray)dict.getDictionaryObject(COSName.DESCENDANT_FONTS);
- COSDictionary descendantFontDictionary = (COSDictionary) descendantFonts.getObject(0);
-
- if (descendantFontDictionary == null)
- {
- throw new IOException("Missing descendant font dictionary");
- }
-
- descendantFont = PDFontFactory.createDescendantFont(descendantFontDictionary, this);
- readEncoding();
- fetchCMapUCS2();
- }
-
- /**
- * Private. Creates a new TrueType font for embedding.
- */
- private PDType0Font(PDDocument document, TrueTypeFont ttf, boolean embedSubset)
- throws IOException
- {
- embedder = new PDCIDFontType2Embedder(document, dict, ttf, embedSubset, this);
- descendantFont = embedder.getCIDFont();
- readEncoding();
- fetchCMapUCS2();
- }
-
@Override
public void addToSubset(int codePoint)
{
@@ -506,6 +506,13 @@ public class PDType0Font extends PDFont
return descendantFont.getPath(code);
}
+
+ @Override
+ public GeneralPath getNormalizedPath(int code) throws IOException
+ {
+ return descendantFont.getNormalizedPath(code);
+ }
+
@Override
public boolean hasGlyph(int code) throws IOException
{
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1CFont.java Wed Aug 10 16:06:07 2016
@@ -51,19 +51,18 @@ import static org.apache.pdfbox.pdmodel.
* @author Villu Ruusmann
* @author John Hewson
*/
-public class PDType1CFont extends PDSimpleFont
+public class PDType1CFont extends PDSimpleFont implements PDVectorFont
{
private static final Log LOG = LogFactory.getLog(PDType1CFont.class);
private final Map<String, Float> glyphHeights = new HashMap<String, Float>();
- private Float avgWidth = null;
- private Matrix fontMatrix;
private final AffineTransform fontMatrixTransform;
-
private final CFFType1Font cffFont; // embedded font
private final FontBoxFont genericFont; // embedded or system font for rendering
private final boolean isEmbedded;
private final boolean isDamaged;
+ private Float avgWidth = null;
+ private Matrix fontMatrix;
private BoundingBox fontBBox;
/**
@@ -133,16 +132,6 @@ public class PDType1CFont extends PDSimp
fontMatrixTransform.scale(1000, 1000);
}
- private class ByteSource implements CFFParser.ByteSource
- {
- @Override
- public byte[] getBytes() throws IOException
- {
- PDStream ff3Stream = getFontDescriptor().getFontFile3();
- return IOUtils.toByteArray(ff3Stream.createInputStream());
- }
- }
-
@Override
public FontBoxFont getFontBoxFont()
{
@@ -172,6 +161,32 @@ public class PDType1CFont extends PDSimp
}
@Override
+ public boolean hasGlyph(int code) throws IOException
+ {
+ String name = getEncoding().getName(code);
+ return hasGlyph(name);
+ }
+
+ @Override
+ public GeneralPath getPath(int code) throws IOException
+ {
+ String name = getEncoding().getName(code);
+ return getPath(name);
+ }
+
+ @Override
+ public GeneralPath getNormalizedPath(int code) throws IOException
+ {
+ String name = getEncoding().getName(code);
+ GeneralPath path = getPath(name);
+ if (path == null)
+ {
+ return getPath(".notdef");
+ }
+ return path;
+ }
+
+ @Override
public boolean hasGlyph(String name) throws IOException
{
return genericFont.hasGlyph(name);
@@ -211,7 +226,7 @@ public class PDType1CFont extends PDSimp
{
return getEncoding().getName(code);
}
-
+
@Override
protected Encoding readEncodingFromFont() throws IOException
{
@@ -234,7 +249,7 @@ public class PDType1CFont extends PDSimp
}
}
}
-
+
@Override
public int readCode(InputStream in) throws IOException
{
@@ -331,7 +346,7 @@ public class PDType1CFont extends PDSimp
int code = inverted.get(name);
return new byte[] { (byte)code };
}
-
+
@Override
public float getStringWidth(String string) throws IOException
{
@@ -344,7 +359,7 @@ public class PDType1CFont extends PDSimp
}
return width;
}
-
+
@Override
public float getAverageFontWidth()
{
@@ -371,7 +386,7 @@ public class PDType1CFont extends PDSimp
// todo: not implemented, highly suspect
return 500;
}
-
+
/**
* Maps a PostScript glyph name to the name in the underlying font, for example when
* using a TTF font we might map "W" to "uni0057".
@@ -397,4 +412,14 @@ public class PDType1CFont extends PDSimp
}
return ".notdef";
}
+
+ private class ByteSource implements CFFParser.ByteSource
+ {
+ @Override
+ public byte[] getBytes() throws IOException
+ {
+ PDStream ff3Stream = getFontDescriptor().getFontFile3();
+ return IOUtils.toByteArray(ff3Stream.createInputStream());
+ }
+ }
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType1Font.java Wed Aug 10 16:06:07 2016
@@ -42,38 +42,20 @@ import org.apache.pdfbox.pdmodel.common.
import org.apache.pdfbox.pdmodel.font.encoding.Encoding;
import org.apache.pdfbox.pdmodel.font.encoding.StandardEncoding;
import org.apache.pdfbox.pdmodel.font.encoding.Type1Encoding;
+import org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding;
+import org.apache.pdfbox.pdmodel.font.encoding.ZapfDingbatsEncoding;
import org.apache.pdfbox.util.Matrix;
import static org.apache.pdfbox.pdmodel.font.UniUtil.getUniNameOfCodePoint;
-import org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding;
-import org.apache.pdfbox.pdmodel.font.encoding.ZapfDingbatsEncoding;
/**
* A PostScript Type 1 Font.
*
* @author Ben Litchfield
*/
-public class PDType1Font extends PDSimpleFont
+public class PDType1Font extends PDSimpleFont implements PDVectorFont
{
- private static final Log LOG = LogFactory.getLog(PDType1Font.class);
-
- // alternative names for glyphs which are commonly encountered
- private static final Map<String, String> ALT_NAMES = new HashMap<String, String>();
- static
- {
- ALT_NAMES.put("ff", "f_f");
- ALT_NAMES.put("ffi", "f_f_i");
- ALT_NAMES.put("ffl", "f_f_l");
- ALT_NAMES.put("fi", "f_i");
- ALT_NAMES.put("fl", "f_l");
- ALT_NAMES.put("st", "s_t");
- ALT_NAMES.put("IJ", "I_J");
- ALT_NAMES.put("ij", "i_j");
- ALT_NAMES.put("ellipsis", "elipsis"); // misspelled in ArialMT
- }
- private static final int PFB_START_MARKER = 0x80;
-
// todo: replace with enum? or getters?
public static final PDType1Font TIMES_ROMAN = new PDType1Font("Times-Roman");
public static final PDType1Font TIMES_BOLD = new PDType1Font("Times-Bold");
@@ -89,6 +71,23 @@ public class PDType1Font extends PDSimpl
public static final PDType1Font COURIER_BOLD_OBLIQUE = new PDType1Font("Courier-BoldOblique");
public static final PDType1Font SYMBOL = new PDType1Font("Symbol");
public static final PDType1Font ZAPF_DINGBATS = new PDType1Font("ZapfDingbats");
+ private static final Log LOG = LogFactory.getLog(PDType1Font.class);
+ // alternative names for glyphs which are commonly encountered
+ private static final Map<String, String> ALT_NAMES = new HashMap<String, String>();
+ private static final int PFB_START_MARKER = 0x80;
+
+ static
+ {
+ ALT_NAMES.put("ff", "f_f");
+ ALT_NAMES.put("ffi", "f_f_i");
+ ALT_NAMES.put("ffl", "f_f_l");
+ ALT_NAMES.put("fi", "f_i");
+ ALT_NAMES.put("fl", "f_l");
+ ALT_NAMES.put("st", "s_t");
+ ALT_NAMES.put("IJ", "I_J");
+ ALT_NAMES.put("ij", "i_j");
+ ALT_NAMES.put("ellipsis", "elipsis"); // misspelled in ArialMT
+ }
/**
* embedded font.
@@ -102,14 +101,13 @@ public class PDType1Font extends PDSimpl
private final boolean isEmbedded;
private final boolean isDamaged;
- private Matrix fontMatrix;
private final AffineTransform fontMatrixTransform;
- private BoundingBox fontBBox;
-
/**
* to improve encoding speed.
*/
private final Map <Integer,byte[]> codeToBytesMap;
+ private Matrix fontMatrix;
+ private BoundingBox fontBBox;
/**
* Creates a Type 1 standard 14 font for embedding.
@@ -562,12 +560,37 @@ public class PDType1Font extends PDSimpl
}
@Override
+ public GeneralPath getPath(int code) throws IOException
+ {
+ String name = getEncoding().getName(code);
+ return getPath(name);
+ }
+
+ @Override
+ public GeneralPath getNormalizedPath(int code) throws IOException
+ {
+ String name = getEncoding().getName(code);
+ GeneralPath path = getPath(name);
+ if (path == null)
+ {
+ return getPath(".notdef");
+ }
+ return path;
+ }
+
+ @Override
public boolean hasGlyph(String name) throws IOException
{
return genericFont.hasGlyph(getNameInFont(name));
}
@Override
+ public boolean hasGlyph(int code) throws IOException
+ {
+ return !getEncoding().getName(code).equals(".notdef");
+ }
+
+ @Override
public final Matrix getFontMatrix()
{
if (fontMatrix == null)
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDVectorFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDVectorFont.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDVectorFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDVectorFont.java Wed Aug 10 16:06:07 2016
@@ -34,6 +34,16 @@ public interface PDVectorFont
* @throws java.io.IOException if the font could not be read
*/
GeneralPath getPath(int code) throws IOException;
+
+ /**
+ * Returns the normalized glyph path for the given character code. The resulting path is
+ * normalized to the PostScript 1000 unit square, and fallback glyphs are returned
+ * where appropriate, e.g. for missing glyphs.
+ *
+ * @param code character code
+ * @throws java.io.IOException if the font could not be read
+ */
+ GeneralPath getNormalizedPath(int code) throws IOException;
/**
* Returns true if this font contains a glyph for the given character code.
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/GlyphCache.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/GlyphCache.java?rev=1755774&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/GlyphCache.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/GlyphCache.java Wed Aug 10 16:06:07 2016
@@ -0,0 +1,87 @@
+/*
+ * 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.rendering;
+
+import java.awt.geom.GeneralPath;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.pdmodel.font.PDVectorFont;
+
+/**
+ * A simple glyph outline cache.
+ *
+ * @author John Hewson
+ */
+final class GlyphCache
+{
+ private static final Log LOG = LogFactory.getLog(GlyphCache.class);
+
+ private final PDVectorFont font;
+ private final Map<Integer, GeneralPath> cache = new HashMap<Integer, GeneralPath>();
+
+ public GlyphCache(PDVectorFont font)
+ {
+ this.font = font;
+ }
+
+ public void put(int code, GeneralPath path)
+ {
+ cache.put(code, path);
+ }
+
+ public GeneralPath getPathForCharacterCode(int code)
+ {
+ GeneralPath path = cache.get(code);
+ if (path != null)
+ {
+ return path;
+ }
+
+ try
+ {
+ if (!font.hasGlyph(code))
+ {
+ String fontName = ((PDFont)font).getName();
+ if (font instanceof PDType0Font)
+ {
+ int cid = ((PDType0Font) font).codeToCID(code);
+ String cidHex = String.format("%04x", cid);
+ LOG.warn("No glyph for " + code + " (CID " + cidHex + ") in font " + fontName);
+ }
+ else
+ {
+ LOG.warn("No glyph for " + code + " in font " + fontName);
+ }
+ }
+
+ path = font.getNormalizedPath(code);
+ cache.put(code, path);
+ return path;
+ }
+ catch (IOException e)
+ {
+ // todo: escalate this error?
+ LOG.error("Glyph rendering failed", e);
+ return new GeneralPath();
+ }
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/GlyphCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java?rev=1755774&r1=1755773&r2=1755774&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/rendering/PageDrawer.java Wed Aug 10 16:06:07 2016
@@ -47,13 +47,8 @@ import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSNumber;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.common.function.PDFunction;
-import org.apache.pdfbox.pdmodel.font.PDCIDFontType0;
-import org.apache.pdfbox.pdmodel.font.PDCIDFontType2;
import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
-import org.apache.pdfbox.pdmodel.font.PDType0Font;
-import org.apache.pdfbox.pdmodel.font.PDType1CFont;
-import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.pdmodel.font.PDVectorFont;
import org.apache.pdfbox.pdmodel.graphics.PDLineDashPattern;
import org.apache.pdfbox.pdmodel.graphics.blend.SoftMaskPaint;
import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
@@ -92,26 +87,21 @@ public class PageDrawer extends PDFGraph
// parent document renderer - note: this is needed for not-yet-implemented resource caching
private final PDFRenderer renderer;
-
+ // glyph caches
+ private final Map<PDFont, GlyphCache> glyphCaches = new HashMap<PDFont, GlyphCache>();
// the graphics device to draw to, xform is the initial transform of the device (i.e. DPI)
private Graphics2D graphics;
private AffineTransform xform;
-
// the page box to draw (usually the crop box but may be another)
private PDRectangle pageSize;
-
// clipping winding rule used for the clipping path
private int clipWindingRule = -1;
private GeneralPath linePath = new GeneralPath();
-
// last clipping path
private Area lastClip;
-
// buffered clipping area for text being drawn
private Area textClippingArea;
-
- // glyph cache
- private final Map<PDFont, Glyph2D> fontGlyph2D = new HashMap<PDFont, Glyph2D>();
+
/**
* Constructor.
@@ -330,27 +320,41 @@ public class PageDrawer extends PDFGraph
AffineTransform at = textRenderingMatrix.createAffineTransform();
at.concatenate(font.getFontMatrix().createAffineTransform());
- Glyph2D glyph2D = createGlyph2D(font);
- drawGlyph2D(glyph2D, font, code, displacement, at);
+ // create cache if it does not exist
+ PDVectorFont vectorFont = ((PDVectorFont)font);
+ GlyphCache cache = glyphCaches.get(font);
+ if (cache == null)
+ {
+ cache = new GlyphCache(vectorFont);
+ glyphCaches.put(font, cache);
+ }
+
+ // cache glyph path if is not already cache
+ GeneralPath path = cache.getPathForCharacterCode(code);
+ if (path == null)
+ {
+ path = vectorFont.getNormalizedPath(code);
+ cache.put(code, path);
+ }
+
+ drawGlyph(path, font, code, displacement, at);
}
/**
* Render the font using the Glyph2D interface.
*
- * @param glyph2D the Glyph2D implementation provided a GeneralPath for each glyph
+ * @param path the Glyph2D implementation provided a GeneralPath for each glyph
* @param font the font
* @param code character code
* @param displacement the glyph's displacement (advance)
* @param at the transformation
* @throws IOException if something went wrong
*/
- private void drawGlyph2D(Glyph2D glyph2D, PDFont font, int code, Vector displacement,
- AffineTransform at) throws IOException
+ private void drawGlyph(GeneralPath path, PDFont font, int code, Vector displacement, AffineTransform at) throws IOException
{
PDGraphicsState state = getGraphicsState();
RenderingMode renderingMode = state.getTextState().getRenderingMode();
-
- GeneralPath path = glyph2D.getPathForCharacterCode(code);
+
if (path != null)
{
// stretch non-embedded glyph if it does not match the width contained in the PDF
@@ -391,72 +395,7 @@ public class PageDrawer extends PDFGraph
}
}
}
-
- /**
- * Provide a Glyph2D for the given font.
- *
- * @param font the font
- * @return the implementation of the Glyph2D interface for the given font
- * @throws IOException if something went wrong
- */
- private Glyph2D createGlyph2D(PDFont font) throws IOException
- {
- Glyph2D glyph2D = fontGlyph2D.get(font);
- // Is there already a Glyph2D for the given font?
- if (glyph2D != null)
- {
- return glyph2D;
- }
-
- if (font instanceof PDTrueTypeFont)
- {
- PDTrueTypeFont ttfFont = (PDTrueTypeFont)font;
- glyph2D = new TTFGlyph2D(ttfFont); // TTF is never null
- }
- else if (font instanceof PDType1Font)
- {
- PDType1Font pdType1Font = (PDType1Font)font;
- glyph2D = new Type1Glyph2D(pdType1Font); // T1 is never null
- }
- else if (font instanceof PDType1CFont)
- {
- PDType1CFont type1CFont = (PDType1CFont)font;
- glyph2D = new Type1Glyph2D(type1CFont);
- }
- else if (font instanceof PDType0Font)
- {
- PDType0Font type0Font = (PDType0Font) font;
- if (type0Font.getDescendantFont() instanceof PDCIDFontType2)
- {
- glyph2D = new TTFGlyph2D(type0Font); // TTF is never null
- }
- else if (type0Font.getDescendantFont() instanceof PDCIDFontType0)
- {
- // a Type0 CIDFont contains CFF font
- PDCIDFontType0 cidType0Font = (PDCIDFontType0)type0Font.getDescendantFont();
- glyph2D = new CIDType0Glyph2D(cidType0Font); // todo: could be null (need incorporate fallback)
- }
- }
- else
- {
- throw new IllegalStateException("Bad font type: " + font.getClass().getSimpleName());
- }
-
- // cache the Glyph2D instance
- if (glyph2D != null)
- {
- fontGlyph2D.put(font, glyph2D);
- }
-
- if (glyph2D == null)
- {
- // todo: make sure this never happens
- throw new UnsupportedOperationException("No font for " + font.getName());
- }
-
- return glyph2D;
- }
-
+
@Override
public void appendRectangle(Point2D p0, Point2D p1, Point2D p2, Point2D p3)
{
@@ -968,14 +907,6 @@ public class PageDrawer extends PDFGraph
}
}
- private static class AnnotationBorder
- {
- private float[] dashArray = null;
- private boolean underline = false;
- private float width = 0;
- private PDColor color;
- }
-
// return border info. BorderStyle must be provided as parameter because
// method is not available in the base class
private AnnotationBorder getAnnotationBorder(PDAnnotation annotation,
@@ -1034,7 +965,7 @@ public class PageDrawer extends PDFGraph
}
return ab;
}
-
+
private void drawAnnotationLinkBorder(PDAnnotationLink link) throws IOException
{
AnnotationBorder ab = getAnnotationBorder(link, link.getBorderStyle());
@@ -1157,6 +1088,14 @@ public class PageDrawer extends PDFGraph
graphics.setTransform(prev);
}
+ private static class AnnotationBorder
+ {
+ private float[] dashArray = null;
+ private boolean underline = false;
+ private float width = 0;
+ private PDColor color;
+ }
+
/**
* Transparency group.
**/