From 6025b6016517c6d898d8957d1d7e03ba71431912 Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 1 Dec 2006 12:20:24 +0000 Subject: Initial import of release 2.2. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@4 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../java/org/pdfbox/pdmodel/font/PDCIDFont.java | 248 ++++++ .../pdfbox/pdmodel/font/PDCIDFontType0Font.java | 66 ++ .../pdfbox/pdmodel/font/PDCIDFontType2Font.java | 66 ++ src/main/java/org/pdfbox/pdmodel/font/PDFont.java | 863 +++++++++++++++++++++ .../org/pdfbox/pdmodel/font/PDFontDescriptor.java | 530 +++++++++++++ .../pdfbox/pdmodel/font/PDFontDescriptorAFM.java | 446 +++++++++++ .../pdmodel/font/PDFontDescriptorDictionary.java | 580 ++++++++++++++ .../org/pdfbox/pdmodel/font/PDFontFactory.java | 108 +++ .../org/pdfbox/pdmodel/font/PDMMType1Font.java | 62 ++ .../java/org/pdfbox/pdmodel/font/PDSimpleFont.java | 239 ++++++ .../org/pdfbox/pdmodel/font/PDTrueTypeFont.java | 437 +++++++++++ .../java/org/pdfbox/pdmodel/font/PDType0Font.java | 129 +++ .../org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java | 206 +++++ .../java/org/pdfbox/pdmodel/font/PDType1Font.java | 267 +++++++ .../java/org/pdfbox/pdmodel/font/PDType3Font.java | 152 ++++ .../org/pdfbox/pdmodel/font/Type3StreamParser.java | 607 +++++++++++++++ src/main/java/org/pdfbox/pdmodel/font/package.html | 9 + 17 files changed, 5015 insertions(+) create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontDescriptor.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontDescriptorAFM.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontDescriptorDictionary.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDFontFactory.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDMMType1Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDSimpleFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java create mode 100644 src/main/java/org/pdfbox/pdmodel/font/package.html (limited to 'src/main/java/org/pdfbox/pdmodel/font') diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java new file mode 100644 index 0000000..e13b821 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFont.java @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Graphics; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSInteger; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.pdmodel.common.PDRectangle; + +import org.apache.log4j.Logger; + +/** + * This is implementation for the CIDFontType0/CIDFontType2 Fonts. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public abstract class PDCIDFont extends PDFont +{ + private static Logger log = Logger.getLogger(PDCIDFont.class); + + + private Map widthCache = new HashMap(); + + /** + * Constructor. + */ + public PDCIDFont() + { + super(); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDCIDFont( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the fonts bouding box. + * + * @return The fonts bouding box. + * + * @throws IOException If there is an error getting the font bounding box. + */ + public PDRectangle getFontBoundingBox() throws IOException + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the default width. The default value for the default width is 1000. + * + * @return The default width for the glyphs in this font. + */ + public long getDefaultWidth() + { + long dw = 1000; + COSNumber number = (COSNumber)font.getDictionaryObject( COSName.getPDFName( "DW" ) ); + if( number != null ) + { + dw = number.intValue(); + } + return dw; + } + + /** + * This will set the default width for the glyphs of this font. + * + * @param dw The default width. + */ + public void setDefaultWidth( long dw ) + { + font.setItem( COSName.getPDFName( "DW" ), new COSInteger( dw ) ); + } + + /** + * 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 float getFontWidth( byte[] c, int offset, int length ) throws IOException + { + + float retval = 0.0f; + int code = getCodeFromArray( c, offset, length ); + + Float widthFloat = (Float)widthCache.get( new Integer( code ) ); + if( widthFloat == null ) + { + COSArray widths = (COSArray)font.getDictionaryObject( COSName.getPDFName( "W" ) ); + + if( widths != null ) + { + boolean foundWidth = false; + for( int i=0; !foundWidth && i= firstCode.intValue() && + code < firstCode.intValue() + array.size() ) + { + COSNumber rangeWidth = + (COSNumber)array.get( code - firstCode.intValue() ); + retval = rangeWidth.floatValue(); + foundWidth = true; + } + } + else + { + COSNumber secondCode = (COSNumber)next; + i++; + COSNumber rangeWidth = (COSNumber)widths.getObject( i ); + if( code >= firstCode.intValue() && + code <= secondCode.intValue() ) + { + retval = rangeWidth.floatValue(); + foundWidth = true; + } + } + } + widthCache.put( new Integer( code ), new Float( retval ) ); + } + } + else + { + retval = widthFloat.floatValue(); + } + + if(log.isDebugEnabled() ) + { + log.debug( "PDCIDFontType0Font.getFontWidth( code=" + code +" ) retval=" +retval ); + } + return retval; + } + + /** + * 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 float getAverageFontWidth() throws IOException + { + float totalWidths = 0.0f; + float characterCount = 0.0f; + float defaultWidth = getDefaultWidth(); + COSArray widths = (COSArray)font.getDictionaryObject( COSName.getPDFName( "W" ) ); + + if( widths != null ) + { + for( int i=0; i 0 ) + { + totalWidths += rangeWidth.floatValue(); + characterCount += 1; + } + } + } + } + float average = totalWidths / characterCount; + if( average <= 0 ) + { + average = defaultWidth; + } + return average; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java new file mode 100644 index 0000000..4c6589c --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType0Font.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.apache.log4j.Logger; + +/** + * This is implementation of the CIDFontType0 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.4 $ + */ +public class PDCIDFontType0Font extends PDCIDFont +{ + private static Logger log = Logger.getLogger(PDCIDFontType0Font.class); + + /** + * Constructor. + */ + public PDCIDFontType0Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "CIDFontType0" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDCIDFontType0Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java new file mode 100644 index 0000000..bda6c4a --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDCIDFontType2Font.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2003, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.apache.log4j.Logger; + +/** + * This is implementation of the CIDFontType2 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.3 $ + */ +public class PDCIDFontType2Font extends PDCIDFont +{ + private static Logger log = Logger.getLogger(PDCIDFontType2Font.class); + + /** + * Constructor. + */ + public PDCIDFontType2Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "CIDFontType2" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDCIDFontType2Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDFont.java new file mode 100644 index 0000000..593c8b0 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDFont.java @@ -0,0 +1,863 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.afmparser.AFMParser; + +import org.pdfbox.afmtypes.FontMetric; + +import org.pdfbox.cmapparser.CMapParser; + +import org.pdfbox.cmaptypes.CMap; + +import org.pdfbox.encoding.AFMEncoding; +import org.pdfbox.encoding.DictionaryEncoding; +import org.pdfbox.encoding.Encoding; +import org.pdfbox.encoding.EncodingManager; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSBase; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSFloat; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.common.COSArrayList; +import org.pdfbox.pdmodel.common.COSObjectable; +import org.pdfbox.pdmodel.common.PDMatrix; +import org.pdfbox.pdmodel.common.PDRectangle; + +import org.pdfbox.util.ResourceLoader; + +import org.apache.log4j.Logger; + +import java.awt.Graphics; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.IOException; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +/** + * This is the base class for all PDF fonts. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.32 $ + */ +public abstract class PDFont implements COSObjectable +{ + private static Logger log = Logger.getLogger(PDFont.class); + + /** + * The cos dictionary for this font. + */ + protected COSDictionary font; + + /** + * This is only used if this is a font object and it has an encoding. + */ + private Encoding fontEncoding = 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. + */ + private CMap cmap = null; + + private static Map afmResources = null; + private static Map cmapObjects = null; + private static Map afmObjects = null; + private static Map cmapSubstitutions = null; + + static + { + //these are read-only once they are created + afmResources = new HashMap(); + cmapSubstitutions = new HashMap(); + + //these are read-write + cmapObjects = Collections.synchronizedMap( new HashMap() ); + afmObjects = Collections.synchronizedMap( new HashMap() ); + + + afmResources.put( COSName.getPDFName( "Courier-Bold" ), "Resources/afm/Courier-Bold.afm" ); + afmResources.put( COSName.getPDFName( "Courier-BoldOblique" ), "Resources/afm/Courier-BoldOblique.afm" ); + afmResources.put( COSName.getPDFName( "Courier" ), "Resources/afm/Courier.afm" ); + afmResources.put( COSName.getPDFName( "Courier-Oblique" ), "Resources/afm/Courier-Oblique.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica" ), "Resources/afm/Helvetica.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica-Bold" ), "Resources/afm/Helvetica-Bold.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica-BoldOblique" ), "Resources/afm/Helvetica-BoldOblique.afm" ); + afmResources.put( COSName.getPDFName( "Helvetica-Oblique" ), "Resources/afm/Helvetica-Oblique.afm" ); + afmResources.put( COSName.getPDFName( "Symbol" ), "Resources/afm/Symbol.afm" ); + afmResources.put( COSName.getPDFName( "Times-Bold" ), "Resources/afm/Times-Bold.afm" ); + afmResources.put( COSName.getPDFName( "Times-BoldItalic" ), "Resources/afm/Times-BoldItalic.afm" ); + afmResources.put( COSName.getPDFName( "Times-Italic" ), "Resources/afm/Times-Italic.afm" ); + afmResources.put( COSName.getPDFName( "Times-Roman" ), "Resources/afm/Times-Roman.afm" ); + afmResources.put( COSName.getPDFName( "ZapfDingbats" ), "Resources/afm/ZapfDingbats.afm" ); + + cmapSubstitutions.put( "ETenms-B5-H", "ETen-B5-H" ); + cmapSubstitutions.put( "ETenms-B5-V", "ETen-B5-V" ); + } + + /** + * 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 extractaion. THIS METHOD WILL BE MOVED OR REMOVED + * TO ANOTHER LOCATION IN A FUTURE VERSION OF PDFBOX. + */ + public static void clearResources() + { + afmObjects.clear(); + cmapObjects.clear(); + } + + /** + * Constructor. + */ + public PDFont() + { + font = new COSDictionary(); + font.setItem( COSName.TYPE, COSName.FONT ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDFont( COSDictionary fontDictionary ) + { + font = fontDictionary; + } + + /** + * @see COSObjectable#getCOSObject() + */ + public COSBase getCOSObject() + { + return font; + } + + /** + * 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; + + /** + * 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 + { + byte[] data = string.getBytes(); + float totalWidth = 0; + for( int i=0; i= first && code <= last && font.getDictionaryObject( COSName.WIDTHS ) != null ) + { + COSArray widthArray = (COSArray)font.getDictionaryObject( COSName.WIDTHS ); + COSNumber fontWidthObject = (COSNumber)widthArray.get( (int)(code - first) ); + fontWidth = fontWidthObject.floatValue(); + } + else + { + fontWidth = getFontWidthFromAFMFile( code ); + } + } + else + { + fontWidth = getFontWidthFromAFMFile( code ); + } + return fontWidth; + } + + /** + * 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 float getAverageFontWidth() throws IOException + { + float average = 0.0f; + float totalWidth = 0.0f; + float characterCount = 0.0f; + COSArray widths = (COSArray)font.getDictionaryObject( COSName.WIDTHS ); + if( widths != null ) + { + for( int i=0; i 0 ) + { + totalWidth += fontWidth.floatValue(); + characterCount += 1; + } + } + } + + if( totalWidth > 0 ) + { + average = totalWidth / characterCount; + } + else + { + average = getAverageFontWidthFromAFMFile(); + } + return average; + } + + /** + * This will get the font descriptor for this font. + * + * @return The font descriptor for this font. + * + * @throws IOException If there is an error parsing an AFM file, or unable to + * create a PDFontDescriptor object. + */ + public PDFontDescriptor getFontDescriptor() throws IOException + { + PDFontDescriptor retval = null; + COSDictionary fd = (COSDictionary)font.getDictionaryObject( COSName.getPDFName( "FontDescriptor" ) ); + if( fd == null ) + { + FontMetric afm = getAFM(); + if( afm == null ) + { + throw new IOException( "Error: Can't create font descriptor file" ); + } + retval = new PDFontDescriptorAFM( afm ); + } + else + { + retval = new PDFontDescriptorDictionary( fd ); + } + + return retval; + } + + /** + * This will set the font descriptor. + * + * @param fontDescriptor The font descriptor. + */ + public void setFontDescriptor( PDFontDescriptorDictionary fontDescriptor ) + { + COSDictionary dic = null; + if( fontDescriptor != null ) + { + dic = fontDescriptor.getCOSDictionary(); + } + font.setItem( COSName.getPDFName( "FontDescriptor" ), dic ); + } + + /** + * This will get the ToUnicode stream. + * + * @return The ToUnicode stream. + * @throws IOException If there is an error getting the stream. + */ + public PDStream getToUnicode() throws IOException + { + return PDStream.createFromCOS( font.getDictionaryObject( "ToUnicode" ) ); + } + + /** + * This will set the ToUnicode stream. + * + * @param unicode The unicode stream. + */ + public void setToUnicode( PDStream unicode ) + { + font.setItem( "ToUnicode", unicode ); + } + + /** + * This will get the fonts bounding box. + * + * @return The fonts bouding box. + * + * @throws IOException If there is an error getting the bounding box. + */ + public PDRectangle getFontBoundingBox() throws IOException + { + return getFontDescriptor().getFontBoundingBox(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java new file mode 100644 index 0000000..d462255 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDTrueTypeFont.java @@ -0,0 +1,437 @@ +/** + * Copyright (c) 2003-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +import org.pdfbox.pdmodel.PDDocument; + +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.PDStream; + +import org.pdfbox.encoding.WinAnsiEncoding; + +import org.pdfbox.ttf.CMAPEncodingEntry; +import org.pdfbox.ttf.CMAPTable; +import org.pdfbox.ttf.GlyphData; +import org.pdfbox.ttf.GlyphTable; +import org.pdfbox.ttf.HeaderTable; +import org.pdfbox.ttf.HorizontalHeaderTable; +import org.pdfbox.ttf.HorizontalMetricsTable; +import org.pdfbox.ttf.MemoryTTFDataStream; +import org.pdfbox.ttf.NamingTable; +import org.pdfbox.ttf.NameRecord; +import org.pdfbox.ttf.OS2WindowsMetricsTable; +import org.pdfbox.ttf.PostScriptTable; +import org.pdfbox.ttf.TTFParser; +import org.pdfbox.ttf.TrueTypeFont; +import org.pdfbox.util.ResourceLoader; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * This is the TrueType implementation of fonts. + * + * @author Ben Litchfield (ben@benlitchfield.com) + * @version $Revision: 1.14 $ + */ +public class PDTrueTypeFont extends PDSimpleFont +{ + /** + * This is the key to a property in the Resources/PDFBox_External_Fonts.properties file + * to load a Font when a mapping does not exist for the current font. + */ + public static final String UNKNOWN_FONT = "UNKNOWN_FONT"; + + private Font awtFont = null; + + private static Properties externalFonts = new Properties(); + private static Map loadedExternalFonts = new HashMap(); + + static + { + try + { + ResourceLoader.loadProperties( "Resources/PDFBox_External_Fonts.properties", externalFonts ); + } + catch( IOException io ) + { + io.printStackTrace(); + throw new RuntimeException( "Error loading font resources" ); + } + } + + + /** + * Constructor. + */ + public PDTrueTypeFont() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.TRUE_TYPE ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDTrueTypeFont( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * This will load a TTF font from a font file. + * + * @param doc The PDF document that will hold the embedded font. + * @param file The file on the filesystem that holds the font file. + * @return A true type font. + * @throws IOException If there is an error loading the file data. + */ + public static PDTrueTypeFont loadTTF( PDDocument doc, String file ) throws IOException + { + return loadTTF( doc, new File( file ) ); + } + + /** + * This will load a TTF to be embedding into a document. + * + * @param doc The PDF document that will hold the embedded font. + * @param file A TTF file stream. + * @return A PDF TTF. + * @throws IOException If there is an error loading the data. + */ + public static PDTrueTypeFont loadTTF( PDDocument doc, File file ) throws IOException + { + PDTrueTypeFont retval = new PDTrueTypeFont(); + PDFontDescriptorDictionary fd = new PDFontDescriptorDictionary(); + PDStream fontStream = new PDStream(doc, new FileInputStream( file ), false ); + fontStream.getStream().setInt( COSName.LENGTH1, (int)file.length() ); + fontStream.addCompression(); + fd.setFontFile2( fontStream ); + retval.setFontDescriptor( fd ); + //only support winansi encoding right now, should really + //just use Identity-H with unicode mapping + retval.setEncoding( new WinAnsiEncoding() ); + TrueTypeFont ttf = null; + try + { + TTFParser parser = new TTFParser(); + ttf = parser.parseTTF( file ); + NamingTable naming = ttf.getNaming(); + List records = naming.getNameRecords(); + for( int i=0; i 0 ); + fd.setItalicAngle( ps.getItalicAngle() ); + + String[] names = ps.getGlyphNames(); + if( names != null ) + { + for( int i=0; i= 0 && + widths.get( glyphToCCode[i]-firstChar) == zero ) + { + widths.set( glyphToCCode[i]-firstChar, + new Integer( (int)(widthValues[i]* 1000f)/header.getUnitsPerEm() ) ); + } + } + retval.setWidths( widths ); + + retval.setFirstChar( firstChar ); + retval.setLastChar( firstChar + widths.size()-1 ); + + } + finally + { + if( ttf != null ) + { + ttf.close(); + } + } + + return retval; + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) throws IOException + { + PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary)getFontDescriptor(); + if( awtFont == null ) + { + PDStream ttfStream = fd.getFontFile2(); + String fontName = fd.getFontName(); + awtFont = Font.getFont( fontName, null ); + if( ttfStream == null ) + { + //throw new IOException( "Error:TTF Stream is null"); + // Embedded true type programs are optional, + // if there is no stream, we must use an external + // file. + ttfStream = getExternalFontFile2( fd ); + } + if( ttfStream == null ) + { + //if we can't find a font then just fake it. + awtFont = new Font("Arial", Font.PLAIN, 1 ); + } + else + { + try + { + awtFont = Font.createFont( Font.TRUETYPE_FONT, ttfStream.createInputStream() ); + } + catch( FontFormatException e ) + { + throw new IOException( e.getMessage() ); + } + } + } + AffineTransform at = new AffineTransform(); + at.scale( xScale, yScale ); + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); + g2d.setFont( awtFont.deriveFont( at ).deriveFont( fontSize ) ); + g2d.drawString( string, (int)x, (int)y ); + } + + /** + * Permit to load an external TTF Font program file + * + * Created by Pascal Allain + * Vertical7 Inc. + * + * @param fd The font descriptor currently used + * + * @return A PDStream with the Font File program, null if fd is null + * + * @throws IOException If the font is not found + */ + private PDStream getExternalFontFile2(PDFontDescriptorDictionary fd) + throws IOException + { + PDStream retval = null; + + if ( fd != null ) + { + String baseFont = getBaseFont(); + String fontResource = externalFonts.getProperty( UNKNOWN_FONT ); + if( (baseFont != null) && + (externalFonts.containsKey(baseFont)) ) + { + fontResource = externalFonts.getProperty(baseFont); + } + if( fontResource != null ) + { + TrueTypeFont extTTF = (TrueTypeFont)loadedExternalFonts.get( baseFont ); + if( extTTF == null ) + { + TTFParser ttfParser = new TTFParser(); + InputStream is = ResourceLoader.loadResource( fontResource ); + if( is == null ) + { + throw new IOException( "Error missing font resource '" + externalFonts.get(baseFont) + "'" ); + } + MemoryTTFDataStream stream = new MemoryTTFDataStream( is ); + extTTF = ttfParser.parseTTF( stream ); + loadedExternalFonts.put( baseFont, extTTF ); + } + retval = extTTF.getPDStream(); + } + } + + return retval; + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java new file mode 100644 index 0000000..010df33 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType0Font.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Graphics; + +import org.pdfbox.cos.COSArray; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.pdmodel.common.PDRectangle; + +import java.io.IOException; + +/** + * This is implementation of the Type0 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.7 $ + */ +public class PDType0Font extends PDFont +{ + /** + * Constructor. + */ + public PDType0Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "Type0" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDType0Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * This will get the fonts bouding box. + * + * @return The fonts bouding box. + * + * @throws IOException If there is an error getting the bounding box. + */ + public PDRectangle getFontBoundingBox() throws IOException + { + throw new RuntimeException( "Not yet implemented" ); + } + + /** + * 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 float getFontWidth( byte[] c, int offset, int length ) throws IOException + { + COSArray descendantFontArray = + (COSArray)font.getDictionaryObject( COSName.getPDFName( "DescendantFonts" ) ); + + COSDictionary descendantFontDictionary = (COSDictionary)descendantFontArray.getObject( 0 ); + PDFont descendentFont = PDFontFactory.createFont( descendantFontDictionary ); + + return descendentFont.getFontWidth( c, offset, length ); + } + + /** + * 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 float getAverageFontWidth() throws IOException + { + COSArray descendantFontArray = + (COSArray)font.getDictionaryObject( COSName.getPDFName( "DescendantFonts" ) ); + + COSDictionary descendantFontDictionary = (COSDictionary)descendantFontArray.getObject( 0 ); + PDFont descendentFont = PDFontFactory.createFont( descendantFontDictionary ); + + return descendentFont.getAverageFontWidth(); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java b/src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java new file mode 100644 index 0000000..89fdc5e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType1AfmPfbFont.java @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ + +package org.pdfbox.pdmodel.font; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.pdfbox.afmparser.AFMParser; +import org.pdfbox.afmtypes.CharMetric; +import org.pdfbox.afmtypes.FontMetric; +import org.pdfbox.encoding.AFMEncoding; +import org.pdfbox.pdmodel.PDDocument; +import org.pdfbox.pdmodel.common.PDRectangle; +import org.pdfbox.pdmodel.common.PDStream; +import org.pdfbox.pfb.PfbParser; + +/** + * This is implementation of the Type1 Font + * with a afm and a pfb file. + * + * @author Michael Niedermair + * @version $Revision: 1.3 $ + */ +public class PDType1AfmPfbFont extends PDType1Font +{ + /** + * the buffersize. + */ + private static final int BUFFERSIZE = 0xffff; + + /** + * The font descriptor. + */ + private PDFontDescriptorDictionary fd; + + /** + * the font metric. + */ + private FontMetric metric; + + /** + * Create a new object. + * @param doc The PDF document that will hold the embedded font. + * @param afmname The font filename. + * @throws IOException If there is an error loading the data. + */ + public PDType1AfmPfbFont(final PDDocument doc, final String afmname) + throws IOException + { + + super(); + + InputStream afmin = new BufferedInputStream( + new FileInputStream(afmname), BUFFERSIZE); + String pfbname = afmname.replaceAll(".AFM", "").replaceAll(".afm", "") + + ".pfb"; + InputStream pfbin = new BufferedInputStream( + new FileInputStream(pfbname), BUFFERSIZE); + + load(doc, afmin, pfbin); + } + + /** + * Create a new object. + * @param doc The PDF document that will hold the embedded font. + * @param afm The afm input. + * @param pfb The pfb input. + * @throws IOException If there is an error loading the data. + */ + public PDType1AfmPfbFont(final PDDocument doc, final InputStream afm, final InputStream pfb) + throws IOException + { + super(); + + load(doc, afm, pfb); + } + + /** + * This will load a afm and pfb to be embedding into a document. + * + * @param doc The PDF document that will hold the embedded font. + * @param afm The afm input. + * @param pfb The pfb input. + * @throws IOException If there is an error loading the data. + */ + private void load(final PDDocument doc, final InputStream afm, + final InputStream pfb) throws IOException + { + + fd = new PDFontDescriptorDictionary(); + setFontDescriptor(fd); + + // read the pfb + PfbParser pfbparser = new PfbParser(pfb); + pfb.close(); + + PDStream fontStream = new PDStream(doc, pfbparser.getInputStream(), + false); + fontStream.getStream().setInt("Length", pfbparser.size()); + for (int i = 0; i < pfbparser.getLengths().length; i++) + { + fontStream.getStream().setInt("Length" + (i + 1), + pfbparser.getLengths()[i]); + } + fontStream.addCompression(); + fd.setFontFile(fontStream); + + // read the afm + AFMParser parser = new AFMParser(afm); + parser.parse(); + metric = parser.getResult(); + setEncoding(new AFMEncoding(metric)); + + // set the values + setBaseFont(metric.getFontName()); + fd.setFontName(metric.getFontName()); + fd.setFontFamily(metric.getFamilyName()); + fd.setNonSymbolic(true); + fd.setFontBoundingBox(new PDRectangle(metric.getFontBBox())); + fd.setItalicAngle(metric.getItalicAngle()); + fd.setAscent(metric.getAscender()); + fd.setDescent(metric.getDescender()); + fd.setCapHeight(metric.getCapHeight()); + fd.setXHeight(metric.getXHeight()); + fd.setAverageWidth(metric.getAverageCharacterWidth()); + fd.setCharacterSet(metric.getCharacterSet()); + + // get firstchar, lastchar + int firstchar = 255; + int lastchar = 0; + + // widths + List listmetric = metric.getCharMetrics(); + + int maxWidths = 256; + List widths = new ArrayList(maxWidths); + Integer zero = new Integer(0); + Iterator iter = listmetric.iterator(); + while (iter.hasNext()) + { + CharMetric m = (CharMetric) iter.next(); + int n = m.getCharacterCode(); + if (n > 0) + { + firstchar = Math.min(firstchar, n); + lastchar = Math.max(lastchar, n); + if (m.getWx() > 0) + { + float width = m.getWx(); + widths.add(new Float(width)); + } + else + { + widths.add(zero); + } + } + } + setFirstChar(firstchar); + setLastChar(lastchar); + setWidths(widths); + + } + + /** + * @see org.pdfbox.pdmodel.font.PDSimpleFont#getFontDescriptor() + */ + public PDFontDescriptor getFontDescriptor() throws IOException + { + return fd; + } + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java new file mode 100644 index 0000000..891f7c9 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType1Font.java @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2004-2005, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; + +/** + * This is implementation of the Type1 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.10 $ + */ +public class PDType1Font extends PDSimpleFont +{ + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_ROMAN = new PDType1Font( "Times-Roman" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_BOLD = new PDType1Font( "Times-Bold" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_ITALIC = new PDType1Font( "Times-Italic" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font TIMES_BOLD_ITALIC = new PDType1Font( "Times-BoldItalic" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA = new PDType1Font( "Helvetica" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA_BOLD = new PDType1Font( "Helvetica-Bold" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA_OBLIQUE = new PDType1Font( "Helvetica-Oblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font HELVETICA_BOLD_OBLIQUE = new PDType1Font( "Helvetica-BoldOblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER = new PDType1Font( "Courier" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER_BOLD = new PDType1Font( "Courier-Bold" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER_OBLIQUE = new PDType1Font( "Courier-Oblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font COURIER_BOLD_OBLIQUE = new PDType1Font( "Courier-BoldOblique" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font SYMBOL = new PDType1Font( "Symbol" ); + /** + * Standard Base 14 Font. + */ + public static final PDType1Font ZAPF_DINGBATS = new PDType1Font( "ZapfDingbats" ); + + + private static final Map STANDARD_14 = new HashMap(); + static + { + STANDARD_14.put( TIMES_ROMAN.getBaseFont(), TIMES_ROMAN ); + STANDARD_14.put( TIMES_BOLD.getBaseFont(), TIMES_BOLD ); + STANDARD_14.put( TIMES_ITALIC.getBaseFont(), TIMES_ITALIC ); + STANDARD_14.put( TIMES_BOLD_ITALIC.getBaseFont(), TIMES_BOLD_ITALIC ); + STANDARD_14.put( HELVETICA.getBaseFont(), HELVETICA ); + STANDARD_14.put( HELVETICA_BOLD.getBaseFont(), HELVETICA_BOLD ); + STANDARD_14.put( HELVETICA_OBLIQUE.getBaseFont(), HELVETICA_OBLIQUE ); + STANDARD_14.put( HELVETICA_BOLD_OBLIQUE.getBaseFont(), HELVETICA_BOLD_OBLIQUE ); + STANDARD_14.put( COURIER.getBaseFont(), COURIER ); + STANDARD_14.put( COURIER_BOLD.getBaseFont(), COURIER_BOLD ); + STANDARD_14.put( COURIER_OBLIQUE.getBaseFont(), COURIER_OBLIQUE ); + STANDARD_14.put( COURIER_BOLD_OBLIQUE.getBaseFont(), COURIER_BOLD_OBLIQUE ); + STANDARD_14.put( SYMBOL.getBaseFont(), SYMBOL ); + STANDARD_14.put( ZAPF_DINGBATS.getBaseFont(), ZAPF_DINGBATS ); + } + + private Font awtFont = null; + + /** + * Constructor. + */ + public PDType1Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "Type1" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDType1Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * Constructor. + * + * @param baseFont The base font for this font. + */ + public PDType1Font( String baseFont ) + { + this(); + setBaseFont( baseFont ); + } + + /** + * A convenience method to get one of the standard 14 font from name. + * + * @param name The name of the font to get. + * + * @return The font that matches the name or null if it does not exist. + */ + public static PDType1Font getStandardFont( String name ) + { + return (PDType1Font)STANDARD_14.get( name ); + } + + /** + * This will get the names of the standard 14 fonts. + * + * @return An array of the names of the standard 14 fonts. + */ + public static String[] getStandard14Names() + { + return (String[])STANDARD_14.keySet().toArray( new String[14] ); + } + + /** + * @see PDFont#drawString( String, Graphics, float, float, float, float, float ) + */ + public void drawString( String string, Graphics g, float fontSize, + float xScale, float yScale, float x, float y ) throws IOException + { + if( awtFont == null ) + { + String baseFont = this.getBaseFont(); + if( baseFont.equals( TIMES_ROMAN.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.PLAIN, 1 ); + } + else if( baseFont.equals( TIMES_ITALIC.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.ITALIC, 1 ); + } + else if( baseFont.equals( TIMES_BOLD.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.BOLD, 1 ); + } + else if( baseFont.equals( TIMES_BOLD_ITALIC.getBaseFont() ) ) + { + awtFont = new Font( "Times New Roman", Font.BOLD | Font.ITALIC, 1 ); + } + else if( baseFont.equals( HELVETICA.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.PLAIN, 1 ); + } + else if( baseFont.equals( HELVETICA_BOLD.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.BOLD, 1 ); + } + else if( baseFont.equals( HELVETICA_BOLD_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.BOLD | Font.ITALIC, 1 ); + } + else if( baseFont.equals( HELVETICA_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Helvetica", Font.ITALIC, 1 ); + } + else if( baseFont.equals( COURIER.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.PLAIN, 1 ); + } + else if( baseFont.equals( COURIER_BOLD.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.BOLD, 1 ); + } + else if( baseFont.equals( COURIER_BOLD_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.BOLD | Font.ITALIC, 1 ); + } + else if( baseFont.equals( COURIER_OBLIQUE.getBaseFont() ) ) + { + awtFont = new Font( "Courier", Font.ITALIC, 1 ); + } + else if( baseFont.equals( SYMBOL.getBaseFont() ) ) + { + awtFont = new Font( "Symbol", Font.PLAIN, 1 ); + } + else if( baseFont.equals( ZAPF_DINGBATS.getBaseFont() ) ) + { + awtFont = new Font( "ZapfDingbats", Font.PLAIN, 1 ); + } + else + { + awtFont = new Font( "Arial", Font.PLAIN, 1 ); + //throw new IOException( "Not yet implemented:" + getClass().getName() + " " + + //this.getBaseFont() + + //" " + this + " " + TIMES_ROMAN ); + } + } + AffineTransform at = new AffineTransform(); + at.scale( xScale, yScale ); + + Graphics2D g2d = (Graphics2D)g; + g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON ); + g2d.setFont( awtFont.deriveFont( at ).deriveFont( fontSize ) ); + //g2d.getFontRenderContext().getTransform().scale( xScale, yScale ); + + g2d.drawString( string, (int)x, (int)y ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java b/src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java new file mode 100644 index 0000000..5f9c363 --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/PDType3Font.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import org.apache.log4j.Logger; +import org.pdfbox.cos.COSDictionary; +import org.pdfbox.cos.COSName; +import org.pdfbox.cos.COSStream; +import org.pdfbox.pdmodel.common.PDMatrix; + +import java.awt.Graphics; +import java.awt.Image; + +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; + +/** + * This is implementation of the Type3 Font. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.6 $ + */ +public class PDType3Font extends PDSimpleFont +{ + private static Logger log = Logger.getLogger( PDType3Font.class ); + + //A map of character code to java.awt.Image for the glyph + private Map images = new HashMap(); + + /** + * Constructor. + */ + public PDType3Font() + { + super(); + font.setItem( COSName.SUBTYPE, COSName.getPDFName( "Type3" ) ); + } + + /** + * Constructor. + * + * @param fontDictionary The font dictionary according to the PDF specification. + */ + public PDType3Font( COSDictionary fontDictionary ) + { + super( fontDictionary ); + } + + /** + * Type3 fonts have their glyphs defined as a content stream. This + * will create the image that represents that character + * + * @throws IOException If there is an error creating the image. + */ + private Image createImageIfNecessary( char character ) throws IOException + { + Character c = new Character( character ); + Image retval = (Image)images.get( c ); + if( retval == null ) + { + COSDictionary charProcs = (COSDictionary)font.getDictionaryObject( COSName.getPDFName( "CharProcs" ) ); + COSStream stream = (COSStream)charProcs.getDictionaryObject( COSName.getPDFName( "" + character ) ); + if( stream != null ) + { + Type3StreamParser parser = new Type3StreamParser(); + retval = parser.createImage( stream ); + images.put( c, retval ); + } + else + { + log.warn( "Error font type 3 image stream is null" ); + } + } + return retval; + + } + + /** + * This will draw a string on a canvas using the font. + * + * @param string The string to draw. + * @param g The graphics to draw onto. + * @param fontSize The size of the font to draw. + * @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 image on the screen. + */ + public void drawString( String string, Graphics g, float fontSize, float x, float y ) throws IOException + { + //if( string.equals( "V" )|| string.equals( "o" ) ) + { + for(int i=0; i 0 && newHeight > 0 ) + { + image = image.getScaledInstance( newWidth, newHeight, Image.SCALE_SMOOTH ); + g.drawImage( image, (int)x, (int)y, null ); + x+=newWidth; + } + } + } + } + } + + /** + * Set the font matrix for this type3 font. + * + * @param matrix The font matrix for this type3 font. + */ + public void setFontMatrix( PDMatrix matrix ) + { + font.setItem( "FontMatrix", matrix ); + } +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java b/src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java new file mode 100644 index 0000000..a2adc1f --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/Type3StreamParser.java @@ -0,0 +1,607 @@ +/** + * Copyright (c) 2003-2004, www.pdfbox.org + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of pdfbox; nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://www.pdfbox.org + * + */ +package org.pdfbox.pdmodel.font; + +import java.awt.Image; + +import java.io.IOException; + +import java.util.List; + +import org.pdfbox.cos.COSNumber; +import org.pdfbox.cos.COSStream; + +import org.pdfbox.pdmodel.graphics.xobject.PDInlinedImage; + +import org.pdfbox.util.BoundingBox; +import org.pdfbox.util.ImageParameters; +import org.pdfbox.util.PDFOperator; +import org.pdfbox.util.PDFStreamEngine; + +/** + * This class will handle creating an image for a type 3 glyph. + * + * @author Ben Litchfield (ben@csh.rit.edu) + * @version $Revision: 1.8 $ + */ +public class Type3StreamParser extends PDFStreamEngine +{ + private PDInlinedImage image = null; + private BoundingBox box = null; + + + /** + * This will parse a type3 stream and create an image from it. + * + * @param type3Stream The stream containing the operators to draw the image. + * + * @return The image that was created. + * + * @throws IOException If there is an error processing the stream. + */ + public Image createImage( COSStream type3Stream ) throws IOException + { + processStream( null, null, type3Stream ); + return image.createImage(); + } + + /** + * This is used to handle an operation. + * + * @param operator The operation to perform. + * @param arguments The list of arguments. + * + * @throws IOException If there is an error processing the operation. + */ + protected void processOperator( PDFOperator operator, List arguments ) throws IOException + { + super.processOperator( operator, arguments ); + String operation = operator.getOperation(); + /** + if( operation.equals( "b" ) ) + { + //Close, fill, and stroke path using nonzero winding number rule + } + else if( operation.equals( "B" ) ) + { + //Fill and stroke path using nonzero winding number rule + } + else if( operation.equals( "b*" ) ) + { + //Close, fill, and stroke path using even-odd rule + } + else if( operation.equals( "B*" ) ) + { + //Fill and stroke path using even-odd rule + } + else if( operation.equals( "BDC" ) ) + { + //(PDF 1.2) Begin marked-content sequence with property list + } + else **/if( operation.equals( "BI" ) ) + { + ImageParameters params = operator.getImageParameters(); + image = new PDInlinedImage(); + image.setImageParameters( params ); + image.setImageData( operator.getImageData() ); + //begin inline image object + }/** + else if( operation.equals( "BMC" ) ) + { + //(PDF 1.2) Begin marked-content sequence + } + else if( operation.equals( "BT" ) ) + { + log.debug( "" ); + textMatrix = new Matrix(); + textLineMatrix = new Matrix(); + } + else if( operation.equals( "BX" ) ) + { + //(PDF 1.1) Begin compatibility section + } + else if( operation.equals( "c" ) ) + { + //Append curved segment to path (three control points) + } + else if( operation.equals( "cm" ) ) + { + } + else if( operation.equals( "cs" ) ) + { + } + else if( operation.equals( "CS" ) ) + { + } + else if( operation.equals( "d" ) ) + { + //Set the line dash pattern in the graphics state + } + else */if( operation.equals( "d0" ) ) + { + //set glyph with for a type3 font + //COSNumber horizontalWidth = (COSNumber)arguments.get( 0 ); + //COSNumber verticalWidth = (COSNumber)arguments.get( 1 ); + //width = horizontalWidth.intValue(); + //height = verticalWidth.intValue(); + } + else if( operation.equals( "d1" ) ) + { + //set glyph with and bounding box for type 3 font + //COSNumber horizontalWidth = (COSNumber)arguments.get( 0 ); + //COSNumber verticalWidth = (COSNumber)arguments.get( 1 ); + COSNumber llx = (COSNumber)arguments.get( 2 ); + COSNumber lly = (COSNumber)arguments.get( 3 ); + COSNumber urx = (COSNumber)arguments.get( 4 ); + COSNumber ury = (COSNumber)arguments.get( 5 ); + + //width = horizontalWidth.intValue(); + //height = verticalWidth.intValue(); + box = new BoundingBox(); + box.setLowerLeftX( llx.floatValue() ); + box.setLowerLeftY( lly.floatValue() ); + box.setUpperRightX( urx.floatValue() ); + box.setUpperRightY( ury.floatValue() ); + }/* + else if( operation.equals( "Do" ) ) + { + //invoke named object. + } + else if( operation.equals( "DP" ) ) + { + //(PDF 1.2) De.ne marked-content point with property list + } + else if( operation.equals( "EI" ) ) + { + //end inline image object + } + else if( operation.equals( "EMC" ) ) + { + //End inline image object + } + else if( operation.equals( "ET" ) ) + { + log.debug( "" ); + textMatrix = null; + textLineMatrix = null; + } + else if( operation.equals( "EX" ) ) + { + //(PDF 1.1) End compatibility section + } + else if( operation.equals( "f" ) ) + { + //Fill the path, using the nonzero winding number rule to determine the region to .ll + } + else if( operation.equals( "F" ) ) + { + } + else if( operation.equals( "f*" ) ) + { + //Fill path using even-odd rule + } + else if( operation.equals( "g" ) ) + { + } + else if( operation.equals( "G" ) ) + { + } + else if( operation.equals( "gs" ) ) + { + } + else if( operation.equals( "h" ) ) + { + //close subpath + } + else if( operation.equals( "i" ) ) + { + //set flatness tolerance, not sure what this does + } + else if( operation.equals( "ID" ) ) + { + //begin inline image data + } + else if( operation.equals( "j" ) ) + { + //Set the line join style in the graphics state + //System.out.println( "" ); + } + else if( operation.equals( "J" ) ) + { + //Set the line cap style in the graphics state + //System.out.println( "" ); + } + else if( operation.equals( "k" ) ) + { + //Set CMYK color for nonstroking operations + } + else if( operation.equals( "K" ) ) + { + //Set CMYK color for stroking operations + } + else if( operation.equals( "l" ) ) + { + //append straight line segment from the current point to the point. + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + linePath.lineTo( x.floatValue(), pageSize.getHeight()-y.floatValue() ); + } + else if( operation.equals( "m" ) ) + { + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + linePath.reset(); + linePath.moveTo( x.floatValue(), pageSize.getHeight()-y.floatValue() ); + //System.out.println( "" ); + } + else if( operation.equals( "M" ) ) + { + //System.out.println( "" ); + } + else if( operation.equals( "MP" ) ) + { + //(PDF 1.2) Define marked-content point + } + else if( operation.equals( "n" ) ) + { + //End path without .lling or stroking + //System.out.println( "" ); + } + else if( operation.equals( "q" ) ) + { + //save graphics state + if( log.isDebugEnabled() ) + { + log.debug( "<" + operation + "> - save state" ); + } + graphicsStack.push(graphicsState.clone()); + } + else if( operation.equals( "Q" ) ) + { + //restore graphics state + if( log.isDebugEnabled() ) + { + log.debug( "<" + operation + "> - restore state" ); + } + graphicsState = (PDGraphicsState)graphicsStack.pop(); + } + else if( operation.equals( "re" ) ) + { + } + else if( operation.equals( "rg" ) ) + { + //Set RGB color for nonstroking operations + } + else if( operation.equals( "RG" ) ) + { + //Set RGB color for stroking operations + } + else if( operation.equals( "ri" ) ) + { + //Set color rendering intent + } + else if( operation.equals( "s" ) ) + { + //Close and stroke path + } + else if( operation.equals( "S" ) ) + { + graphics.draw( linePath ); + } + else if( operation.equals( "sc" ) ) + { + //set color for nonstroking operations + //System.out.println( "" ); + } + else if( operation.equals( "SC" ) ) + { + //set color for stroking operations + //System.out.println( "" ); + } + else if( operation.equals( "scn" ) ) + { + //set color for nonstroking operations special + } + else if( operation.equals( "SCN" ) ) + { + //set color for stroking operations special + } + else if( operation.equals( "sh" ) ) + { + //(PDF 1.3) Paint area de.ned by shading pattern + } + else if( operation.equals( "T*" ) ) + { + if (log.isDebugEnabled()) + { + log.debug(""); + } + //move to start of next text line + if( graphicsState.getTextState().getLeading() == 0 ) + { + graphicsState.getTextState().setLeading( -.01f ); + } + Matrix td = new Matrix(); + td.setValue( 2, 1, -1 * graphicsState.getTextState().getLeading() * textMatrix.getValue(1,1)); + textLineMatrix = textLineMatrix.multiply( td ); + textMatrix = textLineMatrix.copy(); + } + else if( operation.equals( "Tc" ) ) + { + //set character spacing + COSNumber characterSpacing = (COSNumber)arguments.get( 0 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + graphicsState.getTextState().setCharacterSpacing( characterSpacing.floatValue() ); + } + else if( operation.equals( "Td" ) ) + { + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + Matrix td = new Matrix(); + td.setValue( 2, 0, x.floatValue() * textMatrix.getValue(0,0) ); + td.setValue( 2, 1, y.floatValue() * textMatrix.getValue(1,1) ); + //log.debug( "textLineMatrix before " + textLineMatrix ); + textLineMatrix = textLineMatrix.multiply( td ); + //log.debug( "textLineMatrix after " + textLineMatrix ); + textMatrix = textLineMatrix.copy(); + } + else if( operation.equals( "TD" ) ) + { + //move text position and set leading + COSNumber x = (COSNumber)arguments.get( 0 ); + COSNumber y = (COSNumber)arguments.get( 1 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + graphicsState.getTextState().setLeading( -1 * y.floatValue() ); + Matrix td = new Matrix(); + td.setValue( 2, 0, x.floatValue() * textMatrix.getValue(0,0) ); + td.setValue( 2, 1, y.floatValue() * textMatrix.getValue(1,1) ); + //log.debug( "textLineMatrix before " + textLineMatrix ); + textLineMatrix = textLineMatrix.multiply( td ); + //log.debug( "textLineMatrix after " + textLineMatrix ); + textMatrix = textLineMatrix.copy(); + } + else if( operation.equals( "Tf" ) ) + { + //set font and size + COSName fontName = (COSName)arguments.get( 0 ); + graphicsState.getTextState().setFontSize( ((COSNumber)arguments.get( 1 ) ).floatValue() ); + + if (log.isDebugEnabled()) + { + log.debug(""); + } + + //old way + //graphicsState.getTextState().getFont() = (COSObject)stream.getDictionaryObject( fontName ); + //if( graphicsState.getTextState().getFont() == null ) + //{ + // graphicsState.getTextState().getFont() = (COSObject)graphicsState.getTextState().getFont() + // Dictionary.getItem( fontName ); + //} + graphicsState.getTextState().setFont( (PDFont)fonts.get( fontName.getName() ) ); + if( graphicsState.getTextState().getFont() == null ) + { + throw new IOException( "Error: Could not find font(" + fontName + ") in map=" + fonts ); + } + //log.debug( "Font Resource=" + fontResource ); + //log.debug( "Current Font=" + graphicsState.getTextState().getFont() ); + //log.debug( "graphicsState.getTextState().getFontSize()=" + graphicsState.getTextState().getFontSize() ); + } + else if( operation.equals( "Tj" ) ) + { + COSString string = (COSString)arguments.get( 0 ); + TextPosition pos = showString( string.getBytes() ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + } + else if( operation.equals( "TJ" ) ) + { + Matrix td = new Matrix(); + + COSArray array = (COSArray)arguments.get( 0 ); + for( int i=0; i" ); + } + td.setValue( 2, 0, value ); + textMatrix = textMatrix.multiply( td ); + } + else if( next instanceof COSString ) + { + TextPosition pos = showString( ((COSString)next).getBytes() ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + } + else + { + throw new IOException( "Unknown type in array for TJ operation:" + next ); + } + } + } + else if( operation.equals( "TL" ) ) + { + COSNumber leading = (COSNumber)arguments.get( 0 ); + graphicsState.getTextState().setLeading( leading.floatValue() ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + } + else if( operation.equals( "Tm" ) ) + { + //Set text matrix and text line matrix + COSNumber a = (COSNumber)arguments.get( 0 ); + COSNumber b = (COSNumber)arguments.get( 1 ); + COSNumber c = (COSNumber)arguments.get( 2 ); + COSNumber d = (COSNumber)arguments.get( 3 ); + COSNumber e = (COSNumber)arguments.get( 4 ); + COSNumber f = (COSNumber)arguments.get( 5 ); + + if (log.isDebugEnabled()) + { + log.debug(""); + } + + textMatrix = new Matrix(); + textMatrix.setValue( 0, 0, a.floatValue() ); + textMatrix.setValue( 0, 1, b.floatValue() ); + textMatrix.setValue( 1, 0, c.floatValue() ); + textMatrix.setValue( 1, 1, d.floatValue() ); + textMatrix.setValue( 2, 0, e.floatValue() ); + textMatrix.setValue( 2, 1, f.floatValue() ); + textLineMatrix = textMatrix.copy(); + } + else if( operation.equals( "Tr" ) ) + { + //Set text rendering mode + //System.out.println( "" ); + } + else if( operation.equals( "Ts" ) ) + { + //Set text rise + //System.out.println( "" ); + } + else if( operation.equals( "Tw" ) ) + { + //set word spacing + COSNumber wordSpacing = (COSNumber)arguments.get( 0 ); + if (log.isDebugEnabled()) + { + log.debug(""); + } + graphicsState.getTextState().setWordSpacing( wordSpacing.floatValue() ); + } + else if( operation.equals( "Tz" ) ) + { + //Set horizontal text scaling + } + else if( operation.equals( "v" ) ) + { + //Append curved segment to path (initial point replicated) + } + else if( operation.equals( "w" ) ) + { + //Set the line width in the graphics state + //System.out.println( "" ); + } + else if( operation.equals( "W" ) ) + { + //Set clipping path using nonzero winding number rule + //System.out.println( "" ); + } + else if( operation.equals( "W*" ) ) + { + //Set clipping path using even-odd rule + } + else if( operation.equals( "y" ) ) + { + //Append curved segment to path (final point replicated) + } + else if( operation.equals( "'" ) ) + { + // Move to start of next text line, and show text + // + COSString string = (COSString)arguments.get( 0 ); + if (log.isDebugEnabled()) + { + log.debug("<' string=\"" + string.getString() + "\">"); + } + + Matrix td = new Matrix(); + td.setValue( 2, 1, -1 * graphicsState.getTextState().getLeading() * textMatrix.getValue(1,1)); + textLineMatrix = textLineMatrix.multiply( td ); + textMatrix = textLineMatrix.copy(); + + showString( string.getBytes() ); + } + else if( operation.equals( "\"" ) ) + { + //Set word and character spacing, move to next line, and show text + // + COSNumber wordSpacing = (COSNumber)arguments.get( 0 ); + COSNumber characterSpacing = (COSNumber)arguments.get( 1 ); + COSString string = (COSString)arguments.get( 2 ); + + if (log.isDebugEnabled()) + { + log.debug("<\" wordSpacing=\"" + wordSpacing + + "\", characterSpacing=\"" + characterSpacing + + "\", string=\"" + string.getString() + "\">"); + } + + graphicsState.getTextState().setCharacterSpacing( characterSpacing.floatValue() ); + graphicsState.getTextState().setWordSpacing( wordSpacing.floatValue() ); + + Matrix td = new Matrix(); + td.setValue( 2, 1, -1 * graphicsState.getTextState().getLeading() * textMatrix.getValue(1,1)); + textLineMatrix = textLineMatrix.multiply( td ); + textMatrix = textLineMatrix.copy(); + + showString( string.getBytes() ); + }*/ + } + + +} \ No newline at end of file diff --git a/src/main/java/org/pdfbox/pdmodel/font/package.html b/src/main/java/org/pdfbox/pdmodel/font/package.html new file mode 100644 index 0000000..4e8d27e --- /dev/null +++ b/src/main/java/org/pdfbox/pdmodel/font/package.html @@ -0,0 +1,9 @@ + + + + + + +Classes to deal with font functionality in a PDF Document. + + -- cgit v1.2.3