You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by le...@apache.org on 2013/07/24 21:24:43 UTC
svn commit: r1506667 [1/2] - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox: pdfviewer/
pdfviewer/font/ pdmodel/font/ util/
Author: lehmi
Date: Wed Jul 24 19:24:43 2013
New Revision: 1506667
URL: http://svn.apache.org/r1506667
Log:
PDFBOX-490: added rendering for TTF fonts
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/Glyph2D.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java (with props)
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/PageDrawer.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Font.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/PDFStreamEngine.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/PageDrawer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/PageDrawer.java?rev=1506667&r1=1506666&r2=1506667&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/PageDrawer.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/PageDrawer.java Wed Jul 24 19:24:43 2013
@@ -34,13 +34,19 @@ import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSStream;
+import org.apache.pdfbox.pdfviewer.font.Glyph2D;
+import org.apache.pdfbox.pdfviewer.font.TTFGlyph2D;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.common.PDMatrix;
@@ -48,6 +54,7 @@ import org.apache.pdfbox.pdmodel.common.
import org.apache.pdfbox.pdmodel.font.PDCIDFontType2Font;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDSimpleFont;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType3Font;
import org.apache.pdfbox.pdmodel.graphics.PDGraphicsState;
@@ -70,7 +77,7 @@ import org.apache.pdfbox.util.TextPositi
* This will paint a page in a PDF document to a graphics context.
*
* @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.22 $
+ *
*/
public class PageDrawer extends PDFStreamEngine
{
@@ -98,11 +105,12 @@ public class PageDrawer extends PDFStrea
private GeneralPath linePath = new GeneralPath();
+ private HashMap<PDFont, Glyph2D> fontGlyph2D = new HashMap<PDFont, Glyph2D>();
+
/**
* Default constructor, loads properties from file.
*
- * @throws IOException
- * If there is an error loading properties from the file.
+ * @throws IOException If there is an error loading properties from the file.
*/
public PageDrawer() throws IOException
{
@@ -112,15 +120,11 @@ public class PageDrawer extends PDFStrea
/**
* This will draw the page to the requested context.
*
- * @param g
- * The graphics context to draw onto.
- * @param p
- * The page to draw.
- * @param pageDimension
- * The size of the page to draw.
+ * @param g The graphics context to draw onto.
+ * @param p The page to draw.
+ * @param pageDimension The size of the page to draw.
*
- * @throws IOException
- * If there is an IO error while drawing the page.
+ * @throws IOException If there is an IO error while drawing the page.
*/
public void drawPage(Graphics g, PDPage p, Dimension pageDimension) throws IOException
{
@@ -170,14 +174,33 @@ public class PageDrawer extends PDFStrea
}
}
}
+ }
+ /**
+ * Remove all cached resources.
+ */
+ public void dispose()
+ {
+ if (fontGlyph2D != null)
+ {
+ Iterator<Glyph2D> iter = fontGlyph2D.values().iterator();
+ while (iter.hasNext())
+ {
+ iter.next().dispose();
+ }
+ fontGlyph2D.clear();
+ fontGlyph2D = null;
+ }
+ graphics = null;
+ linePath = null;
+ page = null;
+ pageSize = null;
}
/**
* You should override this method if you want to perform an action when a text is being processed.
*
- * @param text
- * The text to process
+ * @param text The text to process
*/
protected void processTextPosition(TextPosition text)
{
@@ -254,11 +277,22 @@ public class PageDrawer extends PDFStrea
// use different methods to draw the string
if (font.isType3Font())
{
- drawType3String((PDType3Font) font, text.getCharacter(), text.getCodePoints(), at);
+ // Type3 fonts are using streams for each character
+ drawType3String((PDType3Font) font, text.getCharacter(), at);
}
else
{
- drawString((PDSimpleFont) font, text.getCharacter(), text.getCodePoints(), graphics, at, x, y);
+ Glyph2D glyph2D = createGlyph2D(font);
+ if (glyph2D != null)
+ {
+ // Let PDFBox render the font if supported
+ drawGlyph2D(glyph2D, text.getCodePoints(), graphics, at, x, y);
+ }
+ else
+ {
+ // Use AWT to render the font
+ drawString((PDSimpleFont) font, text.getCharacter(), text.getCodePoints(), graphics, at, x, y);
+ }
}
}
catch (IOException io)
@@ -267,9 +301,74 @@ public class PageDrawer extends PDFStrea
}
}
- private void drawType3String(PDType3Font font, String string, int[] codePoints, AffineTransform at)
+ /**
+ * Render the font using the Glyph2d interface.
+ *
+ * @param glyph2D the Glyph2D implementation provided a GeneralPath for each glyph
+ * @param codePoints the string to be rendered
+ * @param graphics the graphics object to be used for rendering
+ * @param at the transformation
+ * @param x the x coordinate of the text
+ * @param y the y coordinate of the text
+ * @throws IOException if something went wrong
+ */
+ private void drawGlyph2D(Glyph2D glyph2D, int[] codePoints, Graphics graphics, AffineTransform at, float x, float y)
throws IOException
{
+ Graphics2D g2d = (Graphics2D) graphics;
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ for (int i = 0; i < codePoints.length; i++)
+ {
+ if (!at.isIdentity())
+ {
+ try
+ {
+ AffineTransform atInv = at.createInverse();
+ // do only apply the size of the transform, rotation will be realized by rotating the graphics,
+ // otherwise the hp printers will not render the font
+ // apply the transformation to the graphics, which should be the same as applying the
+ // transformation itself to the text
+ g2d.transform(at);
+ // translate the coordinates
+ Point2D.Float newXy = new Point2D.Float(x, y);
+ atInv.transform(new Point2D.Float(x, y), newXy);
+
+ GeneralPath path = glyph2D.getPathForCharactercode(codePoints[i]);
+ if (path != null)
+ {
+ g2d.translate(newXy.getX(), newXy.getY());
+ g2d.fill(path);
+ g2d.translate(-newXy.getX(), -newXy.getY());
+ }
+ // restore the original transformation
+ g2d.transform(atInv);
+ }
+ catch (NoninvertibleTransformException e)
+ {
+ LOG.error("Error in " + getClass().getName() + ".drawGlyph2D", e);
+ }
+ }
+ else
+ {
+ GeneralPath path = glyph2D.getPathForCharactercode(codePoints[i]);
+ if (path != null)
+ {
+ g2d.draw(path);
+ }
+ }
+ }
+ }
+
+ /**
+ * Render the text using a type 3 font.
+ *
+ * @param font the type3 font
+ * @param string the string to be rendered
+ * @param at the transformation
+ * @throws IOException if something went wrong
+ */
+ private void drawType3String(PDType3Font font, String string, AffineTransform at) throws IOException
+ {
int stringLength = string.length();
for (int i = 0; i < stringLength; i++)
{
@@ -297,23 +396,15 @@ public class PageDrawer extends PDFStrea
/**
* This will draw a string on a canvas using the font.
*
- * @param font
- * the font to be used to draw the string
- * @param string
- * The string to draw.
- * @param codePoints
- * The codePoints of the given string.
- * @param g
- * The graphics to draw onto.
- * @param at
- * The transformation matrix with all information for scaling and shearing of the font.
- * @param x
- * The x coordinate to draw at.
- * @param y
- * The y coordinate to draw at.
+ * @param font the font to be used to draw the string
+ * @param string The string to draw.
+ * @param codePoints The codePoints of the given string.
+ * @param g The graphics to draw onto.
+ * @param at The transformation matrix with all information for scaling and shearing of the font.
+ * @param x The x coordinate to draw at.
+ * @param y The y coordinate to draw at.
*
- * @throws IOException
- * If there is an error drawing the specific string.
+ * @throws IOException If there is an error drawing the specific string.
*/
private void drawString(PDSimpleFont font, String string, int[] codePoints, Graphics g, AffineTransform at,
float x, float y) throws IOException
@@ -395,6 +486,86 @@ public class PageDrawer extends PDFStrea
}
/**
+ * Provide a Glyh2d for the given font if supported.
+ *
+ * @param font the font
+ * @return the implementation of the Glyph2D interface for the given font if supported
+ * @throws IOException if something went wrong
+ */
+ private Glyph2D createGlyph2D(PDFont font) throws IOException
+ {
+ Glyph2D glyph2D = null;
+ // Is there already a Glyph2D for the given font?
+ if (fontGlyph2D.containsKey(font))
+ {
+ glyph2D = fontGlyph2D.get(font);
+ }
+ else
+ {
+ // check if the given font is supported
+
+ // TTF fonts are supported
+ if (font instanceof PDTrueTypeFont)
+ {
+ PDTrueTypeFont ttfFont = (PDTrueTypeFont) font;
+ // does the font have an optional toUnicode mapping
+ CMap toUnicodeCMap = null;
+ if (ttfFont.hasToUnicode())
+ {
+ toUnicodeCMap = ttfFont.getToUnicodeCMap();
+ }
+ // get the true type font raw data
+ TrueTypeFont ttf = ttfFont.getTTFFont();
+ if (ttf != null)
+ {
+ glyph2D = new TTFGlyph2D(ttf, font.getBaseFont(), ttfFont.isSymbolicFont(), toUnicodeCMap);
+ }
+ // cache the Glyph2D instance
+ if (glyph2D != null)
+ {
+ fontGlyph2D.put(font, glyph2D);
+ }
+ }
+ else if (font instanceof PDType0Font)
+ {
+ PDType0Font type0Font = (PDType0Font) font;
+ CMap toUnicodeCMap = null;
+ if (type0Font.hasToUnicode())
+ {
+ toUnicodeCMap = type0Font.getToUnicodeCMap();
+ }
+ if (type0Font.getDescendantFont() instanceof PDCIDFontType2Font)
+ {
+ // a CIDFontType2Font contains TTF font
+ PDCIDFontType2Font cidType2Font = (PDCIDFontType2Font) type0Font.getDescendantFont();
+ // get the true type font raw data
+ TrueTypeFont ttf = cidType2Font.getTTFFont();
+ if (ttf != null)
+ {
+ if (cidType2Font.hasCIDToGIDMap())
+ {
+ glyph2D = new TTFGlyph2D(ttf, font.getBaseFont(), cidType2Font.isSymbolicFont(),
+ toUnicodeCMap, cidType2Font.getCID2GID());
+ }
+ else
+ {
+ glyph2D = new TTFGlyph2D(ttf, font.getBaseFont(), cidType2Font.isSymbolicFont(),
+ toUnicodeCMap);
+ }
+ }
+ // cache the Glyph2D instance
+ if (glyph2D != null)
+ {
+ fontGlyph2D.put(font, glyph2D);
+ }
+
+ }
+ }
+ }
+ return glyph2D;
+ }
+
+ /**
* Get the graphics that we are currently drawing on.
*
* @return The graphics we are drawing on.
@@ -427,8 +598,7 @@ public class PageDrawer extends PDFStrea
/**
* Fix the y coordinate.
*
- * @param y
- * The y coordinate.
+ * @param y The y coordinate.
* @return The updated y coordinate.
*/
public double fixY(double y)
@@ -449,8 +619,7 @@ public class PageDrawer extends PDFStrea
/**
* Set the line path to draw.
*
- * @param newLinePath
- * Set the line path to draw.
+ * @param newLinePath Set the line path to draw.
*/
public void setLinePath(GeneralPath newLinePath)
{
@@ -467,11 +636,9 @@ public class PageDrawer extends PDFStrea
/**
* Fill the path.
*
- * @param windingRule
- * The winding rule this path will use.
+ * @param windingRule The winding rule this path will use.
*
- * @throws IOException
- * If there is an IO error while filling the path.
+ * @throws IOException If there is an IO error while filling the path.
*/
public void fillPath(int windingRule) throws IOException
{
@@ -498,8 +665,7 @@ public class PageDrawer extends PDFStrea
/**
* This will set the current stroke.
*
- * @param newStroke
- * The current stroke.
+ * @param newStroke The current stroke.
*
*/
public void setStroke(BasicStroke newStroke)
@@ -521,8 +687,7 @@ public class PageDrawer extends PDFStrea
/**
* Stroke the path.
*
- * @throws IOException
- * If there is an IO error while stroking the path.
+ * @throws IOException If there is an IO error while stroking the path.
*/
public void strokePath() throws IOException
{
@@ -549,10 +714,8 @@ public class PageDrawer extends PDFStrea
/**
* Called when the color changed.
*
- * @param bStroking
- * true for the stroking color, false for the non-stroking color
- * @throws IOException
- * if an I/O error occurs
+ * @param bStroking true for the stroking color, false for the non-stroking color
+ * @throws IOException if an I/O error occurs
*/
@Deprecated
public void colorChanged(boolean bStroking) throws IOException
@@ -564,10 +727,8 @@ public class PageDrawer extends PDFStrea
/**
* use the current transformation matrix to transform a single point.
*
- * @param x
- * x-coordinate of the point to be transform
- * @param y
- * y-coordinate of the point to be transform
+ * @param x x-coordinate of the point to be transform
+ * @param y y-coordinate of the point to be transform
* @return the transformed coordinates as Point2D.Double
*/
public java.awt.geom.Point2D.Double transformedPoint(double x, double y)
@@ -582,8 +743,7 @@ public class PageDrawer extends PDFStrea
/**
* Set the clipping Path.
*
- * @param windingRule
- * The winding rule this path will use.
+ * @param windingRule The winding rule this path will use.
*
* @deprecated use {@link #setClippingWindingRule(int)} instead
*
@@ -596,8 +756,7 @@ public class PageDrawer extends PDFStrea
/**
* Set the clipping winding rule.
*
- * @param windingRule
- * The winding rule which will be used for clipping.
+ * @param windingRule The winding rule which will be used for clipping.
*
*/
public void setClippingWindingRule(int windingRule)
@@ -637,10 +796,8 @@ public class PageDrawer extends PDFStrea
* Draw the AWT image. Called by Invoke. Moved into PageDrawer so that Invoke doesn't have to reach in here for
* Graphics as that breaks extensibility.
*
- * @param awtImage
- * The image to draw.
- * @param at
- * The transformation to use when drawing.
+ * @param awtImage The image to draw.
+ * @param at The transformation to use when drawing.
*
*/
public void drawImage(Image awtImage, AffineTransform at)
@@ -653,11 +810,9 @@ public class PageDrawer extends PDFStrea
/**
* Fill with Shading. Called by SHFill operator.
*
- * @param ShadingName
- * The name of the Shading Dictionary to use for this fill instruction.
+ * @param ShadingName The name of the Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*
* @deprecated use {@link #shFill(COSName)) instead.
*/
@@ -669,11 +824,9 @@ public class PageDrawer extends PDFStrea
/**
* Fill with Shading. Called by SHFill operator.
*
- * @param shadingName
- * The name of the Shading Dictionary to use for this fill instruction.
+ * @param shadingName The name of the Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the clipping area.
+ * @throws IOException If there is an IO error while shade-filling the clipping area.
*/
public void shFill(COSName shadingName) throws IOException
{
@@ -714,11 +867,9 @@ public class PageDrawer extends PDFStrea
* Fill with a Function-based gradient / shading. If extending the class, override this and its siblings, not the
* public SHFill method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_Function(PDShading Shading) throws IOException
{
@@ -728,11 +879,9 @@ public class PageDrawer extends PDFStrea
/**
* Fill with an Axial Shading. If extending the class, override this and its siblings, not the public SHFill method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_Axial(PDShading Shading) throws IOException
{
@@ -744,11 +893,9 @@ public class PageDrawer extends PDFStrea
* Fill with a Radial gradient / shading. If extending the class, override this and its siblings, not the public
* SHFill method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_Radial(PDShading Shading) throws IOException
{
@@ -759,11 +906,9 @@ public class PageDrawer extends PDFStrea
* Fill with a Free-form Gourad-shaded triangle mesh. If extending the class, override this and its siblings, not
* the public SHFill method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_FreeGourad(PDShading Shading) throws IOException
{
@@ -774,11 +919,9 @@ public class PageDrawer extends PDFStrea
* Fill with a Lattice-form Gourad-shaded triangle mesh. If extending the class, override this and its siblings, not
* the public SHFill method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_LatticeGourad(PDShading Shading) throws IOException
{
@@ -789,11 +932,9 @@ public class PageDrawer extends PDFStrea
* Fill with a Coons patch mesh If extending the class, override this and its siblings, not the public SHFill
* method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_CoonsPatch(PDShading Shading) throws IOException
{
@@ -804,11 +945,9 @@ public class PageDrawer extends PDFStrea
* Fill with a Tensor-product patch mesh. If extending the class, override this and its siblings, not the public
* SHFill method.
*
- * @param Shading
- * The Shading Dictionary to use for this fill instruction.
+ * @param Shading The Shading Dictionary to use for this fill instruction.
*
- * @throws IOException
- * If there is an IO error while shade-filling the path/clipping area.
+ * @throws IOException If there is an IO error while shade-filling the path/clipping area.
*/
protected void SHFill_TensorPatch(PDShading Shading) throws IOException
{
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/Glyph2D.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/Glyph2D.java?rev=1506667&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/Glyph2D.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/Glyph2D.java Wed Jul 24 19:24:43 2013
@@ -0,0 +1,62 @@
+/*
+
+ 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.pdfviewer.font;
+
+import java.awt.geom.GeneralPath;
+
+/**
+ * This interface is implemented by several font specific classes which is called to get the general path of a single
+ * glyph of the represented font most likely to render it.
+ *
+ */
+public interface Glyph2D
+{
+
+ /**
+ * Returns the path describing the glyph for the given glyphId.
+ *
+ * @param glyphId the glyphId
+ *
+ * @return the GeneralPath for the given glyphId
+ */
+ public GeneralPath getPathForGlyphId(int glyphId);
+
+ /**
+ * Returns the path describing the glyph for the given character code.
+ *
+ * @param code the character code
+ *
+ * @return the GeneralPath for the given character code
+ */
+ public GeneralPath getPathForCharactercode(int code);
+
+ /**
+ * Returns the number of glyphs provided by the given font.
+ *
+ * @return the number of glyphs
+ */
+ public int getNumberOfGlyphs();
+
+ /**
+ * Remove all cached resources.
+ */
+ public void dispose();
+
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/Glyph2D.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java?rev=1506667&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java Wed Jul 24 19:24:43 2013
@@ -0,0 +1,434 @@
+/*
+
+ 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.pdfviewer.font;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.util.HashMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.ttf.CMAPEncodingEntry;
+import org.apache.fontbox.ttf.CMAPTable;
+import org.apache.fontbox.ttf.GlyfDescript;
+import org.apache.fontbox.ttf.GlyphData;
+import org.apache.fontbox.ttf.GlyphDescription;
+import org.apache.fontbox.ttf.HeaderTable;
+import org.apache.fontbox.ttf.TrueTypeFont;
+
+/**
+ * This class provides a glyph to GeneralPath conversion for true type fonts.
+ *
+ * This class is based on code from Apache Batik a subproject of Apache XMLGraphics. see
+ * http://xmlgraphics.apache.org/batik/ for further details.
+ */
+public class TTFGlyph2D implements Glyph2D
+{
+
+ /**
+ * Log instance.
+ */
+ private static final Log LOG = LogFactory.getLog(TTFGlyph2D.class);
+
+ private TrueTypeFont font;
+ private String name;
+ private float scale = 0.001f;
+ private CMAPEncodingEntry cmapMiscUnicode = null;
+ private CMAPEncodingEntry cmapWinUnicode = null;
+ private CMAPEncodingEntry cmapWinSymbol = null;
+ private CMAPEncodingEntry cmapMacintoshSymbol = null;
+ private boolean isSymbol = false;
+ private HashMap<Integer, GeneralPath> glyphs = new HashMap<Integer, GeneralPath>();
+ private CMap toUnicode = null;
+ private int[] cid2gid = null;
+
+ /**
+ * Constructor.
+ *
+ * @param trueTypeFont the true type font containing the glyphs
+ * @param fontname the name of the given font
+ * @param symbolFont indicates if the font is a symbolic font
+ *
+ */
+ public TTFGlyph2D(TrueTypeFont trueTypeFont, String fontname, boolean symbolFont)
+ {
+ this(trueTypeFont, fontname, symbolFont, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param trueTypeFont the true type font containing the glyphs
+ * @param fontname the name of the given font
+ * @param symbolFont indicates if the font is a symbolic font
+ * @param toUnicodeCMap an optional toUnicode mapping
+ *
+ */
+ public TTFGlyph2D(TrueTypeFont trueTypeFont, String fontname, boolean symbolFont, CMap toUnicodeCMap)
+ {
+ this(trueTypeFont, fontname, symbolFont, toUnicodeCMap, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param trueTypeFont the true type font containing the glyphs
+ * @param fontname the name of the given font
+ * @param symbolFont indicates if the font is a symbolic font
+ * @param toUnicodeCMap an optional toUnicode mapping
+ * @param cid2gidMapping an optional CID2GIC mapping
+ *
+ */
+ public TTFGlyph2D(TrueTypeFont trueTypeFont, String fontname, boolean symbolFont, CMap toUnicodeCMap,
+ int[] cid2gidMapping)
+ {
+ font = trueTypeFont;
+ isSymbol = symbolFont;
+ name = fontname;
+ toUnicode = toUnicodeCMap;
+ cid2gid = cid2gidMapping;
+ // get units per em, which is used as scaling factor
+ HeaderTable header = font.getHeader();
+ if (header != null)
+ {
+ scale = 1f / header.getUnitsPerEm();
+ }
+ CMAPTable cmapTable = font.getCMAP();
+ if (cmapTable != null)
+ {
+ // get all relevant CMaps
+ CMAPEncodingEntry[] cmaps = cmapTable.getCmaps();
+ for (int i = 0; i < cmaps.length; i++)
+ {
+ if (CMAPTable.PLATFORM_WINDOWS == cmaps[i].getPlatformId())
+ {
+ if (CMAPTable.ENCODING_UNICODE == cmaps[i].getPlatformEncodingId())
+ {
+ cmapWinUnicode = cmaps[i];
+ }
+ else if (CMAPTable.ENCODING_SYMBOL == cmaps[i].getPlatformEncodingId())
+ {
+ cmapWinSymbol = cmaps[i];
+ }
+ }
+ else if (CMAPTable.PLATFORM_MACINTOSH == cmaps[i].getPlatformId())
+ {
+ if (CMAPTable.ENCODING_SYMBOL == cmaps[i].getPlatformEncodingId())
+ {
+ cmapMacintoshSymbol = cmaps[i];
+ }
+ }
+ else if (CMAPTable.PLATFORM_MISC == cmaps[i].getPlatformId())
+ {
+ if (CMAPTable.ENCODING_UNICODE == cmaps[i].getPlatformEncodingId())
+ {
+ cmapMiscUnicode = cmaps[i];
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Set the points of a glyph from the GlyphDescription.
+ */
+ private Point[] describe(GlyphDescription gd)
+ {
+ int endPtIndex = 0;
+ Point[] points = new Point[gd.getPointCount()];
+ for (int i = 0; i < gd.getPointCount(); i++)
+ {
+ boolean endPt = gd.getEndPtOfContours(endPtIndex) == i;
+ if (endPt)
+ {
+ endPtIndex++;
+ }
+ points[i] = new Point(gd.getXCoordinate(i), -gd.getYCoordinate(i),
+ (gd.getFlags(i) & GlyfDescript.ON_CURVE) != 0, endPt);
+ }
+ return points;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public GeneralPath getPathForGlyphId(int glyphId)
+ {
+ GeneralPath glyphPath = null;
+ if (glyphs.containsKey(glyphId))
+ {
+ glyphPath = glyphs.get(glyphId);
+ }
+ else
+ {
+ GlyphData[] glyphData = font.getGlyph().getGlyphs();
+ if (glyphId < glyphData.length && glyphData[glyphId] != null)
+ {
+ GlyphData glyph = glyphData[glyphId];
+ GlyphDescription gd = glyph.getDescription();
+ Point[] points = describe(gd);
+ glyphPath = calculatePath(points);
+ AffineTransform atScale = AffineTransform.getScaleInstance(scale, scale);
+ glyphPath.transform(atScale);
+ glyphs.put(glyphId, glyphPath);
+ }
+ else
+ {
+ LOG.debug(name + ": Glyph not found:" + glyphId);
+ }
+ }
+ return glyphPath != null ? (GeneralPath) glyphPath.clone() : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public GeneralPath getPathForCharactercode(int code)
+ {
+ if (isSymbol)
+ {
+ // symbol fonts
+ if (cmapWinSymbol != null)
+ {
+ int glyphId = cmapWinSymbol.getGlyphId(code);
+ // microsoft sometimes uses PUA unicode values for symbol fonts
+ // the range 0x0020 - 0x00FF maps to 0xF020 - 0xF0FF
+ if (glyphId == 0 && code >= 0x0020 && code <= 0x00FF)
+ {
+ glyphId = cmapWinSymbol.getGlyphId(code + 0xF000);
+ }
+ return getPathForGlyphId(glyphId);
+ }
+ }
+ else
+ {
+ // non symbol fonts
+ // Unicode mapping
+ if (cmapWinUnicode != null)
+ {
+ return getPathForGlyphId(cmapWinUnicode.getGlyphId(code));
+ }
+ // some fonts provide a custom CMap
+ if (cmapMiscUnicode != null)
+ {
+ int unicode = code;
+ // map the given code to a valid unicode value, if necessary
+ if (toUnicode != null)
+ {
+ String unicodeStr = toUnicode.lookup(code, 1);
+ if (unicodeStr != null)
+ {
+ unicode = unicodeStr.codePointAt(0);
+ }
+ }
+ return getPathForGlyphId(cmapMiscUnicode.getGlyphId(unicode));
+ }
+ // use a mac related mapping
+ if (cmapMacintoshSymbol != null)
+ {
+ return getPathForGlyphId(cmapMacintoshSymbol.getGlyphId(code));
+ }
+ }
+ // there isn't any mpping, but propably an optional CID2GID mapping
+ if (cid2gid != null && code <= cid2gid.length)
+ {
+ code = cid2gid[code];
+ }
+ return getPathForGlyphId(code);
+ }
+
+ /**
+ * Use the given points to calculate a GeneralPath.
+ *
+ * @param points the points to be used to generate the GeneralPath
+ *
+ * @return the calculated GeneralPath
+ */
+ private GeneralPath calculatePath(Point[] points)
+ {
+ GeneralPath path = new GeneralPath();
+ int numberOfPoints = points.length;
+ int i = 0;
+ boolean endOfContour = true;
+ Point startingPoint = null;
+ Point lastCtrlPoint = null;
+ while (i < numberOfPoints)
+ {
+ Point point = points[i % numberOfPoints];
+ Point nextPoint1 = points[(i + 1) % numberOfPoints];
+ Point nextPoint2 = points[(i + 2) % numberOfPoints];
+ // new contour
+ if (endOfContour)
+ {
+ // skip endOfContour points
+ if (point.endOfContour)
+ {
+ i++;
+ continue;
+ }
+ // move to the starting point
+ path.moveTo(point.x, point.y);
+ endOfContour = false;
+ startingPoint = point;
+ }
+ // lineTo
+ if (point.onCurve && nextPoint1.onCurve)
+ {
+ path.lineTo(nextPoint1.x, nextPoint1.y);
+ i++;
+ if (point.endOfContour || nextPoint1.endOfContour)
+ {
+ endOfContour = true;
+ path.closePath();
+ }
+ continue;
+ }
+ // quadratic bezier
+ if (point.onCurve && !nextPoint1.onCurve && nextPoint2.onCurve)
+ {
+ if (nextPoint1.endOfContour)
+ {
+ // use the starting point as end point
+ path.quadTo(nextPoint1.x, nextPoint1.y, startingPoint.x, startingPoint.y);
+ }
+ else
+ {
+ path.quadTo(nextPoint1.x, nextPoint1.y, nextPoint2.x, nextPoint2.y);
+ }
+ if (nextPoint1.endOfContour || nextPoint2.endOfContour)
+ {
+ endOfContour = true;
+ path.closePath();
+ }
+ i += 2;
+ lastCtrlPoint = nextPoint1;
+ continue;
+ }
+ if (point.onCurve && !nextPoint1.onCurve && !nextPoint2.onCurve)
+ {
+ // interpolate endPoint
+ int endPointX = midValue(nextPoint1.x, nextPoint2.x);
+ int endPointY = midValue(nextPoint1.y, nextPoint2.y);
+ path.quadTo(nextPoint1.x, nextPoint1.y, endPointX, endPointY);
+ if (point.endOfContour || nextPoint1.endOfContour || nextPoint2.endOfContour)
+ {
+ path.quadTo(nextPoint2.x, nextPoint2.y, startingPoint.x, startingPoint.y);
+ endOfContour = true;
+ path.closePath();
+ }
+ i += 2;
+ lastCtrlPoint = nextPoint1;
+ continue;
+ }
+ if (!point.onCurve && !nextPoint1.onCurve)
+ {
+ Point2D lastEndPoint = path.getCurrentPoint();
+ // calculate new control point using the previous control point
+ lastCtrlPoint = new Point(midValue(lastCtrlPoint.x, (int) lastEndPoint.getX()), midValue(
+ lastCtrlPoint.y, (int) lastEndPoint.getY()));
+ // interpolate endPoint
+ int endPointX = midValue((int) lastEndPoint.getX(), nextPoint1.x);
+ int endPointY = midValue((int) lastEndPoint.getY(), nextPoint1.y);
+ path.quadTo(lastCtrlPoint.x, lastCtrlPoint.y, endPointX, endPointY);
+ if (point.endOfContour || nextPoint1.endOfContour)
+ {
+ endOfContour = true;
+ path.closePath();
+ }
+ i++;
+ continue;
+ }
+ if (!point.onCurve && nextPoint1.onCurve)
+ {
+ path.quadTo(point.x, point.y, nextPoint1.x, nextPoint1.y);
+ if (point.endOfContour || nextPoint1.endOfContour)
+ {
+ endOfContour = true;
+ path.closePath();
+ }
+ i++;
+ lastCtrlPoint = point;
+ continue;
+ }
+ System.err.println("Unknown glyph command!!");
+ break;
+ }
+ return path;
+ }
+
+ private int midValue(int a, int b)
+ {
+ return a + (b - a) / 2;
+ }
+
+ /**
+ * This class represents one point of a glyph.
+ *
+ */
+ private class Point
+ {
+
+ public int x = 0;
+ public int y = 0;
+ public boolean onCurve = true;
+ public boolean endOfContour = false;
+
+ public Point(int xValue, int yValue, boolean onCurveValue, boolean endOfContourValue)
+ {
+ x = xValue;
+ y = yValue;
+ onCurve = onCurveValue;
+ endOfContour = endOfContourValue;
+ }
+
+ public Point(int xValue, int yValue)
+ {
+ this(xValue, yValue, false, false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int getNumberOfGlyphs()
+ {
+ return font != null ? font.getGlyph().getGlyphs().length : 0;
+ }
+
+ @Override
+ public void dispose()
+ {
+ cid2gid = null;
+ cmapMacintoshSymbol = null;
+ cmapMiscUnicode = null;
+ cmapWinSymbol = null;
+ cmapWinUnicode = null;
+ font = null;
+ toUnicode = null;
+ if (glyphs != null)
+ {
+ glyphs.clear();
+ }
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdfviewer/font/TTFGlyph2D.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Font.java?rev=1506667&r1=1506666&r2=1506667&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Font.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Font.java Wed Jul 24 19:24:43 2013
@@ -16,12 +16,12 @@
*/
package org.apache.pdfbox.pdmodel.font;
-import java.awt.Font;
-import java.awt.FontFormatException;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.ttf.TTFParser;
+import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
@@ -31,7 +31,7 @@ import org.apache.pdfbox.pdmodel.common.
/**
* This is implementation of the CIDFontType2 Font.
- *
+ *
* @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
*
*/
@@ -45,56 +45,24 @@ public class PDCIDFontType2Font extends
private Boolean hasCIDToGIDMap = null;
private int[] cid2gid = null;
-
+
/**
* Constructor.
*/
public PDCIDFontType2Font()
{
super();
- font.setItem( COSName.SUBTYPE, COSName.CID_FONT_TYPE2 );
+ font.setItem(COSName.SUBTYPE, COSName.CID_FONT_TYPE2);
}
/**
* Constructor.
- *
+ *
* @param fontDictionary The font dictionary according to the PDF specification.
*/
- public PDCIDFontType2Font( COSDictionary fontDictionary )
+ public PDCIDFontType2Font(COSDictionary fontDictionary)
{
- super( fontDictionary );
- }
-
- /**
- * {@inheritDoc}
- */
- public Font getawtFont() throws IOException
- {
- Font awtFont = null;
- PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary)getFontDescriptor();
- PDStream ff2Stream = fd.getFontFile2();
- if( ff2Stream != null )
- {
- try
- {
- // create a font with the embedded data
- awtFont = Font.createFont( Font.TRUETYPE_FONT, ff2Stream.createInputStream() );
- }
- catch( FontFormatException f )
- {
- LOG.info("Can't read the embedded font " + fd.getFontName() );
- }
- if (awtFont == null)
- {
- awtFont = FontManager.getAwtFont(fd.getFontName());
- if (awtFont != null)
- {
- LOG.info("Using font "+awtFont.getName()+ " instead");
- }
- setIsFontSubstituted(true);
- }
- }
- return awtFont;
+ super(fontDictionary);
}
/**
@@ -103,28 +71,28 @@ public class PDCIDFontType2Font extends
private void readCIDToGIDMapping()
{
COSBase map = font.getDictionaryObject(COSName.CID_TO_GID_MAP);
- if (map instanceof COSStream)
+ if (map instanceof COSStream)
{
- COSStream stream = (COSStream)map;
- try
+ COSStream stream = (COSStream) map;
+ try
{
byte[] mapAsBytes = IOUtils.toByteArray(stream.getUnfilteredStream());
int numberOfInts = mapAsBytes.length / 2;
cid2gid = new int[numberOfInts];
int offset = 0;
- for(int index = 0;index < numberOfInts;index++)
+ for (int index = 0; index < numberOfInts; index++)
{
cid2gid[index] = getCodeFromArray(mapAsBytes, offset, 2);
- offset+=2;
+ offset += 2;
}
}
- catch(IOException exception)
+ catch (IOException exception)
{
LOG.error("Can't read the CIDToGIDMap", exception);
}
}
}
-
+
/**
* Indicates if this font has a CIDToGIDMap.
*
@@ -146,16 +114,16 @@ public class PDCIDFontType2Font extends
}
return hasCIDToGIDMap.booleanValue();
}
-
+
/**
* Maps the given CID to the correspondent GID.
*
* @param cid the given CID
* @return the mapped GID, or -1 if something went wrong.
*/
- public int mapCIDToGID(int cid)
+ public int mapCIDToGID(int cid)
{
- if (hasCIDToGIDMap())
+ if (hasCIDToGIDMap())
{
if (cid2gid == null)
{
@@ -173,4 +141,41 @@ public class PDCIDFontType2Font extends
return cid;
}
}
+
+ /**
+ * Returns the CID2GID mapping if present.
+ *
+ * @return the CID2GID mapping
+ */
+ public int[] getCID2GID()
+ {
+ if (hasCIDToGIDMap())
+ {
+ if (cid2gid == null)
+ {
+ readCIDToGIDMapping();
+ }
+ }
+ return cid2gid;
+ }
+
+ /**
+ * Returns the embedded true type font.
+ *
+ * @return the true type font
+ * @throws IOException exception if something went wrong
+ */
+ public TrueTypeFont getTTFFont() throws IOException
+ {
+ PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary) getFontDescriptor();
+ PDStream ff2Stream = fd.getFontFile2();
+ TrueTypeFont trueTypeFont = null;
+ if (ff2Stream != null)
+ {
+ TTFParser ttfParser = new TTFParser(true);
+ trueTypeFont = ttfParser.parseTTF(ff2Stream.createInputStream());
+ }
+ return trueTypeFont;
+ }
+
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java?rev=1506667&r1=1506666&r2=1506667&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java Wed Jul 24 19:24:43 2013
@@ -16,13 +16,18 @@
*/
package org.apache.pdfbox.pdmodel.font;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
import org.apache.fontbox.afm.AFMParser;
import org.apache.fontbox.afm.FontMetric;
-import org.apache.fontbox.cmap.CMapParser;
import org.apache.fontbox.cmap.CMap;
-
-import org.apache.pdfbox.encoding.Encoding;
-
+import org.apache.fontbox.cmap.CMapParser;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
@@ -30,28 +35,18 @@ import org.apache.pdfbox.cos.COSFloat;
import org.apache.pdfbox.cos.COSInteger;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
-
+import org.apache.pdfbox.encoding.Encoding;
import org.apache.pdfbox.pdmodel.common.COSArrayList;
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.pdmodel.common.PDMatrix;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
-
import org.apache.pdfbox.util.ResourceLoader;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
/**
* This is the base class for all PDF fonts.
- *
+ *
* @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
- * @version $Revision: 1.46 $
+ *
*/
public abstract class PDFont implements COSObjectable
{
@@ -67,18 +62,17 @@ public abstract class PDFont implements
private Encoding fontEncoding = null;
/**
- * The descriptor of the font.
+ * The descriptor of the font.
*/
private PDFontDescriptor fontDescriptor = null;
/**
- * The font matrix.
+ * The font matrix.
*/
protected PDMatrix fontMatrix = null;
/**
- * This is only used if this is a font object and it has an encoding and it is
- * a type0 font with a cmap.
+ * This is only used if this is a font object and it has an encoding and it is a type0 font with a cmap.
*/
protected CMap cmap = null;
@@ -86,62 +80,59 @@ public abstract class PDFont implements
* The CMap holding the ToUnicode mapping.
*/
protected CMap toUnicodeCmap = null;
-
+
private boolean hasToUnicode = false;
- protected static Map<String, CMap> cmapObjects =
- Collections.synchronizedMap( new HashMap<String, CMap>() );
+ protected static Map<String, CMap> cmapObjects = Collections.synchronizedMap(new HashMap<String, CMap>());
/**
- * A list a floats representing the widths.
+ * A list a floats representing the widths.
*/
private List<Float> widths = null;
/**
* The static map of the default Adobe font metrics.
*/
- private static final Map<String, FontMetric> afmObjects =
- Collections.unmodifiableMap( getAdobeFontMetrics() );
+ private static final Map<String, FontMetric> afmObjects = Collections.unmodifiableMap(getAdobeFontMetrics());
// TODO move the Map to PDType1Font as these are the 14 Standard fonts
// which are definitely Type 1 fonts
private static Map<String, FontMetric> getAdobeFontMetrics()
{
Map<String, FontMetric> metrics = new HashMap<String, FontMetric>();
- addAdobeFontMetric( metrics, "Courier-Bold" );
- addAdobeFontMetric( metrics, "Courier-BoldOblique" );
- addAdobeFontMetric( metrics, "Courier" );
- addAdobeFontMetric( metrics, "Courier-Oblique" );
- addAdobeFontMetric( metrics, "Helvetica" );
- addAdobeFontMetric( metrics, "Helvetica-Bold" );
- addAdobeFontMetric( metrics, "Helvetica-BoldOblique" );
- addAdobeFontMetric( metrics, "Helvetica-Oblique" );
- addAdobeFontMetric( metrics, "Symbol" );
- addAdobeFontMetric( metrics, "Times-Bold" );
- addAdobeFontMetric( metrics, "Times-BoldItalic" );
- addAdobeFontMetric( metrics, "Times-Italic" );
- addAdobeFontMetric( metrics, "Times-Roman" );
- addAdobeFontMetric( metrics, "ZapfDingbats" );
+ addAdobeFontMetric(metrics, "Courier-Bold");
+ addAdobeFontMetric(metrics, "Courier-BoldOblique");
+ addAdobeFontMetric(metrics, "Courier");
+ addAdobeFontMetric(metrics, "Courier-Oblique");
+ addAdobeFontMetric(metrics, "Helvetica");
+ addAdobeFontMetric(metrics, "Helvetica-Bold");
+ addAdobeFontMetric(metrics, "Helvetica-BoldOblique");
+ addAdobeFontMetric(metrics, "Helvetica-Oblique");
+ addAdobeFontMetric(metrics, "Symbol");
+ addAdobeFontMetric(metrics, "Times-Bold");
+ addAdobeFontMetric(metrics, "Times-BoldItalic");
+ addAdobeFontMetric(metrics, "Times-Italic");
+ addAdobeFontMetric(metrics, "Times-Roman");
+ addAdobeFontMetric(metrics, "ZapfDingbats");
return metrics;
}
protected static final String resourceRootCMAP = "org/apache/pdfbox/resources/cmap/";
private static final String resourceRootAFM = "org/apache/pdfbox/resources/afm/";
- private static void addAdobeFontMetric(
- Map<String, FontMetric> metrics, String name )
+ private static void addAdobeFontMetric(Map<String, FontMetric> metrics, String name)
{
try
{
String resource = resourceRootAFM + name + ".afm";
- InputStream afmStream = ResourceLoader.loadResource( resource );
- if( afmStream != null )
+ InputStream afmStream = ResourceLoader.loadResource(resource);
+ if (afmStream != null)
{
try
{
- AFMParser parser = new AFMParser( afmStream );
+ AFMParser parser = new AFMParser(afmStream);
parser.parse();
- metrics.put( name, parser.getResult() );
+ metrics.put(name, parser.getResult());
}
finally
{
@@ -156,15 +147,13 @@ public abstract class PDFont implements
}
/**
- * This will clear AFM resources that are stored statically.
- * This is usually not a problem unless you want to reclaim
- * resources for a long running process.
- *
- * SPECIAL NOTE: The font calculations are currently in COSObject, which
- * is where they will reside until PDFont is mature enough to take them over.
- * PDFont is the appropriate place for them and not in COSObject but we need font
- * calculations for text extraction. THIS METHOD WILL BE MOVED OR REMOVED
- * TO ANOTHER LOCATION IN A FUTURE VERSION OF PDFBOX.
+ * This will clear AFM resources that are stored statically. This is usually not a problem unless you want to
+ * reclaim resources for a long running process.
+ *
+ * SPECIAL NOTE: The font calculations are currently in COSObject, which is where they will reside until PDFont is
+ * mature enough to take them over. PDFont is the appropriate place for them and not in COSObject but we need font
+ * calculations for text extraction. THIS METHOD WILL BE MOVED OR REMOVED TO ANOTHER LOCATION IN A FUTURE VERSION OF
+ * PDFBOX.
*/
public static void clearResources()
{
@@ -177,15 +166,15 @@ public abstract class PDFont implements
public PDFont()
{
font = new COSDictionary();
- font.setItem( COSName.TYPE, COSName.FONT );
+ font.setItem(COSName.TYPE, COSName.FONT);
}
/**
* Constructor.
- *
+ *
* @param fontDictionary The font dictionary according to the PDF specification.
*/
- public PDFont( COSDictionary fontDictionary )
+ public PDFont(COSDictionary fontDictionary)
{
font = fontDictionary;
determineEncoding();
@@ -193,25 +182,25 @@ public abstract class PDFont implements
/**
* This will get the font descriptor for this font.
- *
+ *
* @return The font descriptor for this font.
- *
+ *
*/
public PDFontDescriptor getFontDescriptor()
{
- if(fontDescriptor == null)
+ if (fontDescriptor == null)
{
- COSDictionary fd = (COSDictionary)font.getDictionaryObject( COSName.FONT_DESC );
+ COSDictionary fd = (COSDictionary) font.getDictionaryObject(COSName.FONT_DESC);
if (fd != null)
{
- fontDescriptor = new PDFontDescriptorDictionary( fd );
+ fontDescriptor = new PDFontDescriptorDictionary(fd);
}
else
{
getAFM();
- if( afm != null )
+ if (afm != null)
{
- fontDescriptor = new PDFontDescriptorAFM( afm );
+ fontDescriptor = new PDFontDescriptorAFM(afm);
}
}
}
@@ -220,24 +209,23 @@ public abstract class PDFont implements
/**
* This will set the font descriptor.
- *
+ *
* @param fdDictionary The font descriptor.
*/
- public void setFontDescriptor( PDFontDescriptorDictionary fdDictionary )
+ public void setFontDescriptor(PDFontDescriptorDictionary fdDictionary)
{
COSDictionary dic = null;
- if( fdDictionary != null )
+ if (fdDictionary != null)
{
dic = fdDictionary.getCOSDictionary();
}
- font.setItem( COSName.FONT_DESC, dic );
+ font.setItem(COSName.FONT_DESC, dic);
fontDescriptor = fdDictionary;
}
/**
- * Determines the encoding for the font.
- * This method as to be overwritten, as there are different
- * possibilities to define a mapping.
+ * Determines the encoding for the font. This method as to be overwritten, as there are different possibilities to
+ * define a mapping.
*/
protected abstract void determineEncoding();
@@ -251,112 +239,112 @@ public abstract class PDFont implements
/**
* This will get the font width for a character.
- *
+ *
* @param c The character code to get the width for.
* @param offset The offset into the array.
* @param length The length of the data.
- *
+ *
* @return The width is in 1000 unit of text space, ie 333 or 777
- *
+ *
* @throws IOException If an error occurs while parsing.
*/
- public abstract float getFontWidth( byte[] c, int offset, int length ) throws IOException;
+ public abstract float getFontWidth(byte[] c, int offset, int length) throws IOException;
/**
* This will get the font width for a character.
- *
+ *
* @param c The character code to get the width for.
* @param offset The offset into the array.
* @param length The length of the data.
- *
+ *
* @return The width is in 1000 unit of text space, ie 333 or 777
- *
+ *
* @throws IOException If an error occurs while parsing.
*/
- public abstract float getFontHeight( byte[] c, int offset, int length ) throws IOException;
+ public abstract float getFontHeight(byte[] c, int offset, int length) throws IOException;
/**
* This will get the width of this string for this font.
- *
+ *
* @param string The string to get the width of.
- *
+ *
* @return The width of the string in 1000 units of text space, ie 333 567...
- *
+ *
* @throws IOException If there is an error getting the width information.
*/
- public float getStringWidth( String string ) throws IOException
+ public float getStringWidth(String string) throws IOException
{
byte[] data = string.getBytes("ISO-8859-1");
float totalWidth = 0;
- for( int i=0; i<data.length; i++ )
+ for (int i = 0; i < data.length; i++)
{
- totalWidth+=getFontWidth( data, i, 1 );
+ totalWidth += getFontWidth(data, i, 1);
}
return totalWidth;
}
/**
* This will get the average font width for all characters.
- *
+ *
* @return The width is in 1000 unit of text space, ie 333 or 777
- *
+ *
* @throws IOException If an error occurs while parsing.
*/
public abstract float getAverageFontWidth() throws IOException;
/**
* Used for multibyte encodings.
- *
+ *
* @param data The array of data.
* @param offset The offset into the array.
* @param length The number of bytes to use.
- *
+ *
* @return The int value of data from the array.
*/
- public int getCodeFromArray( byte[] data, int offset, int length )
+ public int getCodeFromArray(byte[] data, int offset, int length)
{
int code = 0;
- for( int i=0; i<length; i++ )
+ for (int i = 0; i < length; i++)
{
code <<= 8;
- code |= (data[offset+i]+256)%256;
+ code |= (data[offset + i] + 256) % 256;
}
return code;
}
/**
* This will attempt to get the font width from an AFM file.
- *
+ *
* @param code The character code we are trying to get.
- *
+ *
* @return The font width from the AFM file.
- *
+ *
* @throws IOException if we cannot find the width.
*/
- protected float getFontWidthFromAFMFile( int code ) throws IOException
+ protected float getFontWidthFromAFMFile(int code) throws IOException
{
float retval = 0;
FontMetric metric = getAFM();
- if( metric != null )
+ if (metric != null)
{
- String characterName = fontEncoding.getName( code );
- retval = metric.getCharacterWidth( characterName );
+ String characterName = fontEncoding.getName(code);
+ retval = metric.getCharacterWidth(characterName);
}
return retval;
}
/**
* This will attempt to get the average font width from an AFM file.
- *
+ *
* @return The average font width from the AFM file.
- *
+ *
* @throws IOException if we cannot find the width.
*/
protected float getAverageFontWidthFromAFMFile() throws IOException
{
float retval = 0;
FontMetric metric = getAFM();
- if( metric != null )
+ if (metric != null)
{
retval = metric.getAverageCharacterWidth();
}
@@ -365,33 +353,33 @@ public abstract class PDFont implements
/**
* This will get an AFM object if one exists.
- *
+ *
* @return The afm object from the name.
- *
+ *
*/
protected FontMetric getAFM()
{
if (isType1Font() && afm == null)
{
- COSBase baseFont = font.getDictionaryObject( COSName.BASE_FONT );
+ COSBase baseFont = font.getDictionaryObject(COSName.BASE_FONT);
String name = null;
- if( baseFont instanceof COSName )
+ if (baseFont instanceof COSName)
{
- name = ((COSName)baseFont).getName();
+ name = ((COSName) baseFont).getName();
if (name.indexOf("+") > -1)
{
- name = name.substring(name.indexOf("+")+1);
+ name = name.substring(name.indexOf("+") + 1);
}
}
- else if ( baseFont instanceof COSString )
+ else if (baseFont instanceof COSString)
{
- COSString string = (COSString)baseFont;
+ COSString string = (COSString) baseFont;
name = string.getString();
}
- if ( name != null )
+ if (name != null)
{
- afm = afmObjects.get( name );
+ afm = afmObjects.get(name);
}
}
return afm;
@@ -400,46 +388,49 @@ public abstract class PDFont implements
private FontMetric afm = null;
private COSBase encoding = null;
+
/**
- * cache the {@link COSName#ENCODING} object from
- * the font's dictionary since it is called so often.
+ * cache the {@link COSName#ENCODING} object from the font's dictionary since it is called so often.
* <p>
* Use this method instead of
+ *
* <pre>
- * font.getDictionaryObject(COSName.ENCODING);
+ * font.getDictionaryObject(COSName.ENCODING);
* </pre>
+ *
* @return the encoding
*/
protected COSBase getEncoding()
{
if (encoding == null)
{
- encoding = font.getDictionaryObject( COSName.ENCODING );
+ encoding = font.getDictionaryObject(COSName.ENCODING);
}
return encoding;
}
/**
* Set the encoding object from the fonts dictionary.
+ *
* @param encodingValue the given encoding.
*/
protected void setEncoding(COSBase encodingValue)
{
- font.setItem( COSName.ENCODING, encodingValue );
+ font.setItem(COSName.ENCODING, encodingValue);
encoding = encodingValue;
}
/**
* Encode the given value using the CMap of the font.
- *
+ *
* @param code the code to encode.
* @param length the byte length of the given code.
* @param isCIDFont indicates that the used font is a CID font.
- *
+ *
* @return The value of the encoded character.
* @throws IOException if something went wrong
*/
- protected String cmapEncoding( int code, int length, boolean isCIDFont, CMap sourceCmap ) throws IOException
+ protected String cmapEncoding(int code, int length, boolean isCIDFont, CMap sourceCmap) throws IOException
{
String retval = null;
// there is not sourceCmap if this is a descendant font
@@ -457,75 +448,76 @@ public abstract class PDFont implements
}
return retval;
}
+
/**
* This will perform the encoding of a character if needed.
- *
+ *
* @param c The character to encode.
* @param offset The offset into the array to get the data
* @param length The number of bytes to read.
- *
+ *
* @return The value of the encoded character.
- *
+ *
* @throws IOException If there is an error during the encoding.
*/
- public String encode( byte[] c, int offset, int length ) throws IOException
+ public String encode(byte[] c, int offset, int length) throws IOException
{
String retval = null;
- int code = getCodeFromArray( c, offset, length );
- if( toUnicodeCmap != null )
+ int code = getCodeFromArray(c, offset, length);
+ if (toUnicodeCmap != null)
{
retval = cmapEncoding(code, length, false, toUnicodeCmap);
}
- if( retval == null && cmap != null )
+ if (retval == null && cmap != null)
{
retval = cmapEncoding(code, length, false, cmap);
}
// there is no cmap but probably an encoding with a suitable mapping
- if( retval == null )
+ if (retval == null)
{
- if( fontEncoding != null )
+ if (fontEncoding != null)
{
- retval = fontEncoding.getCharacter( code );
+ retval = fontEncoding.getCharacter(code);
}
- if( retval == null && (cmap == null || length == 2))
+ if (retval == null && (cmap == null || length == 2))
{
- retval = getStringFromArray( c, offset, length );
+ retval = getStringFromArray(c, offset, length);
}
}
return retval;
}
- public int encodeToCID( byte[] c, int offset, int length ) throws IOException
+ public int encodeToCID(byte[] c, int offset, int length) throws IOException
{
int code = -1;
- if (encode(c, offset, length) != null)
+ if (encode(c, offset, length) != null)
{
- code = getCodeFromArray( c, offset, length );
+ code = getCodeFromArray(c, offset, length);
}
return code;
}
-
+
private static final String[] SINGLE_CHAR_STRING = new String[256];
private static final String[][] DOUBLE_CHAR_STRING = new String[256][256];
static
{
- for( int i=0; i<256; i++ )
+ for (int i = 0; i < 256; i++)
{
try
{
- SINGLE_CHAR_STRING[i] = new String( new byte[] {(byte)i}, "ISO-8859-1" );
+ SINGLE_CHAR_STRING[i] = new String(new byte[] { (byte) i }, "ISO-8859-1");
}
catch (UnsupportedEncodingException e)
{
// Nothing should happen here
e.printStackTrace();
}
- for( int j=0; j<256; j++ )
+ for (int j = 0; j < 256; j++)
{
try
{
- DOUBLE_CHAR_STRING[i][j] = new String( new byte[] {(byte)i, (byte)j}, "UTF-16BE" );
+ DOUBLE_CHAR_STRING[i][j] = new String(new byte[] { (byte) i, (byte) j }, "UTF-16BE");
}
catch (UnsupportedEncodingException e)
{
@@ -536,57 +528,59 @@ public abstract class PDFont implements
}
}
- private static String getStringFromArray( byte[] c, int offset, int length ) throws IOException
+ private static String getStringFromArray(byte[] c, int offset, int length) throws IOException
{
String retval = null;
- if( length == 1 )
+ if (length == 1)
{
- retval = SINGLE_CHAR_STRING[(c[offset]+256)%256];
+ retval = SINGLE_CHAR_STRING[(c[offset] + 256) % 256];
}
- else if( length == 2 )
+ else if (length == 2)
{
- retval = DOUBLE_CHAR_STRING[(c[offset]+256)%256][(c[offset+1]+256)%256];
+ retval = DOUBLE_CHAR_STRING[(c[offset] + 256) % 256][(c[offset + 1] + 256) % 256];
}
else
{
- throw new IOException( "Error:Unknown character length:" + length );
+ throw new IOException("Error:Unknown character length:" + length);
}
return retval;
}
- protected CMap parseCmap( String cmapRoot, InputStream cmapStream)
+ protected CMap parseCmap(String cmapRoot, InputStream cmapStream)
{
CMap targetCmap = null;
- if( cmapStream != null )
+ if (cmapStream != null)
{
CMapParser parser = new CMapParser();
try
{
- targetCmap = parser.parse( cmapRoot, cmapStream );
+ targetCmap = parser.parse(cmapRoot, cmapStream);
// limit the cache to external CMaps
if (cmapRoot != null)
{
- cmapObjects.put( targetCmap.getName(), targetCmap );
+ cmapObjects.put(targetCmap.getName(), targetCmap);
}
}
- catch (IOException exception) {}
+ catch (IOException exception)
+ {
+ }
}
return targetCmap;
}
/**
* The will set the encoding for this font.
- *
+ *
* @param enc The font encoding.
*/
- public void setFontEncoding( Encoding enc )
+ public void setFontEncoding(Encoding enc)
{
fontEncoding = enc;
}
/**
* This will get or create the encoder.
- *
+ *
* @return The encoding to use.
*/
public Encoding getFontEncoding()
@@ -596,12 +590,12 @@ public abstract class PDFont implements
/**
* This will always return "Font" for fonts.
- *
+ *
* @return The type of object that this is.
*/
public String getType()
{
- return font.getNameAsString( COSName.TYPE );
+ return font.getNameAsString(COSName.TYPE);
}
// Memorized values to avoid repeated dictionary lookups
@@ -613,14 +607,14 @@ public abstract class PDFont implements
/**
* This will get the subtype of font, Type1, Type3, ...
- *
+ *
* @return The type of font that this is.
*/
public String getSubType()
{
if (subtype == null)
{
- subtype = font.getNameAsString( COSName.SUBTYPE );
+ subtype = font.getNameAsString(COSName.SUBTYPE);
type1Font = "Type1".equals(subtype);
trueTypeFont = "TrueType".equals(subtype);
type0Font = "Type0".equals(subtype);
@@ -631,6 +625,7 @@ public abstract class PDFont implements
/**
* Determines if the font is a type 1 font.
+ *
* @return returns true if the font is a type 1 font
*/
public boolean isType1Font()
@@ -641,6 +636,7 @@ public abstract class PDFont implements
/**
* Determines if the font is a type 3 font.
+ *
* @return returns true if the font is a type 3 font
*/
public boolean isType3Font()
@@ -648,9 +644,10 @@ public abstract class PDFont implements
getSubType();
return type3Font;
}
-
+
/**
* Determines if the font is a type 0 font.
+ *
* @return returns true if the font is a type 0 font
*/
public boolean isType0Font()
@@ -661,6 +658,7 @@ public abstract class PDFont implements
/**
* Determines if the font is a true type font.
+ *
* @return returns true if the font is a true type font
*/
public boolean isTrueTypeFont()
@@ -670,78 +668,92 @@ public abstract class PDFont implements
}
/**
+ * Determines if the font is a symbolic font.
+ *
+ * @return returns true if the font is a symbolic font
+ */
+ public boolean isSymbolicFont()
+ {
+ if (getFontDescriptor() != null)
+ {
+ return getFontDescriptor().isSymbolic();
+ }
+ return false;
+ }
+
+ /**
* The PostScript name of the font.
- *
+ *
* @return The postscript name of the font.
*/
public String getBaseFont()
{
- return font.getNameAsString( COSName.BASE_FONT );
+ return font.getNameAsString(COSName.BASE_FONT);
}
/**
* Set the PostScript name of the font.
- *
+ *
* @param baseFont The postscript name for the font.
*/
- public void setBaseFont( String baseFont )
+ public void setBaseFont(String baseFont)
{
- font.setName( COSName.BASE_FONT, baseFont );
+ font.setName(COSName.BASE_FONT, baseFont);
}
/**
* The code for the first char or -1 if there is none.
- *
+ *
* @return The code for the first character.
*/
public int getFirstChar()
{
- return font.getInt( COSName.FIRST_CHAR, -1 );
+ return font.getInt(COSName.FIRST_CHAR, -1);
}
/**
* Set the first character this font supports.
- *
+ *
* @param firstChar The first character.
*/
- public void setFirstChar( int firstChar )
+ public void setFirstChar(int firstChar)
{
- font.setInt( COSName.FIRST_CHAR, firstChar );
+ font.setInt(COSName.FIRST_CHAR, firstChar);
}
/**
* The code for the last char or -1 if there is none.
- *
+ *
* @return The code for the last character.
*/
public int getLastChar()
{
- return font.getInt( COSName.LAST_CHAR, -1 );
+ return font.getInt(COSName.LAST_CHAR, -1);
}
/**
* Set the last character this font supports.
- *
+ *
* @param lastChar The last character.
*/
- public void setLastChar( int lastChar )
+ public void setLastChar(int lastChar)
{
- font.setInt( COSName.LAST_CHAR, lastChar );
+ font.setInt(COSName.LAST_CHAR, lastChar);
}
/**
- * The widths of the characters. This will be null for the standard 14 fonts.
- *
+ * The widths of the characters. This will be null for the standard 14 fonts.
+ *
* @return The widths of the characters.
*/
public List<Float> getWidths()
{
if (widths == null)
{
- COSArray array = (COSArray)font.getDictionaryObject( COSName.WIDTHS );
+ COSArray array = (COSArray) font.getDictionaryObject(COSName.WIDTHS);
if (array != null)
{
- widths = COSArrayList.convertFloatCOSArrayToList( array );
+ widths = COSArrayList.convertFloatCOSArrayToList(array);
}
}
return widths;
@@ -749,39 +761,38 @@ public abstract class PDFont implements
/**
* Set the widths of the characters code.
- *
+ *
* @param widthsList The widths of the character codes.
*/
- public void setWidths( List<Float> widthsList )
+ public void setWidths(List<Float> widthsList)
{
widths = widthsList;
- font.setItem( COSName.WIDTHS, COSArrayList.converterToCOSArray( widths ) );
+ font.setItem(COSName.WIDTHS, COSArrayList.converterToCOSArray(widths));
}
/**
- * This will get the matrix that is used to transform glyph space to
- * text space. By default there are 1000 glyph units to 1 text space
- * unit, but type3 fonts can use any value.
- *
- * Note:If this is a type3 font then it can be modified via the PDType3Font.setFontMatrix, otherwise this
- * is a read-only property.
- *
+ * This will get the matrix that is used to transform glyph space to text space. By default there are 1000 glyph
+ * units to 1 text space unit, but type3 fonts can use any value.
+ *
+ * Note:If this is a type3 font then it can be modified via the PDType3Font.setFontMatrix, otherwise this is a
+ * read-only property.
+ *
* @return The matrix to transform from glyph space to text space.
*/
public PDMatrix getFontMatrix()
{
if (fontMatrix == null)
{
- COSArray array = (COSArray)font.getDictionaryObject( COSName.FONT_MATRIX );
- if( array == null )
+ COSArray array = (COSArray) font.getDictionaryObject(COSName.FONT_MATRIX);
+ if (array == null)
{
array = new COSArray();
- array.add( new COSFloat( 0.001f ) );
- array.add( COSInteger.ZERO );
- array.add( COSInteger.ZERO );
- array.add( new COSFloat( 0.001f ) );
- array.add( COSInteger.ZERO );
- array.add( COSInteger.ZERO );
+ array.add(new COSFloat(0.001f));
+ array.add(COSInteger.ZERO);
+ array.add(COSInteger.ZERO);
+ array.add(new COSFloat(0.001f));
+ array.add(COSInteger.ZERO);
+ array.add(COSInteger.ZERO);
}
fontMatrix = new PDMatrix(array);
}
@@ -790,9 +801,9 @@ public abstract class PDFont implements
/**
* This will get the fonts bounding box.
- *
+ *
* @return The fonts bounding box.
- *
+ *
* @throws IOException If there is an error getting the bounding box.
*/
public abstract PDRectangle getFontBoundingBox() throws IOException;
@@ -800,9 +811,9 @@ public abstract class PDFont implements
/**
* {@inheritDoc}
*/
- public boolean equals( Object other )
+ public boolean equals(Object other)
{
- return other instanceof PDFont && ((PDFont)other).getCOSObject() == this.getCOSObject();
+ return other instanceof PDFont && ((PDFont) other).getCOSObject() == this.getCOSObject();
}
/**
@@ -815,10 +826,11 @@ public abstract class PDFont implements
/**
* Determines the width of the given character.
+ *
* @param charCode the code of the given character
* @return the width of the character
*/
- public float getFontWidth( int charCode )
+ public float getFontWidth(int charCode)
{
float width = -1;
int firstChar = getFirstChar();
@@ -829,7 +841,7 @@ public abstract class PDFont implements
getWidths();
if (widths != null)
{
- width = widths.get(charCode-firstChar).floatValue();
+ width = widths.get(charCode - firstChar).floatValue();
}
}
else
@@ -845,26 +857,38 @@ public abstract class PDFont implements
/**
* Determines if a font as a ToUnicode entry.
+ *
* @return true if the font has a ToUnicode entry
*/
- protected boolean hasToUnicode()
+ public boolean hasToUnicode()
{
return hasToUnicode;
}
/**
* Sets hasToUnicode to the given value.
+ *
* @param hasToUnicodeValue the given value for hasToUnicode
*/
protected void setHasToUnicode(boolean hasToUnicodeValue)
{
hasToUnicode = hasToUnicodeValue;
}
-
+
/**
* Determines the width of the space character.
+ *
* @return the width of the space character
*/
public abstract float getSpaceWidth();
-
+
+ /**
+ * Returns the toUnicode mapping if present.
+ *
+ * @return the CMap representing the toUnicode mapping
+ */
+ public CMap getToUnicodeCMap()
+ {
+ return toUnicodeCmap;
+ }
}